Получить текст из объекта RemoteViews - PullRequest
5 голосов
/ 15 февраля 2012

Мне нужно получить текст из объекта RemoteViews. Я могу получить LayoutId, но я не знаю, как извлечь текст из TextView, который находится в этом RemoteView (а именно в уведомлении).

Также RemoteView содержит только сеттеры, но не геттеры, поэтому я думаю, что мне нужно использовать LayoutId (как-то).

Можете ли вы помочь мне с этим? Спасибо!

/ edit: Причина, по которой я спрашиваю об этом, заключается в том, что у меня есть AccessibilityService, который получает уведомление. Поэтому это единственный способ получить значение.

/ edit2: Я использую этот код для получения уведомления:

@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();
        }
        if (!(parcel instanceof Notification)) {
            return;
        }
        final Notification notification = (Notification) parcel;
        doMoreStuff();

    }
}

С объектом notification у меня есть доступ к RemoteViews (notification.contentView) и к PendingIntent (notification.contentIntent). Чтобы получить layoutId, я могу позвонить contentView.getLayoutId()

Ответы [ 4 ]

7 голосов
/ 02 декабря 2013

Я предложил подобное решение здесь , которое также использует отражение для решения проблемы, но более доступным способом. Это моё решение. В этом контексте RemoteViews пришли из Уведомления, поэтому первые три строки, вероятно, можно игнорировать, если у вас уже есть доступ к объекту RemoteViews. Ссылка на странице дает гораздо более подробное объяснение того, что на самом деле происходит. Я надеюсь, что это поможет любому с подобной проблемой.

public static List<String> getText(Notification notification)
{
    // We have to extract the information from the view
    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<String>();
    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 actions
        for (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 ID
            parcel.readInt();

            String methodName = parcel.readString();
            if (methodName == null) continue;

            // Save strings
            else if (methodName.equals("setText"))
            {
                // Parameter type (10 = Character Sequence)
                parcel.readInt();

                // Store the actual string
                String t = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel).toString().trim();
                text.add(t);
            }

            // Save times. Comment this section out if the notification time isn't important
            else if (methodName.equals("setTime"))
            {
                // Parameter type (5 = Long)
                parcel.readInt();

                String t = new SimpleDateFormat("h:mm a").format(new Date(parcel.readLong()));
                text.add(t);
            }

            parcel.recycle();
        }
    }

    // It's not usually good style to do this, but then again, neither is the use of reflection...
    catch (Exception e)
    {
        Log.e("NotificationClassifier", e.toString());
    }

    return text;
}
4 голосов
/ 11 июня 2012

Взято из Извлечение текста уведомления из parcelable, contentView или contentIntent :

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();
}
0 голосов
/ 14 августа 2016

Если вы ориентируетесь на Android 19+, вы можете использовать следующий код для получения заголовка / текста из объекта уведомления без использования каких-либо частных API.

Notification noty = ...;
Bundle extras = noty.extras;
if (extras != null) {
  String title = extras.getString(Notification.EXTRA_TITLE);
  String text = extras.getString(Notification.EXTRA_TEXT);
}
0 голосов
/ 10 июня 2012

CommonsWare в этот вопрос говорит:

... Виджеты приложения только для записи : вы можете передавать данныеим, но вы не можете их прочитать.Вместо этого, когда вы обновите виджет вашего приложения новым текстом, вам нужно будет сохранить этот текст где-нибудь, возможно, в файле.

Его ответ кажется логичным.

...