从parcelable、contentView 或contentIntent 中提取通知文本 [英] Extract notification text from parcelable, contentView or contentIntent

查看:26
本文介绍了从parcelable、contentView 或contentIntent 中提取通知文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我让我的 AccessibilityService 使用以下代码:

@Override公共无效 onAccessibilityEvent(AccessibilityEvent 事件){if (event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {列表通知列表 = event.getText();for (int i = 0; i 

它可以很好地读出创建通知时显示的文本(1).

唯一的问题是,我还需要用户打开通知栏时显示的(3)的值.(2) 对我来说并不重要,但知道如何阅读它会很好.您可能知道,所有值都可能不同.

那么,我怎样才能读出(3)?我怀疑这是不可能的,但我的 notificationList 似乎只有一个条目(至少只显示了一个 toast).

非常感谢!

/edit:我可以用

提取通知包

if (!(parcel instanceof Notification)) {返回;}最终通知通知 = (Notification) 包裹;

但是,我不知道如何从 notificationnotification.contentView/notification.contentIntent 中提取通知的消息.

有什么想法吗?

/edit:澄清这里的问题:我怎样才能读出(3)?

解决方案

我已经浪费了最后几天的几个小时来找出一种方法来做你(顺便说一下,我也是)想做的事情.在查看了 RemoteViews 的整个源代码两次后,我认为完成这项任务的唯一方法是使用旧的、丑陋的和 hacky 的 Java 反射.

这是:

 Notification notification = (Notification) event.getParcelableData();RemoteViews 视图 = notification.contentView;类secretClass = views.getClass();尝试 {映射<整数,字符串>text = new HashMap();字段outerFields[] = secretClass.getDeclaredFields();for (int i = 0; i 动作 = (ArrayList) outerFields[i].get(views);for(对象动作:动作){字段innerFields[] = action.getClass().getDeclaredFields();对象值 = 空;整数类型 = null;整数 viewId = null;for(字段字段:innerFields){field.setAccessible(true);if (field.getName().equals("value")) {值 = field.get(action);} else if (field.getName().equals("type")) {type = field.getInt(action);} else if (field.getName().equals("viewId")) {viewId = field.getInt(action);}}如果(类型 == 9 || 类型 == 10){text.put(viewId, value.toString());}}System.out.println("标题为:" + text.get(16908310));System.out.println("信息为:" + text.get(16909082));System.out.println("文本为:" + text.get(16908358));}} 捕获(异常 e){e.printStackTrace();}

此代码在搭载 Android 4.0.3 的 Nexus S 上运行良好.但是,我没有测试它是否适用于其他版本的 Android.很可能某些值,尤其是 viewId 发生了变化.我认为应该有办法支持所有版本的 Android,而无需对所有可能的 ID 进行硬编码,但这是另一个问题的答案......;)

PS:您要查找的值(在原始问题中称为(3)")是文本"值.

So I got my AccessibilityService working with the following code:

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    if (event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
        List<CharSequence> notificationList = event.getText();
        for (int i = 0; i < notificationList.size(); i++) {
            Toast.makeText(this.getApplicationContext(), notificationList.get(i), 1).show();
        }
    }
}

It works fine for reading out the text displayed when the notifcation was created (1).

The only problem is, I also need the value of (3) which is displayed when the user opens the notification bar. (2) is not important for me, but it would be nice to know how to read it out. As you probably know, all values can be different.

So, how can I read out (3)? I doubt this is impossible, but my notificationList seems to have only one entry (at least only one toast is shown).

Thanks a lot!

/edit: I could extract the notification parcel with

if (!(parcel instanceof Notification)) {
            return;
        }
        final Notification notification = (Notification) parcel;

However, I have no idea how to extract the notifcation's message either from notification or notification.contentView / notification.contentIntent.

Any ideas?

/edit: To clarify what is asked here: How can I read out (3)?

解决方案

I've wasted a few hours of the last days figuring out a way to do what you (and, me too, by the way) want to do. After looking through the whole source of RemoteViews twice, I figured the only way to accomplish this task is good old, ugly and hacky Java Reflections.

Here it is:

    Notification notification = (Notification) event.getParcelableData();
    RemoteViews views = notification.contentView;
    Class secretClass = views.getClass();

    try {
        Map<Integer, String> text = new HashMap<Integer, String>();

        Field outerFields[] = secretClass.getDeclaredFields();
        for (int i = 0; i < outerFields.length; i++) {
            if (!outerFields[i].getName().equals("mActions")) continue;

            outerFields[i].setAccessible(true);

            ArrayList<Object> actions = (ArrayList<Object>) outerFields[i]
                    .get(views);
            for (Object action : actions) {
                Field innerFields[] = action.getClass().getDeclaredFields();

                Object value = null;
                Integer type = null;
                Integer viewId = null;
                for (Field field : innerFields) {
                    field.setAccessible(true);
                    if (field.getName().equals("value")) {
                        value = field.get(action);
                    } else if (field.getName().equals("type")) {
                        type = field.getInt(action);
                    } else if (field.getName().equals("viewId")) {
                        viewId = field.getInt(action);
                    }
                }

                if (type == 9 || type == 10) {
                    text.put(viewId, value.toString());
                }
            }

            System.out.println("title is: " + text.get(16908310));
            System.out.println("info is: " + text.get(16909082));
            System.out.println("text is: " + text.get(16908358));
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

This code worked fine on a Nexus S with Android 4.0.3. However, I didn't test if it works on other versions of Android. It's very likely that some values, especially the viewId changed. I think there should be ways to support all versions of Android without hard-coding all possible ids, but that's the answer to another question... ;)

PS: The value you're looking for (referring to as "(3)" in your original question) is the "text"-value.

这篇关于从parcelable、contentView 或contentIntent 中提取通知文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆