Android(安卓)6.0 监听系统通知(Notification)
------------------
由于近期商显项目需求,需要在侧边栏菜单中增加通知列表,就类似systemui中的通知一样。先上效果图
于是就去百度上查找如何监听通知消息的方法,大概是需要这么几个步骤
1 写一个服务MyNotificationListenService 继承 NotificationListenerService 并且重写三个方法 代码如下
package com.protruly.floatwindowlib.service;import android.service.notification.NotificationListenerService;import android.service.notification.StatusBarNotification;import android.util.Log;public class MyNotificationListenerService extends NotificationListenerService { @Override public void onNotificationPosted(StatusBarNotification sbn) { super.onNotificationPosted(sbn); Log.i("gyx","onNotificationPosted"); } @Override public void onListenerConnected() { Log.i("gyx","onListenerConnected"); super.onListenerConnected(); } @Override public void onNotificationRemoved(StatusBarNotification sbn) { super.onNotificationRemoved(sbn); Log.i("gyx","onNotificationRemoved"); } }
Mainfest.xml 注册服务
启动服务
Intent intent =new Intent(this, MyNotificationListenerService.class);startService(intent);
到这里其实还没有结束,因为应用需要监听通知消息,需要去设置,安全,通知里面设置允许通知消息,但是由于我是商显项目,并没有这一项设置,所以需要手动设置去设置打开监听通知消息的权限
private final HashSet mEnabledServices = new HashSet();mConfig = getNotificationListenerConfig();mEnabledServices.add(new ComponentName(this, MyNotificationListenerService.class));saveEnabledServices(); private void saveEnabledServices() { StringBuilder sb = null; for (ComponentName cn : mEnabledServices) { if (sb == null) { sb = new StringBuilder(); } else { sb.append(':'); } sb.append(cn.flattenToString()); } Settings.Secure.putString(getContentResolver(), mConfig.setting, sb != null ? sb.toString() : ""); } private static Config getNotificationListenerConfig() { final Config c = new Config(); c.tag = "gyx"; c.setting = "enabled_notification_listeners"; c.intentAction = NotificationListenerService.SERVICE_INTERFACE; c.permission = android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE; c.noun = "notification listener"; return c; } protected static class Config { String tag; String setting; String intentAction; String permission; String noun; }
这部分代码是去原生的setting上挪过来的代码,怎么判断是否设置成功呢?
private static boolean isNotificationListenerServiceEnabled(Context context) { Set packageNames = NotificationManagerCompat.getEnabledListenerPackages(context); if (packageNames.contains(context.getPackageName())) { return true; } return false; }
通过这个方法可以判断是否开启通知权限,以上步骤都做完了之后通过命令串口命令 dumpsys notification查看结果
很明显已经设置成功,但是很奇怪的是接收通知的回调方法并没有触发,前前后后花了大概一天的时间也没有找到原因,无奈之下只好去SystemUI查看它是怎么做的。
首先创建一个NotificationListenerService 对象,重写NotificationListenerService 几个方法
private final NotificationListenerService mNotificationListener = new NotificationListenerService() { @Override public void onListenerConnected() { if (DEBUG) Log.d(TAG, "onListenerConnected"); final StatusBarNotification[] notifications = getActiveNotifications(); final RankingMap currentRanking = getCurrentRanking(); mHandler.post(new Runnable() { @Override public void run() { for (StatusBarNotification sbn : notifications) { addNotification(sbn, currentRanking, null /* oldEntry */); } } }); } @Override public void onNotificationPosted(final StatusBarNotification sbn, final RankingMap rankingMap) { if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn); if (sbn != null) { mHandler.post(new Runnable() { @Override public void run() { String key = sbn.getKey(); boolean isUpdate = mNotificationData.get(key) != null; // In case we don't allow child notifications, we ignore children of // notifications that have a summary, since we're not going to show them // anyway. This is true also when the summary is canceled, // because children are automatically canceled by NoMan in that case. if (!ENABLE_CHILD_NOTIFICATIONS && mGroupManager.isChildInGroupWithSummary(sbn)) { if (DEBUG) { Log.d(TAG, "Ignoring group child due to existing summary: " + sbn); } // Remove existing notification to avoid stale data. if (isUpdate) { removeNotification(key, rankingMap); } else { mNotificationData.updateRanking(rankingMap); } return; } Bundle extras =sbn.getNotification().extras; if(extras==null){ // Log.i("gyx","extras==null"); }else{ //Log.i("gyx","extras!=null"); String notificationText = extras.getString(Notification.EXTRA_TEXT); if(notificationText==null){ //Log.i("gyx","notificationText==null"); return; }else{ // Log.i("gyx","notificationText="+notificationText); } } if (isUpdate) { // Log.i("gyx","isUpdate"); updateNotification(sbn, rankingMap); } else { // Log.i("gyx","not Update"); addNotification(sbn, rankingMap, null /* oldEntry */); } } }); } } @Override public void onNotificationRemoved(StatusBarNotification sbn, final RankingMap rankingMap) { if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn); if (sbn != null) { final String key = sbn.getKey(); mHandler.post(new Runnable() { @Override public void run() { removeNotification(key, rankingMap); } }); } } @Override public void onNotificationRankingUpdate(final RankingMap rankingMap) { if (DEBUG) Log.d(TAG, "onRankingUpdate"); if (rankingMap != null) { mHandler.post(new Runnable() { @Override public void run() { updateNotificationRanking(rankingMap); } }); } } };
然后把这个实例通过系统API registerAsSystemService 注册成系统服务
try { mNotificationListener.registerAsSystemService(mContext, new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),UserHandle.USER_ALL); } catch (RemoteException e) { Log.e(TAG, "Unable to register notification listener", e); }
就这样实现了监听系统通知消息的方法,既然SystemUI可以这样做,那么我也尝试这种办法,创建NotificationListenerService 实例,通过反射拿到registerAsSystemService 方法,并且注册成系统服务,
try { Class clazz = Class.forName("android.service.notification.NotificationListenerService"); Method registerAsSystemService = clazz.getDeclaredMethod("registerAsSystemService", Context.class, ComponentName.class, int.class); registerAsSystemService.invoke(mNotificationListener,this,new ComponentName(getPackageName(), getClass().getCanonicalName()),-1); } catch (Exception e) { e.printStackTrace(); Log.i("gyx","e.printStackTrace()="+e.getMessage()); } NotificationListenerService mNotificationListener = new NotificationListenerService(){ @Override public void onNotificationPosted(StatusBarNotification sbn) { super.onNotificationPosted(sbn); Log.i("gyx","onNotificationPosted"); } @Override public void onNotificationRemoved(StatusBarNotification sbn) { super.onNotificationRemoved(sbn); Log.i("gyx","onNotificationRemoved"); } };
代码很简单,看一下打印
注册成功
以上就是监听系统通知的方法,目前还是不清楚第一个方法为什么没有作用,有兴趣的小伙伴可以研究一下,评论回复。感谢大家的支持。看完别忘了点赞哟。
更多相关文章
- Android反挂钩技术-Java层
- android 隔几秒再执行
- Handler部分原理
- EditText 的setKeyListener()方法的用法是输入某些特殊的字符
- [置顶] Canvas开篇之drawBitmap方法讲解
- android实战项目五做一个倒计时的button
- Android开发本地及网络Mp3音乐播放器(二十)歌曲下载完成后通知主
- 据说程序员是最爱学习的群体,IT男都知道,这个行业日新月异,必须不断
- android Studio与数据库SQLserver连接实现登录