[Android] Service服务详解以及如何使service服务不被杀死 (4)

  前台服务是被认为是用户已知的正在运行的服务,当系统需要释放内存时不会优先杀掉该进程。前台进程必须发一个notification在状态栏中显示,直到进程被杀死。因为前台服务会一直消耗一部分资源,但不像一般服务那样会在需要的时候被杀掉,所以为了能节约资源,保护电池寿命,一定要在建前台服务的时候发notification,提示用户。当然,系统提供的方法就是必须有notification参数的,所以不要想着怎么把notification隐藏掉。

@Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub Intent notificationIntent = new Intent(this, MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); Notification noti = new Notification.Builder(this) .setContentTitle("Title") .setContentText("Message") .setSmallIcon(R.drawable.ic_launcher) .setContentIntent(pendingIntent) .build(); startForeground(12346, noti); return Service.START_STICKY; }

startForeground()方法就是将服务设为前台服务。参数12346就是这个通知唯一的id,只要不为0即可。

服务的生命周期

生命周期图

启动的服务:
startService()->onCreate()->onStartCommand()->running->stopService()/stopSelf()->onDestroy()->stopped
其中,服务未运行时会调用一次onCreate(),运行时不调用。

绑定的服务:
bindService()->onCreate()->onBind()->running->onUnbind()->onDestroy()->stopped

服务起始于onCreate(),终止于onDestory()
服务的开关过程,只有onStartCommand()可多次调用,其他在一个生命周期只调用一次。

这两个过程并不完全独立,也可以绑定一个由startService()启动过的服务

关于怎样让服务不被杀死

  这个倒是有点流氓软件的意思,但有些特定情况还是需要服务能保持开启不被杀死,当然这样做我还是在程序里添加了关闭服务的按钮,也就是开启了就杀不死,除非在软件里关闭。

服务不被杀死分3种来讨论
1.系统根据资源分配情况杀死服务
2.用户通过settings->Apps->Running->Stop方式杀死服务
3.用户通过settings->Apps->Downloaded->Force Stop方式杀死服务

第一种情况:
  用户不干预,完全靠系统来控制,办法有很多。比如onStartCommand()方法的返回值设为START_STICKY,服务就会在资源紧张的时候被杀掉,然后在资源足够的时候再恢复。当然也可设置为前台服务,使其有高的优先级,在资源紧张的时候也不会被杀掉。

第二种情况:
  用户干预,主动杀掉运行中的服务。这个过程杀死服务会通过服务的生命周期,也就是会调用onDestory()方法,这时候一个方案就是在onDestory()中发送广播开启自己。这样杀死服务后会立即启动。如下:

@Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); mBR = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub Intent a = new Intent(ServiceA.this, ServiceA.class); startService(a); } }; mIF = new IntentFilter(); mIF.addAction("listener"); registerReceiver(mBR, mIF); } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); Intent intent = new Intent(); intent.setAction("listener"); sendBroadcast(intent); unregisterReceiver(mBR); }

  当然,从理论上来讲这个方案是可行的,实验一下也可以。但有些情况下,发送的广播在消息队列中排的靠后,就有可能服务还没接收到广播就销毁了(这是我对实验结果的猜想,具体执行步骤暂时还不了解)。所以为了能让这个机制完美运行,可以开启两个服务,相互监听,相互启动。服务A监听B的广播来启动B,服务B监听A的广播来启动A。经过实验,这个方案可行,并且用360杀掉后几秒后服务也还是能自启的。到这里再说一句,如果不是某些功能需要的服务,不建议这么做,会降低用户体验。

第三种情况:
  强制关闭就没有办法。这个好像是从包的level去关的,并不走完整的生命周期。所以在服务里加代码是无法被调用的。处理这个情况的唯一方法是屏蔽掉force stop和uninstall按钮,让其不可用。方法自己去找吧。当然有些手机自带的清理功能就是从这个地方清理的,比如华为的清理。所以第三种情况我也没有什么更好的办法了。

  最后再说一句,别在这上面太折腾,弄成流氓软件就不好了。我就是讨厌一些软件乱发通知,起服务才转而用iPhone的。不过下一代Android好像可以支持用户选择是否开启软件设置的权限了,倒是可以期待一下。
推荐一篇文章:Diamonds Are Forever. Services Are Not.

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zysjwx.html