利用NotificationListenerService获取微信通知消息的头像和内容
强调下:利用Android原生功能获取第三方APP通知消息是流氓且不道德的(可能沾上官司),本文只讲原理
强调下:利用Android原生功能获取第三方APP通知消息是流氓且不道德的(可能沾上官司),本文只讲原理
强调下:利用Android原生功能获取第三方APP通知消息是流氓且不道德的(可能沾上官司),本文只讲原理
提供一篇灵感文章,写的很好推荐看看https://blog.csdn.net/Vanswells/article/details/81033280
获取Android 微信通知有两条思路,一条是走辅助功能(AccessibilityService),一条是走NotificationListenerService,这里讲第二条路NotificationListenerService。
在App中加入一个类继承NotificationListenerService,用法类似于AccessibilityService,都是需要开通一个权限,但是开通的权限不同
需要在应用启动的时候加一个权限判断,没有开启跳转到对应的Settings界面
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); } 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(); System.out.println("-------------对不起,您的手机暂不支持------------->>"); e.printStackTrace(); return false; } } public boolean isNotificationListenersEnabled() { String pkgName = getPackageName(); final String flat = Settings.Secure.getString(getContentResolver(), "enabled_notification_listeners"); System.out.println("-----flat-------->" + flat); 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; }
权限开通以后,在sevices中就可以获取到我们想要的数据了
import android.app.Notification;import android.app.PendingIntent;import android.graphics.Bitmap;import android.os.Bundle;import android.service.notification.NotificationListenerService;import android.service.notification.StatusBarNotification;import org.greenrobot.eventbus.EventBus;public class MyNotificationListenerService extends NotificationListenerService { @Override public void onListenerConnected() { //当连接成功时调用,一般在开启监听后会回调一次该方法 System.out.println("----------------onListenerConnected--------->"); } @Override public void onNotificationPosted(StatusBarNotification sbn) { //当收到一条消息时回调,sbn里面带有这条消息的具体信息 System.out.println("----------------onNotificationPosted--------->"); System.out.println("----------------onNotificationPosted----1----->" + sbn.getPackageName()); Bundle extras = sbn.getNotification().extras; String title = extras.getString(Notification.EXTRA_TITLE); //通知title String content = extras.getString(Notification.EXTRA_TEXT); //通知内容 int smallIconId = extras.getInt(Notification.EXTRA_SMALL_ICON); //通知小图标id Bitmap largeIcon = extras.getParcelable(Notification.EXTRA_LARGE_ICON); //通知的大图标,注意和获取小图标的区别 PendingIntent pendingIntent = sbn.getNotification().contentIntent; //获取通知的PendingIntent System.out.println("----------------onNotificationPosted----1--1--->" + extras); System.out.println("----------------onNotificationPosted----2----->" + title); System.out.println("----------------onNotificationPosted----3----->" + content); System.out.println("----------------onNotificationPosted----4----->" + smallIconId); System.out.println("----------------onNotificationPosted----5----->" + largeIcon); System.out.println("----------------onNotificationPosted----6----->" + pendingIntent); NoticesBean mBean = new NoticesBean(); mBean.setLargeIcon(largeIcon); mBean.setSmallIconId(smallIconId); if (title == null || largeIcon == null) { return; } EventBus.getDefault().post(mBean); } @Override public void onNotificationRemoved(StatusBarNotification sbn) { //当移除一条消息的时候回调,sbn是被移除的消息 System.out.println("----------------onNotificationRemoved--------->"); }}
log就看的很明显了
title可以用来区分是群聊还是个人消息,如果是群聊,title就是群聊,如果是个人消息,这里就显示消息的发送人
content 是通知消息内容,结构是这样的:[第几条]发件人: 消息内容
largeIcon:获取头像直接用就可以了(个人聊天是可以拿到一个bitmap对象,群聊获取的值是null或者是bitmap对象,是null还是bitmap主要取决于title值的内容,如果title值是“群聊”,那就是null,如果不是群聊就会有头像的bitmap对象)
smallIcon:值衡为0
我加的非空判断是因为有时候会有收到一条消息,但是上报两次,其中第二次是任何数据都没的,为了过滤掉无效数据,这里加个判断
由于数据是在service中获取的,我们肯定是要在Activity或者是fragment中修改view,用EventBus传递数据就可以,很方便
在AndroidManifest.xml配置service
更多相关文章
- 将Unity3D项目导出到Android工程中二次开发并实现之间的数据交互
- android连接onenet之获取onenet数据流和更新onnet数据流
- Android如何用json格式传数据到后台(SSM) 做一个简单的登录流程
- Android Handler消息队列的实现原理
- Android登录客户端,验证码的获取,网页数据抓取与解析,HttpWatch基本
- Android 中 ListView 分页加载数据
- Android中的通知和自定义通知布局