对NotificationManager和方法notify的理解
NotificationManager myNotiManager=(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
myNotiManager.notify(myNoti.flags,myNoti);
1,NOTIFICATION_SERVICE怎么得到的?
2,NotificationManager怎么产生的?
3,notify的动作又是怎么做到的?
从上面的函数:
@Overridepublic Object getSystemService(String name) {if (getBaseContext() == null) {throw new IllegalStateException("System services not available to Activities before onCreate()");}if (WINDOW_SERVICE.equals(name)) {return mWindowManager;} else if (SEARCH_SERVICE.equals(name)) {ensureSearchManager();return mSearchManager;}return super.getSystemService(name);}
继续跟入父类:getSystemService(name)
@Override public Object getSystemService(String name) {if (LAYOUT_INFLATER_SERVICE.equals(name)) {if (mInflater == null) {mInflater = LayoutInflater.from(mBase).cloneInContext(this);}return mInflater;}return mBase.getSystemService(name);}
继续跟入mBase.getSystemService(name)
在Context.java中文件,此函数的实现在ContextImp.java
public abstract Object getSystemService(String name);static {registerService(ACCESSIBILITY_SERVICE, new ServiceFetcher() {public Object getService(ContextImpl ctx) {return AccessibilityManager.getInstance(ctx);}});----------------------------registerService(NOTIFICATION_SERVICE, new ServiceFetcher() {public Object createService(ContextImpl ctx) {final Context outerContext = ctx.getOuterContext();return new NotificationManager(new ContextThemeWrapper(outerContext,Resources.selectSystemTheme(0,outerContext.getApplicationInfo().targetSdkVersion,com.android.internal.R.style.Theme_Dialog,com.android.internal.R.style.Theme_Holo_Dialog,com.android.internal.R.style.Theme_DeviceDefault_Dialog)),ctx.mMainThread.getHandler());}});----------------------------------registerService(WINDOW_SERVICE, new ServiceFetcher() {public Object getService(ContextImpl ctx) {return WindowManagerImpl.getDefault(ctx.mPackageInfo.mCompatibilityInfo);}});}
以上的静态块加载完成后会放到SYSTEM_SERVICE_MAP中,在通过开始的serviceName得到。
private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP =new HashMap<String, ServiceFetcher>();private static int sNextPerContextServiceCacheIndex = 0;private static void registerService(String serviceName, ServiceFetcher fetcher) {if (!(fetcher instanceof StaticServiceFetcher)) {fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;}SYSTEM_SERVICE_MAP.put(serviceName, fetcher);}
通过下面的函数对public abstract Object getSystemService(String name)真正实现 ContextImpl.java
@Overridepublic Object getSystemService(String name) {ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);return fetcher == null ? null : fetcher.getService(this);}
很明显此时有NOTIFICATION_SERVICE即service != null,直接返回service;返回一个对应的Manager
public Object getService(ContextImpl ctx) {ArrayList<Object> cache = ctx.mServiceCache;Object service;synchronized (cache) {if (cache.size() == 0) {// Initialize the cache vector on first access.// At this point sNextPerContextServiceCacheIndex// is the number of potential services that are// cached per-Context.for (int i = 0; i < sNextPerContextServiceCacheIndex; i++) {cache.add(null);}} else {service = cache.get(mContextCacheIndex);if (service != null) {return service; }}service = createService(ctx);cache.set(mContextCacheIndex, service);return service;}}
在看 myNotiManager.notify(myNoti.flags,myNoti);
public void notify(int id, Notification notification){notify(null, id, notification);}public void notify(String tag, int id, Notification notification){int[] idOut = new int[1];INotificationManager service = getService();String pkg = mContext.getPackageName();if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");try {service.enqueueNotificationWithTag(pkg, tag, id, notification, idOut);if (id != idOut[0]) {Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);}} catch (RemoteException e) {}}static public INotificationManager getService(){if (sService != null) {return sService;}IBinder b = ServiceManager.getService("notification");sService = INotificationManager.Stub.asInterface(b);return sService;}public static IBinder getService(String name) {try {IBinder service = sCache.get(name);if (service != null) {return service;} else {return getIServiceManager().getService(name);}} catch (RemoteException e) {Log.e(TAG, "error in getService", e);}return null;}
那么 notification 这个key的IBinder有吗?
在Context.java里定义了:public static final String NOTIFICATION_SERVICE = "notification";
public static void initServiceCache(Map<String, IBinder> cache) {
if (sCache.size() != 0) {
throw new IllegalStateException("setServiceCache may only be called once");
}
sCache.putAll(cache);
}
上面的代码是在系统第一次启动时就加载的。
再回到
public void notify(String tag, int id, Notification notification){int[] idOut = new int[1];INotificationManager service = getService(); //这里已经得到实例String pkg = mContext.getPackageName();if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");try {service.enqueueNotificationWithTag(pkg, tag, id, notification, idOut);if (id != idOut[0]) {Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);}} catch (RemoteException e) {}}
在NotificationManagerService.java下实现 enqueueNotificationWithTag
public void enqueueNotificationWithTag(String pkg, String tag, int id, Notification notification,int[] idOut){enqueueNotificationInternal(pkg, Binder.getCallingUid(), Binder.getCallingPid(),tag, id, notification, idOut);}
最终到:
public void enqueueNotificationInternal(String pkg, int callingUid, int callingPid,String tag, int id, int priority, Notification notification, int[] idOut){checkIncomingCall(pkg);// Limit the number of notifications that any given package except the android// package can enqueue. Prevents DOS attacks and deals with leaks.if (!"android".equals(pkg)) {synchronized (mNotificationList) {int count = 0;final int N = mNotificationList.size();for (int i=0; i<N; i++) {final NotificationRecord r = mNotificationList.get(i);if (r.pkg.equals(pkg)) {count++;if (count >= MAX_PACKAGE_NOTIFICATIONS) {Slog.e(TAG, "Package has already posted " + count+ " notifications. Not showing more. package=" + pkg);return;}}}}}// This conditional is a dirty hack to limit the logging done on// behalf of the download manager without affecting other apps.if (!pkg.equals("com.android.providers.downloads")|| Log.isLoggable("DownloadManager", Log.VERBOSE)) {EventLog.writeEvent(EventLogTags.NOTIFICATION_ENQUEUE, pkg, id, tag,notification.toString());}if (pkg == null || notification == null) {throw new IllegalArgumentException("null not allowed: pkg=" + pkg+ " id=" + id + " notification=" + notification);}if (notification.icon != 0) {if (notification.contentView == null) {throw new IllegalArgumentException("contentView required: pkg=" + pkg+ " id=" + id + " notification=" + notification);}}synchronized (mNotificationList) {NotificationRecord r = new NotificationRecord(pkg, tag, id, callingUid, callingPid, priority,notification);NotificationRecord old = null;int index = indexOfNotificationLocked(pkg, tag, id);if (index < 0) {mNotificationList.add(r);} else {old = mNotificationList.remove(index);mNotificationList.add(index, r);// Make sure we don't lose the foreground service state.if (old != null) {notification.flags |=old.notification.flags&Notification.FLAG_FOREGROUND_SERVICE;}}// Ensure if this is a foreground service that the proper additional// flags are set.if ((notification.flags&Notification.FLAG_FOREGROUND_SERVICE) != 0) {notification.flags |= Notification.FLAG_ONGOING_EVENT| Notification.FLAG_NO_CLEAR;}if (notification.icon != 0) {StatusBarNotification n = new StatusBarNotification(pkg, id, tag,r.uid, r.initialPid, notification);n.priority = r.priority;if (old != null && old.statusBarKey != null) {r.statusBarKey = old.statusBarKey;long identity = Binder.clearCallingIdentity();try {mStatusBar.updateNotification(r.statusBarKey, n);}finally {Binder.restoreCallingIdentity(identity);}} else {long identity = Binder.clearCallingIdentity();try {r.statusBarKey = mStatusBar.addNotification(n);mAttentionLight.pulse();}finally {Binder.restoreCallingIdentity(identity);}}sendAccessibilityEvent(notification, pkg);} else {Slog.e(TAG, "Ignoring notification with icon==0: " + notification);if (old != null && old.statusBarKey != null) {long identity = Binder.clearCallingIdentity();try {mStatusBar.removeNotification(old.statusBarKey);}finally {Binder.restoreCallingIdentity(identity);}}}// If we're not supposed to beep, vibrate, etc. then don't.if (((mDisabledNotifications & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) == 0)&& (!(old != null&& (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))&& mSystemReady) {final AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);// soundfinal boolean useDefaultSound =(notification.defaults & Notification.DEFAULT_SOUND) != 0;if (useDefaultSound || notification.sound != null) {Uri uri;if (useDefaultSound) {uri = Settings.System.DEFAULT_NOTIFICATION_URI;} else {uri = notification.sound;try {MediaPlayer mMediaPlayer = new MediaPlayer();mMediaPlayer.setDataSource(notification.sound.toString());} catch (Exception ex) {Slog.d(TAG, "default notification will be used");uri = Settings.System.DEFAULT_NOTIFICATION_URI;}}boolean looping = (notification.flags & Notification.FLAG_INSISTENT) != 0;int audioStreamType;if (notification.audioStreamType >= 0) {audioStreamType = notification.audioStreamType;} else {audioStreamType = DEFAULT_STREAM_TYPE;}mSoundNotification = r;// do not play notifications if stream volume is 0// (typically because ringer mode is silent).if (audioManager.getStreamVolume(audioStreamType) != 0) {long identity = Binder.clearCallingIdentity();try {mSound.play(mContext, uri, looping, audioStreamType);}finally {Binder.restoreCallingIdentity(identity);}}}// vibratefinal boolean useDefaultVibrate =(notification.defaults & Notification.DEFAULT_VIBRATE) != 0;if ((useDefaultVibrate || notification.vibrate != null)&& audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_NOTIFICATION)) {mVibrateNotification = r;mVibrator.vibrate(useDefaultVibrate ? DEFAULT_VIBRATE_PATTERN: notification.vibrate,((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1);}}// this option doesn't shut off the lights// light// the most recent thing gets the lightmLights.remove(old);if (mLedNotification == old) {mLedNotification = null;}//Slog.i(TAG, "notification.lights="// + ((old.notification.lights.flags & Notification.FLAG_SHOW_LIGHTS) != 0));if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0) {mLights.add(r);updateLightsLocked();} else {if (old != null&& ((old.notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0)) {updateLightsLocked();}}}idOut[0] = id;}
以上就是对
NotificationManager myNotiManager=(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
myNotiManager.notify(myNoti.flags,myNoti);
这2行代码的初略理解!
对NotificationManager和方法notify的理解相关推荐
- wait和notify的理解与使用
1.对于wait()和notify()的理解 对于wait()和notify()的理解,还是要从jdk官方文档中开始,在Object类方法中有: void notify() Wakes up a s ...
- JVM学习笔记之-方法区,栈、堆、方法区的交互关系,方法区的理解,设置方法区大小与OOM,方法区的内部结构,方法区使用举例
栈.堆.方法区的交互关系 运行时数据区结构图 从线程共享与否的角度来看 栈,堆,方法区的交互关系 方法区的理解 方法区在哪里? <Java虚拟机规范>中明确说明:"尽管所有的方法 ...
- 1路电磁继电器模块的使用方法的直观理解
1路电磁继电器的使用方法的直观理解 使用的1路电磁继电器模块如下: 此为低电平触发的继电器,其中,NC为常闭端,NO为常开端,COM为常闭端,左侧就相当于一个单掷开关,右侧引脚为模块供电以及输入控制信 ...
- Thread线程notify方法的自我理解
感谢博主:http://zy19982004.iteye.com/blog/1626916 这篇博文给予我线程知识很大的帮助 知识背景:(1)wait().notify()均是Object的方法,故每 ...
- convertViewsetTag方法的一点理解
转自:http://blog.163.com/freemanls@126/blog/static/164585061201171210504864/ 前言 首先我们要知道setTag方法是干什么的,S ...
- Allan方差分析方法的直观理解
Allan方差是时频分析和惯性导航领域常用的一种误差分析方法,它有效地刻画了待研究的误差时间序列在不同时间尺度上的波动水平(不稳定性),并可根据不同时间尺度上的Allan方差值所构成的曲线的形状特征来 ...
- python参数传递方法_深入理解python中函数传递参数是值传递还是引用传递
python 的 深入理解python中函数传递参数是值传递还是引用传递 目前网络上大部分博客的结论都是这样的: Python不允许程序员选择采用传值还是传 引用.Python参数传递采用的肯定是&q ...
- Java里main的写法_main方法的深入理解和例子
大家好,又是一个令人振奋的周三啊,今天说一下main方法,大家应该对它很熟悉了,在Java中,main()方法是Java应用程序的入口方法,也就是说,程序在运行的时候,第一个执行的方法就是main() ...
- 【收藏】Vue+elementUI的this.$refs.对象名.方法名的理解
以前根本看不懂这么写是什么意思: this.$refs.tree.getCheckedKeys()); 其实上面的方法就是已经封装好的,直接调用即可,this,代表在当前vue里,$refs代表一个引 ...
最新文章
- 位置传感器:电位器,电容位置传感器
- [转载]WSUS客户端排错--使用wsus client tools
- 关于jQuery中的trigger和triggerHandler方法的使用
- 三种常见单片机时钟电路方案,对比其优缺点
- 【ArcGIS微课1000例】0018:ArcGIS设置相对路径和数据源
- singleton 类_在Java中对Singleton类进行双重检查锁定
- MEF初体验之九:部件生命周期
- .NET中如何深度判断2个对象相等
- SendMessage 与 PostMessage
- android so劫持,防劫持SDK
- 【PS】制作透明质感按钮
- yshon对讲机如何调频率_对讲机频率怎么调?四步教你给对讲机调频
- 办公小技巧:excel删除重复项
- idea运行maven工程,并且tomcat运行成功,但是仍然是404错误
- 投标任性,围标串标一查实,扫黑除恶,现在投标必须签订一样协议
- LPDDR4x 的 学习总结(3) - SDRAM基本功能
- 安卓按键精灵之比较运算符
- 图像变换(Image transformations)
- python作品-python 作品
- Python爬虫实战(3)古诗文网