今天我们只写前三种方式,第四种native层双进程守护将在下一篇来讲解。
我们先来看下进程的优先级 :
前台进程
- Activity已调用onResume()方法
- Service服务已调用startForeground()
- 生命周期回调的Service (onCreate() 、onStart()或onDestroy())
- 正执行其onReceive()方法的BroadcastReceiver
,
可见进程
- 不在前台、但仍对用户可见的Activity(比如调用其onPause()方法)
- 绑定到可见(或前台)Activity 的Service
后台进程
- 对用户不可见的 Activity 的进程已调用 Activity 的onStop()方法
空进程
- 不含任何活动应用组件的进程
1.应用内存不足,回收进程
提高进程优先级,减少进程oom_adj值,如启动进程的setForeground()提高进程优先级
当应用程序退到后台时,释放占用的资源,因为当oom_adj相同时,优先释放内存消耗大的进程
一直在后台运行的进程一定要轻
2.系统第三方清理软件,杀死进程
使用aidl,实现双进程守护
白名单
3.各大rom厂商在应用退出时,会清理杀死进程
使用NDK,轮询查看指定进程是否被杀死,如果杀死fork进程,启动
使用JobScheduler,轮询查看指定进程是否被杀死,如果杀死,启动
这里我们将用到aidl,有不了解的同学可以自己去了解下,我们先来上代码:
interface ProcessConnect {
}
接口里面什么都没有,这个只是用来监听是否断开连接,如果断开,就代码启动服务。
public class MessageService extends Service {
private String TAG = "MessageService";
private int ID=0X00022;
private static Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
Log.e(TAG, "MessageService====>print");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//assert uri
String path = "file:///android_asset/xiaoxin.wav";
Notification.Builder builder = new Notification.Builder(mContext);
Notification notification = builder
.setContentText("messageservice")
.setSmallIcon(R.drawable.ting)
.setSound(Uri.parse(path))
.build();
startForeground(ID,notification);
bindService(new Intent(MessageService.this,GuardService.class),mServiceConnection,BIND_WAIVE_PRIORITY);
return START_STICKY;
}
public ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(TAG, "MessageService====>onServiceConnected");
}
@Override
public void onServiceDisconnected(ComponentName name) {
startService(new Intent(MessageService.this,GuardService.class));
bindService(new Intent(MessageService.this,GuardService.class),mServiceConnection,BIND_WAIVE_PRIORITY);
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new ProcessConnect.Stub() {
};
}
}
public class GuardService extends Service {
private Context mContext;
private int ID=0X00021;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//assert uri
String path = "file:///android_asset/xiaoxin.wav";
Notification.Builder builder = new Notification.Builder(mContext);
Notification notification = builder
.setContentText("GuardService")
.setSmallIcon(R.drawable.ting)
.setSound(Uri.parse(path))
.build();
startForeground(ID,notification);
bindService(new Intent(GuardService.this,MessageService.class),mServiceConnection,BIND_WAIVE_PRIORITY);
return START_STICKY;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new ProcessConnect.Stub(){
};
}
public ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e("GuardService", "GuardService====>onServiceConnected");
}
@Override
public void onServiceDisconnected(ComponentName name) {
startService(new Intent(GuardService.this,MessageService.class));
bindService(new Intent(GuardService.this,MessageService.class),mServiceConnection,BIND_WAIVE_PRIORITY);
}
};
}
从上面两个服务可以看到,每当一个服务结束,另一个服务就会启动它,来实现进程不被关闭。
startService(new Intent(this,MessageService.class));
startService(new Intent(this,GuardService.class));
//新的进程中运行
主要五步就搞定了,很简单吧,但是不要高兴的太早,因为这种双进程守护的方法,只能对4.0以下有效,对于4.0以上机型,只能部分有用,这个问题最后再说,我们先来看下使用JobScheduler,轮询启动被杀死的进程。
在android开发中,会存在这么些场景 : 你需要在稍后的某个时间点或者当满足某个特定的条件时执行一个任务,例如当设备接通电源适配器或者连接到WIFI。幸运的是在API 21 ( Android 5.0,即Lollipop )中,google提供了一个新叫做JobScheduler API的组件来处理这样的场景。
当一系列预置的条件被满足时,JobScheduler API为你的应用执行一个操作。与AlarmManager不同的是这个执行时间是不确定的。除此之外,JobScheduler API允许同时执行多个任务。这允许你的应用执行某些指定的任务时不需要考虑时机控制引起的电池消耗。
下面我们就使用JobScheduler来启动我们被杀死的服务:
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class JobWakeUpService extends JobService {
private JobScheduler service;
private int JobId=100;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
JobInfo info = new JobInfo.Builder(JobId,new ComponentName(this,JobWakeUpService.class))
.setPeriodic(2000)
.build();
service = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
service.schedule(info);
return START_STICKY;
}
@Override
public boolean onStartJob(JobParameters params) {
Log.e("JobWakeUpService", "JobWakeUpService====>print");
//开始定时任务
if(!isServiceWork(this,MessageService.class.getName())){
//
startService(new Intent(this,MessageService.class));
}
return false;
}
@Override
public boolean onStopJob(JobParameters params) {
//停止
service.cancel(JobId);
// service.cancelAll();
return false;
}
private boolean isServiceWork(Context context,String serviceName){
ActivityManager am= (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List runningServices = am.getRunningServices(100);
if(runningServices == null){
return false;
}
for (ActivityManager.RunningServiceInfo service : runningServices) {
String className = service.service.getClassName();
if(className.equals(serviceName)){
return true;
}
}
return false;
}
}
我们看到这边就是使用JobScheduler服务来进行循环调用我们的JobWakeUpService的onStartJob。
我们接下来看下配置:
调用:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
startService(new Intent(this, JobWakeUpService.class));
}
这个就能实现轮询查看指定进程是否被杀死,如果杀死,启动的功能。
可能你们想问这种方式是否可以解决5.0以上进程不被杀死吗?我只能遗憾的告诉你,不能,我在华为7.0上的测试,没有能够起来。
我们看了这么多的方式,也不能解决进程不被杀死的情况,那有没有更好的办法呢?
下面一篇我们将讲解使用NDK来实现双进程守护。