这篇是接上一篇的,demo会在之后一篇中给出,不然代码量太少。
关于android中的后台常驻进程只能说是理想化的,因为总会有不合理的地方的,这里只给出一种实现思路,其他的大同小异,需要你自己去衡量
① 修改Service中startCommand方法的返回值,这个是系统层面的告诉系统,我想要这个servcie在销毁之后自动去重生。这里我们设置为START_REDELIVER_INTENT
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
。。。
return START_REDELIVER_INTENT;
}
*Android开发的过程中,每次调用startService(Intent)的时候,都会调用该Service对象的onStartCommand(Intent,int,int)方法,然后在onStartCommand方法中做一些处理。然后我们注意到这个函数有一个int的返回值
START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。*
② 使用AlarmManager这个系统的时钟类,去重复唤醒这个Service来保证这个Service是“活着”的 ,其实这样做有点强制的意味,还有其他方案(比如两个进程互相调用)
完整的代码
public class MyService extends Service{
private final static String TAG = "MyService";
AlarmManager mAlarmManager = null;
PendingIntent mPendingIntent = null;
@Override
public void onCreate() {
Log.e(TAG, "onCreate"+System.currentTimeMillis());
Intent intent = new Intent(getApplicationContext(), MyService.class);
mAlarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
mPendingIntent = PendingIntent.getService(this, 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK);
long now = System.currentTimeMillis();
/*
* AlarmManager.ELAPSED_REALTIME表示闹钟在手机睡眠状态下不可用,该状态下闹钟使用相对时间
* (相对于系统启动开始),状态值为3;AlarmManager.ELAPSED_REALTIME_WAKEUP表示闹钟在睡
* 眠状态下会唤醒系统并执行提示功能,该状态下闹钟也使用相对时间,状态值为2;
* AlarmManager.RTC 表示闹钟在睡眠状态下不可用,该状态下闹钟使用绝对时间,即当前系统时间,状态值为1;
* AlarmManager.RTC_WAKEUP表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟使用绝对时间,
* 状态值为0;
* AlarmManager.POWER_OFF_WAKEUP表示闹钟在手机关机状态下也能正常进行提示功能,
* 所以是5个状态中用的最多的状态之一,该状态下闹钟也是用绝对时间,状态值为4;
* 不过本状态好像受SDK版本影响,某些版本并不支持;*/
mAlarmManager.setInexactRepeating(AlarmManager.RTC, now, 6000, mPendingIntent);//6秒启动一次
super.onCreate();
}
// @Override
// public int onStartCommand(Intent intent, int flags, int startId) {
// Log.e(TAG, "onStartCommand"+flags+":"+startId+System.currentTimeMillis()+isServiceRunning(this.getClass().getName()));
// return START_STICKY;//super.onStartCommand(intent, flags, startId);
// }
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String name = intent.getStringExtra("name");
Notification notification = new Notification(R.drawable.ic_launcher, "test", System.currentTimeMillis());
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, "title", "content", pendingIntent);
startForeground(1, notification);
Log.e(TAG, "onStartCommand"+flags+":"+name+System.currentTimeMillis()+isServiceRunning(this.getClass().getName()));
return START_REDELIVER_INTENT;
}
@Override
public IBinder onBind(Intent arg0) {
Log.e(TAG, "onBind"+System.currentTimeMillis());
return null;
}
@Override
public void onDestroy() {
Log.e(TAG, "onDestroy"+System.currentTimeMillis());
super.onDestroy();
}
public boolean isServiceRunning(String strServiceName)
{
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE))
{
String allServiceName = service.service.getClassName();
if (allServiceName.equals(strServiceName))
{
return true;
}
}
return false;
}
}
当然,还要声明service,在androidmainfest中
<!-- 注册一个永不休眠的服务(理想的)
当Service需要运行在单独的进程中,AndroidManifest.xml声明时需要通过
android:process指明此进程名称,当此Service需要对其他App开放时,
android:exported属性值需要设置为true(当然,在有intent-filter时默认值就是true)。 -->
<service android:name="com.example.receivertest.MyService"
android:enabled="true"
android:process=":remote">
</service>
有不足及错误之处请多多指正,我会及时更新并修改错误的,demo在下一篇中就会提供下载。/呲牙