安卓app 实现监听手机app全局弹窗消息通知功能
安卓app 实现监听手机app全局弹窗消息通知功能
-
获取相关权限.
try {startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)); } catch (Exception e) {startActivity(new Intent(Settings.ACTION_SETTINGS)); } startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));
-
创建无障碍, 监听消息通知全局Service
package com.yuqirong.listenwechatnotification;import android.accessibilityservice.AccessibilityService; import android.app.Notification; import android.app.PendingIntent; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.view.accessibility.AccessibilityEvent; import android.widget.RemoteViews;import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List;/*** Created by Anyway on 2017/2/11.*/public class WeChatAccessibilityService extends AccessibilityService {@Overridepublic void onAccessibilityEvent(AccessibilityEvent event) {if (Build.VERSION.SDK_INT < 18) {Notification notification = (Notification) event.getParcelableData();List<String> textList = getText(notification);if (textList != null && textList.size() > 0) {for (String text : textList) {if (!TextUtils.isEmpty(text)) {System.out.println(text);}break;}}}}@Overridepublic void onInterrupt() {}public List<String> getText(Notification notification) {if (null == notification) {return null;}RemoteViews views = notification.bigContentView;if (views == null) {views = notification.contentView;}if (views == null) {return null;}// Use reflection to examine the m_actions member of the given RemoteViews object.// It's not pretty, but it works.List<String> text = new ArrayList<>();try {Field field = views.getClass().getDeclaredField("mActions");field.setAccessible(true);@SuppressWarnings("unchecked")ArrayList<Parcelable> actions = (ArrayList<Parcelable>) field.get(views);// Find the setText() and setTime() reflection actionsfor (Parcelable p : actions) {Parcel parcel = Parcel.obtain();p.writeToParcel(parcel, 0);parcel.setDataPosition(0);// The tag tells which type of action it is (2 is ReflectionAction, from the source)int tag = parcel.readInt();if (tag != 2) continue;// View IDparcel.readInt();String methodName = parcel.readString();if (null == methodName) {continue;} else if (methodName.equals("setText")) {// Parameter type (10 = Character Sequence)parcel.readInt();// Store the actual stringString t = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel).toString().trim();text.add(t);}parcel.recycle();}} catch (Exception e) {e.printStackTrace();}return text;}}
package com.yuqirong.listenwechatnotification;import android.annotation.TargetApi; import android.app.Notification; import android.app.PendingIntent; import android.os.Build; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; import android.text.TextUtils; import android.widget.RemoteViews;import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List;/*** Created by Anyway on 2017/2/10.*/@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) public class WeChatNotificationListenerService extends NotificationListenerService {@Overridepublic void onNotificationPosted(StatusBarNotification sbn) {// 如果该通知的包名不是微信,那么 pass 掉if (!"com.tencent.mm".equals(sbn.getPackageName())) {return;}Notification notification = sbn.getNotification();if (notification == null) {return;}PendingIntent pendingIntent = null;// 当 API > 18 时,使用 extras 获取通知的详细信息if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {Bundle extras = notification.extras;if (extras != null) {// 获取通知标题String title = extras.getString(Notification.EXTRA_TITLE, "");// 获取通知内容String content = extras.getString(Notification.EXTRA_TEXT, "");if (!TextUtils.isEmpty(content)) {System.out.println(title+":"+content);}}} else {// 当 API = 18 时,利用反射获取内容字段List<String> textList = getText(notification);if (textList != null && textList.size() > 0) {for (String text : textList) {if (!TextUtils.isEmpty(text) && text.contains("[微信红包]")) {pendingIntent = notification.contentIntent;break;}}}}// send pendingIntent to open wechattry {if (pendingIntent != null) {pendingIntent.send();}} catch (PendingIntent.CanceledException e) {e.printStackTrace();}}@Overridepublic void onNotificationRemoved(StatusBarNotification sbn) {super.onNotificationRemoved(sbn);}public List<String> getText(Notification notification) {if (null == notification) {return null;}RemoteViews views = notification.bigContentView;if (views == null) {views = notification.contentView;}if (views == null) {return null;}// Use reflection to examine the m_actions member of the given RemoteViews object.// It's not pretty, but it works.List<String> text = new ArrayList<>();try {Field field = views.getClass().getDeclaredField("mActions");field.setAccessible(true);@SuppressWarnings("unchecked")ArrayList<Parcelable> actions = (ArrayList<Parcelable>) field.get(views);// Find the setText() and setTime() reflection actionsfor (Parcelable p : actions) {Parcel parcel = Parcel.obtain();p.writeToParcel(parcel, 0);parcel.setDataPosition(0);// The tag tells which type of action it is (2 is ReflectionAction, from the source)int tag = parcel.readInt();if (tag != 2) continue;// View IDparcel.readInt();String methodName = parcel.readString();if (null == methodName) {continue;} else if (methodName.equals("setText")) {// Parameter type (10 = Character Sequence)parcel.readInt();// Store the actual stringString t = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel).toString().trim();text.add(t);}parcel.recycle();}} catch (Exception e) {e.printStackTrace();}return text;}}
参考github项目, NotificationListenerService
if (!"com.tencent.mm".equals(sbn.getPackageName())) {return;}非微信的通知, 直接返回, 不处理.if (extras != null) {// 获取通知标题String title = extras.getString(Notification.EXTRA_TITLE, "");// 获取通知内容String content = extras.getString(Notification.EXTRA_TEXT, "");if (!TextUtils.isEmpty(content)) {// 这里就可以获取到弹窗通知的头和消息题了.System.out.println(title+":"+content);}}
注意: 想要获取到具体的内容, 需要到app内部消息通知开启消息详情.
-
声明: 本文章只做为技术分享, 切勿用于非法行为, 造成后果与本人无关