NotificationManagerService使用详解与原理分析(一)

概况

Android在4.3的版本中(即API 18)加入了NotificationListenerService,根据SDK的描述(AndroidDeveloper)可以知道,当系统收到新的通知或者通知被删除时,会触发NotificationListenerService的回调方法。同时在Android 4.4 中新增了Notification.extras 字段,也就是说可以使用NotificationListenerService获取系统通知具体信息,这在以前是需要用反射来实现的。

转载请务必注明出处:http://blog.csdn.net/yihongyuelan

重要关系

对于系统通知,三方APP使用NotificationListenerService主要目的是为了获取系统通知相关信息,主要包括:通知的新增和删除,获取当前通知数量,通知内容相关信息等。这些信息可以通过NotificationListenerService类提供的方法以及StatusBarNotification类对象来获取。

NotificationListenerService主要方法(成员变量):

cancelAllNotifications() :删除系统中所有可被清除的通知;
cancelNotification(String pkg, String tag, int id) :删除具体某一个通知;
getActiveNotifications() :返回当前系统所有通知到StatusBarNotification[];
onNotificationPosted(StatusBarNotification sbn) :当系统收到新的通知后出发回调;
onNotificationRemoved(StatusBarNotification sbn) :当系统通知被删掉后出发回调;

以上是NotificationListenerService的主要方法,通过这些方法就可以在应用中操作系统通知,在NotificationListenerService中除了对通知的操作之外,还可以获取到通知的StatusBarNotification对象,通过该对象可以获取通知更详细的数据。

StatusBarNotification主要方法(成员变量):

getId():返回通知对应的id;
getNotification():返回通知对象;
getPackageName():返回通知对应的包名;
getPostTime():返回通知发起的时间;
getTag():返回通知的Tag,如果没有设置返回null;
getUserId():返回UserId,用于多用户场景;
isClearable():返回该通知是否可被清楚,FLAG_ONGOING_EVENT、FLAG_NO_CLEAR;
isOngoing():检查该通知的flag是否为FLAG_ONGOING_EVENT;

使用简介

正确使用NotificationListenerService需要注意三点:

(1). 新建一个类并继承自NotificationListenerService,override其中重要的两个方法;

[java] view plaincopy

  1. public class NotificationMonitor extends NotificationListenerService {
  2. @Override
  3. public void onNotificationPosted(StatusBarNotification sbn) {
  4. Log.i("SevenNLS","Notification posted");
  5. }
  6. @Override
  7. public void onNotificationRemoved(StatusBarNotification sbn) {
  8. Log.i("SevenNLS","Notification removed");
  9. }
  10. }

(2). 在AndroidManifest.xml中注册Service并声明相关权限;

[html] view plaincopy

  1. <service android:name=".NotificationMonitor"
  2. android:label="@string/service_name"
  3. android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
  4. <intent-filter>
  5. <action android:name="android.service.notification.NotificationListenerService" />
  6. </intent-filter>
  7. </service>

(3). 开启NotificationMonitor的监听功能;

完成以上两步之后,将程序编译并安装到手机上,但此时该程序是无法监听到新增通知和删除通知的,还需要在"Settings > Security > Notification access"中,勾选NotificationMonitor。此时如果系统收到新的通知或者通知被删除就会打印出相应的log了。

这里需要注意,如果手机上没有安装使用NotificationListenerService类的APP,Notification access是不会显示出来的。可以在源码/packages/apps/Settings/src/com/android/settings/SecuritySettings.java中看到,如果没有使用NotificationListenerService的APK,直接就不显示这一项了。

[java] view plaincopy

  1. mNotificationAccess = findPreference(KEY_NOTIFICATION_ACCESS);
  2. if (mNotificationAccess != null) {
  3. final int total = NotificationAccessSettings.getListenersCount(mPM);
  4. if (total == 0) {
  5. if (deviceAdminCategory != null) {
  6. deviceAdminCategory.removePreference(mNotificationAccess);
  7. }
  8. } else {
  9. final int n = getNumEnabledNotificationListeners();
  10. if (n == 0) {
  11. mNotificationAccess.setSummary(getResources().getString(
  12. R.string.manage_notification_access_summary_zero));
  13. } else {
  14. mNotificationAccess.setSummary(String.format(getResources().getQuantityString(
  15. R.plurals.manage_notification_access_summary_nonzero,
  16. n, n)));
  17. }
  18. }
  19. }

使用详解

通过前面的讲解(实际上就是对AndroidDeveloper的解释),已经可以正常使用NotificationListenerService了,但对于实际应用中,需要考虑的事情还比较多。比如:

1. 如何检测应用已开启Notification access监听功能?

如果检测到应用没有激活Notification access监听功能,需要提示用户开启;

2. 能不能主动跳转到Notification access监听页面?

如果能够根据第1步的判断自动跳转到对应的页面,那可以省掉很多操作;

3. 如何与NotificationListenerService交互?

涉及到与Service的交互,但又与普通的Service不同,这里后文解释;

4. NotificationListenerService使用过程中有哪些注意事项?

在使用NotificationListenerService过程中自己遇到了一些坑,后文会通过分析给出相应的解决方案;

程序运行截图

NotificationManagerService使用详解与原理分析(一)
NotificationManagerService使用详解与原理分析(一)

图 1 程序运行截图

示例介绍

NotificationListenerDemo主要用于获取系统当前通知信息,并可手动创建"可清除通知",逐条删除"可清除通知",一次性删除"可清除通知",以及显示系统当前活动的通知信息。实际上该示例回答了前面使用详解中提出的各项疑问,在实际使用过程中相信大部分人都会遇到,因此这里逐条展开与大家分享。

NotificationManagerService使用详解与原理分析(一)

图 2 主界面

功能分析

1. 如何检测应用已开启Notification access监听功能?

在程序启动时,执行Notification access的检测,查看是否访问Notification的权限。如果用户没有Enable Notification access,则弹出提示对话框,点击OK跳转到Notification access设置页面。

NotificationManagerService使用详解与原理分析(一)
NotificationManagerService使用详解与原理分析(一)

图 3 首次启动 isEnable

使用NotificationListenerService的应用如果开启了Notification access,系统会将包名等相关信息写入SettingsProver数据库中,因此可以从数据库中获取相关信息并过滤,从而判断应用是否开启了Notification access,代码如下:

[java] view plaincopy

  1. private static final String ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners";
  2. private boolean isEnabled() {
  3. String pkgName = getPackageName();
  4. final String flat = Settings.Secure.getString(getContentResolver(),
  5. ENABLED_NOTIFICATION_LISTENERS);
  6. if (!TextUtils.isEmpty(flat)) {
  7. final String[] names = flat.split(":");
  8. for (int i = 0; i < names.length; i++) {
  9. final ComponentName cn = ComponentName.unflattenFromString(names[i]);
  10. if (cn != null) {
  11. if (TextUtils.equals(pkgName, cn.getPackageName())) {
  12. return true;
  13. }
  14. }
  15. }
  16. }
  17. return false;
  18. }

在返回值flat中如果包含了应用的包名,即可确定应用已开启Notification access,反之则表示没有开启。

2. 能不能主动跳转到Notification access监听页面?

通过查看可以知道,Notification access界面接收action为"android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"的intent启动,因此使用startActivity可以很容易的跳转到该页面,从而避免用户在Settings中查找。代码如下:

[java] view plaincopy

  1. private static final String ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS";
  2. private void openNotificationAccess() {
  3. startActivity(new Intent(ACTION_NOTIFICATION_LISTENER_SETTINGS));
  4. }

3. 如何与NotificationListenerService交互?

因为NotificationListenerService中包含了四个重要的方法,分别是:onNotificationPosted、onNotificationRemoved、cancelNotification、cancelAllNotifications。通过这些方法我们才能实现诸如通知信息的获取以及删除等功能,虽然这些方法是public的,那是不是意味着我们只要拿到NotificationListenerService的对象就可以直接调用这些方法了呢?那如何拿到Service的对象呢?在之前的博文中,曾有提到与Service的交互( 具体可参考拙作《Android中程序与Service交互的方式——交互方式》),可以看到与Service的交互有很多种方法,但如果要拿到Service的对象,归根到底还是需要Binder。

也就是说得使用bindService的办法,将onServiceConnected回调中的IBinder对象转型成NotificationListenerService的对象。测试代码如下:

[java] view plaincopy

  1. //在MainActivity.java的onCreate方法中使用bindService帮顶NotificationMonitor服务
  2. bindService(new Intent(this,NotificationMonitor.class ), new ServiceConnection() {
  3. @Override
  4. public void onServiceDisconnected(ComponentName arg0) {
  5. }
  6. @Override
  7. public void onServiceConnected(ComponentName arg0, IBinder arg1) {
  8. NotificationMonitor.MyBinder localBinder = (MyBinder)arg1;
  9. NotificationMonitor mMonitor = localBinder.getService();
  10. }
  11. }, BIND_AUTO_CREATE);

[java] view plaincopy

  1. //NotificationMonitor的onBind方法返回构造的Binder对象
  2. public class NotificationMonitor extends NotificationListenerService {
  3. private MyBinder mBinder = new MyBinder();
  4. public class MyBinder extends Binder{
  5. public NotificationMonitor getService(){
  6. return NotificationMonitor.this;
  7. }
  8. }
  9. @Override
  10. public IBinder onBind(Intent arg0) {
  11. return mBinder;
  12. }
  13. @Override
  14. public void onNotificationPosted(StatusBarNotification sbn) {
  15. getActiveNotifications();
  16. cancelAllNotifications();
  17. }
  18. @Override
  19. public void onNotificationRemoved(StatusBarNotification sbn) {
  20. }
  21. }

那这样操作之后是不是就意味着可以拿到NotificationMonitor的对象并直接调用getActiveNotifications()方法,用于获取当前系统通知的信息了呢?很抱歉,事实证明这样是不行的。这里简单的分析下,在后面的NotificationListenerService原理分析中再详细讲解。在NotificationListenerService的源码中可以看到:

[java] view plaincopy

  1. @Override
  2. public IBinder onBind(Intent intent) {
  3. if (mWrapper == null) {
  4. mWrapper = new INotificationListenerWrapper();
  5. }
  6. return mWrapper;
  7. }

这里的INotificationListenerWrapper是NotificationListenerService的一个内部类:

[java] view plaincopy

  1. private class INotificationListenerWrapper extends INotificationListener.Stub

而NotificationMonitor继承自NotificationListenerService,默认的onBind方法却是:

[java] view plaincopy

  1. @Override
  2. public IBinder onBind(Intent intent) {
  3. return super.onBind(intent);
  4. }

这里注意,一般情况下service的onBind方法返回要么是null要么是Binder对象,可这里直接调用父类NotificationListenerService的onBind方法,而父类返回的是INotificationListenerWrapper的对象。这说明Binder对象已经被指定了,不能再给NotificationMonitor指定其它的Binder对象。如果你非要给NotificationMonitor指定其它的Binder对象,那么就无法使用INotificationListenerWrapper提供的方法。也就是说要么就用系统NotificationListenerService提供的方法,要么就把NotificationMonitor当一个普通的Service来用,系统提供的方法都不能使用。

那应该如何使用NotificationListenerService中的方法呢?在拙作《Android中程序与Service交互的方式——交互方式》中,已经提供了很多的例子,这里仅以广播的方式为例。

既然NotificationMonitor可以使用NotificationListenerService的方法,那通过NotificationMonitor把通知状态的改变以及数据获取到,并使用static数据进行存储,之后再在MainActivity中直接使用即可。在MainActivity中控制通知的单个删除和全部删除,则使用广播的方式发送给NotificationMonitor进行处理。MainActivity与NotificationMonitor的关系类图如下:

NotificationManagerService使用详解与原理分析(一)

图 4 结构类图

NotificationMonitor和MainActivity关键代码如下:

[java] view plaincopy

  1. public class NotificationMonitor extends NotificationListenerService {
  2. private static final String TAG = "SevenNLS";
  3. private static final String TAG_PRE = "[" + NotificationMonitor.class.getSimpleName() + "] ";
  4. private static final int EVENT_UPDATE_CURRENT_NOS = 0;
  5. public static final String ACTION_NLS_CONTROL = "com.seven.notificationlistenerdemo.NLSCONTROL";
  6. //用于存储当前所有的Notification的StatusBarNotification对象数组
  7. public static List<StatusBarNotification[]> mCurrentNotifications = new ArrayList<StatusBarNotification[]>();
  8. public static int mCurrentNotificationsCounts = 0;
  9. //收到新通知后将通知的StatusBarNotification对象赋值给mPostedNotification
  10. public static StatusBarNotification mPostedNotification;
  11. //删除一个通知后将通知的StatusBarNotification对象赋值给mRemovedNotification
  12. public static StatusBarNotification mRemovedNotification;
  13. private CancelNotificationReceiver mReceiver = new CancelNotificationReceiver();
  14. // String a;
  15. private Handler mMonitorHandler = new Handler() {
  16. @Override
  17. public void handleMessage(Message msg) {
  18. switch (msg.what) {
  19. case EVENT_UPDATE_CURRENT_NOS:
  20. updateCurrentNotifications();
  21. break;
  22. default:
  23. break;
  24. }
  25. }
  26. };
  27. class CancelNotificationReceiver extends BroadcastReceiver {
  28. @Override
  29. public void onReceive(Context context, Intent intent) {
  30. String action;
  31. if (intent != null && intent.getAction() != null) {
  32. action = intent.getAction();
  33. if (action.equals(ACTION_NLS_CONTROL)) {
  34. String command = intent.getStringExtra("command");
  35. if (TextUtils.equals(command, "cancel_last")) {
  36. if (mCurrentNotifications != null && mCurrentNotificationsCounts >= 1) {
  37. //每次删除通知最后一个
  38. StatusBarNotification sbnn = getCurrentNotifications()[mCurrentNotificationsCounts - 1];
  39. cancelNotification(sbnn.getPackageName(), sbnn.getTag(), sbnn.getId());
  40. }
  41. } else if (TextUtils.equals(command, "cancel_all")) {
  42. //删除所有通知
  43. cancelAllNotifications();
  44. }
  45. }
  46. }
  47. }
  48. }
  49. @Override
  50. public void onCreate() {
  51. super.onCreate();
  52. logNLS("onCreate...");
  53. IntentFilter filter = new IntentFilter();
  54. filter.addAction(ACTION_NLS_CONTROL);
  55. registerReceiver(mReceiver, filter);
  56. //在onCreate时第一次调用getActiveNotifications()
  57. mMonitorHandler.sendMessage(mMonitorHandler.obtainMessage(EVENT_UPDATE_CURRENT_NOS));
  58. }
  59. @Override
  60. public void onDestroy() {
  61. super.onDestroy();
  62. unregisterReceiver(mReceiver);
  63. }
  64. @Override
  65. public IBinder onBind(Intent intent) {
  66. // a.equals("b");
  67. logNLS("onBind...");
  68. return super.onBind(intent);
  69. }
  70. @Override
  71. public void onNotificationPosted(StatusBarNotification sbn) {
  72. //当系统收到新的通知后,更新mCurrentNotifications列表
  73. updateCurrentNotifications();
  74. logNLS("onNotificationPosted...");
  75. logNLS("have " + mCurrentNotificationsCounts + " active notifications");
  76. mPostedNotification = sbn;
  77. //通过以下方式可以获取Notification的详细信息
  78. /*
  79. * Bundle extras = sbn.getNotification().extras; String
  80. * notificationTitle = extras.getString(Notification.EXTRA_TITLE);
  81. * Bitmap notificationLargeIcon = ((Bitmap)
  82. * extras.getParcelable(Notification.EXTRA_LARGE_ICON)); Bitmap
  83. * notificationSmallIcon = ((Bitmap)
  84. * extras.getParcelable(Notification.EXTRA_SMALL_ICON)); CharSequence
  85. * notificationText = extras.getCharSequence(Notification.EXTRA_TEXT);
  86. * CharSequence notificationSubText =
  87. * extras.getCharSequence(Notification.EXTRA_SUB_TEXT);
  88. * Log.i("SevenNLS", "notificationTitle:"+notificationTitle);
  89. * Log.i("SevenNLS", "notificationText:"+notificationText);
  90. * Log.i("SevenNLS", "notificationSubText:"+notificationSubText);
  91. * Log.i("SevenNLS",
  92. * "notificationLargeIcon is null:"+(notificationLargeIcon == null));
  93. * Log.i("SevenNLS",
  94. * "notificationSmallIcon is null:"+(notificationSmallIcon == null));
  95. */
  96. }
  97. @Override
  98. public void onNotificationRemoved(StatusBarNotification sbn) {
  99. //当有通知被删除后,更新mCurrentNotifications列表
  100. updateCurrentNotifications();
  101. logNLS("removed...");
  102. logNLS("have " + mCurrentNotificationsCounts + " active notifications");
  103. mRemovedNotification = sbn;
  104. }
  105. private void updateCurrentNotifications() {
  106. try {
  107. StatusBarNotification[] activeNos = getActiveNotifications();
  108. if (mCurrentNotifications.size() == 0) {
  109. mCurrentNotifications.add(null);
  110. }
  111. mCurrentNotifications.set(0, activeNos);
  112. mCurrentNotificationsCounts = activeNos.length;
  113. } catch (Exception e) {
  114. logNLS("Should not be here!!");
  115. e.printStackTrace();
  116. }
  117. }
  118. //获取当前状态栏显示通知总数
  119. public static StatusBarNotification[] getCurrentNotifications() {
  120. if (mCurrentNotifications.size() == 0) {
  121. logNLS("mCurrentNotifications size is ZERO!!");
  122. return null;
  123. }
  124. return mCurrentNotifications.get(0);
  125. }
  126. private static void logNLS(Object object) {
  127. Log.i(TAG, TAG_PRE + object);
  128. }
  129. }

而MainActivity主要负责界面显示与交互,关键代码如下:

[java] view plaincopy

  1. public class MainActivity extends Activity {
  2. private static final String TAG = "SevenNLS";
  3. private static final String TAG_PRE = "["+MainActivity.class.getSimpleName()+"] ";
  4. private static final int EVENT_SHOW_CREATE_NOS = 0;
  5. private static final int EVENT_LIST_CURRENT_NOS = 1;
  6. private static final String ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners";
  7. private static final String ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS";
  8. private boolean isEnabledNLS = false;
  9. private TextView mTextView;
  10. private Handler mHandler = new Handler() {
  11. @Override
  12. public void handleMessage(Message msg) {
  13. switch (msg.what) {
  14. case EVENT_SHOW_CREATE_NOS:
  15. //显示创建的Notification对应的pkgName、Tag、Id
  16. showCreateNotification();
  17. break;
  18. case EVENT_LIST_CURRENT_NOS:
  19. //显示当前所有的Notification数量及其包名
  20. listCurrentNotification();
  21. break;
  22. default:
  23. break;
  24. }
  25. }
  26. };
  27. @Override
  28. protected void onCreate(Bundle savedInstanceState) {
  29. super.onCreate(savedInstanceState);
  30. setContentView(R.layout.activity_main);
  31. mTextView = (TextView) findViewById(R.id.textView);
  32. }
  33. @Override
  34. protected void onResume() {
  35. super.onResume();
  36. //判断是否有开启Notification access
  37. isEnabledNLS = isEnabled();
  38. logNLS("isEnabledNLS = " + isEnabledNLS);
  39. if (!isEnabledNLS) {
  40. //如果没有开启则显示确认对话框
  41. showConfirmDialog();
  42. }
  43. }
  44. public void buttonOnClicked(View view) {
  45. mTextView.setTextColor(Color.BLACK);
  46. switch (view.getId()) {
  47. case R.id.btnCreateNotify:
  48. logNLS("Create notifications...");
  49. //创建可清除的Notification
  50. createNotification(this);
  51. //显示当前状态栏中所有Notification数量及其包名
  52. mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_SHOW_CREATE_NOS), 50);
  53. break;
  54. case R.id.btnClearLastNotify:
  55. logNLS("Clear Last notification...");
  56. //清除最后一个Notification
  57. clearLastNotification();
  58. //显示当前状态栏中所有Notification数量及其包名
  59. mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_LIST_CURRENT_NOS), 50);
  60. break;
  61. case R.id.btnClearAllNotify:
  62. logNLS("Clear All notifications...");
  63. //清除所有"可被清除"的Notification
  64. clearAllNotifications();
  65. mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_LIST_CURRENT_NOS), 50);
  66. break;
  67. case R.id.btnListNotify:
  68. logNLS("List notifications...");
  69. listCurrentNotification();
  70. break;
  71. case R.id.btnEnableUnEnableNotify:
  72. logNLS("Enable/UnEnable notification...");
  73. //打开Notification access启动/取消界面
  74. openNotificationAccess();
  75. break;
  76. default:
  77. break;
  78. }
  79. }
  80. //......省略
  81. }

4. NotificationListenerService使用过程中有哪些注意事项?

如果细心察看代码的童鞋,一定发现代码中有使用Handler,以及一些奇怪但又被注释掉的代码,比如"a.equals("b")"。从使用上来说,没有必要使用handler,那干嘛要多次一举?这里就给大家分享一下在写NotificationListenerDemo时遇到的一些坑。

①. NotificationMonitor的onCreate方法中使用handler来调用getActiveNotifications()方法

若直接在onCreate或者onBind方法中调用getActiveNotifications()方法是无法获取当前系统通知。主要是因为NotificationMonitor还未完成初始化,而根本原因则是INotificationListenerWrapper对象mWrapper还未初始化,此时使用getActiveNotifications()方法又会调用到mWrapper,因此无法返回正常数据。在NotificationListenerService中可以看到getActiveNotifications()的源码:

[java] view plaincopy

  1. public StatusBarNotification[] getActiveNotifications() {
  2. try {
  3. return getNotificationInterface().getActiveNotificationsFromListener(mWrapper);
  4. } catch (android.os.RemoteException ex) {
  5. Log.v(TAG, "Unable to contact notification manager", ex);
  6. }
  7. return null;
  8. }

也就是说只要在onBind方法完成之后,再调用getActiveNotifications()方法就可以正常获取数据了,因此这里使用了handler多线程的方式。当然,为了保险可以使用sendEmptyMessgeDelay加上延时。

②. 如果NotificationMonitor在onCreate或onBind方法中crash,则该service已经失效,需重启手机才能进行后续开发验证

如果在onCreate或者onBind方法中,出现异常导致NotificationMonitor发生crash,就算找到问题并将其改正,之后的验证还是无法继续进行的,也就是无法收到通知的新增和删除消息,onNotificationPosted和onNotificationRemoved方法不会被调用。

这也是我在onBind方法中故意注释导致空指针异常的代码,有兴趣的童鞋可以把注释去掉后尝试,去掉注释会导致NotificationListenerDemo异常停止,此时你再加上注释再次运行NotificationListenerDemo,虽然程序可以正常启动,但无法正常执行NotificationMonitor中的onNotificationPosted和onNotificationRemoved方法。这个涉及NotificationListenerService的原理,后面会另行分析。

③. MainActivity中onClick方法里使用handler操作

当点击删除通知时,系统通知相关状态还未更新,此时还没有回调到NotificationMonitor中,所以获取的数据就还是上一次的数据。为了能够获取到正确的Notification数据,可以使用handler并加上延时,这样再去获取Notification信息时,系统已经触发了NotificationMonitor回调,数据也有正常了。另外,50ms的延时几乎是感知不到的。

④. 为什么要使用ArrayList来保存StatusBarNotification数组对象

当新增或者删除通知时,会触发onNotificationPosted或onNotificationRemoved回调,在该方法中调用getActiveNotifications()方法用以获取当前系统通知信息。而getActiveNotifications()返回的是StatusBarNotification[]数组,因为这个数组是可变长的,也就是长度会随时变化,因此无法直接存储。使用ArrayList可以很好的解决这个问题,在ArrayList对象中添加一个StatusBarNotification[]对象,之后使用ArrayList.set(0,statusbar[])方法对数据进行更新即可。

总结

NotificationListenerService是Android 4.3 之后新增的接口服务,用于获取系统Notification信息,这在之前的Android版本是无法直接办到的。在Android 4.4中,增加了Notification.extra变量,使得获取Notification相关信息更加丰富,这些接口的开放更加利于三方应用的使用,但同时也会带来一些隐私问题。

本文针对NotificationListenerService的使用进行了详细分析,当然其中不乏有失偏颇的地方,本着互联网知识共享精神也将自己的一些记录发布出来,一来可做笔记,二来希望能够给苦苦寻觅的童鞋一些帮助。

后续会对NotificationListenerService的原理进行分析,敬请期待。

NotificationMonitor代码免积分下载:下载Demo

为了后续能够更新,已经代码传到github上,有兴趣的童鞋可以在github上查看,连接戳这里

分类:Android 时间:2015-05-12 人气:2685
本文关键词:
分享到:

相关文章

iOS 开发

Android 开发

Python 开发

JAVA 开发

开发语言

PHP 开发

Ruby 开发

搜索

前端开发

数据库

开发工具

开放平台

Javascript 开发

.NET 开发

云计算

服务器

Copyright (C) code.minzu.gov.cn, All Rights Reserved.

CodeMinZu 版权所有 苏ICP备163523615号

processed in 1.282 (s). 9 q(s)