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

一、引言

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

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

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

(本文同步發佈於:http://www.52im.net/thread-2881-1-1.htmlgit

二、關於做者

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

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

三、相關文章

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

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

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

全面盤點當前Android後臺保活方案的真實運行效果(截止2019年前)
應用保活終極總結(一):Android6.0如下的雙進程守護保活實踐
應用保活終極總結(二):Android6.0及以上的保活實踐(進程防殺篇)
應用保活終極總結(三):Android6.0及以上的保活實踐(被殺復活篇)
Android進程保活詳解:一篇文章解決你的全部疑問
Android端消息推送總結:實現原理、心跳保活、遇到的問題等
深刻的聊聊Android消息推送這件小事
爲什麼基於TCP協議的移動端IM仍然須要心跳保活機制?
微信團隊原創分享:Android版微信後臺保活實戰分享(進程保活篇)
融雲技術分享:融雲安卓端IM產品的網絡鏈路保活技術實踐

四、Android保活現狀

咱們知道,Android 系統會存在殺後臺進程的狀況,而且隨着系統版本的更新,殺進程的力度還有愈來愈大的趨勢(見:《Android P正式版即將到來:後臺應用保活、消息推送的真正噩夢》)。網絡

系統這種作法自己出發點是好的,由於能夠節省內存,下降功耗,也避免了一些流氓行爲。測試

但有一部分應用,應用自己的使用場景就須要在後臺運行,用戶也是願意讓它在後臺運行的,好比跑步類應用、一些懶得對接廠商推送通道的IM應用、消息推送資訊類應用等。

一方面流氓軟件用各類流氓手段進行保活,另外一方面系統加大殺後臺的力度,致使咱們一些真正須要在後臺運行的應用被誤殺,苦不堪言。

五、優雅的保活?

爲了作到保活,出現了很多「黑科技」,好比 1 個像素的 Activity,播放無聲音頻,雙進程互相守護等(能夠讀讀這個系列:《應用保活終極總結(一):Android6.0如下的雙進程守護保活實踐》、《應用保活終極總結(二):Android6.0及以上的保活實踐(進程防殺篇)》、《應用保活終極總結(三):Android6.0及以上的保活實踐(被殺復活篇)》)。

這些作法能夠說是很流氓了,甚至破壞了 Android 的生態,好在隨着 Android 系統版本的更新,這些很是規的保活手段不少都已失效了。

對於那些確實須要在後臺運行的應用,咱們如何作到優雅的保活呢?

六、加入後臺運行白名單,能夠優雅的實現保活

從 Android 6.0 開始,系統爲了省電增長了休眠模式,系統待機一段時間後,會殺死後臺正在運行的進程。但系統會有一個後臺運行白名單,白名單裏的應用將不會受到影響,在原生系統下,經過:「設置」 - 「電池」 - 「電池優化」 - 「未優化應用」,能夠看到這個白名單。

一般會看到下面這兩位: 

下次被產品說「 XXX 均可以保活,爲何咱們不行!」的時候,你就知道怎麼懟回去了。大廠經過和手機廠商的合做,將本身的應用默認加入到白名單中。若是你在一個能談成這種合做的大廠,也就不用往下看了。

好在系統尚未拋棄咱們,容許咱們申請把應用加入白名單。

首先,在 AndroidManifest.xml 文件中配置一下權限:

<uses-permissionandroid:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>

能夠經過如下方法,判斷咱們的應用是否在白名單中:

@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();
    }
}

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

能夠看到,這個系統彈窗會有影響電池續航的提醒,因此若是想讓用戶點容許,必需要有相關的說明。若是要判斷用戶是否點擊了容許,能夠在申請的時候調用 startActivityForResult,在 onActivityResult 裏再判斷一次是否在白名單中。

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

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

操做步驟:權限管理 -> 自啓動權限管理 -> 點擊應用 -> 容許被系統啓動。

八、友商致敬?

在以前作的跑步應用中,我在設置裏增長了一個權限設置頁面,將上面提到的設置放在這裏面。

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

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

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

附錄:更多相關技術文章

應用保活終極總結(一):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

相關文章
相關標籤/搜索