Android適配總結之服務

1 參考

本文內容沒有什麼技術,僅做問題及方案記錄。

2 變更記錄

2.1 Android 8.0 後臺執行限制

手機同時運行的應用越多,對系統造成的負擔越大。 如果還有應用或服務在後臺運行,這會對系統造成更大負擔,進而可能導致用戶體驗下降;例如,音樂應用可能會突然關閉。

爲了降低發生這些問題的機率,Android 8.0 對應用在用戶不與其直接交互時可以執行的操作施加了限制。

應用在兩個方面受到限制:

後臺服務限制:處於空閒狀態時,應用可以使用的後臺服務存在限制。 這些限制不適用於前臺服務,因爲前臺服務更容易引起用戶注意。

廣播限制:除了有限的例外情況,應用無法使用清單註冊隱式廣播。 它們仍然可以在運行時註冊這些廣播,並且可以使用清單註冊專門針對它們的顯式廣播。

注:默認情況下,這些限制僅適用於針對 O 的應用。 不過,用戶可以從 Settings 屏幕爲任意應用啓用這些限制,即使應用並不是以 O 爲目標平臺。

在大多數情況下,應用都可以使用 JobScheduler 作業克服這些限制。 這種方式讓應用安排爲在未活躍運行時執行工作,不過仍能夠使系統可以在不影響用戶體驗的情況下安排這些作業。

評價一下,JobScheduler最大的缺點是不支持Android5.0以下版本,如果你想使你的應用兼容至Android.4.4,還是得老老實實用Service。所以到現在我還沒用過JobScheduler。。。

Android 8.0 對特定函數做出了以下變更:

  • 如果針對 Android 8.0 的應用嘗試在不允許其創建後臺服務的情況下使用 startService() 函數,則該函數將引發一個 IllegalStateException。
  • 新的 Context.startForegroundService() 函數將啓動一個前臺服務。現在,即使應用在後臺運行,系統也允許其調用 Context.startForegroundService()。不過,應用必須在創建服務後的五秒內調用該服務的 startForeground() 函數。同時,調用startForeground()需要傳入一個通知notification,注意notification也要適配Android8.0。

2.2 Android 9.0 前臺服務

針對 Android 9 或更高版本並使用前臺服務的應用必須請求 FOREGROUND_SERVICE 權限。這是普通權限,因此,系統會自動爲請求權限的應用授予此權限。 如果針對 Android 9 或更高版本的應用嘗試創建一個前臺服務且未請求 FOREGROUND_SERVICE,則系統會引發 SecurityException。

2.3 解決方案

本方案的目的是使應用的服務在鎖屏後不被銷燬,比如我最近做了集成mqtt的項目,mqtt本質是個長連接,隨時都得接收和發送mqtt消息,所以mqtt最好是待在一個不容易被銷燬的Service上。

1 適配啓動服務代碼

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
    // Android 8.0 改爲前臺服務方式啓動
        context.startForegroundService(intent);
    } else {
        context.startService(intent);
    }

2 系統說明在調用 context.startForegroundService(intent)後5s內需要調用service.startForeground()

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        // 注意notification也要適配Android 8 哦
        ...
        startForeground(1, notification);
    }

這裏要說下,startForeground()方法的第一個參數不能爲0,即使調用了,也是啓動服務後5s程序崩潰,異常說你沒有在5s內調startForeground(),也不知道什麼原因,反正爲0就是會出錯。

谷歌官方就是希望你應用的常駐服務在運行時能讓用戶看見,然後用戶可以選擇關閉服務。。我們開發者或者產品肯定是不希望讓用戶看到的,較敏感的用戶可能看到這個通知立馬就給你屏蔽了,讓你服務都啓動不了。

小米手機MIUI10效果就像這樣:

剛開始startForeground(0, notification),通知是沒有顯示的,但是出現了沒調startForeground()的崩潰問題。

應用業務就是需要常駐服務,暫時就用這樣方案了。

爲什麼QQ,微信的常駐服務沒有顯示通知,我猜想的方案是有一個定時任務不斷的啓動服務,保證它不會被kill掉,其它方案就可能是些黑科技了。

停止服務時

要加上這個:

  if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        stopForeground(true);// 只是移除通知,沒有停止服務的功能
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章