【Android 进程保活】应用进程拉活 ( 双进程守护 + JobScheduler 保活 | 成功率最高 | 推荐使用 )
文章目錄
- 一、 雙進(jìn)程守護(hù)保活 + JobScheduler 原理
- 二、 雙進(jìn)程守護(hù)保活 + JobScheduler 源碼
- 1、JobService 代碼
- 2、判定服務(wù)運(yùn)行工具類
- 3、清單文件
- 4、MainActivity 代碼
- 5、運(yùn)行效果
- 三、 源碼資源
一、 雙進(jìn)程守護(hù)保活 + JobScheduler 原理
【Android 進(jìn)程保活】應(yīng)用進(jìn)程拉活 ( JobScheduler 拉活 | JobScheduler 使用流程 | JobService 服務(wù) | 不同版本兼容 | 源碼資源 ) 博客中介紹了 JobScheduler 的用法 ;
【Android 進(jìn)程保活】應(yīng)用進(jìn)程拉活 ( 雙進(jìn)程守護(hù)保活 ) 博客中介紹了雙進(jìn)程守護(hù)保活用法 ;
使用 " 雙進(jìn)程守護(hù)保活 + JobScheduler " 機(jī)制 , 成功率最高 ;
" 雙進(jìn)程守護(hù)保活 + JobScheduler " 整合方法 :
在 JobService 的 onStartJob 方法中 , 判定 " 雙進(jìn)程守護(hù)保活 " 中的雙進(jìn)程是否掛了 , 如果這兩個進(jìn)程掛了 , 就重新將掛掉的進(jìn)程重啟 ;
判定 Service 進(jìn)程是否運(yùn)行 :
public static boolean isServiceRunning(Context context, String serviceName){if(TextUtils.isEmpty(serviceName)) return false;ActivityManager activityManager =(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);// 最多獲取 200 個正在運(yùn)行的 ServiceList<ActivityManager.RunningServiceInfo> infos =activityManager.getRunningServices(200);// 遍歷當(dāng)前運(yùn)行的 Service 信息, 如果找到相同名稱的服務(wù) , 說明某進(jìn)程正在運(yùn)行for (ActivityManager.RunningServiceInfo info: infos){if (TextUtils.equals(info.service.getClassName(), serviceName)){return true;}}return false;}二、 雙進(jìn)程守護(hù)保活 + JobScheduler 源碼
大部分代碼與 【Android 進(jìn)程保活】應(yīng)用進(jìn)程拉活 ( 雙進(jìn)程守護(hù)保活 ) 博客中重復(fù) , 這里只貼出 JobScheduler 相關(guān)源碼 ;
1、JobService 代碼
package kim.hsl.two_progress_alive;import android.app.job.JobInfo; import android.app.job.JobParameters; import android.app.job.JobScheduler; import android.app.job.JobService; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.os.Build; import android.util.Log;import androidx.annotation.RequiresApi;@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public class KeepAliveJobService extends JobService {@Overridepublic boolean onStartJob(JobParameters params) {Log.i("KeepAliveJobService", "JobService onStartJob 開啟");if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){// 如果當(dāng)前設(shè)備大于 7.0 , 延遲 5 秒 , 再次執(zhí)行一次startJob(this);}// 判定本地前臺進(jìn)程是否正在運(yùn)行boolean isLocalServiceRunning =ServiceUtils.isServiceRunning(this, LocalForegroundService.class.getName());if (!isLocalServiceRunning){startService(new Intent(this, LocalForegroundService.class));}// 判定遠(yuǎn)程前臺進(jìn)程是否正在運(yùn)行boolean isRemoteServiceRunning =ServiceUtils.isServiceRunning(this, RemoteForegroundService.class.getName());if (!isRemoteServiceRunning){startService(new Intent(this, RemoteForegroundService.class));}return false;}@Overridepublic boolean onStopJob(JobParameters params) {Log.i("KeepAliveJobService", "JobService onStopJob 關(guān)閉");return false;}public static void startJob(Context context){// 創(chuàng)建 JobSchedulerJobScheduler jobScheduler =(JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);// 第一個參數(shù)指定任務(wù) ID// 第二個參數(shù)指定任務(wù)在哪個組件中執(zhí)行// setPersisted 方法需要 android.permission.RECEIVE_BOOT_COMPLETED 權(quán)限// setPersisted 方法作用是設(shè)備重啟后 , 依然執(zhí)行 JobScheduler 定時任務(wù)JobInfo.Builder jobInfoBuilder = new JobInfo.Builder(10,new ComponentName(context.getPackageName(), KeepAliveJobService.class.getName())).setPersisted(true);// 7.0 以下的版本, 可以每隔 5000 毫秒執(zhí)行一次任務(wù)if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N){jobInfoBuilder.setPeriodic(5_000);}else{// 7.0 以上的版本 , 設(shè)置延遲 5 秒執(zhí)行// 該時間不能小于 JobInfo.getMinLatencyMillis 方法獲取的最小值jobInfoBuilder.setMinimumLatency(5_000);}// 開啟定時任務(wù)jobScheduler.schedule(jobInfoBuilder.build());} }
2、判定服務(wù)運(yùn)行工具類
package kim.hsl.two_progress_alive;import android.app.Activity; import android.app.ActivityManager; import android.content.Context; import android.text.TextUtils;import org.w3c.dom.Text;import java.util.List;public class ServiceUtils {/*** 判定 Service 是否在運(yùn)行* @param context* @return*/public static boolean isServiceRunning(Context context, String serviceName){if(TextUtils.isEmpty(serviceName)) return false;ActivityManager activityManager =(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);// 最多獲取 200 個正在運(yùn)行的 ServiceList<ActivityManager.RunningServiceInfo> infos =activityManager.getRunningServices(200);// 遍歷當(dāng)前運(yùn)行的 Service 信息, 如果找到相同名稱的服務(wù) , 說明某進(jìn)程正在運(yùn)行for (ActivityManager.RunningServiceInfo info: infos){if (TextUtils.equals(info.service.getClassName(), serviceName)){return true;}}return false;} }
3、清單文件
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"package="kim.hsl.two_progress_alive"><uses-permission android:name="android.permission.FOREGROUND_SERVICE" /><uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.Two_Progress_Alive"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><!-- 本地提權(quán)前臺服務(wù) Service --><serviceandroid:name=".LocalForegroundService"android:enabled="true"android:exported="true"></service><!-- 本地服務(wù) , API 18 ~ 25 以上的設(shè)備, 關(guān)閉通知到專用服務(wù) --><serviceandroid:name=".LocalForegroundService$CancelNotificationService"android:enabled="true"android:exported="true"></service><!-- 遠(yuǎn)程提權(quán)前臺服務(wù) Service --><serviceandroid:name=".RemoteForegroundService"android:enabled="true"android:exported="true"android:process=":remote"></service><!-- 遠(yuǎn)程服務(wù) , API 18 ~ 25 以上的設(shè)備, 關(guān)閉通知到專用服務(wù) --><serviceandroid:name=".RemoteForegroundService$CancelNotificationService"android:enabled="true"android:exported="true"android:process=":remote"></service><!-- JobScheduler 拉活 --><serviceandroid:name=".KeepAliveJobService"android:enabled="true"android:exported="true"android:permission="android.permission.BIND_JOB_SERVICE"></service></application></manifest>
4、MainActivity 代碼
package kim.hsl.two_progress_alive;import android.content.Intent; import android.os.Build; import android.os.Bundle;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 通過前臺 Service 提升應(yīng)用權(quán)限// 啟動普通 Service , 但是在該 Service 的 onCreate 方法中執(zhí)行了 startForeground// 變成了前臺 Service 服務(wù)startService(new Intent(this, LocalForegroundService.class));startService(new Intent(this, RemoteForegroundService.class));// JobScheduler 拉活if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {KeepAliveJobService.startJob(this);}} }
5、運(yùn)行效果
運(yùn)行后 , 兩個進(jìn)程成功運(yùn)行 ;
即使將啟動雙進(jìn)程的代碼注釋掉 , 也可以成功拉起雙進(jìn)程 ;
三、 源碼資源
源碼資源 :
- GitHub 地址 : https://github.com/han1202012/Two_Progress_Alive
- CSDN 源碼快照 : https://download.csdn.net/download/han1202012/16623594
總結(jié)
以上是生活随笔為你收集整理的【Android 进程保活】应用进程拉活 ( 双进程守护 + JobScheduler 保活 | 成功率最高 | 推荐使用 )的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 进程保活】应用进程拉活
- 下一篇: 【Android 热修复】热修复原理 (