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 -->
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 通知设置相关推荐
- android 跳转系统通知,android 跳转到应用通知设置界面
4.4以下并没有提过从app跳转到应用通知设置页面的Action,可考虑跳转到应用详情页面,下面是直接跳转到应用通知设置的代码: if (android.os.Build.VERSION.SDK_IN ...
- Android:检查通知权限并跳转到通知设置界面
声明:该方案只对API19及以上版本有效 一.目标需求 最近项目中在完善推送功能,需要进入APP时检测一下是否开启了推送权限,如果没有开启弹窗提醒,当用户点击弹窗时直接跳转到APP的通知设置界面,就像 ...
- Android 11.0 下拉状态栏通知栏的通知设置默认展开
1.概述 在11.0 的产品定制化中,对于SystemUI的定制也是常用的功能,而在下拉状态栏中的通知栏部分也是极其重要的部分,每条通知实时更新在通知栏部分,由于通知栏高度的限制,每条通知是默认收缩的 ...
- android通过代码设置铃声_有打扰 漏消息?那是Android手机通知设置没弄好!
点击上方电脑爱好者关注我们 在Android系统手机的设置内容中,"通知"是最容易被我们忽略的选项.实际上,如果你每天休息时都会被各种推送提醒打扰,又或是经常错过微信.邮箱.闲鱼等 ...
- android 跳转到应用通知设置界面【Android 8.0 需要特殊处理】
整理下安卓跳转通知设置页面的代码,如下: 常量补充: private static final String CHECK_OP_NO_THROW = "checkOpNoThrow" ...
- android 跳转oppo应用中心_android 跳转到应用通知设置界面的示例
4.4以下并没有提过从app跳转到应用通知设置页面的Action,可考虑跳转到应用详情页面,下面是直接跳转到应用通知设置的代码: if (android.os.Build.VERSION.SDK_IN ...
- android notification设置不同字体颜色,Android Notification自定义通知样式你要知道的事...
本文将根据个人经验对Notification做个总结,以供参考! 什么是通知(Notification) 通知是一个可以在应用程序正常的用户界面之外显示给用户的消息. 通知发出时,它首先出现在状态栏的 ...
- Android手机关闭短信提醒,有打扰 漏消息?那是Android手机通知设置没弄好!
原标题:有打扰 漏消息?那是Android手机通知设置没弄好! 在Android系统手机的设置内容中,"通知"是最容易被我们忽略的选项.实际上,如果你每天休息时都会被各种推送提醒打 ...
- 20_Android中apk安装器,通过WebView来load进一个页面,Android通知,程序退出自动杀死进程,通过输入包名的方式杀死进程
场景:实现安装一个apk应用程序的过程.界面如下: 编写如下应用,应用结构如下: <RelativeLayout xmlns:android="http://schemas.an ...
- android activity 被notification启动,Android通知Notification全面剖析
原标题:Android通知Notification全面剖析 通知 通知是您可以在应用的常规 UI 外部向用户显示的消息.当您告知系统发出通知时,它将先以图标的形式显示在通知区域中.用户可以打开抽屉式通 ...
最新文章
- 【C#串口编程计划】C#串口协议解析 -- 二进制数据
- 经典:盘点80后男人找老婆的20条标准
- python 冷门_Python最冷门的模块
- LACP/PAGP的定义与差别—Vecloud微云
- UA STAT687 线性模型II 最小二乘理论2 约束最小二乘估计
- HTML5能做哪些东西呢?这篇文章给你答案
- ruby中的特殊字符
- xml文件的三种解析方式 DOM SAM PULL
- Redis 发布/订阅模式
- 如何正确的卸载MATLAB7?
- 05 Java 求职简历制作
- 东南大学计算机科学与网络,顾冠群
- thymeleaf内嵌变量
- facebookdownload_downloadfacebook
- 新浪张俊林:大语言模型的涌现能力——现象与解释
- Ubuntu 18.04 LTS 安装wine 、exe程序安装和卸载
- Podman容器之签名分发与网络
- 图形图像学习随笔:计算机图形学的一些基本概念
- 高效能人士的习惯.提炼一种高效能思维
- IntelliJ IDEA全局内容搜索和替换
热门文章
- 2020 2月 月末总结
- 2007年12月25日至2008年1月1日百宝箱游戏下载排行榜
- js 判断是企业微信或微信
- [linux]记录内核编译日志
- 【论文阅读】RegNet-Designing Network Design Space
- latex 中对同一脚注进行引用
- 海德汉圆光栅编码器RON786C/RON886C/RON785C/RPN886/RON285/RON287/RON275参数针脚定义
- 百度SiteApp构建网站APP
- 代码原理 webkit WebKit-利用百度siteapp开发网站App-(IOS和Android版本)
- 有多少旅游企业入驻了抖音平台?有多少抖音用户喜欢看旅游视频?