在android App开发过程中,经常会需要一些常驻的服务,这些服务一般由service来完成,那么如何来保证这个service不会自动或者被其他应用程序终止,这就是本文要来讨论的问题。实现service的常驻主要有两方面,一是开机启动,二是运行时不会被系统或者其他软件kill掉。下面分别介绍下这两个方面的解决办法。
一、开机启动
1.获取系统开机广播
<!-- 获取获得系统开机的广播的权限 ,当Android系统完成BOOT阶段之后,就会发出开机广播 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
2.静态注册receiver接收开机广播
<receiver android:name="com.lawlielt.BootReceiver" android:enabled="true">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
3.开机广播中启动service
public class ScreenReceiver extends BroadcastReceiver {
public final static String TAG = "com.lawlielt.ScreenReceiver";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, action);
if(action.equals(TAG)){
Intent service = new Intent(context,ScreenService.class);
context.startService(service);
}
}
}
以上,就完成了开机启动service。如何能有效防止自己的service被别人kill掉呢,最简单的方法,一直启动呗。
二、定时启动service
定时启动service需要用到AlarmManager的setRepeating方法。AlarmManager的广播不能静态注册,所以我们可以在应用打开时,动态注册。例如在application得onCreate方法中注册。主要原理就是注册一个重复系统广播,每间隔一段时间发送一个广播,然后应用程序再捕捉这个广播,打开service。动态注册广播代码如下:
//获取AlarmManager系统服务
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
//包装需要执行Service的Intent
Intent intent = new Intent(this, ScreenReceiver.class);
intent.setAction(ScreenReceiver.TAG);
intent.setPackage(getPackageName());
if (android.os.Build.VERSION.SDK_INT >= 12){
intent.setFlags(32);
}
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,0,intent, PendingIntent.FLAG_UPDATE_CURRENT);
manager.cancel(pendingIntent);
//触发服务的起始时间
long triggerAtTime = SystemClock.elapsedRealtime();
//使用AlarmManger的setRepeating方法设置定期执行的时间间隔(seconds秒)和需要执行的Service
manager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime,3 * 1000, pendingIntent);
之后我们所做的工作和开机启动类似,ScreenReceiver中捕获广播,然后启动service。
在service中,我们还可以在onStartCommand方法中设置flags =START_STICKY;这样对于被kill的service,会保留运行的状态,这样系统稍后会尝试再次启动。
除了上面说的,还有一种方法是保持service放在前台,防止被系统回收,部分参考代码如下:
Notification notif = new Notification();
notif.setLatestEventInfo(BackgroundService.this, "", "", null);
startForeground(0, notif);//service放前台 不会因为low memory等原因被kill 除非service stop or stopForeground 为0失效
以上就是自己遇到此类问题时,所想到的方法,这里列出来,供大家参考下,也给自己留个记录,方便之后查找。
由于自己是半路被拉去做android开发,所以以上描述也许有不严谨的地方,大家多提意见,互相学习,今后,我也会更多地分享我在项目中遇到的问题。