------------------
由於近期商顯項目需求,需要在側邊欄菜單中增加通知列表,就類似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 註冊服務
<service android:name=".service.MyNotificationListenerService"
android:label="notification listener"
android:persistent="true"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action
android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
啓動服務
Intent intent =new Intent(this, MyNotificationListenerService.class);
startService(intent);
到這裏其實還沒有結束,因爲應用需要監聽通知消息,需要去設置,安全,通知裏面設置允許通知消息,但是由於我是商顯項目,並沒有這一項設置,所以需要手動設置去設置打開監聽通知消息的權限
private final HashSet<ComponentName> mEnabledServices = new HashSet<ComponentName>();
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<String> 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");
}
};
代碼很簡單,看一下打印
註冊成功
以上就是監聽系統通知的方法,目前還是不清楚第一個方法爲什麼沒有作用,有興趣的小夥伴可以研究一下,評論回覆。感謝大家的支持。看完別忘了點贊喲。