对NotificationManager和方法notify的理解
来源:互联网 发布:列生成算法思想 编辑:程序博客网 时间:2024/06/08 09:48
NotificationManager myNotiManager=(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
myNotiManager.notify(myNoti.flags,myNoti);
1,NOTIFICATION_SERVICE怎么得到的?
2,NotificationManager怎么产生的?
继续跟入父类:getSystemService(name)
继续跟入mBase.getSystemService(name)
以上的静态块加载完成后会放到SYSTEM_SERVICE_MAP中,在通过开始的serviceName得到。
通过下面的函数对public abstract Object getSystemService(String name)真正实现 ContextImpl.java
很明显此时有NOTIFICATION_SERVICE即service != null,直接返回service;返回一个对应的Manager
在看 myNotiManager.notify(myNoti.flags,myNoti);
那么 notification 这个key的IBinder有吗?
在NotificationManagerService.java下实现 enqueueNotificationWithTag
最终到:
以上就是对
NotificationManager myNotiManager=(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
myNotiManager.notify(myNoti.flags,myNoti);
这2行代码的初略理解!
myNotiManager.notify(myNoti.flags,myNoti);
1,NOTIFICATION_SERVICE怎么得到的?
2,NotificationManager怎么产生的?
3,notify的动作又是怎么做到的?
从上面的函数:
@Override public 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
@Override public 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); // sound final 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); } } } // vibrate final 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 light mLights.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的理解
- 对Object 的wait 和 notify的新理解
- wait 和 notify的一点理解
- 通俗的去理解 wait()和notify()
- wait和notify的理解与使用
- wait和notify的理解与使用
- wait和notify的理解与使用
- 理解wait和notify
- 自己对多线程 的wait 跟notify的理解
- object的notify、wait对线程使用的理解
- synchronized方法和wait、notify的关联
- Object的Wait() 和notify()方法使用
- java的wait和notify方法浅析
- Notification和NotificationManager的使用
- wait和notify方法
- 对方法的理解
- Java wait() 和 notify() 理解
- Java基础(高级)——多线程的理解和Synchronized实例,以及线程间通信,wait,notify等方法
- oracle 发送邮件 实现方法
- eclipse下axis2创建web service(三)
- 尼玛 jquery在父页面获取iframe 的元素!
- c/c++ main 中int argc和char** argv的说明
- android的layout布局种类
- 对NotificationManager和方法notify的理解
- android-serialport-api
- zlib压缩中uncompress函数返回Z_DATA_ERROR错误!!!
- B_树的C实现原理插入、删除、查找的原理
- Display number of replies in disscussion board
- eclipse下axis2创建web service(四)
- HDU1384 差分约束
- hsql使用架构包启动数据库
- _stdcall与_cdecl的区别