6

オブジェクトからテキストを取得する必要がありRemoteViewsます。LayoutIdを取得することは可能ですが、これに含まれるテキストTextViewRemoteViewつまり通知)からテキストを取得する方法がわかりません。

また、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にアクセスできます。layoutIdを取得するには、RemoteViewsnotification.contentViewPendingIntentnotification.contentIntentcontentView.getLayoutId()

4

4 に答える 4

9

ここで、リフレクションを使用して問題を解決する同様のソリューションを提案しましたが、より親しみやすい方法です。これが私の解決策です。このコンテキストでは、RemoteViews は Notification から取得されたものであるため、RemoteViews オブジェクトに既にアクセスできる場合は、最初の 3 行はおそらく無視できます。ページ上のリンクは、実際に何が起こっているかについてのより詳細な説明を提供します。これが同様の問題を抱えている人に役立つことを願っています。

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;
}
于 2013-12-02T06:44:21.787 に答える
5

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();
}
于 2012-06-11T09:17:20.503 に答える
0

この質問のCommonsWareは次のように述べて います。

... アプリ ウィジェットは書き込み専用です。データをプッシュすることはできますが、読み取ることはできません。代わりに、アプリ ウィジェットを新しいテキストで更新する場合、そのテキストをどこかに (おそらくファイルに) 保存する必要があります。

彼の答えは論理的であるようだ。

于 2012-06-10T14:19:54.203 に答える