Android的startForeground前台Service如何去掉通知显示

关于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正在运行。”,如下图:


查看文档,知道,当SDK<18时,系统不会有该通知,当SDK>=18时,系统有显示该通知。系统显示该通知,应该是为了防止滥用“startForeground”。

那,如果我就是不想显示该通知给用户?怎么搞?



二、去掉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;
	}


再看那个辅助消除通知的Service的代码,非常的简单:

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()

看来这种方法可行~~

如果那位大神有更好的方法,希望能分享分享,小弟先谢过了!!



  • 29
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值