優(yōu)雅保活方案讥蟆,原來Android還可以這樣崩障海活!

作者:NanBox 瘸彤,轉(zhuǎn)載修然,鏈接:https://juejin.im/post/5dfaeccbf265da33910a441d
參考:https://mp.weixin.qq.com/s/F7W66Y03BBTWOnsds1ZX3A
補充科班出身保活

我們知道,Android 系統(tǒng)會存在殺后臺進程的情況愕宋,并且隨著系統(tǒng)版本的更新玻靡,殺進程的力度還有越來越大的趨勢。系統(tǒng)這種做法本身出發(fā)點是好的掏婶,因為可以節(jié)省內(nèi)存啃奴,降低功耗,也避免了一些流氓行為雄妥。但有一部分應(yīng)用最蕾,應(yīng)用本身的使用場景就需要在后臺運行,用戶也是愿意讓它在后臺運行的老厌,比如跑步類應(yīng)用瘟则。一方面流氓軟件用各種流氓手段進行保活枝秤,另一方面系統(tǒng)加大殺后臺的力度醋拧,導(dǎo)致我們一些真正需要在后臺運行的應(yīng)用被誤殺,苦不堪言淀弹。

為了提高app的钡ず荆活可能性,項目中使用1px像素Activity 薇溃,前臺服務(wù)菌赖,播放無聲音樂Job Service等方法沐序。手機設(shè)置:進程加鎖琉用,自啟動,允許后臺運行策幼,部分機型有解凍app設(shè)置邑时。這么做也實屬無奈,甲方是我大爺特姐。

如果優(yōu)雅本穑活?別那么粗暴

為了做到钡窖罚活铣口,出現(xiàn)了不少「黑科技」,比如 1 個像素的 Activity觉壶,播放無聲音頻脑题,雙進程互相守護等。這些做法可以說是很流氓了铜靶,甚至破壞了 Android 的生態(tài)叔遂,好在隨著 Android 系統(tǒng)版本的更新他炊,這些非常規(guī)的保活手段很多都已失效了已艰。

對于那些確實需要在后臺運行的應(yīng)用痊末,我們?nèi)绾巫龅絻?yōu)雅的保活呢哩掺? 凿叠,上面提到過 【手機設(shè)置:進程加鎖,自啟動嚼吞,允許后臺運行盒件,部分機型有解凍app設(shè)置】,但這些需要用戶手動操作舱禽,這不符合程序員性格炒刁。

  • 后臺運行白名單
    從 Android 6.0 開始,系統(tǒng)為了省電增加了休眠模式誊稚,系統(tǒng)待機一段時間后翔始,會殺死后臺正在運行的進程。但系統(tǒng)會有一個后臺運行白名單里伯,白名單里的應(yīng)用將不會受到影響城瞎,在原生系統(tǒng)下,通過「設(shè)置」 - 「電池」 - 「電池優(yōu)化」 - 「未優(yōu)化應(yīng)用」疾瓮,可以看到這個白名單全谤,通常會看到下面這兩位:


    image.png

    下次被產(chǎn)品說「 XXX 都可以保活爷贫,為什么我們不行!」的時候补憾,你就知道怎么懟回去了漫萄。大廠通過和手機廠商的合作,將自己的應(yīng)用默認加入到白名單中盈匾。如果你在一個能談成這種合作的大廠腾务,也就不用往下看了。

好在系統(tǒng)還沒有拋棄我們削饵,允許我們申請把應(yīng)用加入白名單岩瘦。

首先,在 AndroidManifest.xml 文件中配置一下權(quán)限:

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

可以通過以下方法窿撬,判斷我們的應(yīng)用是否在白名單中:

@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 = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
        intent.setData(Uri.parse("package:" + getPackageName()));
        startActivity(intent);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

申請時,應(yīng)用上會出現(xiàn)這樣一個窗口:


image.png

可以看到劈伴,這個系統(tǒng)彈窗會有影響電池續(xù)航的提醒密末,所以如果想讓用戶點允許,必須要有相關(guān)的說明。如果要判斷用戶是否點擊了允許严里,可以在申請的時候調(diào)用 startActivityForResult新啼,在 onActivityResult 里再判斷一次是否在白名單中。

  • 廠商后臺管理
    Android 開發(fā)的一個難點在于刹碾,各大手機廠商對原生系統(tǒng)進行了不同的定制燥撞,導(dǎo)致我們需要進行不同的適配,后臺管理就是一個很好的體現(xiàn)迷帜。幾乎各個廠商都有自己的后臺管理物舒,就算應(yīng)用加入了后臺運行白名單,仍然可能會被廠商自己的后臺管理干掉瞬矩。

如果能把應(yīng)用加入廠商系統(tǒng)的后臺管理白名單茶鉴,可以進一步降低進程被殺的概率。不同的廠商在不同的地方進行設(shè)置景用,一般是在各自的「手機管家」涵叮,但更難的是,就算同一個廠商的系統(tǒng)伞插,不同的版本也可能是在不同地方設(shè)置割粮。

最理想的做法是,我們根據(jù)不同手機媚污,甚至是不同的系統(tǒng)版本舀瓢,給用戶呈現(xiàn)一個圖文操作步驟,并且提供一個按鈕耗美,直接跳轉(zhuǎn)到指定頁面進行設(shè)置京髓。但需要對每個廠商每個版本進行適配,工作量是比較大的商架。我使用真機測試了大部分主流 Android 廠商的手機后堰怨,整理出了部分手機的相關(guān)資料。首先我們可以定義這樣兩個方法:

/**
 * 跳轉(zhuǎn)到指定應(yīng)用的首頁
 */
private void showActivity(@NonNull String packageName) {
    Intent intent = getPackageManager().getLaunchIntentForPackage(packageName);
    startActivity(intent);
}

/**
 * 跳轉(zhuǎn)到指定應(yīng)用的指定頁面
 */
private void showActivity(@NonNull String packageName, @NonNull String activityDir) {
    Intent intent = new Intent();
    intent.setComponent(new ComponentName(packageName, activityDir));
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
}

以下是部分手機的廠商判斷蛇摸,跳轉(zhuǎn)方法及對應(yīng)設(shè)置步驟备图,跳轉(zhuǎn)方法不保證在所有版本上都能成功跳轉(zhuǎn),都需要加 try catch.

華為
// 廠商判斷
public boolean isHuawei() {
    if (Build.BRAND == null) {
        return false;
    } else {
        return Build.BRAND.toLowerCase().equals("huawei") || Build.BRAND.toLowerCase().equals("honor");
    }
}

//跳轉(zhuǎn)華為手機管家的啟動管理頁:
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");
    }
}
//操作步驟:應(yīng)用啟動管理 -> 關(guān)閉應(yīng)用開關(guān) -> 打開允許自啟動
小米
// 廠商判斷
public static boolean isXiaomi() {
    return Build.BRAND != null && Build.BRAND.toLowerCase().equals("xiaomi");
}

//代碼跳轉(zhuǎn)小米安全中心的自啟動管理頁面:
private void goXiaomiSetting() {
    showActivity("com.miui.securitycenter",
        "com.miui.permcenter.autostart.AutoStartManagementActivity");
}
//操作步驟:授權(quán)管理 -> 自啟動管理 -> 允許應(yīng)用自啟動
OPPO
// 廠商判斷
public static boolean isOPPO() {
    return Build.BRAND != null && Build.BRAND.toLowerCase().equals("oppo");
}

//代碼跳轉(zhuǎn) 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");
            }
        }
    }
}
//操作步驟:權(quán)限隱私 -> 自啟動管理 -> 允許應(yīng)用自啟動
VIVO
// 廠商判斷
public static boolean isVIVO() {
    return Build.BRAND != null && Build.BRAND.toLowerCase().equals("vivo");
}

//代碼跳轉(zhuǎn) VIVO 手機管家:
private void goVIVOSetting() {
    showActivity("com.iqoo.secure");
}
//操作步驟:權(quán)限管理 -> 自啟動 -> 允許應(yīng)用自啟動
魅族
// 廠商判斷
public static boolean isMeizu() {
    return Build.BRAND != null && Build.BRAND.toLowerCase().equals("meizu");
}


//代碼跳轉(zhuǎn)魅族手機管家:
private void goMeizuSetting() {
    showActivity("com.meizu.safe");
}
//操作步驟:權(quán)限管理 -> 后臺管理 -> 點擊應(yīng)用 -> 允許后臺運行
三星
// 廠商判斷
public static boolean isSamsung() {
    return Build.BRAND != null && Build.BRAND.toLowerCase().equals("samsung");
}
//代碼跳轉(zhuǎn)三星智能管理器:
private void goSamsungSetting() {
    try {
        showActivity("com.samsung.android.sm_cn");
    } catch (Exception e) {
        showActivity("com.samsung.android.sm");
    }
}
//操作步驟:自動運行應(yīng)用程序 -> 打開應(yīng)用開關(guān) -> 電池管理 -> 未監(jiān)視的應(yīng)用程序 -> 添加應(yīng)用
樂視
// 廠商判斷
public static boolean isLeTV() {
    return Build.BRAND != null && Build.BRAND.toLowerCase().equals("letv");
}
//代碼跳轉(zhuǎn)樂視手機管家:
private void goLetvSetting() {
    showActivity("com.letv.android.letvsafe",
        "com.letv.android.letvsafe.AutobootManageActivity");
}
//操作步驟:自啟動管理 -> 允許應(yīng)用自啟動
錘子
// 廠商判斷
 public static boolean isSmartisan() {
        return Build.BRAND != null && Build.BRAND.toLowerCase().equals("smartisan");
    }
//代碼跳轉(zhuǎn)手機管理:
private void goSmartisanSetting() {
    showActivity("com.smartisanos.security");
}
//操作步驟:權(quán)限管理 -> 自啟動權(quán)限管理 -> 點擊應(yīng)用 -> 允許被系統(tǒng)啟動
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末赶袄,一起剝皮案震驚了整個濱河市揽涮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌饿肺,老刑警劉巖蒋困,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異唬格,居然都是意外死亡家破,警方通過查閱死者的電腦和手機颜说,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來汰聋,“玉大人门粪,你說我怎么就攤上這事∨肜В” “怎么了玄妈?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長髓梅。 經(jīng)常有香客問我拟蜻,道長,這世上最難降的妖魔是什么枯饿? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任酝锅,我火速辦了婚禮,結(jié)果婚禮上奢方,老公的妹妹穿的比我還像新娘搔扁。我一直安慰自己,他們只是感情好蟋字,可當(dāng)我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布稿蹲。 她就那樣靜靜地躺著,像睡著了一般鹊奖。 火紅的嫁衣襯著肌膚如雪苛聘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天忠聚,我揣著相機與錄音设哗,去河邊找鬼。 笑死两蟀,一個胖子當(dāng)著我的面吹牛熬拒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播垫竞,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蛀序!你這毒婦竟也來了欢瞪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤徐裸,失蹤者是張志新(化名)和其女友劉穎遣鼓,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體重贺,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡骑祟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年回懦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片次企。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡怯晕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出缸棵,到底是詐尸還是另有隱情舟茶,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布堵第,位于F島的核電站吧凉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏踏志。R本人自食惡果不足惜阀捅,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望针余。 院中可真熱鬧饲鄙,春花似錦、人聲如沸涵紊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽摸柄。三九已至颤练,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間驱负,已是汗流浹背嗦玖。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留跃脊,地道東北人宇挫。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像酪术,于是被迫代替她去往敵國和親器瘪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容