1、Service设置成START_STICKY(onStartCommand方法中),kill 后会被重启(等待5秒左右),重传Intent,保持与重启前一样

2、通过 startForeground将进程设置为前台进程,做前台服务,优先级和前台应用一个级别​,除非在系统内存非常缺,否则此进程不会被 kill.具体实现方式为在service中创建一个notification,再调用void android.app.Service.startForeground(int id,Notificationnotification)方法运行在前台即可。

3、双进程Service:让2个进程互相保护,其中一个Service被清理后,另外没被清理的进程可以立即重启进程

  双进程守护:

  首先是一个AIDL接口,两边的Service都要通过继承ServiceAidl.Stub来实现AIDL接口中的方法。接口声明如下:

interface ServiceAidl {
String getName();
}

  然后是两个Service,为了保持连接,内部写一个内部类实现ServiceConnection的接口,当外部杀了其中一个进程的时候,会进入onDisConnection中,那么此时要做的就是start和bind另一个进程,因为Service的启动是可以多次的,所以这样是没问题的,代码如下:

public class LocalService extends Service {
private ServiceConnection conn;
private MyService myService; @Override
public IBinder onBind(Intent intent) {
return myService;
} @Override
public void onCreate() {
super.onCreate();
init(); } private void init() {
if (conn == null) {
conn = new MyServiceConnection();
}
myService = new MyService();
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(getApplicationContext(), "本地进程启动", Toast.LENGTH_LONG).show();
Intent intents = new Intent();
intents.setClass(this, RemoteService.class);
bindService(intents, conn, Context.BIND_IMPORTANT);
return START_STICKY;
} class MyService extends ServiceAidl.Stub { @Override
public String getName() throws RemoteException {
return null;
}
} class MyServiceConnection implements ServiceConnection { @Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("获取连接"); } @Override
public void onServiceDisconnected(ComponentName name) {
Toast.makeText(LocalService.this, "远程连接被干掉了", Toast.LENGTH_SHORT).show();
LocalService.this.startService(new Intent(LocalService.this,
RemoteService.class));
LocalService.this.bindService(new Intent(LocalService.this,
RemoteService.class), conn, Context.BIND_IMPORTANT); } } }

远程服务类如下:

public class RemoteService extends Service {
private MyBinder binder;
private ServiceConnection conn; @Override
public void onCreate() {
super.onCreate();
// System.out.println("远程进程开启");
init(); } @Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(getApplicationContext(), "远程进程启动", Toast.LENGTH_LONG).show();
Intent intents = new Intent();
intents.setClass(this, LocalService.class);
bindService(intents, conn, Context.BIND_IMPORTANT);
return START_STICKY;
} private void init() {
if (conn == null) {
conn = new MyConnection();
}
binder = new MyBinder();
} @Override
public IBinder onBind(Intent intent) {
return binder;
} static class MyBinder extends ServiceAidl.Stub { @Override
public String getName() throws RemoteException {
return "远程连接";
}
} class MyConnection implements ServiceConnection { @Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("获取远程连接");
} @Override
public void onServiceDisconnected(ComponentName nme) {
Toast.makeText(RemoteService.this, "本地连接被干掉了", Toast.LENGTH_SHORT).show();
RemoteService.this.startService(new Intent(RemoteService.this,
LocalService.class));
RemoteService.this.bindService(new Intent(RemoteService.this,
LocalService.class), conn, Context.BIND_IMPORTANT);
}
} }

  布局文件里要加上声明

<service android:name=".LocalService" />
<service
android:name=".RemoteService"
android:process=":remote" />

  实际情况我个人测试,在5.0以下的模拟器上是没问题的,不管多次从系统的进程里kill掉,也还是会重新启动tos,但是5.0以上这种方法是无效的,5.0以上Android应该是意识到了这种双进程守护的方式,因此修改了一下源码,让这种双进程保活应用的方式无效。因此,针对5.0以上,我们采用另一种方案。

  JobScheduler执行任务调度保活

  JobScheduler这个类是21版本google新出来的api。

  这个任务其实是在设备空闲期执行的,而且系统设计的这个api不会很耗电,本意是用来执行一些任务调度的,但是我们设想一下,如果用这个类来执行我们的开启双进程,那么也是一定会在设备空闲期执行的,因此我们写一个类继承JobService,在onstart里声明创建JobScheduler对象,并设置多久执行一次和开机自启动,这样就能确保及时在息屏状态,也能够执行重启进程,所以我们在JobService的onStopJob方法里判断我们的进程是否被回收了,如果被回收了就重启进程,这样子就可以实现5.0以上的进程保活了。具体代码如下:

public class JobHandlerService extends JobService {
private JobScheduler mJobScheduler; @Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("服务被创建"); // startService(new Intent(this, LocalService.class));
// startService(new Intent(this, RemoteService.class)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mJobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo.Builder builder = new JobInfo.Builder(startId++,
new ComponentName(getPackageName(), JobHandlerService.class.getName())); builder.setPeriodic(5000); //每隔5秒运行一次
builder.setRequiresCharging(true);
builder.setPersisted(true); //设置设备重启后,是否重新执行任务
builder.setRequiresDeviceIdle(true); if (mJobScheduler.schedule(builder.build()) <= 0) {
//If something goes wrong
System.out.println("工作失败");
} else {
System.out.println("工作成功");
}
}
return START_STICKY;
} @Override
public boolean onStartJob(JobParameters params) { Toast.makeText(this, "服务启动", Toast.LENGTH_SHORT).show();
// || isServiceRunning(this, "com.ph.myservice.RemoteService") == false
System.out.println("开始工作");
// if (!isServiceRunning(getApplicationContext(), "com.ph.myservice") || !isServiceRunning(getApplicationContext(), "com.ph.myservice:remote")) {
// startService(new Intent(this, LocalService.class));
// startService(new Intent(this, RemoteService.class));
// } /* boolean serviceRunning = isServiceRunning(getApplicationContext(), "com.ph.myservice");
System.out.println("进程一" + serviceRunning); boolean serviceRunning2 = isServiceRunning(getApplicationContext(), "com.ph.myservice:remote");
System.out.println("进程二" + serviceRunning2);*/
return false;
} @Override
public boolean onStopJob(JobParameters params) {
if (!isServiceRunning(this, "com.ph.myservice.LocalService") || !isServiceRunning(this, "com.ph.myservice.RemoteService")) {
startService(new Intent(this, LocalService.class));
startService(new Intent(this, RemoteService.class));
}
return false;
} // 服务是否运行
public boolean isServiceRunning(Context context, String serviceName) {
boolean isRunning = false;
ActivityManager am = (ActivityManager) this
.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> lists = am.getRunningAppProcesses(); for (ActivityManager.RunningAppProcessInfo info : lists) {// 获取运行服务再启动
System.out.println(info.processName);
if (info.processName.equals(serviceName)) {
isRunning = true;
}
}
return isRunning; } }
public class MainActivity extends AppCompatActivity {

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
openJobService();
} else {
openTwoService();
} } private void openTwoService() {
startService(new Intent(this, LocalService.class));
startService(new Intent(this, RemoteService.class));
} private void openJobService() { Intent intent = new Intent();
intent.setClass(MainActivity.this, JobHandlerService.class);
startService(intent); }
}

  经过我6.0系统的华为真机测试是没有问题的,就算处于息屏状态进程也还是活着的,不管过多久打开屏幕还是会tos,并且关机了开机也会吐司。

4、AlarmManager不断启动service。该方式原理是通过定时警报来不断启动service,这样就算service被杀死,也能再启动

参考实现方式如下:

Intent intent =new Intent(mContext, MyService.class);

PendingIntent sender=PendingIntent

.getService(mContext, 0, intent, 0);

AlarmManager alarm=(AlarmManager)getSystemService(ALARM_SERVICE);

alarm.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis,5*1000,sender);

该方式基本可以保证在正常运行情况下,以及任务栏移除历史任务后(小米、魅族手机除外),service不被杀死。但是360等软件管家依然可以杀死。另外还有不断启动的逻辑处理麻烦。

5、监听系统广播判断Service状态(比如:手机重启、网络切换、开锁屏)

6、QQ黑科技:在应用退到后台后,另起一个只有 1 像素的页面停留在桌面上,让自己保持前台状态,保护自己不被后台清理工具杀死

7、在已经root的设备下,修改相应的权限文件,将App伪装成系统级的应用(Android4.0系列的一个漏洞,已经确认可行)

  • Android系统中当前进程(Process)fork出来的子进程,被系统认为是两个不同的进程。当父进程被杀死的时候,子进程仍然可以存活,并不受影响。鉴于目前提到的在Android-Service层做双守护都会失败,我们可以fork出c进程,多进程守护。死循环在那检查是否还存在,具体的思路如下(Android5.0以下可行)
  1. 用C编写守护进程(即子进程),守护进程做的事情就是循环检查目标进程是否存在,不存在则启动它。
  2. 在NDK环境中将1中编写的C代码编译打包成可执行文件(BUILD_EXECUTABLE)。
  3. 主进程启动时将守护进程放入私有目录下,赋予可执行权限,启动它即可。

8、联系厂商,加入白名单

转载连接

http://www.cnblogs.com/shen-hua/p/5836386.html

http://blog.csdn.net/pan861190079/article/details/72773549

保证Service不被Kill的解决方案的更多相关文章

  1. Android 开发之如何保证Service不被杀掉(broadcast+system/app)

    序言 最近项目要实现这样一个效果:运行后,要有一个service始终保持在后台运行,不管用户作出什么操作,都要保证service不被kill,这可真是一个难题.参考了现今各种定制版的系统和安全厂商牛虻 ...

  2. Android开发之如何保证Service不被杀掉(前台服务)

    序言 最近项目要实现这样一个效果:运行后,要有一个service始终保持在后台运行,不管用户作出什么操作,都要保证service不被kill.参考了现今各种定制版的系统和安全厂商牛虻软件,如何能保证自 ...

  3. Android开发之如何保证Service不被杀掉(broadcast+system/app)

    序言 最近项目要实现这样一个效果:运行后,要有一个service始终保持在后台运行,不管用户作出什么操作,都要保证service不被kill,这可真是一个难题.参考了现今各种定制版的系统和安全厂商牛虻 ...

  4. [转] Android开发之如何保证Service不被杀掉(broadcast+system/app)

    转发:原文链接http://blog.csdn.net/mad1989/article/details/22492519 序言 最近项目要实现这样一个效果:运行后,要有一个service始终保持在后台 ...

  5. Android开发之如何保证Service不被杀掉(broadcast+system/app

    Android开发之如何保证Service不被杀掉(broadcast+system/app) 序言 最近项目要实现这样一个效果:运行后,要有一个service始终保持在后台运行,不管用户作出什么操作 ...

  6. 如何保证Service在后台不被kill

    如何保证Service在后台不被kill 相信很多Android开发者在面试过程中会经常被问到“如何保证Service在后台不被kill”这个问题,总结了下一些大神给的答案. 引用知乎Android ...

  7. Android 如何保证service在后台不被kill

    Android 其实无法做多绝对的不被后台kill掉,我们只能尽量使用一些操作提升不被kill的机会. 一.onStartCommand方法,返回START_STICKY   START_STICKY ...

  8. Android 保持Service不被Kill掉的方法--双Service守护 && Android实现双进程守护

    本文分为两个部分,第一部分为双Service守护,第二部分为双进程守护 第一部分: 一.Service简介:Java.lang.Object ↳Android.content.Context  ↳an ...

  9. 保持Service不被Kill掉的方法--双Service守护 && Android实现双进程守护

    本文分为两个部分,第一部分为双Service守护,第二部分为双进程守护 第一部分: 一.Service简介:Java.lang.Object ↳Android.content.Context  ↳an ...

随机推荐

  1. HDU2546题解

    解题思路:先对价格排序(顺序或倒序都可以),然后,对前n-1(从1开始.排序方式为顺序)做容量为m(卡上余额)-5的01背包(背包体积和价值相等).假设dp[i][j]表示从前i个背包中挑选体积不超过 ...

  2. mongoDB的权限管理

    最近做一个关于mongoDB权限的功能, 在网上找了好久,各种命令,各种配置,各种修改,都没有解决哥的困惑.无奈,睡一觉后,灵光乍现,灵感来了. 下面就是我的最新发现,当然在各位看官的眼里,我的这个也 ...

  3. opatch lsinventory –details

    今天把RAC的数据库升完级后,在RAC1节点执行opatch lsinventory –detail 命令,没有报错.在rac2节点执行报错: [oracle@rac2 ~]$ opatch lsin ...

  4. svn代码回滚和合并的利器svn merge

    1.svn merge可以将两个对象的diff体现到本地工作目录上. (1)两个对象 这个两个对象可以是同一个svn url的两个revison,也可以是不用的url,比如分支和主干. (2)diff ...

  5. django之使用jquery完成ajax

    使用Ajax 使用视图通过上下文向模板中传递数据,需要先加载完成模板的静态页面,再执行模型代码,生成最张的html,返回给浏览器,这个过程将页面与数据集成到了一起,扩展性差 改进方案:通过ajax的方 ...

  6. jQuery基本API小结(上)--选择器-DOM操作-动画-Ajax

    一.JQuery基础选择器 1.基本选择器(CSS选择器) 2.$()中的()不一定是指定元素,也可能是函数. 3.“*”号选择器,它的功能是获取页面中的全部元素:$(“*”). 由于使用*选择器获取 ...

  7. (转存 作者未知)深入理解HTML协议

    深入理解HTML协议 http协议学 习系列 1. 基础概念篇 1.1 介绍 HTTP是Hyper Text Transfer Protocol(超文本传输协议)的缩写.它的发展是万维网协会(Worl ...

  8. Tmux (转)

    Tmux是一个优秀的终端复用软件,类似GNU Screen,但来自于OpenBSD,采用BSD授权.使用它最直观的好处就是,通过一个终端登录远程主机并运行tmux后,在其中可以开启多个控制台而无需再“ ...

  9. cas-client单点登录客户端拦截请求和忽略/排除不需要拦截的请求URL的问题

    http://blog.csdn.net/eguid_1/article/details/73611781

  10. js对象的几种创建方式和js实现继承的方式[转]

    一.js对象的创建方式 1. 使用Object构造函数来创建一个对象,下面代码创建了一个person对象,并用两种方式打印出了Name的属性值. var person = new Object(); ...