写在前面,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 -->

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,提示并阻止通知发送,所以应用发送通知必需先创建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方法内部做一些检查,判断通知是否合法等。

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 通知设置相关推荐

  1. android 跳转系统通知,android 跳转到应用通知设置界面

    4.4以下并没有提过从app跳转到应用通知设置页面的Action,可考虑跳转到应用详情页面,下面是直接跳转到应用通知设置的代码: if (android.os.Build.VERSION.SDK_IN ...

  2. Android:检查通知权限并跳转到通知设置界面

    声明:该方案只对API19及以上版本有效 一.目标需求 最近项目中在完善推送功能,需要进入APP时检测一下是否开启了推送权限,如果没有开启弹窗提醒,当用户点击弹窗时直接跳转到APP的通知设置界面,就像 ...

  3. Android 11.0 下拉状态栏通知栏的通知设置默认展开

    1.概述 在11.0 的产品定制化中,对于SystemUI的定制也是常用的功能,而在下拉状态栏中的通知栏部分也是极其重要的部分,每条通知实时更新在通知栏部分,由于通知栏高度的限制,每条通知是默认收缩的 ...

  4. android通过代码设置铃声_有打扰 漏消息?那是Android手机通知设置没弄好!

    点击上方电脑爱好者关注我们 在Android系统手机的设置内容中,"通知"是最容易被我们忽略的选项.实际上,如果你每天休息时都会被各种推送提醒打扰,又或是经常错过微信.邮箱.闲鱼等 ...

  5. android 跳转到应用通知设置界面【Android 8.0 需要特殊处理】

    整理下安卓跳转通知设置页面的代码,如下: 常量补充: private static final String CHECK_OP_NO_THROW = "checkOpNoThrow" ...

  6. android 跳转oppo应用中心_android 跳转到应用通知设置界面的示例

    4.4以下并没有提过从app跳转到应用通知设置页面的Action,可考虑跳转到应用详情页面,下面是直接跳转到应用通知设置的代码: if (android.os.Build.VERSION.SDK_IN ...

  7. android notification设置不同字体颜色,Android Notification自定义通知样式你要知道的事...

    本文将根据个人经验对Notification做个总结,以供参考! 什么是通知(Notification) 通知是一个可以在应用程序正常的用户界面之外显示给用户的消息. 通知发出时,它首先出现在状态栏的 ...

  8. Android手机关闭短信提醒,有打扰 漏消息?那是Android手机通知设置没弄好!

    原标题:有打扰 漏消息?那是Android手机通知设置没弄好! 在Android系统手机的设置内容中,"通知"是最容易被我们忽略的选项.实际上,如果你每天休息时都会被各种推送提醒打 ...

  9. 20_Android中apk安装器,通过WebView来load进一个页面,Android通知,程序退出自动杀死进程,通过输入包名的方式杀死进程

     场景:实现安装一个apk应用程序的过程.界面如下: 编写如下应用,应用结构如下: <RelativeLayout xmlns:android="http://schemas.an ...

  10. android activity 被notification启动,Android通知Notification全面剖析

    原标题:Android通知Notification全面剖析 通知 通知是您可以在应用的常规 UI 外部向用户显示的消息.当您告知系统发出通知时,它将先以图标的形式显示在通知区域中.用户可以打开抽屉式通 ...

最新文章

  1. 【C#串口编程计划】C#串口协议解析 -- 二进制数据
  2. 经典:盘点80后男人找老婆的20条标准
  3. python 冷门_Python最冷门的模块
  4. LACP/PAGP的定义与差别—Vecloud微云
  5. UA STAT687 线性模型II 最小二乘理论2 约束最小二乘估计
  6. HTML5能做哪些东西呢?这篇文章给你答案
  7. ruby中的特殊字符
  8. xml文件的三种解析方式 DOM SAM PULL
  9. Redis 发布/订阅模式
  10. 如何正确的卸载MATLAB7?
  11. 05 Java 求职简历制作
  12. 东南大学计算机科学与网络,顾冠群
  13. thymeleaf内嵌变量
  14. facebookdownload_downloadfacebook
  15. 新浪张俊林:大语言模型的涌现能力——现象与解释
  16. Ubuntu 18.04 LTS 安装wine 、exe程序安装和卸载
  17. Podman容器之签名分发与网络
  18. 图形图像学习随笔:计算机图形学的一些基本概念
  19. 高效能人士的习惯.提炼一种高效能思维
  20. IntelliJ IDEA全局内容搜索和替换

热门文章

  1. 2020 2月 月末总结
  2. 2007年12月25日至2008年1月1日百宝箱游戏下载排行榜
  3. js 判断是企业微信或微信
  4. [linux]记录内核编译日志
  5. 【论文阅读】RegNet-Designing Network Design Space
  6. latex 中对同一脚注进行引用
  7. 海德汉圆光栅编码器RON786C/RON886C/RON785C/RPN886/RON285/RON287/RON275参数针脚定义
  8. 百度SiteApp构建网站APP
  9. 代码原理 webkit WebKit-利用百度siteapp开发网站App-(IOS和Android版本)
  10. 有多少旅游企业入驻了抖音平台?有多少抖音用户喜欢看旅游视频?