Android利用NotificationListenerService实现消息盒子功能

背景

现在市面上很多垃圾清理软件基本上都有消息盒子这个功能,就是把用户收到的推送消息全部收集起来集中管理,避免太多推送给用户带来烦恼。这个功能就是基于Android 提供的NotificationListenerService来实现的。

使用

在api18(Android 4.3) Google加入了NotificationListenerService,下面我们来看看NotificationListenerService的具体使用。

新建一个MyNotificationListenerService继承自NotificationListenerService,实现其中的三个方法onListenerConnected()、onNotificationPosted(StatusBarNotification sbn)和onNotificationRemoved(StatusBarNotification sbn)。

public class MyNotificationListenerService extends NotificationListenerService {@Override
public void onListenerConnected() {//当连接成功时调用,一般在开启监听后会回调一次该方法
}@Override
public void onNotificationPosted(StatusBarNotification sbn) {//当收到一条消息时回调,sbn里面带有这条消息的具体信息
}@Override
public void onNotificationRemoved(StatusBarNotification sbn) {//当移除一条消息的时候回调,sbn是被移除的消息
}

}

当然,还需要在Manifest中声明这个服务

 <serviceandroid:name=".MyNotificationListenerService"android:label="@string/app_name"android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"><intent-filter><action android:name="android.service.notification.NotificationListenerService" /></intent-filter></service>

每个方法是主要作用在上面的注释都写的比较清楚了。

NotificationListenerService中还有一些方法可供我们使用,下面是一些经常使用的方法:

  • cancelAllNotifications(); //移除所有可移除的通知
  • cancelNotification(String key); //移除指定key的通知,要求api21以上
  • cancelNotifications(String[] keys); //移除指定数组内的所有key的通知,要求api21以上
  • getActiveNotifications(); //获取通知栏上的所有通知,返回一个StatusBarNotification[]

StatusBarNotification

StatusBarNotification是通知栏的通知对象,里面包含了一条通知的所有信息。具体的如下:

  • getPackageName(); //获取发送通知的应用程序包名
  • isClearable(); //通知是否可被清除
  • getId(); //获取通知id
  • getKey(); //获取通知的key
  • getPostTime(); //通知的发送时间
  • getNotification(); //获取Notification

通过上面我们看到,StatusBarNotification能直接获取到到信息很少,但是其中有一个getNotification()方法可以获取到一个Notification对象,通过Notification可以获取到通知到标题,内容,图标以及通知的意图PendingIntent等信息。
如下:

@Override
public void onNotificationPosted(StatusBarNotification sbn) {Bundle extras = sbn.getNotification().extras;String title = extras.getString(Notification.EXTRA_TITLE); //通知titleString content = extras.getString(Notification.EXTRA_TEXT); //通知内容int smallIconId = extras.getInt(Notification.EXTRA_SMALL_ICON); //通知小图标idBitmap largeIcon =  extras.getParcelable(Notification.EXTRA_LARGE_ICON); //通知的大图标,注意和获取小图标的区别PendingIntent pendingIntent = sbn.getNotification().contentIntent; //获取通知的PendingIntent
}

注意

在上面的代码中,注意获取通知小图标和大图标时的区别,小图标获取到的是一个int型的资源id,而大图标是一个序列化后的bitmap,这点需要特别注意,还有,一些通知的大图标获取可能为null,需要注意空指针异常。

获取到的小图标id怎么转为图标呢?可以使用下面的方法:

/*** * @param context* @param id 图标id* @param pkgName 图标所在的包名* @return bitmap*/
public static Bitmap getSmallIcon(ApplicationContext context,String pkgName, int id) {Bitmap smallIcon = null;Context remotePkgContext;try {remotePkgContext = context.createPackageContext(pkgName, 0);Drawable drawable = remotePkgContext.getResources().getDrawable(id);if (drawable != null) {smallIcon = ((BitmapDrawable) drawable).getBitmap();}} catch (Exception e) {e.printStackTrace();}return smallIcon;
}

通过上面的介绍,现在就可以监听到通知的产生和清除事件了,并且可以获取到通知的具体内容进行一些自己的处理。

NotificationListenerService是一个系统级别的服务,它不需要我们去start或者bind来开启,也不能关闭它,会自动监听消息,但是前提是你的App拥有获取通知权限,下面介绍怎么判断应用是否拥有获取通知权限以及怎么打开获取通知权限。

获取通知权限的判断及打开通知权限设置页面

判断是否拥有通知权限

public boolean isNotificationListenersEnabled() {String pkgName = getPackageName();final String flat = Settings.Secure.getString(getContentResolver(), "enabled_notification_listeners");if (!TextUtils.isEmpty(flat)) {final String[] names = flat.split(":");for (int i = 0; i < names.length; i++) {final ComponentName cn = ComponentName.unflattenFromString(names[i]);if (cn != null) {if (TextUtils.equals(pkgName, cn.getPackageName())) {return true;}}}}return false;
}

打开通知权限设置页面

protected boolean gotoNotificationAccessSetting() {try {Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);startActivity(intent);return true;} catch (ActivityNotFoundException e) {//普通情况下找不到的时候需要再特殊处理找一次try {Intent intent = new Intent();intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);ComponentName cn = new ComponentName("com.android.settings", "com.android.settings.Settings$NotificationAccessSettingsActivity");intent.setComponent(cn);intent.putExtra(":settings:show_fragment", "NotificationAccessSettings");startActivity(intent);return true;} catch (Exception e1) {e1.printStackTrace();}Toast.makeText(this, "对不起,您的手机暂不支持", Toast.LENGTH_SHORT).show();e.printStackTrace();return false;}
}

最后

在使用过程中,我发现了一个问题,就是在退出app后,再次打开,监听不生效,这个时候我们需要做一些处理。在app启动时,我们去重新关闭打开一次监听服务,让它正常工作。

 private void toggleNotificationListenerService(Context context) {PackageManager pm = context.getPackageManager();pm.setComponentEnabledSetting(new ComponentName(context, MyNotificationListenerService .class),PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);pm.setComponentEnabledSetting(new ComponentName(context, MyNotificationListenerService .class),PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
}

在打开服务后,在某些手机上,NotificationListenerService并不会马上触发onListenerConnected()方法,需要等待几秒的时间。

总结

总体来说,NotificationListenerService的使用还是比较简单,主要就是onListenerConnected(),onNotificationPosted(StatusBarNotification sbn),onNotificationRemoved(StatusBarNotification sbn)这三个方法和通过StatusBarNotification,Notification获取消息的具体内容。

若有问题,欢迎指出
email:fzp0804@163.com

Android利用NotificationListenerService实现消息盒子功能相关推荐

  1. 我的Android进阶之旅------Android利用Sensor(传感器)实现水平仪功能的小例

    这里介绍的水平仪,指的是比较传统的气泡水平仪,在一个透明圆盘内充满液体,液体中留有一个气泡,当一端翘起时,该气泡就会浮向翘起的一端.    利用方向传感器返回的第一个参数,实现了一个指南针小应用.   ...

  2. android mysql 搜索功能_android利用数据库实现搜索联想功能

    [实例简介] android利用数据库实现搜索联想功能.主要实现的效果是和google百度搜索一样,实现联想功能. [实例截图] [核心代码] 4e431bd8-d287-4028-8476-7510 ...

  3. android列表实现置顶,Android利用RecyclerView实现全选、置顶和拖拽功能示例

    Android利用RecyclerView实现全选.置顶和拖拽功能示例 发布时间:2020-08-23 16:26:42 来源:脚本之家 阅读:159 作者:爱开发 前言 今天给大家分享是如何在Rec ...

  4. android实现计算器功能吗,利用Android实现一个简单的计算器功能

    利用Android实现一个简单的计算器功能 发布时间:2020-11-20 16:25:01 来源:亿速云 阅读:90 作者:Leah 今天就跟大家聊聊有关利用Android实现一个简单的计算器功能, ...

  5. android放微信@功能,Android仿微信语音消息的录制和播放功能

    一.简述 效果: 实现功能: 长按Button时改变Button显示文字,弹出Dialog(动态更新音量),动态生成录音文件,开始录音: 监听手指动作,规定区域.录音状态下手指划出规定区域取消录音,删 ...

  6. 利用 Android 系统原生 API 实现分享功能

    对于 App 的分享功能,基本上是一个刚需,本文主要介绍运用系统原生分享功能时候需要注意的一些问题.对于某些特定平台的一些高级分享特性,比如微信或者微博之类的分享来源标注,需要在其开放平台注册应用再接 ...

  7. android仿微信语音聊天功能,Android仿微信发送语音消息的功能及示例代码

    微信的发送语音是有一个向上取消的,我们使用ontouchlistener来监听手势,然后做出相应的操作就行了. 直接上代码: //语音操作对象 private mediaplayer mplayer ...

  8. Android仿微信朋友圈6之实现消息提醒功能

    之前有朋友问我消息提醒咋实现,我一直没有整理出来,今天就放出来.微信朋友圈的消息提醒就是收到朋友的评论后背景底部显示消息条数和评论用户,顶部是一张相册背景和当前用户昵称头像. 1.消息提醒的布局如下: ...

  9. LINE分享android利用系统自带分享实现LINE分享功能

    android利用系统自带分享实现分享功能之LINE分享 最近公司向海外发展,提出了一个国外主流的社交APP分享需求.原来我使用的是第三方分享工具,但是太鸡肋,国内的APP支持的还是不错的,但是国外支 ...

  10. Android 融云单聊与群聊消息免打扰功能设置与消息删除功能实现

    一.设置群聊与单聊消息免打扰功能: 1.下面直接进入逻辑代码: 实现监听事件: /*** 设置会话列表界面操作的监听器.*/RongIM.setConversationListBehaviorList ...

最新文章

  1. 55.npm install 报错 :stack Error: Can't find Python executable python
  2. 如何确定开关电源TL431反馈回路的参数
  3. 【集合框架】JDK1.8源码分析之IdentityHashMap(四)
  4. php打印文件目录结构,php和java关于目录树(列出某一目录下文件结构)
  5. 用系统滚动条实现NumericUpDown的原理
  6. Android组件之Service
  7. iOS之LLVM编译流程和Clang插件开发集成
  8. wordpress中非插件统计文章浏览次数
  9. CSU 1203 Super-increasing sequence
  10. Python在运维工作中的经典应用之ansible
  11. js库编写的环境和准备工作
  12. ViewState EnableViewState 禁用与使用心得
  13. html调色板快捷键,12款web前端最佳调色板工具
  14. H5传奇源码,附带微信支付,商城系统,新增了元宝交易商城系统源码
  15. 苹果电脑上的Word打不开怎么办?Word文件怎么恢复?
  16. 申请计算机助理的英语作文,高考模拟英语作文 申请暑假英语助理编辑职位
  17. 晶品特装科创板上市:市值68亿 主打地面无人装备研发与产销
  18. linux vmware 共享文件夹共享,解决vmware上使用linux虚拟,无法共享文件的问题
  19. 前端调取.net core webapi 报错:“...CORS policy: Response to preflight request ...“的问题成因和解决办法。
  20. Java方向发展前景与就业方向探讨

热门文章

  1. android平板太卡要怎么办,怎么解决平板电脑卡顿的问题?
  2. Graphene-SGX 总结
  3. 机器学习可解释性(二) 之 可解释模型
  4. ERP开源框架 + 二次开发平台 介绍
  5. Effective C++ item 6
  6. 新浪云存储 php,【PHP】新浪云SAE平台将本地图片和远程图片保存至Storage
  7. Android解析XML文件(assets目录)
  8. P1834 种花小游戏
  9. 计算机无法显示移动硬盘,谁知道移动硬盘在电脑显示不出来是怎么回事?
  10. 什么是智能DNS解析?