在 如何让我们的Android应用进程保活? 文章里总结了一些进程保活方法,本文以双进程守护和进程提权来保活我们的服务进程。
双进程守护:
主要设计AB两个不同服务进程,A进程的服务轮询检查B进程的服务是否存活,没存活的话将其拉起,同样B进程服务轮询检查A进程服务是否存活,没存活的话也将其拉起
进程提权
主要设计中调用 startForeground方法将service置为“前台进程”,不过这样会显示我们发送的Notification。为了取消这个Notification通知栏,我们需要第三个服务C来进行取消通知栏的工作。
在AndroidMainfest中对三个服务进行注册,其中FirstService和SecondService运行在新开的两个进程中,以进行我们的双进程守护。ThirdService主要用来取消我们的通知栏,将其放在应用的原进程就好。
对FirstService与SecondService进行设计,使其相互守护,为了提醒对方自己已挂,在这里使用相互绑定对方服务的方法,当一方出现异常断开绑定时,则另一方在回调方法中拉起对方,并再进行相互绑定。
以下为FirstService的设计:
public class FirstService extends Service {
private MyBinder binder; //绑定服务需要Binder进行交互
private MyConn conn;
@Override
public IBinder onBind(Intent intent) {
return binder;
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onCreate() {
super.onCreate();
binder = new MyBinder();
if(conn==null)
conn = new MyConn();
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
// 与SecondSevice绑定
FirstService.this.bindService(new Intent(this,SecondService.class),conn, Context.BIND_IMPORTANT);
}
//使用aidl实现进程通信
class MyBinder extends ProcessService.Stub{
@Override
public String getServiceName() throws RemoteException {
return "I am FirstService";
}
}
//建立相互绑定时的连接
class MyConn implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.i("Info","与SecondService连接成功");
}
//在异常断开的回调方法进行拉起对方服务并绑定
@Override
public void onServiceDisconnected(ComponentName componentName) {
Toast.makeText(FirstService.this,"SecondService被杀死",Toast.LENGTH_SHORT).show();
// 启动FirstService
FirstService.this.startService(new Intent(FirstService.this,SecondService.class));
//绑定FirstService
FirstService.this.bindService(new Intent(FirstService.this,SecondService.class),conn, Context.BIND_IMPORTANT);
}
}
}
SecondService的设计和FirstService的设计差不多,都是在onStart中与对方相互绑定,在异常断开时重启对方并绑定。
SecondService多了一层服务进程提权设计(FirstService也可以加上这层设计):
public class SecondService extends Service {
private MyBinder binder;
private MyConn conn;
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return binder;
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onCreate() {
super.onCreate();
binder = new MyBinder();
if(conn==null)
conn = new MyConn();
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
//创建通知栏
Notification.Builder builder = new Notification.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher);
//显示通知栏,服务进程提权为前台服务。
startForeground(250, builder.build());//使用id:250标记该通知栏
// 启动第三个服务ThirdService来消除通知栏
startService(new Intent(this,ThirdService.class));
SecondService.this.bindService(new Intent(this,FirstService.class),conn, Context.BIND_IMPORTANT);
}
class MyBinder extends ProcessService.Stub{
@Override
public String getServiceName() throws RemoteException {
return "I am SecondService";
}
}
class MyConn implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.i("Info","与FirtService连接成功"+SecondService.this.getApplicationInfo().processName);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Toast.makeText(SecondService.this,"FirstService被杀死",Toast.LENGTH_SHORT).show();
// 启动FirstService
SecondService.this.startService(new Intent(SecondService.this,FirstService.class));
//绑定FirstService
SecondService.this.bindService(new Intent(SecondService.this,FirstService.class),conn, Context.BIND_IMPORTANT);
}
}
}
在ThirdService消除通知栏 :
public class ThirdService extends Service {
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return null;
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 被启动后创建相互id的通知栏,并提权服务
Notification.Builder builder = new Notification.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher);
startForeground(250, builder.build());
//开启新的线程消除通知栏
new Thread(new Runnable() {
@Override
public void run() {
SystemClock.sleep(1000);
stopForeground(true);//停止前台
NotificationManager manager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.cancel(250); // 消除通知栏
stopSelf(); // 停止服务
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
}
最后在MainActivity或其他适当的地方启动FirstService和SecondService这两个服务:
this.startService(new Intent(this,FirstService.class));
this.startService(new Intent(this,SecondService.class));
当应用处于后台时,双进程守护起很好的效果,但一方服务进程被杀掉时,另一方服务可即时地重启了被杀掉的服务进程。(也可以在设置->应用->正在运行中进行手动地杀死进程查看效果)
当FirstService和SecondService进行服务提权为前台服务时,可以躲过360卫士的手机加速的查杀。