Android 通知设置
寫在前面,8.0以后的通知寫法如下
Android 8.0中各種通知寫法匯總
最終通過?NotificationManager.notify()發送通知。
?
1、通知發送流程
相關類
frameworks/base/core/java/android/app/NotificationManager.java
frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
frameworks/base/core/java/android/service/notification/NotificationListenerService.java
packages/apps/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
packages/apps/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
NotificationManager notify() --> notifyAsUser??-->
NotificationManagerService?enqueueNotificationWithTag -->?enqueueNotificationInternal?-->
?enqueueNotificationInternal方法內部做一些檢查,判斷通知是否合法等。
NotificationManagerService.EnqueueNotificationRunnable.run()? -->
NotificationManagerService.PostNotificationRunnable.run()???-->
NotificationManagerService.NotificationListeners.notifyPostedLocked()???-->
NotificationManagerService.NotificationListeners.notifyPosted()???-->
INotificationListener.onNotificationPosted()??-->
/** @hide */protected class NotificationListenerWrapper extends INotificationListener.Stub {@Overridepublic void onNotificationPosted(IStatusBarNotificationHolder sbnHolder,NotificationRankingUpdate update) {StatusBarNotification sbn;try {sbn = sbnHolder.get();} catch (RemoteException e) {Log.w(TAG, "onNotificationPosted: Error receiving StatusBarNotification", e);return;}try {// convert icon metadata to legacy format for older clientscreateLegacyIconExtras(sbn.getNotification());maybePopulateRemoteViews(sbn.getNotification());maybePopulatePeople(sbn.getNotification());} catch (IllegalArgumentException e) {// warn and drop corrupt notificationLog.w(TAG, "onNotificationPosted: can't rebuild notification from " +sbn.getPackageName());sbn = null;}// protect subclass from concurrent modifications of (@link mNotificationKeys}.synchronized (mLock) {applyUpdateLocked(update);if (sbn != null) {SomeArgs args = SomeArgs.obtain();args.arg1 = sbn;args.arg2 = mRankingMap;mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_POSTED,args).sendToTarget();} else {// still pass along the ranking map, it may contain other informationmHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_RANKING_UPDATE,mRankingMap).sendToTarget();}}}... ...}... ...case MSG_ON_NOTIFICATION_POSTED: {SomeArgs args = (SomeArgs) msg.obj;StatusBarNotification sbn = (StatusBarNotification) args.arg1;RankingMap rankingMap = (RankingMap) args.arg2;args.recycle();onNotificationPosted(sbn, rankingMap);} break;通過 MyHandler.MSG_ON_NOTIFICATION_POSTED,調用 NotificationListenerService.onNotificationPosted ()。
NotificationListener 繼承 NotificationListenerWithPlugins 繼承 NotificationListenerService。最終實現在NotificationListener中,
@Overridepublic void onNotificationPosted(final StatusBarNotification sbn,final RankingMap rankingMap) {if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);if (sbn != null && !onPluginNotificationPosted(sbn, rankingMap)) {Dependency.get(Dependency.MAIN_HANDLER).post(() -> {processForRemoteInput(sbn.getNotification(), mContext);String key = sbn.getKey();boolean isUpdate =mEntryManager.getNotificationData().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) {mEntryManager.removeNotification(key, rankingMap, UNDEFINED_DISMISS_REASON);} else {mEntryManager.getNotificationData().updateRanking(rankingMap);}return;}if (isUpdate) {mEntryManager.updateNotification(sbn, rankingMap);} else {mEntryManager.addNotification(sbn, rankingMap);}});}}最后由 NotificationEntryManager.addNotification() --> NotificationEntryManager.addNotificationInternal() 完成通知創建顯示。
?
2、設置APP通知開啟/關閉接口?
private void disableAppNotification(String packagename) {INotificationManager mNotificationManager = INotificationManager.Stub.asInterface(ServiceManager.getService(Context.NOTIFICATION_SERVICE));try {int uid = mPackageManagerService.getPackageUid(packagename, 0, UserHandle.USER_SYSTEM);//Slog.i("NotificationsEnabled", "PMS getPackageUid disable app pkg=" + packagename + ",uid=" + uid);mNotificationManager.setNotificationsEnabledForPackage(packagename, uid, false);} catch (Exception e) {Slog.e("NotificationsEnabled", "PMS Error calling NoMan" + e);} }NotificationManagerService.setNotificationsEnabledForPackage 設置APP默認通知狀態,可在系統啟動時或者APK安裝時(監聽 Intent.ACTION_PACKAGE_ADDED 安裝結束廣播)進行設置。
@Override public void setNotificationsEnabledForPackage(String pkg, int uid, boolean enabled) {enforceSystemOrSystemUI("setNotificationsEnabledForPackage");mPreferencesHelper.setEnabled(pkg, uid, enabled);mMetricsLogger.write(new LogMaker(MetricsEvent.ACTION_BAN_APP_NOTES).setType(MetricsEvent.TYPE_ACTION).setPackageName(pkg).setSubtype(enabled ? 1 : 0));// Now, cancel any outstanding notifications that are part of a just-disabled appif (!enabled) {cancelAllNotificationsInt(MY_UID, MY_PID, pkg, null, 0, 0, true,UserHandle.getUserId(uid), REASON_PACKAGE_BANNED, null);}try {getContext().sendBroadcastAsUser(new Intent(ACTION_APP_BLOCK_STATE_CHANGED).putExtra(NotificationManager.EXTRA_BLOCKED_STATE, !enabled).addFlags(Intent.FLAG_RECEIVER_FOREGROUND).setPackage(pkg),UserHandle.of(UserHandle.getUserId(uid)), null);} catch (SecurityException e) {Slog.w(TAG, "Can't notify app about app block change", e);}handleSavePolicyFile(); }通知開啟關閉后還會發送一個 ACTION_APP_BLOCK_STATE_CHANGED,應用中可以進行監聽判斷通知狀態變化。
?
3、強制過濾APP通知
packages/apps/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
packages/apps/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
protected NotificationData.Entry createNotificationViews(StatusBarNotification sbn)throws InflationException {if (CHATTY) {Log.d(TAG, "createNotificationViews(notification=" + sbn);}// 獲取包名和flags是否是常駐通知String pkg = sbn.getPackageName();boolean isClearable = (sbn.getNotification().flags& Notification.FLAG_AUTO_CANCEL) == Notification.FLAG_AUTO_CANCEL;// 根據通知的包名或者flags來過濾if (!isClearable /*"com.xxx.xxx".equals(pkg)*/) {return null;}NotificationData.Entry entry = new NotificationData.Entry(sbn);Dependency.get(LeakDetector.class).trackInstance(entry);entry.createIcons(mContext, sbn);// Construct the expanded view.inflateViews(entry, mListContainer.getViewParentForNotification(entry));return entry; }private void addNotificationInternal(StatusBarNotification notification,NotificationListenerService.RankingMap ranking) throws InflationException {String key = notification.getKey();if (DEBUG) Log.d(TAG, "addNotification key=" + key);mNotificationData.updateRanking(ranking);NotificationData.Entry shadeEntry = createNotificationViews(notification);// 判斷是否創建了通知if (shadeEntry == null) {return;}boolean isHeadsUped = shouldPeek(shadeEntry);... ... }調用順序是從 NotificationListener.onNotificationPosted? -->?NotificationEntryManager.addNotification -->?addNotificationInternal ,最終創建顯示通知布局。通過 StatusBarNotification 對象的屬性值獲知通知的包名及通知的flags,判斷是否需要過濾。
常用的通知的flags如下
public static final int FLAG_SHOW_LIGHTS = 0x00000001;//設置閃光 public static final int FLAG_ONGOING_EVENT = 0x00000002;//將flag設置為這個屬性那么通知就會常駐 public static final int FLAG_INSISTENT = 0x00000004;//重復發出聲音,直到用戶響應此通知 public static final int FLAG_ONLY_ALERT_ONCE = 0x00000008;//標記聲音或者震動一次 public static final int FLAG_AUTO_CANCEL = 0x00000010;//在通知欄上點擊此通知后自動清除此通知 public static final int FLAG_NO_CLEAR = 0x00000020;//將flag設置為該值,則通知欄的清楚按鈕不會出現 public static final int FLAG_FOREGROUND_SERVICE = 0x00000040;//前臺服務標記 public static final int FLAG_HIGH_PRIORITY = 0x00000080;//高權限,已過時?
總結
以上是生活随笔為你收集整理的Android 通知设置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机科学之父――图灵
- 下一篇: 图文讲解如何在outlook里设置绑定G