转载请注明出处:z_zhaojun的博客 原文地址
这篇博文主要是关于进程保活的应用,通过对网上各种进程保活方式的学习,自己理解后做汇总、优化、简单封装。
进程保活,主要就为了加强你写的app在手机上的生存能力,降低被手机干掉的几率。当然,如果想要完全保证app不被杀死,那是不可能的(因为就是你再厉害,也厉害不过手机厂商),所以只能是尽量提高app的存活几率。下面将通过‘AIDL +JobService(JobScheduler)’来实现这个目标。
第一步、通过AIDL来实现双进程守护,达到初步加强app存活能力的目的
显示在最开始你必须先新建一个AIDL服务(具体玩法自行百度),先上相关代码:
LocalService.java
//LocalService是一个运行在当前app进程的一个服务,在这里你可以实现你想要一直放在后台执行的功能。实现了ServiceConnection接口,用于监听兄弟服务RemoteService(具体代码请往下看)状态,在监听到RemoteService被杀死后,重新开启兄弟服务RemoteSerivce
class LocalService extends Service implements ServiceConnection {
private static final String TAG = "LocalService";
private LocalServiceBinder localBinder;
private Notification notification;
@Override
public void onCreate() {
Log.d(TAG, "onCreate");
if (null == localBinder) {
//与RemoteService绑定时需要
localBinder = new LocalServiceBinder();
}
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
startJob();
//提高服务优先级,降低被杀的概率
startForeground(startId, getNotification());
//与兄弟服务RemoteService绑定,这有这样才能监听到RemoteService的状态
bindService(new Intent(LocalService.this, RemoteService.class),
this, Context.BIND_IMPORTANT);
return START_STICKY;
}
//在这里开始你想要实现的功能,已经做了简单封装,博文末尾会有操作方式
private boolean startJob() {
return AliveServiceManagerImpl.getInstance().startJob();
}
@NonNull
private Notification getNotification() {
if (null == notification) {
Notification.Builder builder = new Notification.Builder(this);
builder.setDefaults(NotificationCompat.FLAG_AUTO_CANCEL);
builder.setContentTitle(TAG);
builder.setSmallIcon(R.drawable.logonews);
builder.setSubText(TAG);
builder.setContentText(TAG);
builder.setWhen(System.currentTimeMillis());
/*PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
builder.setContentIntent(pi);*/
notification = builder.build();
}
return notification;
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
return localBinder;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected");
}
//当兄弟服务RemoteService被杀死时,会触发onServiceDisconnected方法,在这里重新开启RemoteService,并绑定
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected");
startService(new Intent(this, RemoteService.class));
bindService(new Intent(this, RemoteService.class), this, Context.BIND_IMPORTANT);
}
//AIDL服务
private class LocalServiceBinder extends IServiceAidlInterface.Stub {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
Log.d(TAG, "basicTypes");
}
}
}
RemoteService .java
//RemoteService 是一个运行在与当前app进程相独立的进程中的服务,并实现了ServiceConnection接口,用于监听兄弟服务LocalService的状态,在监听到LocalService被杀死后,重新开启兄弟服务LocalService
class RemoteService extends Service implements ServiceConnection {
private static final String TAG = "RemoteService";
private RemoteServiceBinder remoteBinder;
private Notification notification;
@Override
public void onCreate() {
Log.d(TAG, "onCreate");
if (null == remoteBinder) {
remoteBinder = new RemoteServiceBinder();
}
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
//提高服务优先级,降低被杀的概率
startForeground(startId, getNotification());
//与兄弟服务LocalService绑定,这有这样才能监听到LocalService的状态
bindService(new Intent(this, LocalService.class), this, Context.BIND_IMPORTANT);
return START_STICKY;
}
@NonNull
private Notification getNotification() {
if (null == notification) {
Notification.Builder builder = new Notification.Builder(this);
builder.setDefaults(NotificationCompat.FLAG_AUTO_CANCEL);
builder.setContentTitle(TAG);
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setSubText(TAG);
builder.setContentText(TAG);
builder.setWhen(System.currentTimeMillis());
/*PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
builder.setContentIntent(pi);*/
notification = builder.build();
}
return notification;
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
return remoteBinder;
}
//当兄弟服务LocalService被杀死时,会触发onServiceDisconnected方法,在这里重新开启LocalService,并绑定
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected");
startService(new Intent(this, LocalService.class));
bindService(new Intent(this, LocalService.class), this, Context.BIND_IMPORTANT);
}
private class RemoteServiceBinder extends IServiceAidlInterface.Stub {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
Log.d(TAG, "basicTypes");
}
}
}
LocalService、RemoteService在AndroidManifest.xml中的添加方式:
<service
android:name=".aliveservice.LocalService"
android:enabled="true"
android:exported="true">
</service>
<service
android:name=".aliveservice.RemoteService"
android:process=":remote"//用于开启新的进程:包名+“:remote”
android:enabled="true"
android:exported="true">//为true表示对其它进程可见
</service>
第二步、结合JobService使用
JobService+Jobschedule有点类似手机系统闹钟(alertmanager),是android5.0之后提供的机制,可以让系统在某些特定环境下或固定时间间隔里,异步执行一些作业,其主要目的就是为了优化电池。当然,在这里主要是为了保护兄弟服务LocalService+RemoteService。
具体代码:
LocalJobService.java
<service
android:name=".aliveservice.LocalJobService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:enabled="true"
android:exported="true">
</service>
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
class LocalJobService extends JobService {
private static final String TAG = "LocalJobService";
private static final String KEY_LOCAL_SERVICE_NAME = LocalService.class.getName();
private static final String KEY_REMOTE_SERVICE_NAME = RemoteService.class.getName();
private JobInfo jobInfo;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand");
scheduleJob(getJobInfo());
return START_NOT_STICKY;
}
//一旦开启当前服务,系统会定时调用onStartJob方法,在其中判断兄弟服务LocalService+RemoteService的存活情况,如果被杀死则重新启动相应服务
@Override
public boolean onStartJob(JobParameters params) {
Log.i(TAG, "onStartJob");
boolean isLocalServiceWork = isServiceWork(this, KEY_LOCAL_SERVICE_NAME);
boolean isRemoteServiceWork = isServiceWork(this, KEY_REMOTE_SERVICE_NAME);
if (!isLocalServiceWork) {
this.startService(new Intent(this, LocalService.class));
}
if (!isRemoteServiceWork) {
this.startService(new Intent(this, RemoteService.class));
}
return true;
}
@Override
public boolean onStopJob(JobParameters params) {
Log.i(TAG, "onStopJob");
scheduleJob(getJobInfo());
return true;
}
/**
* 将任务作业发送到作业调度中去
*/
public void scheduleJob(JobInfo info) {
Log.i(TAG, "scheduleJob");
JobScheduler js = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
js.schedule(info);
}
public JobInfo getJobInfo() {
Log.i(TAG, "getJobInfo");
if (null == jobInfo) {
JobInfo.Builder builder = new JobInfo.Builder(0, new ComponentName(this, LocalJobService.class));
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
builder.setPersisted(true);
builder.setRequiresCharging(false);
builder.setRequiresDeviceIdle(false);
//间隔100毫秒
builder.setPeriodic(100);
jobInfo = builder.build();
}
return jobInfo;
}
/**
* 判断服务是否正在运行
*/
public boolean isServiceWork(Context mContext, String serviceName) {
if (TextUtils.isEmpty(serviceName)) {
return false;
}
boolean isWorking = false;
ActivityManager manager = (ActivityManager) mContext
.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> list = manager.getRunningServices(100);
for (ActivityManager.RunningServiceInfo info : list) {
String name = info.service.getClassName();
if (serviceName.equals(name)) {
isWorking = true;
break;
}
}
return isWorking;
}
}
第三步、简单封装
具体实现请看代码:
AliveServiceManagerImpl.java
/**
* package: com.zzj.chris.processalivedemo.aliveservice
* <p>
* description: 保活service管理
* <p>
* Created by chris on 2017/8/7.
*/
public class AliveServiceManagerImpl implements AliveServiceManager {
private static final Byte[] LOCK = new Byte[0];
private static AliveServiceManager mInstance;
private List<JobSchedule> mJobObservers;
private AliveServiceManagerImpl() {}
//单例
public static AliveServiceManager getInstance() {
if (null == mInstance){
synchronized (LOCK) {
if (null == mInstance){
mInstance = new AliveServiceManagerImpl();
}
}
}
return mInstance;
}
//在这里开启进程保活功能
@Override
public void start(Context context) {//app.getContext
context.startService(new Intent(context, LocalService.class));
context.startService(new Intent(context, RemoteService.class));
if (Build.VERSION.SDK_INT >= 21) {
context.startService(new Intent(context, LocalJobService.class));
}
}
@Override
public void stop(Context context) {
}
@Override
public void destroy() {
if (null != mJobObservers) {
mJobObservers.clear();
mJobObservers = null;
}
mInstance = null;
}
//开始执行你在后台想要实现的功能
@Override
public boolean startJob() {
boolean isWorking = false;
getObservers();
for (JobSchedule schedule : mJobObservers) {
if (!schedule.isWorking()) {
schedule.start();
isWorking = true;
}
}
return isWorking;
}
private void getObservers() {
if (null == mJobObservers) {
mJobObservers = new ArrayList<>();
}
if (mJobObservers.size() <= 0) {
//这里需要手动添加
mJobObservers.add(NotificationHelper.getInstance());
mJobObservers.add(*******);
......
}
}
}
使用实例:
新建NotificationHelper类实现AliveServiceManager.JobSchedule接口(具体请看demo源码,末尾附下载地址):
NotificationHelper。java
public class NotificationHelper implements AliveServiceManager.JobSchedule {
private static final String TAG = "NotificationHelper";
private static NotificationHelper mHelper;
private boolean isWork;
private NotificationHelper() {}
public static NotificationHelper getInstance() {
if (null == mHelper) {
mHelper = new NotificationHelper();
}
return mHelper;
}
@Override
public void start() {//在这执行需要实现的工作
if (!isWork) {
// startTimer();
isWork = true;
}
}
@Override
public void stop() {
// stopTimer();
isWork = false;
}
@Override
public boolean isWorking() {
return isWork;
}
最后就是具体用法:
AliveServiceManagerImpl.getInstance().start(this);