前言
我们可能需要监听通知栏,来获取系统通知,然后去得到通知的相关信息,或者我们可能需要知道某一个通知是否处于活动状态还是已经被用户处理了!
概况
在Android4.4之前,我们更多的是通过反射来获取通知的相关信息!NotificationListenerService是在Android4.3中添加的,当系统收到新的通知或者通知被删除时,会触发NotificationListenerService的回调方法。而且在4.4中加入了Notification.extras
字段,可以用来获取通知的具体信息!
NotificationListenerService的使用
①新建NotificationMonitor继承NotificationListenerService,然后重写下边两个方法
public class NotificationMonitor extends NotificationListenerService {
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
//有新通知添加的时候调用
Log.e("onNotificationPosted","posted");
}
@Override
public void onNotificationRemoved(StatusBarNotification sbn) {
//通知被移除的时候调用
Log.e("onNotificationRemoved","posted");
}
}
②在AndroidManifest.xml中注册Service并声明相关权限
<service android:name=".NotificationMonitor" android:label="给这个服务一个名字" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
③然后开启通知监听权限
将程序安装到手机上之后,然后在设置->安全->通知读取权限
,找到你上边服务对应的名字,把这个勾选上!
需要注意的是:如果你的手机上面没有安装需要NotificationListenerService这个权限的应用的时候,设置中是不会出现通知读取权限这一选项的!
这样就能监听到手机中的通知了,当新通知弹出或者通知被移除都能被上面两个方法监听到!
如何知道权限是否开启
上边说监听通知必须开启获取通知权限,这里要说明的一点就是,如果你的应用是第一次安装,那么直到你把获取通知权限勾选上的那一秒才开始能够监听通知!
获取通知权限是:enabled_notification_listeners
之前我们来看这一权限是否开启,可能是这样:
private static final String ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners";
private boolean isNotificationListenerEnabled() {
String pkgName = getPackageName();
final String flat = Settings.Secure.getString(getContentResolver(),
ENABLED_NOTIFICATION_LISTENERS);
if (!TextUtils.isEmpty(flat)) {
final String[] names = flat.split(":");
for (int i = 0; i < names.length; i++) {
final ComponentName cn = ComponentName.unflattenFromString(names[i]);
if (cn != null) {
if (TextUtils.equals(pkgName, cn.getPackageName())) {
return true;
}
}
}
}
return false;
}
现在,我们可以使用v4包中的NotificationManagerCompat
来获取,非常简单:
public boolean isNotificationListenerEnabled(Context context) {
Set<String> packageNames = NotificationManagerCompat.getEnabledListenerPackages(this);
if (packageNames.contains(context.getPackageName())) {
return true;
}
return false;
}
那么如果检测到没有开启这一权限,能否在代码中跳转到设置界面呢?答案是可以:
开启获取通知权限的设置对应的action是:
android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS
private static final String ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS";
private void openNotificationAccess() {
startActivity(new Intent(ACTION_NOTIFICATION_LISTENER_SETTINGS));
}
之后我们就能获取通知的相关信息了,比如label,icon等具体的内容:
可以参考这篇文章,里边有4.4使用Notification.extras
,和4.4之前通过反射获取的内容!
NotificationListenerService的那些事儿
可能出现的问题
有的时候,我们也使用上边配置了,但是会出现监听没有反应的情况!可能就是我们这一个服务被干掉了!
搜到这么一个解决办法,能有些帮助,它的方法是写一个常驻服务,来确保我们这个监听服务一直保持运行:
Cannot get the NotificationListenerService class to work
获取通知状态
获取通知状态可以通过调用:getActiveNotifications()
这个方法来实现,它返回一个StatusBarNotification[]
的数组,我们查看源码可以发现,不仅NotificationListenerService中可以调用这个方法!其实之前的NotificationManagerService中也有这个方法,只不过这个方法外部无法调用!
其实追究到底,都是调用的INotificationManager#getActiveNotifications()
中的方法,看名字可以看出是一个AIDL的服务接口,具体的实现都交给底层了!源码中涉及最多的IPC通讯!
具体细节上面的,可以参考这篇文章:
Android 4.4 KitKat NotificationManagerService使用详解与原理分析(一)__使用详解
这是一个系列的文章,能够帮助我们更好的了解Notification机制!
另外,在Android 6.0之后,也就是api23之后,官方在NotificationManager
中添加了这一方法getActiveNotifications()
,我们可以使用NotificationManager
直接调用该方法来获取通知状态!查看其源码发现也是调用的底层的代码,跟上边是一样的!
当然,这样就更加方便了!