日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android 进程保活实践

發布時間:2024/3/26 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 进程保活实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者:08_carmelo

鏈接:

https://www.jianshu.com/p/53c4d8303e19

首先申明這篇文章非本人原創,轉載的上面的朋友的,原文鏈接及作者就是上面的。感覺文章寫的很好,所以轉載了便于以后翻出來看看。



1前言


進程保活的關鍵點有兩個,一個是進程優先級的理解,優先級越高存活幾率越大。二是弄清楚哪些場景會導致進程會kill,然后采取下面的策略對各種場景進行優化:


  • 提高進程的優先級

  • 在進程被kill之后能夠喚醒


  • 進程優先級


    Android一般的進程優先級劃分:

  • 前臺進程 (Foreground process)

  • 可見進程 (Visible process)

  • 服務進程 (Service process)

  • 后臺進程 (Background process)

  • 空進程 (Empty process)

  • 這是一種粗略的劃分,進程其實有一種具體的數值,稱作oom_adj,注意:數值越大優先級越低:



    圖片出自騰訊bugly


    • 紅色部分是容易被回收的進程,屬于android進程

    • 綠色部分是較難被回收的進程,屬于android進程

    • 其他部分則不是android進程,也不會被系統回收,一般是ROM自帶的app和服務才能擁有


    如何查看某個進程的oom_adj數值呢?


    oom_adj 存儲在proc/PID/oom_adj文件中,其中PID是進程的id,直接 adb shell進入手機根目錄查看這個文件即可。


    演示一下:以我自己的項目為例,app中有兩個進程,一個是主進程,另一個是運行service的進程取名為:remote。首先用android studio查看每個進程的PID:



    然后分別查看app在前臺,app退到后臺,這2中場景主進程的oom_adj數值:



    可見,當app在前臺時 oom_adj = 0,對應上面的表格是前臺進程。
    當app退到后臺時,oom_adj = 6,對應后臺進程。


    然后查看運行著service的進程:



    ok,知道了進程優先級的概念以及如何查看優先級,我們就可以對app進程優化,然后通過查看這個數值判斷我們的優化是否有效果。


    2 進程被kill的場景
    1.點擊home鍵使app長時間停留在后臺,內存不足被kill

    處理這種情況前提是你的app至少運行了一個service,然后通過Service.startForeground() 設置為前臺服務,可以將oom_adj的數值由4降低到1,大大提高存活率。


    • 要注意的是android4.3之后Service.startForeground() 會強制彈出通知欄,解決辦法是再啟動一個service和推送共用一個通知欄,然后stop這個service使得通知欄消失。

    • Android 7.1之后google修復這個bug,目前沒有解決辦法
      下面的代碼放到你的service的onStartCommand方法中:

    //設置service為前臺服務,提高優先級
    if (Build.VERSION.SDK_INT < 18) {
    ? ?//Android4.3以下 ,此方法能有效隱藏Notification上的圖標
    ? ?service.startForeground(GRAY_SERVICE_ID, new Notification());
    } else if(Build.VERSION.SDK_INT>18 && Build.VERSION.SDK_INT<25){
    ? ?//Android4.3 - Android7.0,此方法能有效隱藏Notification上的圖標
    ? ?Intent innerIntent = new Intent(service, GrayInnerService.class);
    ? ?service.startService(innerIntent);
    ? ?service.startForeground(GRAY_SERVICE_ID, new Notification());
    }else{
    ? ?//Android7.1 google修復了此漏洞,暫無解決方法(現狀:Android7.1以上app啟動后通知欄會出現一條"正在運行"的通知消息)
    ? ?service.startForeground(GRAY_SERVICE_ID, new Notification());
    }


    經過改進之后,再來看下這個后臺service進程的oom_adj,發現被提升為前臺進程。




    2.在大多數國產手機下,進入鎖屏狀態一段時間,省電機制會kill后臺進程


    這種情況和上面不太一樣,是很過國產手機rom自帶的優化,當鎖屏一段時間之后,即使手機內存夠用為了省電,也會釋放掉一部分內存。


    策略:注冊廣播監聽鎖屏和解鎖事件, 鎖屏后啟動一個1像素的透明Activity,這樣直接把進程的oom_adj數值降低到0,0是android進程的最高優先級。 解鎖后銷毀這個透明Activity。這里我把這個Activity放到:remote進程也就是我那個后臺服務進程,當然你也可以放到主進程,看你打算保活哪個進程。



    我們可以寫一個KeepLiveManager來負責接收廣播,維護這個Activity的常見和銷毀,注意鎖屏廣播和解鎖分別是:ACTION_SCREEN_OOF和ACTION_USER_PRESENT,并且只能通過動態注冊來綁定,并且是綁定到你的后臺service里面,onCreate綁定,onDestroy里面解綁。


    配好之后把手機鎖屏,看下:remote進程的oom_adj:



    3. 用戶手動釋放內存:包括手機自帶清理工具,和第三方app(360,獵豹清理大師等)


    清理內存軟件會把 優先級低于 前臺進程(oom_adj = 0)的所有進程放入清理列表,而當我們打開了清理軟件就意味著其他app不可能處于前臺。所以說理論上可以kill任何app。
    以360安全衛士為例,打開內存清理:



    因此這類場景唯一的處理辦法就是加入 手機rom 白名單,比如你打開小米,魅族的權限管理 -> 自啟動管理可以看到 QQ,微信,天貓默認被勾選,這就是廠商合作。


    那我們普通app可以這么做:在app的設置界面加一個選項,提示用戶自己去勾選自啟動,我封裝了一個工具類給出國內各廠商的自啟動的Intent跳轉方法:

    /**
    * Created by carmelo on 2018/3/17.
    * 國內手機廠商白名單跳轉工具類
    */

    public class SettingUtils {
    ? ?public static void enterWhiteListSetting(Context context){
    ? ? ? ?try {
    ? ? ? ? ? ?context.startActivity(getSettingIntent());
    ? ? ? ?}catch (Exception e){
    ? ? ? ? ? ?context.startActivity(new Intent(Settings.ACTION_SETTINGS));
    ? ? ? ?}
    ? ?}
    ? ?private static Intent getSettingIntent(){
    ? ? ? ?ComponentName componentName = null;
    ? ? ? ?String brand = android.os.Build.BRAND;
    ? ? ? ?switch (brand.toLowerCase()){
    ? ? ? ? ? ?case "samsung":
    ? ? ? ? ? ? ? ?componentName = new ComponentName("com.samsung.android.sm",
    ? ? ? ? ? ? ? ? ? ? ? ?"com.samsung.android.sm.app.dashboard.SmartManagerDashBoardActivity");
    ? ? ? ? ? ? ? ?break;
    ? ? ? ? ? ?case "huawei":
    ? ? ? ? ? ? ? ?componentName = new ComponentName("com.huawei.systemmanager",
    ? ? ? ? ? ? ? ? ? ? ? ?"com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity");
    ? ? ? ? ? ? ? ?break;
    ? ? ? ? ? ?case "xiaomi":
    ? ? ? ? ? ? ? ?componentName = new ComponentName("com.miui.securitycenter",
    ? ? ? ? ? ? ? ? ? ? ? ?"com.miui.permcenter.autostart.AutoStartManagementActivity");
    ? ? ? ? ? ? ? ?break;
    ? ? ? ? ? ?case "vivo":
    ? ? ? ? ? ? ? ?componentName = new ComponentName("com.iqoo.secure",
    ? ? ? ? ? ? ? ? ? ? ? ?"com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity");
    ? ? ? ? ? ? ? ?break;
    ? ? ? ? ? ?case "oppo":
    ? ? ? ? ? ? ? ?componentName = new ComponentName("com.coloros.oppoguardelf",
    ? ? ? ? ? ? ? ? ? ? ? ?"com.coloros.powermanager.fuelgaue.PowerUsageModelActivity");
    ? ? ? ? ? ? ? ?break;
    ? ? ? ? ? ?case "360":
    ? ? ? ? ? ? ? ?componentName = new ComponentName("com.yulong.android.coolsafe",
    ? ? ? ? ? ? ? ? ? ? ? ?"com.yulong.android.coolsafe.ui.activity.autorun.AutoRunListActivity");
    ? ? ? ? ? ? ? ?break;
    ? ? ? ? ? ?case "meizu":
    ? ? ? ? ? ? ? ?componentName = new ComponentName("com.meizu.safe",
    ? ? ? ? ? ? ? ? ? ? ? ?"com.meizu.safe.permission.SmartBGActivity");
    ? ? ? ? ? ? ? ?break;
    ? ? ? ? ? ?case "oneplus":
    ? ? ? ? ? ? ? ?componentName = new ComponentName("com.oneplus.security",
    ? ? ? ? ? ? ? ? ? ? ? ?"com.oneplus.security.chainlaunch.view.ChainLaunchAppListActivity");
    ? ? ? ? ? ? ? ?break;
    ? ? ? ? ? ?default:
    ? ? ? ? ? ? ? ?break;
    ? ? ? ?}
    ? ? ? ?Intent intent = new Intent();
    ? ? ? ?intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    ? ? ? ?if(componentName!=null){
    ? ? ? ? ? ?intent.setComponent(componentName);
    ? ? ? ?}else{
    ? ? ? ? ? ?intent.setAction(Settings.ACTION_SETTINGS);
    ? ? ? ?}
    ? ? ? ?return intent;
    ? ?}
    }


    補充幾點:


    • 額外說下 自啟動是什么意思? 網上都是小米開啟自啟動就是加入白名單,其實根本不是這樣的,經過實測就算app勾選自啟動也會被內存優化加速清理掉,只不過進程會在半分鐘后復活。

    • 除了還有自啟動還有一個設置就是電池管理,比如小米的神隱模式,這部分和自啟動不同的是它是管理app在鎖屏之后被省電機制殺死的場景,當然每家廠商也有對應的Intent跳轉路徑。

    • 如何查找不同廠商的設置界面跳轉Intent,比如上面的國內手機廠商白名單,給個方法:(前提是你有N多個不同手機,像我這樣。。。)



    在酷安應用市場下載一個叫 當前Activity 的app,打開后可以看到當前界面的className,例如:



    就找到了魅族MX4 pro 后臺權限的Activity。


    3 進程喚醒


    分兩種情況,一是主進程(含有Activity沒有service),這種進程由于內存不足被kill之后,用戶再次打開app系統會恢復到上次的Activity,這個不在本文話題之內。另一種是service的后臺進程被kill,可以通過service自有api來重啟service:

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    ? ?//.....
    ? ?return START_STICKY; ? ?// service被異常停止后,系統嘗試重啟service,不能保證100%重啟成功
    }


    配好START_STICKY后,通過android studio 釋放進程的工具測試下,可以發現:remote進程被kill之后馬上重啟了:



    但它不是100%保證重啟成功,比如下面2種情況:(本人經過測試,這里就不放效果圖了)


    • Service 第一次被異常殺死后會在5秒內重啟,第二次被殺死會在10秒內重啟,第三次會在20秒內重啟,一旦在短時間內 Service 被殺死達到5次,則系統不再拉起。

    • 進程被取得 Root 權限的管理工具或系統工具通過 forestop 停止掉,無法重啟。


    總結


    本文通過兩種 提高進程優先級的方法,針對鎖屏 和非鎖屏模式下進程在后臺被kill的場景處理,把后臺進程優先級提升到可見級別,基本可以保證絕大多數場景不會被kill。另外,針對含有service的進程被kill給出了可喚醒的辦法。


    最后,我將進程保活的代碼上傳到了Github,地址:
    https://github.com/08carmelo/android-keeplive



    1前言


    進程保活的關鍵點有兩個,一個是進程優先級的理解,優先級越高存活幾率越大。二是弄清楚哪些場景會導致進程會kill,然后采取下面的策略對各種場景進行優化:


  • 提高進程的優先級

  • 在進程被kill之后能夠喚醒


  • 進程優先級


    Android一般的進程優先級劃分:

  • 前臺進程 (Foreground process)

  • 可見進程 (Visible process)

  • 服務進程 (Service process)

  • 后臺進程 (Background process)

  • 空進程 (Empty process)

  • 這是一種粗略的劃分,進程其實有一種具體的數值,稱作oom_adj,注意:數值越大優先級越低:



    圖片出自騰訊bugly


    • 紅色部分是容易被回收的進程,屬于android進程

    • 綠色部分是較難被回收的進程,屬于android進程

    • 其他部分則不是android進程,也不會被系統回收,一般是ROM自帶的app和服務才能擁有


    如何查看某個進程的oom_adj數值呢?


    oom_adj 存儲在proc/PID/oom_adj文件中,其中PID是進程的id,直接 adb shell進入手機根目錄查看這個文件即可。


    演示一下:以我自己的項目為例,app中有兩個進程,一個是主進程,另一個是運行service的進程取名為:remote。首先用android studio查看每個進程的PID:



    然后分別查看app在前臺,app退到后臺,這2中場景主進程的oom_adj數值:



    可見,當app在前臺時 oom_adj = 0,對應上面的表格是前臺進程。
    當app退到后臺時,oom_adj = 6,對應后臺進程。


    然后查看運行著service的進程:



    ok,知道了進程優先級的概念以及如何查看優先級,我們就可以對app進程優化,然后通過查看這個數值判斷我們的優化是否有效果。


    2進程被kill的場景
    1.點擊home鍵使app長時間停留在后臺,內存不足被kill

    處理這種情況前提是你的app至少運行了一個service,然后通過Service.startForeground() 設置為前臺服務,可以將oom_adj的數值由4降低到1,大大提高存活率。


    • 要注意的是android4.3之后Service.startForeground() 會強制彈出通知欄,解決辦法是再啟動一個service和推送共用一個通知欄,然后stop這個service使得通知欄消失。

    • Android 7.1之后google修復這個bug,目前沒有解決辦法
      下面的代碼放到你的service的onStartCommand方法中:

    //設置service為前臺服務,提高優先級
    if (Build.VERSION.SDK_INT < 18) {
    ? ?//Android4.3以下 ,此方法能有效隱藏Notification上的圖標
    ? ?service.startForeground(GRAY_SERVICE_ID, new Notification());
    } else if(Build.VERSION.SDK_INT>18 && Build.VERSION.SDK_INT<25){
    ? ?//Android4.3 - Android7.0,此方法能有效隱藏Notification上的圖標
    ? ?Intent innerIntent = new Intent(service, GrayInnerService.class);
    ? ?service.startService(innerIntent);
    ? ?service.startForeground(GRAY_SERVICE_ID, new Notification());
    }else{
    ? ?//Android7.1 google修復了此漏洞,暫無解決方法(現狀:Android7.1以上app啟動后通知欄會出現一條"正在運行"的通知消息)
    ? ?service.startForeground(GRAY_SERVICE_ID, new Notification());
    }


    經過改進之后,再來看下這個后臺service進程的oom_adj,發現被提升為前臺進程。




    2.在大多數國產手機下,進入鎖屏狀態一段時間,省電機制會kill后臺進程


    這種情況和上面不太一樣,是很過國產手機rom自帶的優化,當鎖屏一段時間之后,即使手機內存夠用為了省電,也會釋放掉一部分內存。


    策略:注冊廣播監聽鎖屏和解鎖事件, 鎖屏后啟動一個1像素的透明Activity,這樣直接把進程的oom_adj數值降低到0,0是android進程的最高優先級。 解鎖后銷毀這個透明Activity。這里我把這個Activity放到:remote進程也就是我那個后臺服務進程,當然你也可以放到主進程,看你打算保活哪個進程。



    我們可以寫一個KeepLiveManager來負責接收廣播,維護這個Activity的常見和銷毀,注意鎖屏廣播和解鎖分別是:ACTION_SCREEN_OOF和ACTION_USER_PRESENT,并且只能通過動態注冊來綁定,并且是綁定到你的后臺service里面,onCreate綁定,onDestroy里面解綁。


    配好之后把手機鎖屏,看下:remote進程的oom_adj:



    3. 用戶手動釋放內存:包括手機自帶清理工具,和第三方app(360,獵豹清理大師等)


    清理內存軟件會把 優先級低于 前臺進程(oom_adj = 0)的所有進程放入清理列表,而當我們打開了清理軟件就意味著其他app不可能處于前臺。所以說理論上可以kill任何app。
    以360安全衛士為例,打開內存清理:



    因此這類場景唯一的處理辦法就是加入 手機rom 白名單,比如你打開小米,魅族的權限管理 -> 自啟動管理可以看到 QQ,微信,天貓默認被勾選,這就是廠商合作。


    那我們普通app可以這么做:在app的設置界面加一個選項,提示用戶自己去勾選自啟動,我封裝了一個工具類給出國內各廠商的自啟動的Intent跳轉方法:

    /**
    * Created by carmelo on 2018/3/17.
    * 國內手機廠商白名單跳轉工具類
    */

    public class SettingUtils {
    ? ?public static void enterWhiteListSetting(Context context){
    ? ? ? ?try {
    ? ? ? ? ? ?context.startActivity(getSettingIntent());
    ? ? ? ?}catch (Exception e){
    ? ? ? ? ? ?context.startActivity(new Intent(Settings.ACTION_SETTINGS));
    ? ? ? ?}
    ? ?}
    ? ?private static Intent getSettingIntent(){
    ? ? ? ?ComponentName componentName = null;
    ? ? ? ?String brand = android.os.Build.BRAND;
    ? ? ? ?switch (brand.toLowerCase()){
    ? ? ? ? ? ?case "samsung":
    ? ? ? ? ? ? ? ?componentName = new ComponentName("com.samsung.android.sm",
    ? ? ? ? ? ? ? ? ? ? ? ?"com.samsung.android.sm.app.dashboard.SmartManagerDashBoardActivity");
    ? ? ? ? ? ? ? ?break;
    ? ? ? ? ? ?case "huawei":
    ? ? ? ? ? ? ? ?componentName = new ComponentName("com.huawei.systemmanager",
    ? ? ? ? ? ? ? ? ? ? ? ?"com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity");
    ? ? ? ? ? ? ? ?break;
    ? ? ? ? ? ?case "xiaomi":
    ? ? ? ? ? ? ? ?componentName = new ComponentName("com.miui.securitycenter",
    ? ? ? ? ? ? ? ? ? ? ? ?"com.miui.permcenter.autostart.AutoStartManagementActivity");
    ? ? ? ? ? ? ? ?break;
    ? ? ? ? ? ?case "vivo":
    ? ? ? ? ? ? ? ?componentName = new ComponentName("com.iqoo.secure",
    ? ? ? ? ? ? ? ? ? ? ? ?"com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity");
    ? ? ? ? ? ? ? ?break;
    ? ? ? ? ? ?case "oppo":
    ? ? ? ? ? ? ? ?componentName = new ComponentName("com.coloros.oppoguardelf",
    ? ? ? ? ? ? ? ? ? ? ? ?"com.coloros.powermanager.fuelgaue.PowerUsageModelActivity");
    ? ? ? ? ? ? ? ?break;
    ? ? ? ? ? ?case "360":
    ? ? ? ? ? ? ? ?componentName = new ComponentName("com.yulong.android.coolsafe",
    ? ? ? ? ? ? ? ? ? ? ? ?"com.yulong.android.coolsafe.ui.activity.autorun.AutoRunListActivity");
    ? ? ? ? ? ? ? ?break;
    ? ? ? ? ? ?case "meizu":
    ? ? ? ? ? ? ? ?componentName = new ComponentName("com.meizu.safe",
    ? ? ? ? ? ? ? ? ? ? ? ?"com.meizu.safe.permission.SmartBGActivity");
    ? ? ? ? ? ? ? ?break;
    ? ? ? ? ? ?case "oneplus":
    ? ? ? ? ? ? ? ?componentName = new ComponentName("com.oneplus.security",
    ? ? ? ? ? ? ? ? ? ? ? ?"com.oneplus.security.chainlaunch.view.ChainLaunchAppListActivity");
    ? ? ? ? ? ? ? ?break;
    ? ? ? ? ? ?default:
    ? ? ? ? ? ? ? ?break;
    ? ? ? ?}
    ? ? ? ?Intent intent = new Intent();
    ? ? ? ?intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    ? ? ? ?if(componentName!=null){
    ? ? ? ? ? ?intent.setComponent(componentName);
    ? ? ? ?}else{
    ? ? ? ? ? ?intent.setAction(Settings.ACTION_SETTINGS);
    ? ? ? ?}
    ? ? ? ?return intent;
    ? ?}
    }


    補充幾點:


    • 額外說下 自啟動是什么意思? 網上都是小米開啟自啟動就是加入白名單,其實根本不是這樣的,經過實測就算app勾選自啟動也會被內存優化加速清理掉,只不過進程會在半分鐘后復活。

    • 除了還有自啟動還有一個設置就是電池管理,比如小米的神隱模式,這部分和自啟動不同的是它是管理app在鎖屏之后被省電機制殺死的場景,當然每家廠商也有對應的Intent跳轉路徑。

    • 如何查找不同廠商的設置界面跳轉Intent,比如上面的國內手機廠商白名單,給個方法:(前提是你有N多個不同手機,像我這樣。。。)



    在酷安應用市場下載一個叫 當前Activity 的app,打開后可以看到當前界面的className,例如:



    就找到了魅族MX4 pro 后臺權限的Activity。


    3進程喚醒


    分兩種情況,一是主進程(含有Activity沒有service),這種進程由于內存不足被kill之后,用戶再次打開app系統會恢復到上次的Activity,這個不在本文話題之內。另一種是service的后臺進程被kill,可以通過service自有api來重啟service:

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    ? ?//.....
    ? ?return START_STICKY; ? ?// service被異常停止后,系統嘗試重啟service,不能保證100%重啟成功
    }


    配好START_STICKY后,通過android studio 釋放進程的工具測試下,可以發現:remote進程被kill之后馬上重啟了:



    但它不是100%保證重啟成功,比如下面2種情況:(本人經過測試,這里就不放效果圖了)


    • Service 第一次被異常殺死后會在5秒內重啟,第二次被殺死會在10秒內重啟,第三次會在20秒內重啟,一旦在短時間內 Service 被殺死達到5次,則系統不再拉起。

    • 進程被取得 Root 權限的管理工具或系統工具通過 forestop 停止掉,無法重啟。


    總結


    本文通過兩種 提高進程優先級的方法,針對鎖屏 和非鎖屏模式下進程在后臺被kill的場景處理,把后臺進程優先級提升到可見級別,基本可以保證絕大多數場景不會被kill。另外,針對含有service的進程被kill給出了可喚醒的辦法。


    最后,我將進程保活的代碼上傳到了Github,地址:
    https://github.com/08carmelo/android-keeplive


    總結

    以上是生活随笔為你收集整理的android 进程保活实践的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。