一般为了保证后台进程不被系统干掉,人为的或者是系统因为内存不足的原因,我们希望自己应用的进程一直存在或者不被轻易的杀死,一般的套路会包含以下几点:
(1)提升service进程优先级
在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = “1000”这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同时实用于广播
<service
android:name="com.dbjtech.acbxt.waiqin.UploadService"
android:enabled="true" >
<intent-filter android:priority="1000" >
<action android:name="com.test.service" />
</intent-filter>
</service>
这个办法对普通应用而言,只是降低了应用被杀死的概率,但是如果真的被系统回收了,还是无法让应用自动重新启动!
(2)提升service优先级
Android中的进程是托管的,当系统进程空间紧张的时候,会依照优先级自动进行进程的回收。Android将进程分为6个等级,它们按优先级顺序由高到低依次是:
1.前台进程( FOREGROUND_APP)
A. 拥有用户正在交互的 Activity( onResume()状态)
B. 正在与bound绑定服务交互的 Activity
C. 正在“前台”运行的 Service(startForeground()被调用)
D. 生命周期函数正在被执行的 Service(onCreate()、onStart() 或 onDestroy())
E. 正执行 onReceive() 方法的 BroadcastReceiver
(该进程优先级别最高,杀死前台进程需要用户的响应。)
2.可视进程(VISIBLE_APP )
该进程并不是在最前端,并没有得到焦点,但是我们却能看到它们。
A. 拥有不在前台、但仍对用户可见的 Activity(例如弹出一个对话框的Activity)
B. 绑定到可见进程(或前台进程)中的Activity 的 Service
3.服务进程(Service process)
正在运行的通过 startService() 启动的,且不属于上述两个更高进程状态的Service
4.后台进程(Background process)
不可见状态的Activity进程
5.空进程(Empty process)
没有运行任何应用组件的进程,保留这个进程主要是为了缓存的需要,待下次相关组件运行时直接从内存中获取数据,缩短对数据获取的时间
当service运行在低内存的环境时,将会kill掉一些存在的进程。因此进程的优先级将会很重要,可以使用startForeground API将service放到前台状态。这样在低内存时被kill的几率更低,但是如果在极度极度低内存的压力下,该service还是会被kill掉。
在onStartCommand方法内
public class MyService extends Service {
public static final String TAG = "MyService";
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.w(TAG, "in onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.w(TAG, "in onStartCommand");
Log.w(TAG, "MyService:" + this);
String name = intent.getStringExtra("name");
Log.w(TAG, "name:" + name);
Notification notification = new Notification(R.drawable.ic_launcher, "test", System.currentTimeMillis());
Intent notificationIntent = new Intent(this, DActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntesnt, 0);
notification.setLatestEventInfo(this, "title", "content", pendingIntent);
startForeground(1, notification);
return START_REDELIVER_INTENT;
}
@Override
public void onDestroy() {
super.onDestroy();
stopForeground(true);
Log.w(TAG, "in onDestroy");
}
}
(3)在Service中的onDestroy方法里发送广播重启service
<receiver android:name="com.test.BootReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
<action android:name="com.define.destory>
</receiver>
(4)设置 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"
android:theme="@style/AppTheme" >
</application>
属性设置后,优先级提高不少,或许是相当于系统级的进程,但是还是无法保证存活
(5)本地service与远端service绑定,双进程监听
假设我们的APP中开启了两个Service,分别是LocalService和RemoteService,那么:
如果LocalService守护RemoteService,则RemoteService挂掉的同时,,反之亦然,也就是说无论谁被杀掉,对方就把它拉起来。
public class LocalService extends Service {
MyBinder myBinder;
private PendingIntent pintent;
MyServiceConnection myServiceConnection;
@Override
public void onCreate() {
super.onCreate();
if (myBinder == null) {
myBinder = new MyBinder();
}
myServiceConnection = new MyServiceConnection();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
this.bindService(new Intent(this, RemoteCastielService.class), myServiceConnection, Context.BIND_IMPORTANT);
Notification notification = new Notification(R.drawable.ic_launcher, "本地服务启动中", System.currentTimeMillis());
pintent = PendingIntent.getService(this, 0, intent, 0);
notification.setLatestEventInfo(this, "本地服务", "本地服务不会被杀死!", pintent);
// 设置service为前台进程
startForeground(startId, notification);
return START_STICKY;
}
class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
Log.i("Local", "远程服务连接成功");
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
// 连接出现了异常断开了,RemoteService被杀掉了
Toast.makeText(LocalCastielService.this, "远程服务Remote被干掉", Toast.LENGTH_LONG).show();
// 启动RemoteService
LocalServiceA.this.startService(new Intent(LocalServiceA.this, RemotelService.class));
LocalServiceA.this.bindService(new Intent(LocalServiceA.this, RemoteService.class),
myServiceConnection, Context.BIND_IMPORTANT);
}
}
class MyBinder extends AIDLInterface.Stub {
@Override
public String message() throws RemoteException {
return "message"
}
}
@Override
public IBinder onBind(Intent arg0) {
return myBinder;
}
}
AIDL自定义文件
package com.test.aidl;
interface AIDLInterface.{
String message();
}
RemoteService
public class RemoteService extends Service {
MyBinder myBinder;
private PendingIntent pintent;
MyServiceConnection myServiceConnection;
@Override
public void onCreate() {
super.onCreate();
if (myBinder == null) {
myBinder = new MyBinder();
}
myServiceConnection = new MyServiceConnection();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
this.bindService(new Intent(this,LocalService.class), myServiceConnection, Context.BIND_IMPORTANT);
Notification notification = new Notification(R.drawable.ic_launcher,
"远程服务启动中",
System.currentTimeMillis());
pintent=PendingIntent.getService(this, 0, intent, 0);
notification.setLatestEventInfo(this, "远程服务",
"远程服务不被杀死", pintent);
//设置service为前台进程
startForeground(startId, notification);
return START_STICKY;
}
class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
Log.i("RemoteService", "链接本地服务成功");
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
// 连接出现了异常断开了,LocalService被杀死了
Toast.makeText(RemoteService.this, "本地服务被干掉", Toast.LENGTH_LONG).show();
RemoteService.this.startService(new Intent(RemoteService.this,LocalService.class));
RemoteService.this.bindService(new Intent(RemoteService.this,LocalService.class), myServiceConnection, Context.BIND_IMPORTANT);
}
}
class MyBinder extends AIDLInterface.Stub {
@Override
public String message() throws RemoteException {
return "双进程守护";
}
}
@Override
public IBinder onBind(Intent arg0) {
return myBinder;
}
}
应用程序启动的时候开启服务
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 启动本地服务和远程服务
startService(new Intent(this, LocalService.class));
startService(new Intent(this, RemoteService.class));
}
配置文件
<service
android:name=".services.LocalService"
android:process=":local" />
<service
android:name=".services.RemoteService"
android:process=":remote" />