关于Android Service的内容,本人上一篇转载的博客非常详细,有需要的可以到下面链接查看:Android Service 完全解析
本文是根据其中某一个知识点扩展出来的。
一、正常的前台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正在运行。”,如下图:
那,如果我就是不想显示该通知给用户?怎么搞?
二、去掉startForeground的通知
本人之前因接触过一些通知相关的内容,于是,大胆假设:把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()
看来这种方法可行~~
如果那位大神有更好的方法,希望能分享分享,小弟先谢过了!!