前台服务是被认为是用户已知的正在运行的服务,当系统需要释放内存时不会优先杀掉该进程。前台进程必须发一个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()中发送广播开启自己。这样杀死服务后会立即启动。如下:
当然,从理论上来讲这个方案是可行的,实验一下也可以。但有些情况下,发送的广播在消息队列中排的靠后,就有可能服务还没接收到广播就销毁了(这是我对实验结果的猜想,具体执行步骤暂时还不了解)。所以为了能让这个机制完美运行,可以开启两个服务,相互监听,相互启动。服务A监听B的广播来启动B,服务B监听A的广播来启动A。经过实验,这个方案可行,并且用360杀掉后几秒后服务也还是能自启的。到这里再说一句,如果不是某些功能需要的服务,不建议这么做,会降低用户体验。
第三种情况:
强制关闭就没有办法。这个好像是从包的level去关的,并不走完整的生命周期。所以在服务里加代码是无法被调用的。处理这个情况的唯一方法是屏蔽掉force stop和uninstall按钮,让其不可用。方法自己去找吧。当然有些手机自带的清理功能就是从这个地方清理的,比如华为的清理。所以第三种情况我也没有什么更好的办法了。
最后再说一句,别在这上面太折腾,弄成流氓软件就不好了。我就是讨厌一些软件乱发通知,起服务才转而用iPhone的。不过下一代Android好像可以支持用户选择是否开启软件设置的权限了,倒是可以期待一下。
推荐一篇文章:Diamonds Are Forever. Services Are Not.