关于Android Service的内容,本人上一篇转载的博客非常详细,有需要的可以到下面链接查看:Android Service 完全解析
本文是根据其中某一个知识点扩展出来的。
我们都知道,Service几乎都是在后台运行的,所以Service的系统优先级还是比较低的,当系统出现内存不足情况时,就有可能回收掉正在后台运行的Service。如果你希望Service可以一直保持运行状态,而不会由于系统内存不足的原因导致被回收,那么就要提高Service的优先级,而提高优先级的方法有多种,其中一种就是考虑使用前台Service。
如何把Service设置为前台Service?很简单,使用startForeground即可。要取消前台,使用stopForeground即可。
不多说,直接上代码,非常的简单,不解释:
public class MyService extends Service { private static final String TAG = "wxx"; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); Log.d(TAG, "MyService: onCreate()"); //定义一个notification Notification notification = new Notification(); Intent notificationIntent = new Intent(this, MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); notification.setLatestEventInfo(this, "My title", "My content", pendingIntent); //把该service创建为前台service startForeground(1, notification); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub Log.d(TAG, "MyService: onStartCommand()"); return super.onStartCommand(intent, flags, startId); } }
有留心的朋友会发现,每当启动该前台Service的时候,手机都会收到一个通知,下拉通知栏,会看到一个通知如“XXService正在运行。”,如下图:
那,如果我就是不想显示该通知给用户?怎么搞?
本人之前因接触过一些通知相关的内容,于是,大胆假设:把2个同进程的Service都用startForeground设置为前台进程,但他们使用相同的Notification ID,那么他们只会产生一个通知,然后把其中一个Service取消前台效果,那么就会把通知关闭,剩下的那个Service就是前台Service了,而且通知栏没有通知。
有了假设,当然就要验证是否可行~~
看代码吧。。。
先看最后要保留的那个Service的代码:
public class MyService extends Service { private static final String TAG = "wxx"; private final int PID = android.os.Process.myPid(); private AssistServiceConnection mConnection; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); Log.d(TAG, "MyService: onCreate()"); setForeground(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub Log.d(TAG, "MyService: onStartCommand()"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); Log.d(TAG, "MyService: onDestroy()"); } public void setForeground() { // sdk < 18 , 直接调用startForeground即可,不会在通知栏创建通知 if (VERSION.SDK_INT < 18) { this.startForeground(PID, getNotification()); return; } if (null == mConnection) { mConnection = new AssistServiceConnection(); } this.bindService(new Intent(this, AssistService.class), mConnection, Service.BIND_AUTO_CREATE); } private class AssistServiceConnection implements ServiceConnection { @Override public void onServiceDisconnected(ComponentName name) { Log.d(TAG, "MyService: onServiceDisconnected"); } @Override public void onServiceConnected(ComponentName name, IBinder binder) { Log.d(TAG, "MyService: onServiceConnected"); // sdk >=18 // 的,会在通知栏显示service正在运行,这里不要让用户感知,所以这里的实现方式是利用2个同进程的service,利用相同的notificationID, // 2个service分别startForeground,然后只在1个service里stopForeground,这样即可去掉通知栏的显示 Service assistService = ((AssistService.LocalBinder) binder) .getService(); MyService.this.startForeground(PID, getNotification()); assistService.startForeground(PID, getNotification()); assistService.stopForeground(true); MyService.this.unbindService(mConnection); mConnection = null; } } private Notification getNotification() { // 定义一个notification Notification notification = new Notification(); Intent notificationIntent = new Intent(this, MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); notification.setLatestEventInfo(this, "My title", "My content", pendingIntent); return notification; }
public class AssistService extends Service { private static final String TAG = "wxx"; public class LocalBinder extends Binder { public AssistService getService() { return AssistService.this; } } @Override public IBinder onBind(Intent intent) { Log.d(TAG, "AssistService: onBind()"); return new LocalBinder(); } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); Log.d(TAG, "AssistService: onDestroy()"); } }代码就这么多,上面大体思路是:一个最后保留的MyService,一个辅助消除通知的AssistService, 利用 MyService去绑定AssistService,在关联函数onServiceConnected()中实现两个Service调用startForeground变为前台服务,注意一定要使用一样的Notification ID,然后AssistService取消前台效果stopForeground从而删除通知。
运行上面的代码,发现通知栏真的没有显示通知,成功了? 还要看看两个Service的生命周期是否正常,从日志Log可以看出,两个服务正常,最后只剩下MyService这个服务,而AssistService会destroy掉:
02-15 17:13:01.791: D/wxx(4659): MyService: onCreate() 02-15 17:13:01.801: D/wxx(4659): MyService: onStartCommand() 02-15 17:13:01.801: D/wxx(4659): AssistService: onBind() 02-15 17:13:01.806: D/wxx(4659): MyService: onServiceConnected 02-15 17:13:01.836: D/wxx(4659): AssistService: onDestroy()
如果那位大神有更好的方法,希望能分享分享,小弟先谢过了!!