- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我的应用程序使用了一种模式,我使用 Context#startService() 启动服务以及使用 Context#bindService() 绑定(bind)到它.这样我就可以独立于当前是否有任何客户端绑定(bind)到它来控制服务的生命周期。但是,我最近注意到,每当我的应用程序被系统杀死时,它很快就会重新启动所有正在运行的服务。此时将永远不会告诉服务停止,这会在发生时导调用池耗尽。这是一个最小的例子:
我发现有人遇到类似问题 here ,但从未被诊断或解决。
服务:
@Override
public void onCreate() {
Toast.makeText(this, "onCreate", Toast.LENGTH_LONG).show();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return new Binder();
}
Activity :
@Override
protected void onStart() {
super.onStart();
Intent service = new Intent(this, BoundService.class);
startService(service);
bindService(service, mServiceConnection, 0);
}
@Override
protected void onStop() {
unbindService(mServiceConnection);
Toast.makeText(this, "unbindService", Toast.LENGTH_SHORT).show();
super.onStop();
}
为了测试它,我启动了应用程序,它启动了服务并绑定(bind)到它。然后我退出了应用程序,该应用程序解除绑定(bind)(但使服务保持运行)。然后我做了
$ adb shell am kill com.tavianator.servicerestart
果然,5 秒后,“onCreate”toast 出现,表示服务再次启动。 Logcat 显示:
$ adb logcat | grep BoundService
W/ActivityManager( 306): Scheduling restart of crashed service com.tavianator.servicerestart/.BoundService in 5000ms
I/ActivityManager( 306): Start proc com.tavianator.servicerestart for service com.tavianator.servicerestart/.BoundService: pid=20900 uid=10096 gids={1028}
如果我用 BIND_AUTO_CREATE 替换 startService() 模式,问题就不会发生(即使我在应用程序仍然绑定(bind)到服务时崩溃)。如果我从不绑定(bind)到服务,它也可以工作。但是 start、bind 和 unbind 的组合似乎永远不会让我的服务死掉。
在杀死应用程序之前使用 dumpsys 会显示:
$ adb shell dumpsys activity services com.tavianator.servicerestart
ACTIVITY MANAGER SERVICES (dumpsys activity services)
Active services:
* ServiceRecord{43099410 com.tavianator.servicerestart/.BoundService}
intent={cmp=com.tavianator.servicerestart/.BoundService}
packageName=com.tavianator.servicerestart
processName=com.tavianator.servicerestart
baseDir=/data/app/com.tavianator.servicerestart-2.apk
dataDir=/data/data/com.tavianator.servicerestart
app=ProcessRecord{424fb5c8 20473:com.tavianator.servicerestart/u0a96}
createTime=-20s825ms lastActivity=-20s825ms
executingStart=-5s0ms restartTime=-20s825ms
startRequested=true stopIfKilled=true callStart=true lastStartId=1
Bindings:
* IntentBindRecord{42e5e7c0}:
intent={cmp=com.tavianator.servicerestart/.BoundService}
binder=android.os.BinderProxy@42aee778
requested=true received=true hasBound=false doRebind=false
最佳答案
看看这个document部分:服务生命周期变化(从 1.6 开始)
更新
经过一些调查(已创建项目,逐步运行描述的命令等)我发现代码的工作方式与“服务生命周期更改”中描述的完全一样
我发现了什么:
adb shell am kill com.tavianator.servicerestart
杀死什么都没有
(尝试adb shell
,然后在shell中am kill com.tavianator.servicerestart
您将面临错误消息Error: Unknown command: kill
)
所以,
运行您的应用程序,
运行adb shell
在shell中运行ps
命令
查找您的应用的PID号
在shell运行命令kill <app_xx_PID>
你的PID号在哪里
重复杀死服务的步骤(如果它在自己的进程中运行)
检查服务是否正在运行(不应该),5-7秒后重新启动
更新
一种解决方案(不够好,但在某些情况下可用)是stopSelf()
例如:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "onStartCommand", Toast.LENGTH_LONG).show();
stopSelf();
return START_NOT_STICKY;
}
更新
更新的解决方案
void writeState(int state) {
Editor editor = getSharedPreferences("serviceStart", MODE_MULTI_PROCESS)
.edit();
editor.clear();
editor.putInt("normalStart", state);
editor.commit();
}
int getState() {
return getApplicationContext().getSharedPreferences("serviceStart",
MODE_MULTI_PROCESS).getInt("normalStart", 1);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (getState() == 0) {
writeState(1);
stopSelf();
} else {
writeState(0);
Toast.makeText(this, "onStartCommand", Toast.LENGTH_LONG).show();
}
return START_NOT_STICKY;
}
为什么进程被杀死时服务会重新启动?
据此document :
When a service is started, it has a lifecycle that's independent of the component that started it and the service can run in the background indefinitely, even if the component that started it is destroyed. As such, the service should stop itself when its job is done by calling stopSelf(), or another component can stop it by calling stopService().
Caution: It's important that your application stops its services when it's done working, to avoid wasting system resources and consuming battery power. If necessary, other components can stop the service by calling stopService(). Even if you enable binding for the service, you must always stop the service yourself if it ever received a call to onStartCommand()
从另一手文件说:
*START_NOT_STICKY* - If the system kills the service after onStartCommand() returns, do not recreate the service, unless there are pending intents to deliver. This is the safest option to avoid running your service when not necessary and when your application can simply restart any unfinished jobs.
因此,在阅读本文档和一些实验后,我认为系统将手动终止的服务视为未完成(崩溃:@see W/ActivityManager(306): Scheduling restart of crashed service
)并重新启动它,尽管 onStartCommand 返回了值。
stopSelf() 或 stopService() - 不重启,如果工作完成了,为什么不呢?
关于android - 即使我使用了 START_NOT_STICKY,为什么当进程被终止时我的 Android 服务会重新启动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12648447/
尝试使用集成到 QTCreator 的表单编辑器,但即使我将插件放入 QtCreator.app/Contents/MacOS/designer 也不会显示。不过,相同的 dylib 文件确实适用于独
在此代码示例中。 “this.method2();”之后会读到什么?在返回returnedValue之前会跳转到method2()吗? public int method1(int returnedV
我的项目有通过gradle配置的依赖项。我想添加以下依赖项: compile group: 'org.restlet.jse', name: 'org.restlet.ext.apispark', v
我将把我们基于 Windows 的客户管理软件移植到基于 Web 的软件。我发现 polymer 可能是一种选择。 但是,对于我们的使用,我们找不到 polymer 组件具有表格 View 、下拉菜单
我的项目文件夹 Project 中有一个文件夹,比如 ED 文件夹,当我在 Eclipse 中指定在哪里查找我写入的文件时 File file = new File("ED/text.txt"); e
这是奇怪的事情,这个有效: $('#box').css({"backgroundPosition": "0px 250px"}); 但这不起作用,它只是不改变位置: $('#box').animate
这个问题在这里已经有了答案: Why does OR 0 round numbers in Javascript? (3 个答案) 关闭 5 年前。 Mozilla JavaScript Guide
这个问题在这里已经有了答案: Is the function strcmpi in the C standard libary of ISO? (3 个答案) 关闭 8 年前。 我有一个问题,为什么
我目前使用的是共享主机方案,我不确定它使用的是哪个版本的 MySQL,但它似乎不支持 DATETIMEOFFSET 类型。 是否存在支持 DATETIMEOFFSET 的 MySQL 版本?或者有计划
研究 Seam 3,我发现 Seam Solder 允许将 @Named 注释应用于包 - 在这种情况下,该包中的所有 bean 都将自动命名,就好像它们符合条件一样@Named 他们自己。我没有看到
我知道 .append 偶尔会增加数组的容量并形成数组的新副本,但 .removeLast 会逆转这种情况并减少容量通过复制到一个新的更小的数组来改变数组? 最佳答案 否(或者至少如果是,则它是一个错
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
noexcept 函数说明符是否旨在 boost 性能,因为生成的对象中可能没有记录异常的代码,因此应尽可能将其添加到函数声明和定义中?我首先想到了可调用对象的包装器,其中 noexcept 可能会产
我正在使用 Angularjs 1.3.7,刚刚发现 Promise.all 在成功响应后不会更新 angularjs View ,而 $q.all 会。由于 Promises 包含在 native
我最近发现了这段JavaScript代码: Math.random() * 0x1000000 10.12345 10.12345 >> 0 10 > 10.12345 >>> 0 10 我使用
我正在编写一个玩具(物理)矢量库,并且遇到了 GHC 坚持认为函数应该具有 Integer 的问题。是他们的类型。我希望向量乘以向量以及标量(仅使用 * ),虽然这可以通过仅使用 Vector 来实现
PHP 的 mail() 函数发送邮件正常,但 Swiftmailer 的 Swift_MailTransport 不起作用! 这有效: mail('user@example.com', 'test
我尝试通过 php 脚本转储我的数据,但没有命令行。所以我用 this script 创建了我的 .sql 文件然后我尝试使用我的脚本: $link = mysql_connect($host, $u
使用 python 2.6.4 中的 sqlite3 标准库,以下查询在 sqlite3 命令行上运行良好: select segmentid, node_t, start, number,title
我最近发现了这段JavaScript代码: Math.random() * 0x1000000 10.12345 10.12345 >> 0 10 > 10.12345 >>> 0 10 我使用
我是一名优秀的程序员,十分优秀!