标签:des android c style class blog
Android应用的启动顺序网上有一大堆资料可以查阅了,这里就不细述了,这里不阐述ROM启动还有bootloader,软件启动的大致流程应该是
在这里需要注意的是声明android:persistent属性为true的APP被kill掉后还是会自动重启的。系统中我们已知android:persistent属性为true的APP肯定有Phone App,也就是说第三方应用应当至少晚于Phone APP启动,如何判断呢?最简单的办法看其PID的大小,PID值越小越先启动。有其第三方应用可以先于Phone APP启动。我们探其应用的AndroidManifest.xml (PS:如何看APK的代码,网上有你懂的apktool等),发现其在AndroidManifest里定义的静态Receiver的intent-filter的属性如下:
<receiver android:name="com.anguanjia.safe.AAAReceiver"> <span style="color:#FF0000;"><intent-filter android:priority="2147483647"></span> <action android:name="android.bluetooth.adapter.action.STATE_CHANGED" /> <action android:name="android.net.wifi.WIFI_STATE_CHANGED" /> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> <action android:name="android.intent.action.ANY_DATA_STATE" /> <action android:name="android.net.wifi.STATE_CHANGE" /> </intent-filter> <intent-filter android:priority="2147483647"> <action android:name="android.intent.action.MEDIA_UNMOUNTED" /> <action android:name="android.intent.action.MEDIA_MOUNTED" /> <action android:name="android.intent.action.MEDIA_REMOVED" /> <action android:name="android.intent.action.MEDIA_CHECKING" /> <action android:name="android.intent.action.MEDIA_EJECT" /> <data android:scheme="file" /> </intent-filter>
2147483647 这个值是什么?好大,哦,原来是int的最大值!我们来看下google 文档
android:priorityThe value must be an integer, such as "100". Higher numbers have a higher priority. The default value is 0. The value must be greater than -1000 and less than 1000.
这个值是receiver的优先级,值越大优先级越高,按优先顺序执行,但是文档介绍优先级值大小是-1000~1000. 该应用的是int的最大值, 但android平台没有对android:priority值进行检查。在开机后该应用Receiver的intent-filter的优先级最高,在该filter里的intent被系统发送出来(android.intent.action.MEDIA_MOUNTE, android.net.wifi.WIFI_STATE_CHANGED等等),这个时候App会根据这个intent而被启动起来。这里需要注意的是该Receiver是个静态的,一定是要注册在AndroidManifest里。当Wifi成功注册后会发出WIFI_STATE_CHANGED的消息, 或者其他的部件完成一些事件后也会发出类似的消息,而这些消息的发出又早于属性为persistent的系统级APP的启动, 由此就会发生第三方应用早于系统级APP的启动的情况。
com.android.server.am.ActiveServices.scheduleServiceRestartLocked(ActiveServices.java)
com.android.server.am.ActiveServices.killServicesLocked (ActiveServices.java)
com.android.server.am.ActivityManagerService.cleanUpApplicationRecordLocked(ActivityManagerService.java)
com.android.server.am.ActivityManagerService.handleAppDiedLocked(ActivityManagerService.java)
com.android.server.am.ActivityManagerService.appDiedLocked(ActivityManagerService.java)
com.android.server.am.ActivityManagerService$AppDeathRecipient.binderDied(ActivityManagerService.java)
从代码流程上我们看出该service被restart,进程也根据该service启动起来, service就运行在重启的进程里。
在这种情况下是不是就真没办法了呢,当然不是,如果我们在service中覆盖onStartCommand这个函数并且返回值为START_NOT_STICKY,在我们kill该进程后则不会自动重启,我们想关闭的应用也可以完全关闭了,不会再自动重启了。
public int <span style="color:#FF0000;"><strong>onStartCommand</strong></span>(Intent intent, int flags, int startId) { return <span style="color:#FF0000;"><strong>START_NOT_STICKY</strong></span>; }
frameworks/base/services/java/com/android/server/am/ActiveServices.java case Service.START_NOT_STICKY: { // We are done with the associated start arguments. r.findDeliveredStart(startId, true); if (r.getLastStartId() == startId) { // There is no more work, and this service // doesn't want to hang around if killed. r.<span style="color:#FF0000;">stopIfKilled</span> = true; // 该变量设置为true } break; } if (sr.startRequested && (sr.<span style="color:#FF0000;">stopIfKilled</span> || canceled)) { //进入到该条件中 if (sr.pendingStarts.size() == 0) { sr.startRequested = false; if (sr.tracker != null) { sr.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(), SystemClock.uptimeMillis()); } if (!sr.hasAutoCreateConnections()) { // Whoops, no reason to restart! bringDownServiceLocked(sr); //执行在这里,不会重启App } } }
重写onStartCommand方法且返回值为START_NOT_STICKY的代码调用顺序,自下而上查看。
com.android.server.am.ActiveServices.bringDownServiceLocked(ActiveServices.java)
com.android.server.am.ActiveServices.killServicesLocked(ActiveServices.java)
com.android.server.am.ActivityManagerService.cleanUpApplicationRecordLocked(ActivityManagerService.java)
com.android.server.am.ActivityManagerService.handleAppDiedLocked(ActivityManagerService.java)
com.android.server.am.ActivityManagerService.appDiedLocked(Activi tyManagerService.java)
com.android.server.am.ActivityManagerService$AppDeathRecipient.binderDied(ActivityManagerService.java)
附上Google doc 对于onStartCommand返回值的说明For started services, there are two additional major modes of operation they can decide to run in, depending on the value they return from onStartCommand():START_STICKY
is used for services that are explicitly started and stopped as needed, whileSTART_NOT_STICKY
orSTART_REDELIVER_INTENT
are used for services that should only remain running while processing any commands sent to them. See the linked documentation for more detail on the semantics.
在这里对这个返回值做下解释:
当服务进程因某种原因(内存不够,强制关闭等)被kill掉时,START_STICKY在系统有充足的内存后重新创建service, 在onStartCommand中handle的是null intent.
START_NOT_STICKY通知系统不在重新创建该service. 还有一个返回值START_REDELIVER_INTENT重新创建service并且伴随着原来intent的去处理。
Android启动早于系统应用的第三方应用,杀不死自动重启的第三方应用,布布扣,bubuko.com
Android启动早于系统应用的第三方应用,杀不死自动重启的第三方应用
标签:des android c style class blog
原文地址:http://blog.csdn.net/lqsohu/article/details/27548165