日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android 通知设置

發(fā)布時間:2023/12/16 Android 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 通知设置 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

寫在前面,8.0以后的通知寫法如下

Android 8.0中各種通知寫法匯總

最終通過?NotificationManager.notify()發(fā)送通知。

?

1、通知發(fā)送流程

相關類

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?-->

void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid,final int callingPid, final String tag, final int id, final Notification notification,int incomingUserId) {... ...final int notificationUid = resolveNotificationUid(opPkg, pkg, callingUid, userId);checkRestrictedCategories(notification);// Fix the notification as best we can.try {fixNotification(notification, pkg, userId);} catch (NameNotFoundException e) {Slog.e(TAG, "Cannot create a context for sending app", e);return;}mUsageStats.registerEnqueuedByApp(pkg);// setup local book-keepingString channelId = notification.getChannelId();if (mIsTelevision && (new Notification.TvExtender(notification)).getChannelId() != null) {channelId = (new Notification.TvExtender(notification)).getChannelId();}final NotificationChannel channel = mPreferencesHelper.getNotificationChannel(pkg,notificationUid, channelId, false /* includeDeleted */);if (channel == null) {... ... //channel 為NULL,提示并阻止通知發(fā)送,所以應用發(fā)送通知必需先創(chuàng)建NotificationChannelreturn;}final StatusBarNotification n = new StatusBarNotification(pkg, opPkg, id, tag, notificationUid, callingPid, notification,user, null, System.currentTimeMillis());final NotificationRecord r = new NotificationRecord(getContext(), n, channel);r.setIsAppImportanceLocked(mPreferencesHelper.getIsAppImportanceLocked(pkg, callingUid));... ...mHandler.post(new EnqueueNotificationRunnable(userId, r)); }

?enqueueNotificationInternal方法內(nèi)部做一些檢查,判斷通知是否合法等。

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,調(diào)用 NotificationListenerService.onNotificationPosted ()。

NotificationListener 繼承 NotificationListenerWithPlugins 繼承 NotificationListenerService。最終實現(xiàn)在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() 完成通知創(chuàng)建顯示。

?

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默認通知狀態(tài),可在系統(tǒng)啟動時或者APK安裝時(監(jiān)聽 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(); }

通知開啟關閉后還會發(fā)送一個 ACTION_APP_BLOCK_STATE_CHANGED,應用中可以進行監(jiān)聽判斷通知狀態(tài)變化。

?

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;// 根據(jù)通知的包名或者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);// 判斷是否創(chuàng)建了通知if (shadeEntry == null) {return;}boolean isHeadsUped = shouldPeek(shadeEntry);... ... }

調(diào)用順序是從 NotificationListener.onNotificationPosted? -->?NotificationEntryManager.addNotification -->?addNotificationInternal ,最終創(chuàng)建顯示通知布局。通過 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;//重復發(fā)出聲音,直到用戶響應此通知 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設置為該值,則通知欄的清楚按鈕不會出現(xiàn) public static final int FLAG_FOREGROUND_SERVICE = 0x00000040;//前臺服務標記 public static final int FLAG_HIGH_PRIORITY = 0x00000080;//高權限,已過時

?

總結

以上是生活随笔為你收集整理的Android 通知设置的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。