Android冷知识(2)常驻服务

这篇是接上一篇的,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在下一篇中就会提供下载。/呲牙

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值