前言

Service作为四大组件之一很多安卓开发者对他肯定是又爱又恨,爱在它可以帮助我们去处理常驻后台的任务操作,比如说推送服务,心跳传输等,恨在当Servcie遇到360、腾讯管家之类的杀毒软件,变得脆弱,很容易被杀死,或者当用户手机锁屏会导致服务暂时停止运行。
        我们常用的进程守护的套路无外乎以下几种:
一、提高进程的优先级数值
        对于Service被系统回收,一般做法是通过提高优先级可以解决,在AndroidManifest.xml文件中对于intent-filter可以通过Android:priority = “1000”这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低。
二、改变进程等级

进程的重要性优先级:(越往后的就越容易被系统杀死)
1.前台进程;Foreground process1)用户正在交互的Activity(onResume())2)当某个Service绑定正在交互的Activity。3)被主动调用为前台Service(startForeground())4)组件正在执行生命周期的回调(onCreate()/onStart()/onDestroy())5)BroadcastReceiver 正在执行onReceive();2.可见进程;Visible process1)我们的Activity处在onPause()(没有进入onStop())2)绑定到前台Activity的Service。3.服务进程;Service process简单的startService()启动。
4.后台进程;Background process对用户没有直接影响的进程----Activity出于onStop()的时候。android:process=":xxx"
5.空进程; Empty process不含有任何的活动的组件。(android设计的,为了第二次启动更快,采取的一个权衡)

三、设置 android:persistent属性为true

< application android:name="com.test.Application" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:persistent="true"</span> android:theme="@style/AppTheme" >
< /application> 

这个属性设置后,的确发现优先级提高不少,或许是相当于系统级的进程,但是还是无法保证存活。

四、onDestory方法内调用广播,重启Service
当service执行了onDestory的时候,发送一个自定义的广播,当收到广播的时候,重新启动service。

<receiver android:name="com.dbjtech.acbxt.waiqin.BootReceiver" >  <intent-filter>  <action android:name="android.intent.action.BOOT_COMPLETED" />  <action android:name="android.intent.action.USER_PRESENT" />  <action android:name="com.dbjtech.waiqin.destroy" />//这个就是自定义的action  </intent-filter>
</receiver>  @Override
public void onDestroy() {  stopForeground(true);  Intent intent = new Intent("com.dbjtech.waiqin.destroy");  sendBroadcast(intent);  super.onDestroy();
}  public class BootReceiver extends BroadcastReceiver {  @Override  public void onReceive(Context context, Intent intent) {  if (intent.getAction().equals("com.dbjtech.waiqin.destroy")) {  //TODO  //在这里写重新启动service的相关操作  startUploadService(context);  }  }  }  

但是当使用类似于360卫士和腾讯管家等第三方应用或是在setting里-应用-强制停止时,APP进程可能就直接被干掉了,onDestroy方法都进不来,所以还是无法保证存活。
五、监听系统广播判断Service状态
通过系统的一些广播,比如:手机重启、界面唤醒、应用状态改变等等监听并捕获到,然后判断我们的Service是否还存活,记得加权限

<receiver android:name="com.dbjtech.acbxt.waiqin.BootReceiver" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.USER_PRESENT" /> <action android:name="android.intent.action.PACKAGE_RESTARTED" /> <action android:name="com.dbjtech.waiqin.destroy" /> </intent-filter>
</receiver> 

在BroadcastReceiver中:

@Override
public void onReceive(Context context, Intent intent) { if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { System.out.println("手机开机了...."); startUploadService(context); } if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) { startUploadService(context); }
} 

这个方法监听多了会导致Service很混乱,带来诸多麻烦。

六、QQ采取在锁屏的时候启动一个1个像素的Activity,当用户解锁以后将这个Activity结束掉(顺便同时把自己的核心服务再开启一次,接下来就来模拟实现:

//主界面Activity
public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent = new Intent(this, MyService.class);startService(intent);}public void jump(View v){Intent intent = new Intent(this, KeepLiveActivity.class);startActivity(intent);finish();}
}//1个像素的activity
public class KeepLiveActivity extends Activity {private static final String TAG = "kiven";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
//      setContentView(R.layout.activity_main);Log.i(TAG, "KeepLiveActivity----onCreate!!!");Window window = getWindow();window.setGravity(Gravity.LEFT|Gravity.TOP);LayoutParams params = window.getAttributes();params.height = 1;params.width = 1;params.x = 0;params.y = 0;   window.setAttributes(params);KeepLiveActivityManager.getInstance(this).setKeepLiveActivity(this);}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();Log.i(TAG, "KeepLiveActivity----onDestroy!!!");}
}//管理服务的开启与关闭
public class KeepLiveActivityManager {private static KeepLiveActivityManager instance;private Context context;private WeakReference<Activity> activityInstance;public static KeepLiveActivityManager getInstance(Context context) {if(instance==null){instance = new KeepLiveActivityManager(context.getApplicationContext());}return instance;}private KeepLiveActivityManager(Context context) {this.context = context;}public void setKeepLiveActivity(Activity activity){activityInstance = new WeakReference<Activity>(activity);}public void startKeepLiveActivity() {Intent intent = new  Intent(context, KeepLiveActivity.class);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(intent);}public void finishKeepLiveActivity() {if(activityInstance!=null&&activityInstance.get()!=null){Activity activity = activityInstance.get();activity.finish();}}}//屏幕状态监听
public class ScreenListener {private Context mContext;private ScreenBroadcastReceiver mScreenReceiver;private ScreenStateListener mScreenStateListener;public ScreenListener(Context context) {mContext = context;mScreenReceiver = new ScreenBroadcastReceiver();}/*** screen状态广播接收者*/private class ScreenBroadcastReceiver extends BroadcastReceiver {private String action = null;@Overridepublic void onReceive(Context context, Intent intent) {action = intent.getAction();if (Intent.ACTION_SCREEN_ON.equals(action)) { // 开屏mScreenStateListener.onScreenOn();} else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 锁屏mScreenStateListener.onScreenOff();} else if (Intent.ACTION_USER_PRESENT.equals(action)) { // 解锁mScreenStateListener.onUserPresent();}}}/*** 开始监听screen状态* * @param listener*/public void begin(ScreenStateListener listener) {mScreenStateListener = listener;registerListener();getScreenState();}/*** 获取screen状态*/private void getScreenState() {PowerManager manager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);if (manager.isScreenOn()) {if (mScreenStateListener != null) {mScreenStateListener.onScreenOn();}} else {if (mScreenStateListener != null) {mScreenStateListener.onScreenOff();}}}/*** 停止screen状态监听*/public void unregisterListener() {mContext.unregisterReceiver(mScreenReceiver);}/*** 启动screen状态广播接收器*/private void registerListener() {IntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_SCREEN_ON);filter.addAction(Intent.ACTION_SCREEN_OFF);filter.addAction(Intent.ACTION_USER_PRESENT);mContext.registerReceiver(mScreenReceiver, filter);}public interface ScreenStateListener {// 返回给调用者屏幕状态信息public void onScreenOn();public void onScreenOff();public void onUserPresent();}<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/><uses-permission android:name="android.permission.RECEIVE_USER_PRESENT"/>
}

上面实现了1像素保活,当接受到监听锁屏广播,就会启动这个1个像素的Activity,当监听界面唤醒广播,就结束掉这个1个像素的Activity,要监听锁屏的广播需要使用动态注册的方式(实际项目中不会出现静态注册广播的方式)。
七:双进程守护(重点)
        如何让系统或者第三方应用无法杀死进程,除了上面的六种方式,还有的就是一般手机厂商会与app运营商达成合作,加入到白名单,就不会被杀死。这种方式我们一般是很难用的。但是另一种方式双进程守护方式来实现,什么是双进程守护?双进程守护—可以防止单个进程杀死,同时可以防止第三方的360清理掉。一个进程被杀死,另外一个进程又被他启动。相互监听启动。双进程的互相唤醒,就相当于双进程之间要进行互相通信,进程间的通信是通过binder机制,所以这两个进程之间可以通过aidl来实现。

RemoteConnection.aidl
interface RemoteConnection{String getProcessName();
}LocalService.java 本地服务
public class LocalService extends Service {public static final String TAG = "kiven";private MyBinder binder;private MyServiceConnection conn;@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubreturn binder;}@Overridepublic void onCreate() {super.onCreate();if(binder ==null){binder = new MyBinder();}conn = new MyServiceConnection();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {LocalService.this.bindService(new Intent(LocalService.this, RemoteService.class), conn, Context.BIND_IMPORTANT);PendingIntent contentIntent = PendingIntent.getService(this, 0, intent, 0);NotificationCompat.Builder builder = new NotificationCompat.Builder(this);builder.setTicker("360").setContentIntent(contentIntent).setContentTitle("我是360").setAutoCancel(true).setContentText("hehehe").setWhen(System.currentTimeMillis());//把service设置为前台运行,避免手机系统自动杀掉改服务。startForeground(startId, builder.build());return START_STICKY;}class MyBinder extends RemoteConnection.Stub{@Overridepublic String getProcessName() throws RemoteException {// TODO Auto-generated method stubreturn "LocalService";}}class MyServiceConnection implements ServiceConnection{@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.i(TAG, "建立连接成功!");}@Overridepublic void onServiceDisconnected(ComponentName name) {Log.i(TAG, "RemoteService服务被干掉了~~~~断开连接!");Toast.makeText(LocalService.this, "断开连接", 0).show();//启动被干掉的LocalService.this.startService(new Intent(LocalService.this, RemoteService.class));LocalService.this.bindService(new Intent(LocalService.this, RemoteService.class), conn, Context.BIND_IMPORTANT);}   }
}RemoteService.java: 远程服务(另一个进程)
public class RemoteService extends Service {public static final String TAG = "kiven";private MyBinder binder;private MyServiceConnection conn;@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubreturn binder;}@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate();if(binder ==null){binder = new MyBinder();}conn = new MyServiceConnection();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {RemoteService.this.bindService(new Intent(RemoteService.this, LocalService.class), conn, Context.BIND_IMPORTANT);PendingIntent contentIntent = PendingIntent.getService(this, 0, intent, 0);NotificationCompat.Builder builder = new NotificationCompat.Builder(this);builder.setTicker("360").setContentIntent(contentIntent).setContentTitle("我是360").setAutoCancel(true).setContentText("hehehe").setWhen( System.currentTimeMillis());//把service设置为前台运行,避免手机系统自动杀掉改服务。startForeground(startId, builder.build());return START_STICKY;}class MyBinder extends RemoteConnection.Stub{@Overridepublic String getProcessName() throws RemoteException {// TODO Auto-generated method stubreturn "LocalService";}}class MyServiceConnection implements ServiceConnection{@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.i(TAG, "建立连接成功!");}@Overridepublic void onServiceDisconnected(ComponentName name) {Log.i(TAG, "LocalService服务被干掉了~~~~断开连接!");Toast.makeText(RemoteService.this, "断开连接", 0).show();//启动被干掉的RemoteService.this.startService(new Intent(RemoteService.this, LocalService.class));RemoteService.this.bindService(new Intent(RemoteService.this, LocalService.class), conn, Context.BIND_IMPORTANT);}   }
}MainActivity.java:
public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);startService(new Intent(this, LocalService.class));startService(new Intent(this, RemoteService.class));startService(new Intent(this, JobHandleService.class));}}JobHandleService.java: JobHandlerService的作用是为了防止应用被强制关闭导致服务被杀(实际开发不建议使用,太流氓了)
@SuppressLint("NewApi")
public class JobHandleService extends JobService{private int kJobId = 0;@Overridepublic void onCreate() {super.onCreate();Log.i("INFO", "jobService create");}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.i("INFO", "jobService start");scheduleJob(getJobInfo());return START_NOT_STICKY;}@Overridepublic void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();}@Overridepublic boolean onStartJob(JobParameters params) {// TODO Auto-generated method stubLog.i("INFO", "job start");
//      scheduleJob(getJobInfo());boolean isLocalServiceWork = isServiceWork(this, "com.kiven.keepliveprocess.LocalService");boolean isRemoteServiceWork = isServiceWork(this, "com.kiven.keepliveprocess.RemoteService");
//      Log.i("INFO", "localSericeWork:"+isLocalServiceWork);
//      Log.i("INFO", "remoteSericeWork:"+isRemoteServiceWork);if(!isLocalServiceWork||!isRemoteServiceWork){this.startService(new Intent(this,LocalService.class));this.startService(new Intent(this,RemoteService.class));Toast.makeText(this, "process start", Toast.LENGTH_SHORT).show();}return true;}@Overridepublic boolean onStopJob(JobParameters params) {Log.i("INFO", "job stop");
//      Toast.makeText(this, "process stop", Toast.LENGTH_SHORT).show();scheduleJob(getJobInfo());return true;}/** Send job to the JobScheduler. */public void scheduleJob(JobInfo t) {Log.i("INFO", "Scheduling job");JobScheduler tm =(JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);tm.schedule(t);}public JobInfo getJobInfo(){JobInfo.Builder builder = new JobInfo.Builder(kJobId++, new ComponentName(this, JobHandleService.class));builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);builder.setPersisted(true);builder.setRequiresCharging(false);builder.setRequiresDeviceIdle(false);builder.setPeriodic(10);//间隔时间--周期return builder.build();}/** * 判断某个服务是否正在运行的方法 *  * @param mContext * @param serviceName *            是包名+服务的类名(例如:net.loonggg.testbackstage.TestService) * @return true代表正在运行,false代表服务没有正在运行 */  public boolean isServiceWork(Context mContext, String serviceName) {  boolean isWork = false;  ActivityManager myAM = (ActivityManager) mContext  .getSystemService(Context.ACTIVITY_SERVICE);  List<RunningServiceInfo> myList = myAM.getRunningServices(100);  if (myList.size() <= 0) {  return false;  }  for (int i = 0; i < myList.size(); i++) {  String mName = myList.get(i).service.getClassName().toString();  if (mName.equals(serviceName)) {  isWork = true;  break;  }  }  return isWork;  }
}AndroidManifest.xml:
....
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
...<service android:name="com.kiven.keepliveprocess.LocalService"></service><service android:name="com.kiven.keepliveprocess.RemoteService"android:process=":remoteprocess"></service><service android:name="com.kiven.keepliveprocess.JobHandleService" android:permission="android.permission.BIND_JOB_SERVICE"></service></application></manifest>

至此,进程保活的方式介绍完毕,实际上进程保护有很多种方式,需要根据实际的需求去选择适合的方式,一个小建议:不要把app搞的太”流氓”,会导致用户手机用电量飙升,CPU发热,也对用户的体验不好。

性能优化二十三之Service进程防杀死相关推荐

  1. EMW 性能优化二之---并发配置

    http://www.cnblogs.com/byfhd/p/3723318.html EMW 性能优化二之---并发配置 在前一个日志中写到交货的异步更新,对于RFUI RF的前台操作会提升效率,异 ...

  2. apache php 调优_Apache的性能优化(二)

    具体模块定制: 编译和包含是两个不同的概念.编译是指这个模块被编译了,要想使用它,只用简单的修改httpd.conf加上LoadModule xxx_module libexec/mod_xxx.so ...

  3. android db加载后无法读取任何内容_android性能优化(二)之卡顿优化

    相对于其他类型的性能指标,卡顿是能直接让用户产生视觉反馈的现象,比如App反应滞后于用户的操作,在严重的情况下会出现ANR.关乎用户体验的大事,是很容易遭到用户吐槽的.因此,开发人员平时写代码时必须要 ...

  4. Kubernetes生产实践系列之二十三:Service Mesh之在Kubernetes部署Istio进行service mesh

    一.前言 演进到今天,Istio已经明确了作为ServiceMesh基础设施,它的主要服务能力包括: 在之前的文章<kubernetes系列之十八:使用helm安装istio>中,基于Is ...

  5. MySQL性能优化(二):优化数据库的设计

    一:数据库的设计 数据库命名:数据库名的命名一般和项目的名称保持一致,不要随意的起名字. 数据库编码: 采用utf8mb4而不使用utf8 MySQL 的"utf8"实际上不是真正 ...

  6. Android 性能优化(五)ANR 秒变大神

    Android 性能优化 (一)APK高效瘦身 http://blog.csdn.net/whb20081815/article/details/70140063 Android 性能优化 (二)数据 ...

  7. MySQL 的性能(下篇)—— 性能优化方法

    简介 文中内容均为阅读前辈的文章所整理而来,参考文章已在最后全指明 本文分为上下两篇: 上篇:MySQL 的 SQL 执行分析 下篇:MySQL 性能优化 下面为下篇内容,分为以下部分: 一.创建表时 ...

  8. Android性能优化(一):APP启动优化

    Android性能优化(一):APP启动优化 性能优化系列文章: Android性能优化(一):APP启动优化 Android性能优化(二):UI布局优化 Android性能优化(三):响应优化 An ...

  9. Android性能优化(三):响应优化

    Android性能优化(三):响应优化 性能优化系列文章: Android性能优化(一):APP启动优化 Android性能优化(二):UI布局优化 Android性能优化(三):响应优化 Andro ...

最新文章

  1. encoder-decoder 注意力机制整理名望所
  2. EasyUI –tree、combotree学习总结
  3. 一个Mapreduce案例
  4. 通过DataWorks数据集成归档日志服务数据至MaxCompute进行离线分析
  5. SQL Server 2014 新建数据库
  6. 阿里云虚拟主机针对恶意频繁攻击式访问造成CPU爆满的解决方法
  7. unity3D学习笔记2
  8. 飞信2008内测版下载
  9. 爬PHP网站文件,蜘蛛来访爬取链接详情导出TXT文件(php脚本)
  10. 老徐和阿珍的故事:强引用、软引用、弱引用、虚引用,傻傻分不清楚
  11. vue.js ui框架_定制的第一个Vue.js电子商务UI框架
  12. Vue.js快速入门之五:Mockjs的使用和语法详解
  13. ibm服务器进去阵列卡状态,IBM阵列卡介绍和服务器对阵列卡的支持情况
  14. 工作5年观察:快速在职场崛起,拼这10个认知
  15. 阅读软件怎么添加书源_使用OneDrive给文献管理和阅读软件知之阅读添加云同步功能...
  16. input 禁止手机唤起软键盘,并且光标存在
  17. Quartus问题收集
  18. 腾讯文档在线表格修改工具栏大小
  19. Kafka学习【1】
  20. SAP FICO报表绘制器(Report Painter)

热门文章

  1. javaweb项目完整案例下载,真的太香了!
  2. Java中时间的计算
  3. java前中后序_前序中序求后序的java算法
  4. ios 旋转屏幕试图切换_iOS屏幕横竖屏切换
  5. 大工17春 c 语言,大工20春《C/C++语言程序设计》在线作业【答案100分】
  6. Python处理数据,并经其存储为文本数据(Txt、JSON、CSV、Excel)总结
  7. php正则匹配字符乱码,php正则匹配中文乱码问题怎么解决
  8. 服务器光口位置,linu服务器光口配置ip
  9. 奇异值、奇异值分解、奇异值表示什么物理意义?
  10. win 10系统安装myeclipse 9.1 破解问题