------------------
由于近期商显项目需求,需要在侧边栏菜单中增加通知列表,就类似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");
}
};
以上就是监听系统通知的方法,目前还是不清楚第一个方法为什么没有作用,有兴趣的小伙伴可以研究一下,评论回复。感谢大家的支持。看完别忘了点赞哟。