Android如何隐藏掉前台服务的通知栏,史上详细的资料!

来源:互联网 发布:淘宝手机店铺收藏地址 编辑:程序博客网 时间:2024/04/29 14:46

有些小伙伴会遇到这样的问题:如果想让一个服务在后台长期的运行下去,而且在系统资源不足的情况下不会被系统kill掉,怎么办?这个时候上网google之后会发现,有个叫“前台服务”的东东,貌似很强大,无论怎样都会常驻系统内存。但是,都会发现,在高版本的Android版本中,前台服务一旦运行,就会默认在通知栏显示运行状态,无法手动去除。

有什么好的办法可以让其运行但又不会显示在通知栏的办法吗?

答案肯定有,在我动手实践后,发现了一个绝对有效的办法(也查阅过之前网友的做法,但是好像有漏洞,我这里说明的更详细,会考虑到各个版本,需要的小伙伴直接copy就可以用了),废话不多说,盖茨,上代码!


工程目录:



这里,前台服务名称为ForegroundService,协助我们去掉通知栏的Service为HelpService,入口为MainActivity

package com.example.foregroundservice;import android.os.Bundle;import android.app.Activity;import android.content.Intent;import android.view.View;public class MainActivity extends Activity {public static final String TAG = "MainActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void startForeground(View view) {Intent intent = new Intent(this, ForegroundService.class);startService(intent);}}


ForegroundService部分:

package com.example.foregroundservice;import android.app.Notification;import android.app.PendingIntent;import android.app.Service;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.os.IBinder;import android.os.Build.VERSION;import android.util.Log;/** * 需要开启的前台服务 *  * @author zhouyang */public class ForegroundService extends Service {public static final String TAG = "ForegroundService";private final int PID = android.os.Process.myPid();private ServiceConnection mConnection;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();Log.e(TAG, "ForegroundService is running");startForeground(PID, getNotification());// 正常启动前台服务// setForeground();// 启动前台服务,并隐藏前台服务的通知}public void setForeground() {// sdk < 18 , 直接调用startForeground即可,不会在通知栏创建通知if (VERSION.SDK_INT < 18) {this.startForeground(PID, getNotification());return;}if (null == mConnection) {mConnection = new CoverServiceConnection();}this.bindService(new Intent(this, HelpService.class), mConnection,Service.BIND_AUTO_CREATE);}private Notification getNotification() {// 定义一个notificationNotification notification = new Notification();Intent notificationIntent = new Intent(this, ForegroundService.class);PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,notificationIntent, 0);// notification.setLatestEventInfo(this, "Foreground", "正在运行哦",// pendingIntent);Notification.Builder builder = new Notification.Builder(this).setAutoCancel(true).setContentTitle("ForegroundService").setContentText("正在运行哦").setContentIntent(pendingIntent).setSmallIcon(R.drawable.ic_launcher).setWhen(System.currentTimeMillis()).setOngoing(true);notification = builder.getNotification();return notification;}private class CoverServiceConnection implements ServiceConnection {@Overridepublic void onServiceDisconnected(ComponentName name) {Log.d(TAG, "ForegroundService: onServiceDisconnected");}@Overridepublic void onServiceConnected(ComponentName name, IBinder binder) {Log.d(TAG, "ForegroundService: onServiceConnected");// sdk >= 18 的,会在通知栏显示service正在运行,这里不要让用户感知,所以这里的实现方式是利用2个同进程的service,利用相同的notificationID,// 2个service分别startForeground,然后只在1个service里stopForeground,这样即可去掉通知栏的显示Service helpService = ((HelpService.LocalBinder) binder).getService();ForegroundService.this.startForeground(PID, getNotification());helpService.startForeground(PID, getNotification());helpService.stopForeground(true);ForegroundService.this.unbindService(mConnection);mConnection = null;}}@Overridepublic void onDestroy() {super.onDestroy();stopForeground(true);}}


HelpService部分:

package com.example.foregroundservice;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;import android.util.Log;/** * 协助去掉通知的服务 *  * @author zhouyang */public class HelpService extends Service {private static final String TAG = "HelpService";public class LocalBinder extends Binder {public HelpService getService() {return HelpService.this;}}@Overridepublic IBinder onBind(Intent intent) {Log.d(TAG, "HelpService: onBind()");return new LocalBinder();}@Overridepublic void onDestroy() {super.onDestroy();Log.d(TAG, "HelpService: onDestroy()");}}

现在正常卡开启前台服务:




我们来看效果:


现在改为setForeground()启动:

@Overridepublic void onCreate() {super.onCreate();Log.e(TAG, "ForegroundService is running");// startForeground(PID, getNotification());// 正常启动前台服务setForeground();// 启动前台服务,并隐藏前台服务的通知}

看效果:


是不是隐藏掉了?没看错,确实隐藏了,具体原因代码里有解释,这里我就不详细说明啦,我们再来看打印日志:


确实,前台服务已经在运行了,证明了我们的猜想。


另外,在使用Notifacation的时候,有几点需注意:


低于API Level 11版本,也就是Android 2.3.3以下的系统中,setLatestEventInfo()函数是唯一的实现方法。前面的有关属性设置这里就不再提了,网上资料很多。

Intent  intent = new Intent(this,MainActivity);  PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);  notification.setLatestEventInfo(context, title, message, pendingIntent);          manager.notify(id, notification);  


高于API Level 11,低于API Level 16 (Android 4.1.2)版本的系统中,可使用Notification.Builder来构造函数。但要使用getNotification()来使notification实现。此时,前面版本在notification中设置的Flags,icon等属性都已经无效,要在builder里面设置。

Notification.Builder builder = new Notification.Builder(context)              .setAutoCancel(true)              .setContentTitle("title")              .setContentText("describe")              .setContentIntent(pendingIntent)              .setSmallIcon(R.drawable.ic_launcher)              .setWhen(System.currentTimeMillis())              .setOngoing(true);  notification=builder.getNotification();  

高于API Level 16的版本,就可以用Builder和build()函数来配套的方便使用notification了。

Notification notification = new Notification.Builder(context)             .setAutoCancel(true)             .setContentTitle("title")             .setContentText("describe")             .setContentIntent(pendingIntent)             .setSmallIcon(R.drawable.ic_launcher)             .setWhen(System.currentTimeMillis())             .build();   

所以,使用的时候需要注意版本问题,有些API已经过时了,就不要使用啦!

本次就到这里,希望能对你有所帮助~!微笑

1 0
原创粉丝点击