1.為什么第三方應用程序可能早于System的app啟動?
????? Android能夠查閱了,這里就不細述了,這里不闡述ROM啟動還有bootloader。軟件啟動的大致流程應該是
- 啟動kernel
- 執行servicemanager 把一些native的服務用命令啟動起來(包含wifi, power, rild, surfaceflinger, mediaserver等等)
- 啟動Dalivk中的第一個進程Zygote -> 啟動java 層的系統服務system_server(包含PowerManagerService, ActivityManagerService , telephony.registry, DisplayManagerService等等)該服務中的這些部件跟native的那些服務關聯在一起
- 啟動Luncher和Persistent的App,該程序是系統級的在AndroidManifest.xml里聲明android:persistent="true"
- 發出ACTION_BOOT_COMPLETED廣播給其它應用。
?????? 在這里須要注意的是聲明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"><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: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的優先級,值越大優先級越高,按優先順序運行,可是文檔介紹優先級值大小是-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的啟動的情況。
2. 在Android手機上為什么我想全然關閉的程序關不了?
??????? 有一種理論是Android手機為了有更好的用戶體驗。會后臺自己主動啟動一些程序。 這樣我們前臺在操作的時候會感覺手機更流暢平滑。可是假設程序執行過多。對CPU 內存的開銷過大,往往會導致系統越用越慢,乃至手機掛掉的問題,在內存管理這快Android有兩種機制去解決問題,一個是在framework層在 trimApplication方法中去實現,另外一個就是在kernel里的lowmemorykiller。 這里不再細述。
??????? 可是對于用戶來說。我就是想全然關閉第三方程序,以免過多使用我的流量或者偷偷的做一些我不希望的操作。貌似沒有辦法去關閉,那為什么呢? 我這里先講述當中一種情況。
????????? Service顧名思義是服務。執行在前后臺后都能夠,即能夠執行在當前進程也能夠執行在其它的進程里,Service能夠為多個APP共享使用,是通過binder機制來實現的。當我Kill掉一個帶有服務的進程(沒有調用stopService()), 過一會該應用會自己主動重新啟動。以下是代碼的調用順序。自下往上查看。
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 onStartCommand(Intent intent, int flags, int startId) {return START_NOT_STICKY;}
Framwork實現代碼
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; // 該變量設置為true}break;}if (sr.startRequested && (sr.stopIfKilled || 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圍棋處理。