Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android啟動早於系統應用的第三方應用,殺不死自動重啟的第三方應用

Android啟動早於系統應用的第三方應用,殺不死自動重啟的第三方應用

編輯:關於Android編程

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的屬性如下:

       
            
                
                
                
                
                
            
            
                
                
                
                
                
                
            


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中覆蓋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.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.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)

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved