1、引言

對於移動端IM應用和訊息推送應用的開發者來說,Android後臺保活這件事是再熟悉不過了。

自從Android P(即Android 8。0)出現以後,Android已經從系統層面將後臺保活這條路給堵死了(詳見:《Android P正式版即將到來:後臺應用保活、訊息推送的真正噩夢》),曾今那些層出不窮的保活黑科技能用的也越來越少了(詳見:《全面盤點當前Android後臺保活方案的真實執行效果(截止2019年前)》。雖然可以自已對接廠商的ROOM級推送通道,但一方面各廠商的推送介面都不一樣(而且同一廠商不同的系統版本間也存在推送介面的相容性問題),很不方便。另一方面要一家家引入各自的推送服務SDK包會讓APP變的很大,這讓APP的下載變的很不友好。

總之,Android應用的後臺保活在某些場景下,還是有持續的需求。除了之前那些耳熟能詳的保活黑科技以外,在Android 9。0(甚至Android 10)時代,我們還有哪些保活方法可以用?那麼,請跟著本文作者的思路,看看更優雅的後臺保活實現方法吧。

(本文同步釋出於:

http://www。

52im。net/thread-2881-1-

1。html

2020年了,Android後臺保活還有戲嗎?看我如何優雅的實現!

2、關於作者

網名NanBox:畢業於華中科技大學,現為“悅跑圈APP”高階Android開發工程師。主要負責公司 Android 專案,核心模組的開發。涉及 GPS 定位、地圖、圖片編輯等功能。獨立開發了手表應用專案。 在專案中應入了 Flutter 跨平臺開發技術,實現了原生和 Flutter 的混合開發。

本文作者樂於分享,平時會寫技術文章並分享在多個平臺,是掘金專欄作者的一員,文章總閱讀量超過 10 萬。在 GitHub 上有多個開源專案,多次在團隊內部進行技術分享。是 Android 和 Flutter 官方中文文件譯者。

3、相關文章

如果你想詳細瞭解目前Android平臺上後臺保活技術的挑戰,請閱讀:

《Android P正式版即將到來:後臺應用保活、訊息推送的真正噩夢》。

如果你想回顧那些曾今出現的Android保活黑科技,以下文章值得好好讀讀:

《全面盤點當前Android後臺保活方案的真實執行效果(截止2019年前)》

《應用保活終極總結(一):Android6。0以下的雙程序守護保活實踐》

《應用保活終極總結(二):Android6。0及以上的保活實踐(程序防殺篇)》

《應用保活終極總結(三):Android6。0及以上的保活實踐(被殺復活篇)》

《Android程序保活詳解:一篇文章解決你的所有疑問》

《Android端訊息推送總結:實現原理、心跳保活、遇到的問題等》

《深入的聊聊Android訊息推送這件小事》

《為何基於TCP協議的移動端IM仍然需要心跳保活機制?》

《微信團隊原創分享:Android版微信後臺保活實戰分享(程序保活篇)》

《融雲技術分享:融雲安卓端IM產品的網路鏈路保活技術實踐》

4、Android保活現狀

我們知道,Android 系統會存在殺後臺程序的情況,並且隨著系統版本的更新,殺程序的力度還有越來越大的趨勢(見:《Android P正式版即將到來:後臺應用保活、訊息推送的真正噩夢》)。

系統這種做法本身出發點是好的,因為可以節省記憶體,降低功耗,也避免了一些流氓行為。

但有一部分應用,應用本身的使用場景就需要在後臺執行,使用者也是願意讓它在後臺執行的,比如跑步類應用、一些懶得對接廠商推送通道的IM應用、訊息推送資訊類應用等。

一方面流氓軟體用各種流氓手段進行保活,另一方面系統加大殺後臺的力度,導致我們一些真正需要在後臺執行的應用被誤殺,苦不堪言。

5、優雅的保活?

為了做到保活,出現了不少「黑科技」,比如 1 個畫素的 Activity,播放無聲音訊,雙程序互相守護等(可以讀讀這個系列:《應用保活終極總結(一):Android6。0以下的雙程序守護保活實踐》、《應用保活終極總結(二):Android6。0及以上的保活實踐(程序防殺篇)》、《應用保活終極總結(三):Android6。0及以上的保活實踐(被殺復活篇)》)。

這些做法可以說是很流氓了,甚至破壞了 Android 的生態,好在隨著 Android 系統版本的更新,這些非常規的保活手段很多都已失效了。

對於那些確實需要在後臺執行的應用,我們如何做到優雅的保活呢?

6、加入後臺執行白名單,可以優雅的實現保活

從 Android 6。0 開始,系統為了省電增加了休眠模式,系統待機一段時間後,會殺死後臺正在執行的程序。但系統會有一個後臺執行白名單,白名單裡的應用將不會受到影響,在原生系統下,透過:「設定」 - 「電池」 - 「電池最佳化」 - 「未最佳化應用」,可以看到這個白名單。

通常會看到下面這兩位:

2020年了,Android後臺保活還有戲嗎?看我如何優雅的實現!

下次被產品說「 XXX 都可以保活,為什麼我們不行!」的時候,你就知道怎麼懟回去了。大廠透過和手機廠商的合作,將自己的應用預設加入到白名單中。如果你在一個能談成這種合作的大廠,也就不用往下看了。

好在系統還沒有拋棄我們,允許我們申請把應用加入白名單。

首先,在 AndroidManifest。xml 檔案中配置一下許可權:

可以透過以下方法,判斷我們的應用是否在白名單中:

@RequiresApi(api = Build。VERSION_CODES。M)

private boolean isIgnoringBatteryOptimizations() {

boolean isIgnoring = false;

PowerManager powerManager = (PowerManager) getSystemService(Context。POWER_SERVICE);

if(powerManager != null) {

isIgnoring = powerManager。isIgnoringBatteryOptimizations(getPackageName());

}

return isIgnoring;

}

如果不在白名單中,可以透過以下程式碼申請加入白名單:

@RequiresApi(api = Build。VERSION_CODES。M)

public void requestIgnoreBatteryOptimizations() {

try{

Intent intent = newIntent(Settings。ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);

intent。setData(Uri。parse(”package:“+ getPackageName()));

startActivity(intent);

} catch(Exception e) {

e。printStackTrace();

}

}

申請時,應用上會出現這樣一個視窗:

2020年了,Android後臺保活還有戲嗎?看我如何優雅的實現!

可以看到,這個系統彈窗會有影響電池續航的提醒,所以如果想讓使用者點允許,必須要有相關的說明。如果要判斷使用者是否點選了允許,可以在申請的時候呼叫 startActivityForResult,在 onActivityResult 裡再判斷一次是否在白名單中。

7、加入後臺執行白名單的多廠商適配方法

7.1 基本說明

Android 開發的一個難點在於,各大手機廠商對原生系統進行了不同的定製,導致我們需要進行不同的適配,後臺管理就是一個很好的體現。幾乎各個廠商都有自己的後臺管理,就算應用加入了後臺執行白名單,仍然可能會被廠商自己的後臺管理幹掉。

如果能把應用加入廠商系統的後臺管理白名單,可以進一步降低程序被殺的機率。不同的廠商在不同的地方進行設定,一般是在各自的「手機管家」,但更難的是,就算同一個廠商的系統,不同的版本也可能是在不同地方設定。

最理想的做法是,我們根據不同手機,甚至是不同的系統版本,給使用者呈現一個圖文操作步驟,並且提供一個按鈕,直接跳轉到指定頁面進行設定。但需要對每個廠商每個版本進行適配,工作量是比較大的。我使用真機測試了大部分主流 Android 廠商的手機後,整理出了部分手機的相關資料。

首先我們可以定義這樣兩個方法:

/**

* 跳轉到指定應用的首頁

*/

private void showActivity(@NonNull String packageName) {

Intent intent = getPackageManager()。getLaunchIntentForPackage(packageName);

startActivity(intent);

}

/**

* 跳轉到指定應用的指定頁面

*/

private void showActivity(@NonNull String packageName, @NonNull String activityDir) {

Intent intent = new Intent();

intent。setComponent(newComponentName(packageName, activityDir));

intent。addFlags(Intent。FLAG_ACTIVITY_NEW_TASK);

startActivity(intent);

}

以下是部分手機的廠商判斷,跳轉方法及對應設定步驟,跳轉方法不保證在所有版本上都能成功跳轉,都需要加 try catch。

7.2 華為

廠商判斷:

public boolean isHuawei() {

if(Build。BRAND == null) {

return false;

} else{

return Build。BRAND。toLowerCase()。equals(”huawei“) || Build。BRAND。toLowerCase()。equals(”honor“);

}

}

跳轉華為手機管家的啟動管理頁:

private void goHuaweiSetting() {

try{

showActivity(”com。huawei。systemmanager“,

”com。huawei。systemmanager。startupmgr。ui。StartupNormalAppListActivity“);

} catch(Exception e) {

showActivity(”com。huawei。systemmanager“,

”com。huawei。systemmanager。optimize。bootstart。BootStartActivity“);

}

}

操作步驟:

應用啟動管理 -> 關閉應用開關 -> 開啟允許自啟動

7.3 小米

廠商判斷:

public static boolean isXiaomi() {

return Build。BRAND != null&& Build。BRAND。toLowerCase()。equals(”xiaomi“);

}

跳轉小米安全中心的自啟動管理頁面:

private void goXiaomiSetting() {

showActivity(”com。miui。securitycenter“,

”com。miui。permcenter。autostart。AutoStartManagementActivity“);

}

操作步驟:

授權管理 -> 自啟動管理 -> 允許應用自啟動

7.4 OPPO

廠商判斷:

public static boolean isOPPO() {

return Build。BRAND != null&& Build。BRAND。toLowerCase()。equals(”oppo“);

}

跳轉 OPPO 手機管家:

private void goOPPOSetting() {

try{

showActivity(”com。coloros。phonemanager“);

} catch(Exception e1) {

try{

showActivity(”com。oppo。safe“);

} catch(Exception e2) {

try{

showActivity(”com。coloros。oppoguardelf“);

} catch(Exception e3) {

showActivity(”com。coloros。safecenter“);

}

}

}

}

操作步驟:

許可權隱私 -> 自啟動管理 -> 允許應用自啟動

7.5 VIVO

廠商判斷:

public static boolean isVIVO() {

return Build。BRAND != null&& Build。BRAND。toLowerCase()。equals(”vivo“);

}

跳轉 VIVO 手機管家:

private void goVIVOSetting() {

showActivity(”com。iqoo。secure“);

}

操作步驟:

許可權管理 -> 自啟動 -> 允許應用自啟動

7.6 魅族

廠商判斷:

public static boolean isMeizu() {

return Build。BRAND != null&& Build。BRAND。toLowerCase()。equals(”meizu“);

}

跳轉魅族手機管家:

private void goMeizuSetting() {

showActivity(”com。meizu。safe“);

}

操作步驟:

許可權管理 -> 後臺管理 -> 點選應用 -> 允許後臺執行

7.7 三星

廠商判斷:

public static boolean isSamsung() {

return Build。BRAND != null&& Build。BRAND。toLowerCase()。equals(”samsung“);

}

跳轉三星智慧管理器:

private void goSamsungSetting() {

try{

showActivity(”com。samsung。android。sm_cn“);

} catch(Exception e) {

showActivity(”com。samsung。android。sm“);

}

}

操作步驟:

自動執行應用程式 -> 開啟應用開關 -> 電池管理 -> 未監視的應用程式 -> 新增應用

7.8 樂視

廠商判斷:

public static boolean isLeTV() {

return Build。BRAND != null&& Build。BRAND。toLowerCase()。equals(”letv“);

}

跳轉樂視手機管家:

private void goLetvSetting() {

showActivity(”com。letv。android。letvsafe“,

”com。letv。android。letvsafe。AutobootManageActivity“);

}

操作步驟:

自啟動管理 -> 允許應用自啟動

7.9 錘子

廠商判斷:

public static boolean isSmartisan() {

return Build。BRAND != null&& Build。BRAND。toLowerCase()。equals(”smartisan“);

}

跳轉手機管理:

private void goSmartisanSetting() {

showActivity(”com。smartisanos。security“);

}

操作步驟:

許可權管理 -> 自啟動許可權管理 -> 點選應用 -> 允許被系統啟動。

8、友商致敬?

在之前做的跑步應用中,我在設定裡增加了一個許可權設定頁面,將上面提到的設定放在這裡面。

最近發現友商某咚也跟進了,圖 1 是我們做的,圖 2 是某咚做的:

2020年了,Android後臺保活還有戲嗎?看我如何優雅的實現!

某咚從設計、從我寫的不夠好的文案,甚至是我從十幾臺手機上一張一張截下來的圖,進行了全方位的致敬。感謝某咚的認可,但最近在某個釋出會上聽到這麼一句話:在致敬的同時,能不能說一句謝謝?

某咚的致敬,一方面說明了目前確實存在程序容易被殺,保活難度大的問題,另一方面也說明了這種引導使用者進行白名單設定的手段是有效的。

附錄:更多相關技術文章

《應用保活終極總結(一):Android6。0以下的雙程序守護保活實踐》

《應用保活終極總結(二):Android6。0及以上的保活實踐(程序防殺篇)》

《應用保活終極總結(三):Android6。0及以上的保活實踐(被殺復活篇)》

《Android程序保活詳解:一篇文章解決你的所有疑問》

《Android端訊息推送總結:實現原理、心跳保活、遇到的問題等》

《深入的聊聊Android訊息推送這件小事》

《為何基於TCP協議的移動端IM仍然需要心跳保活機制?》

《微信團隊原創分享:Android版微信後臺保活實戰分享(程序保活篇)》

《微信團隊原創分享:Android版微信後臺保活實戰分享(網路保活篇)》

《移動端IM實踐:實現Android版微信的智慧心跳機制》

《移動端IM實踐:WhatsApp、Line、微信的心跳策略分析》

《Android P正式版即將到來:後臺應用保活、訊息推送的真正噩夢》

《全面盤點當前Android後臺保活方案的真實執行效果(截止2019年前)》

一文讀懂即時通訊應用中的網路心跳包機制:作用、原理、實現思路等

《融雲技術分享:融雲安卓端IM產品的網路鏈路保活技術實踐》

《正確理解IM長連線的心跳及重連機制,並動手實現(有完整IM原始碼)》

《2020年了,Android後臺保活還有戲嗎?看我如何優雅的實現!》

>> 更多同類文章 ……

(本文同步釋出於:

http://www。

52im。net/thread-2881-1-

1。html