保活現(xiàn)狀
我們知道,Android 系統(tǒng)會存在殺后臺進程的情況,并且隨著系統(tǒng)版本的更新,殺進程的力度還有越來越大的趨勢。系統(tǒng)這種做法本身出發(fā)點是好的,因為可以節(jié)省內(nèi)存,降低功耗,也避免了一些流氓行為。
但有一部分應(yīng)用,應(yīng)用本身的使用場景就需要在后臺運行,用戶也是愿意讓它在后臺運行的,比如跑步類應(yīng)用。一方面流氓軟件用各種流氓手段進行?;?,另一方面系統(tǒng)加大殺后臺的力度,導(dǎo)致我們一些真正需要在后臺運行的應(yīng)用被誤殺,苦不堪言。
優(yōu)雅?;??
為了做到?;?,出現(xiàn)了不少「黑科技」,比如 1 個像素的 Activity,播放無聲音頻,雙進程互相守護等。這些做法可以說是很流氓了,甚至破壞了 Android 的生態(tài),好在隨著 Android 系統(tǒng)版本的更新,這些非常規(guī)的保活手段很多都已失效了。
對于那些確實需要在后臺運行的應(yīng)用,我們?nèi)绾巫龅絻?yōu)雅的?;钅兀?/p>
后臺運行白名單
從 Android 6.0 開始,系統(tǒng)為了省電增加了休眠模式,系統(tǒng)待機一段時間后,會殺死后臺正在運行的進程。但系統(tǒng)會有一個后臺運行白名單,白名單里的應(yīng)用將不會受到影響,在原生系統(tǒng)下,通過「設(shè)置」 - 「電池」 - 「電池優(yōu)化」 - 「未優(yōu)化應(yīng)用」,可以看到這個白名單,通常會看到下面這兩位:
下次被產(chǎn)品說「 XXX 都可以?;?,為什么我們不行!」的時候,你就知道怎么懟回去了。大廠通過和手機廠商的合作,將自己的應(yīng)用默認加入到白名單中。如果你在一個能談成這種合作的大廠,也就不用往下看了。
好在系統(tǒng)還沒有拋棄我們,允許我們申請把應(yīng)用加入白名單。
首先,在 AndroidManifest.xml 文件中配置一下權(quán)限:
|
1
|
<uses-permission android:name=``"android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"
/>
|
可以通過以下方法,判斷我們的應(yīng)用是否在白名單中:
|
1
2
3
4
5
6
7
8
9
|
@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;
}
|
如果不在白名單中,可以通過以下代碼申請加入白名單:
|
1
2
3
4
5
6
7
8
9
10
|
@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)這樣一個窗口:
可以看到,這個系統(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)資料。
首先我們可以定義這樣兩個方法:
作者:NanBox
鏈接:http://www.lxweimin.com/p/32b7241124a2
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/**
* 跳轉(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。
華為
廠商判斷:
|
1
2
3
4
5
6
7
|
public
boolean isHuawei() {
if
(Build.BRAND == ``null``) {
return
false``;
} ``else
{
return
Build.BRAND.toLowerCase().``equals``(``"huawei"``) || Build.BRAND.toLowerCase().``equals``(``"honor"``);
}
}
|
跳轉(zhuǎn)華為手機管家的啟動管理頁:
|
1
2
3
4
5
6
7
8
9
|
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) -> 打開允許自啟動
小米
廠商判斷:
|
1
2
3
|
public
static
boolean isXiaomi() {
return
Build.BRAND != ``null
&& Build.BRAND.toLowerCase().``equals``(``"xiaomi"``);
}
|
跳轉(zhuǎn)小米安全中心的自啟動管理頁面:
|
1
2
3
4
|
private
void
goXiaomiSetting() {
showActivity(``"com.miui.securitycenter"``,
"com.miui.permcenter.autostart.AutoStartManagementActivity"``);
}
|
操作步驟:授權(quán)管理 -> 自啟動管理 -> 允許應(yīng)用自啟動
OPPO
廠商判斷:
|
1
2
3
|
public
static
boolean isOPPO() {
return
Build.BRAND != ``null
&& Build.BRAND.toLowerCase().``equals``(``"oppo"``);
}
|
跳轉(zhuǎn) OPPO 手機管家:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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
廠商判斷:
|
1
2
3
|
public
static
boolean isVIVO() {
return
Build.BRAND != ``null
&& Build.BRAND.toLowerCase().``equals``(``"vivo"``);
}
|
跳轉(zhuǎn) VIVO 手機管家:
|
1
2
3
|
private
void
goVIVOSetting() {
showActivity(``"com.iqoo.secure"``);
}
|
操作步驟:權(quán)限管理 -> 自啟動 -> 允許應(yīng)用自啟動
魅族
廠商判斷:
|
1
2
3
|
public
static
boolean isMeizu() {
return
Build.BRAND != ``null
&& Build.BRAND.toLowerCase().``equals``(``"meizu"``);
}
|
跳轉(zhuǎn)魅族手機管家:
|
1
2
3
|
private
void
goMeizuSetting() {
showActivity(``"com.meizu.safe"``);
}
|
操作步驟:權(quán)限管理 -> 后臺管理 -> 點擊應(yīng)用 -> 允許后臺運行
三星
廠商判斷:
|
1
2
3
|
public
static
boolean isSamsung() {
return
Build.BRAND != ``null
&& Build.BRAND.toLowerCase().``equals``(``"samsung"``);
}
|
跳轉(zhuǎn)三星智能管理器:
|
1
2
3
4
5
6
7
|
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)用
樂視
廠商判斷:
|
1
2
3
|
public
static
boolean isLeTV() {
return
Build.BRAND != ``null
&& Build.BRAND.toLowerCase().``equals``(``"letv"``);
}
|
跳轉(zhuǎn)樂視手機管家:
|
1
2
3
4
|
private
void
goLetvSetting() {
showActivity(``"com.letv.android.letvsafe"``,
"com.letv.android.letvsafe.AutobootManageActivity"``);
}
|
操作步驟:自啟動管理 -> 允許應(yīng)用自啟動
錘子
廠商判斷:
|
1
2
3
|
public
static
boolean isSmartisan() {
return
Build.BRAND != ``null
&& Build.BRAND.toLowerCase().``equals``(``"smartisan"``);
}
|
跳轉(zhuǎn)手機管理:
|
1
2
3
|
private
void
goSmartisanSetting() {
showActivity(``"com.smartisanos.security"``);
}
|
操作步驟:權(quán)限管理 -> 自啟動權(quán)限管理 -> 點擊應(yīng)用 -> 允許被系統(tǒng)啟動
友商致敬?
在之前做的跑步應(yīng)用中,我在設(shè)置里增加了一個權(quán)限設(shè)置頁面,將上面提到的設(shè)置放在這里面。最近發(fā)現(xiàn)友商某咚也跟進了,圖 1 是我們做的,圖 2 是某咚做的:
某咚從設(shè)計、從我寫的不夠好的文案,甚至是我從十幾臺手機上一張一張截下來的圖,進行了全方位的致敬。感謝某咚的認可,但最近在某個發(fā)布會上聽到這么一句話:在致敬的同時,能不能說一句謝謝?
某咚的致敬,一方面說明了目前確實存在進程容易被殺,?;铍y度大的問題,另一方面也說明了這種引導(dǎo)用戶進行白名單設(shè)置的手段是有效的。