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

來源:互聯網
上載者:User

標籤:des   android   c   style   class   blog   

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">            <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: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 <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>;    }

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.<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的去處理。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.