Android在第三方应用程序系统应用尽早开始,杀死自己主动的第三方应用程序,以重新启动...
1.為什么第三方應(yīng)用程序可能早于System的app啟動?
????? Android能夠查閱了,這里就不細(xì)述了,這里不闡述ROM啟動還有bootloader。軟件啟動的大致流程應(yīng)該是
- 啟動kernel
- 執(zhí)行servicemanager 把一些native的服務(wù)用命令啟動起來(包含wifi, power, rild, surfaceflinger, mediaserver等等)
- 啟動Dalivk中的第一個進(jìn)程Zygote -> 啟動java 層的系統(tǒng)服務(wù)system_server(包含PowerManagerService, ActivityManagerService , telephony.registry, DisplayManagerService等等)該服務(wù)中的這些部件跟native的那些服務(wù)關(guān)聯(lián)在一起
- 啟動Luncher和Persistent的App,該程序是系統(tǒng)級的在AndroidManifest.xml里聲明android:persistent="true"
- 發(fā)出ACTION_BOOT_COMPLETED廣播給其它應(yīng)用。
?????? 在這里須要注意的是聲明android:persistent屬性為true的APP被kill掉后還是會自己主動重新啟動的。系統(tǒng)中我們已知android:persistent屬性為true的APP肯定有Phone App,也就是說第三方應(yīng)用應(yīng)當(dāng)至少晚于Phone APP啟動,怎樣推斷呢?最簡單的辦法看其PID的大小,PID值越小越先啟動。有其第三方應(yīng)用能夠先于Phone APP啟動。我們探其應(yīng)用的AndroidManifest.xml (PS:怎樣看APK的代碼,網(wǎng)上有你懂的apktool等),發(fā)現(xiàn)其在AndroidManifest里定義的靜態(tài)Receiver的intent-filter的屬性例如以下:
2147483647 這個值是什么?好大,哦,原來是int的最大值!
我們來看下google 文檔
android:priority??? The priority that should be given to the parent component with regard to handling intents of the type described by the filter. This attribute has meaning for both activities and broadcast receivers:
??????? It provides information about how able an activity is to respond to an intent that matches the filter, relative to other activities that could also respond to the intent. When an intent could be handled by multiple activities with different priorities, Android will consider only those with higher priority values as potential targets for the intent.
??????? It controls the order in which broadcast receivers are executed to receive broadcast messages. Those with higher priority values are called before those with lower values. (The order applies only to synchronous messages; it's ignored for asynchronous messages.)
??? Use this attribute only if you really need to impose a specific order in which the broadcasts are received, or want to force Android to prefer one activity over others.
??? The 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的優(yōu)先級,值越大優(yōu)先級越高,按優(yōu)先順序運(yùn)行,可是文檔介紹優(yōu)先級值大小是-1000~1000. 該應(yīng)用的是int的最大值, 但android平臺沒有對android:priority值進(jìn)行檢查。在開機(jī)后該應(yīng)用Receiver的intent-filter的優(yōu)先級最高,在該filter里的intent被系統(tǒng)發(fā)送出來(android.intent.action.MEDIA_MOUNTE, android.net.wifi.WIFI_STATE_CHANGED等等),這個時候App會依據(jù)這個intent而被啟動起來。???????? 這里須要注意的是該Receiver是個靜態(tài)的,一定是要注冊在AndroidManifest里。
當(dāng)Wifi成功注冊后會發(fā)出WIFI_STATE_CHANGED的消息, 或者其它的部件完畢一些事件后也會發(fā)出類似的消息。而這些消息的發(fā)出又早于屬性為persistent的系統(tǒng)級APP的啟動, 由此就會發(fā)生第三方應(yīng)用早于系統(tǒng)級APP的啟動的情況。
2. 在Android手機(jī)上為什么我想全然關(guān)閉的程序關(guān)不了?
??????? 有一種理論是Android手機(jī)為了有更好的用戶體驗。會后臺自己主動啟動一些程序。 這樣我們前臺在操作的時候會感覺手機(jī)更流暢平滑。可是假設(shè)程序執(zhí)行過多。對CPU 內(nèi)存的開銷過大,往往會導(dǎo)致系統(tǒng)越用越慢,乃至手機(jī)掛掉的問題,在內(nèi)存管理這快Android有兩種機(jī)制去解決問題,一個是在framework層在 trimApplication方法中去實現(xiàn),另外一個就是在kernel里的lowmemorykiller。 這里不再細(xì)述。
??????? 可是對于用戶來說。我就是想全然關(guān)閉第三方程序,以免過多使用我的流量或者偷偷的做一些我不希望的操作。貌似沒有辦法去關(guān)閉,那為什么呢? 我這里先講述當(dāng)中一種情況。
????????? Service顧名思義是服務(wù)。執(zhí)行在前后臺后都能夠,即能夠執(zhí)行在當(dāng)前進(jìn)程也能夠執(zhí)行在其它的進(jìn)程里,Service能夠為多個APP共享使用,是通過binder機(jī)制來實現(xiàn)的。當(dāng)我Kill掉一個帶有服務(wù)的進(jìn)程(沒有調(diào)用stopService()), 過一會該應(yīng)用會自己主動重新啟動。以下是代碼的調(diào)用順序。自下往上查看。
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。進(jìn)程也依據(jù)該service啟動起來, service就執(zhí)行在重新啟動的進(jìn)程里。
??????? 在這樣的情況下是不是就真沒辦法了呢,當(dāng)然不是。假設(shè)我們在service中覆蓋onStartCommand這個函數(shù)而且返回值為START_NOT_STICKY,在我們kill該進(jìn)程后則不會自己主動重新啟動,我們想關(guān)閉的應(yīng)用也能夠全然關(guān)閉了。不會再自己主動重新啟動了。
public int onStartCommand(Intent intent, int flags, int startId) {return START_NOT_STICKY;}Framwork實現(xiàn)代碼 frameworks/base/services/java/com/android/server/am/ActiveServices.javacase 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.stopIfKilled = true; // 該變量設(shè)置為true}break;}if (sr.startRequested && (sr.stopIfKilled || canceled)) { //進(jìn)入到該條件中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); //運(yùn)行在這里。不會重新啟動App}}}
??????? 重寫onStartCommand方法且返回值為START_NOT_STICKY的代碼調(diào)用順序,自下而上查看。
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.
?????? 在這里對這個返回值做下解釋:
當(dāng)服務(wù)進(jìn)程因某種原因(內(nèi)存不夠,強(qiáng)制關(guān)閉等)被kill掉時,START_STICKY再次,在系統(tǒng)中創(chuàng)建了后有足夠的內(nèi)存service, 在onStartCommand在handle它是null intent.
START_NOT_STICKY通知系統(tǒng)不會再次創(chuàng)建service. 另一種回報值START_REDELIVER_INTENT再創(chuàng)service而伴隨著原intent圍棋處理。
總結(jié)
以上是生活随笔為你收集整理的Android在第三方应用程序系统应用尽早开始,杀死自己主动的第三方应用程序,以重新启动...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MyBatis总结六:resultMap
- 下一篇: Android项目实战(十五):自定义不