7

私が理解したように、これは可能です。ここから トーストメッセージを検出します が、リンクからのコードスニペットでイベントをキャッチすることはできません。

MyAccessibilityService.java

package com.test.toasts2;

import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.Notification;
import android.os.Parcelable;
import android.view.accessibility.AccessibilityEvent;
import android.widget.Toast;

public class MyAccessibilityService extends AccessibilityService {

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        System.out.println("event catched");
        Toast.makeText(this, "catched " + "!", Toast.LENGTH_SHORT).show();
        if(event.getEventType() != AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED)
            return; // event is not a notification

        String sourcePackageName = (String)event.getPackageName();

        Parcelable parcelable = event.getParcelableData();
        if(parcelable instanceof Notification){
            // Statusbar Notification
        }
        else{
            // something else, e.g. a Toast message
            String log = "Message: "+event.getText().get(0)+" [Source: "+sourcePackageName+"]";
            System.out.println(log);
            // write `log` to file...
        }
    }

                 @Override 
                 public void onInterrupt() {
                  // TODO Auto-generated method stub   
                 }

                 @Override
                 protected void onServiceConnected() {
                  // TODO Auto-generated method stub
                  super.onServiceConnected();
                  AccessibilityServiceInfo info = new AccessibilityServiceInfo();
                  info.feedbackType = AccessibilityServiceInfo.DEFAULT;
                  setServiceInfo(info);
                 }


}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.toasts2"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="15" />

  <application>
  <service android:name=".MyAccessibilityService"
      android:label="label">
    <intent-filter>
      <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>

  </service>
</application>

</manifest>

このサービスは単に開始されていないようです。私が間違っていることは何ですか?

これを行う理由: アプリからストックランチャーに多くのショートカットをインストールしています。これらのショートカットが1つのセルに重ねて配置されているという問題があります(Sleep 500でも役に立ちませんでした)。だから私はそれらを一つずつインストールする方法を見つけています。しかし、ショートカットが正常にインストールされたことを知る方法はありますか?icsランチャーがユーザーに表示するメッセージのみを見つけました。

4

3 に答える 3

3

TYPE_NOTIFICATION_STATE_CHANGED は通常、ステータス バーに配置された NotificationManager とアイコンを指します。とはいえ、以下のコードは、トースト メッセージの出所を明らかにするのに役立つはずです。Android 4.0.4 ICS では、Toast には のクラスがあるandroid.widget.ToastためgetClassName、うまくいくはずです。

その価値のために、Android 4.0.3 で次のメソッドを追加して使用するように変更が加えられたようです。Toast.TN

private void trySendAccessibilityEvent() {
        AccessibilityManager accessibilityManager =
                AccessibilityManager.getInstance(mView.getContext());
        if (!accessibilityManager.isEnabled()) {
            return;
        }
        // treat toasts as notifications since they are used to
        // announce a transient piece of information to the user
        AccessibilityEvent event = AccessibilityEvent.obtain(
                AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
        event.setClassName(getClass().getName());
        event.setPackageName(mView.getContext().getPackageName());
        mView.dispatchPopulateAccessibilityEvent(event);
        accessibilityManager.sendAccessibilityEvent(event);
    }

ToastAndroid のすべてのバージョンのクラスは、こちらで確認できます。

private final String getEventType(AccessibilityEvent event) {
    switch (event.getEventType()) {
        case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
            return "TYPE_NOTIFICATION_STATE_CHANGED";
        case AccessibilityEvent.TYPE_VIEW_CLICKED:
            return "TYPE_VIEW_CLICKED";
        case AccessibilityEvent.TYPE_VIEW_FOCUSED:
            return "TYPE_VIEW_FOCUSED";
        case AccessibilityEvent.TYPE_VIEW_LONG_CLICKED:
            return "TYPE_VIEW_LONG_CLICKED";
        case AccessibilityEvent.TYPE_VIEW_SELECTED:
            return "TYPE_VIEW_SELECTED";
        case AccessibilityEvent.TYPE_VIEW_SCROLLED:
            return "TYPE_VIEW_SCROLLED";
        case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT:
            return "TYPE_VIEW_HOVER_EXIT";
        case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
            return "TYPE_VIEW_HOVER_ENTER";
        case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START:
            return "TYPE_TOUCH_EXPLORATION_GESTURE_START";
        case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END:
            return "TYPE_TOUCH_EXPLORATION_GESTURE_END";
        case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
            return "TYPE_WINDOW_STATE_CHANGED";
        case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
            return "TYPE_WINDOW_CONTENT_CHANGED";
        case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED:
            return "TYPE_VIEW_TEXT_SELECTION_CHANGED";
        case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED:
            return "TYPE_VIEW_TEXT_CHANGED";
    }

    return "default";
}

private final String getEventText(AccessibilityEvent event) {
    StringBuilder sb = new StringBuilder();
    for (CharSequence s : event.getText()) {
        sb.append(s);
        sb.append('\n');
    }
    return sb.toString();
}

@Override
public void onAccessibilityEvent(AccessibilityEvent event)
{
    Log.v(TAG, String.format(
        "onAccessibilityEvent: [type] %s [class] %s [package] %s [time] 
        %s [fullscreen] %s [text] %s", getEventType(event), event.getClassName(),
        event.getPackageName(), event.getEventTime(), Boolean.toString(
        event.isFullScreen()), getEventText(event)));

    if (android.os.Build.VERSION.SDK_INT >= 14)
        Log.v(TAG, "Window ID: " + Integer.toString(event.getWindowId()) + ".");
}

private void setServiceInfo(int feedbackType)
{
    final AccessibilityServiceInfo info = new AccessibilityServiceInfo();
    // We are interested in all types of accessibility events.
    info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
    // We want to provide specific type of feedback.
    info.feedbackType = feedbackType;
    // We want to receive events in a certain interval.
    // info.notificationTimeout = EVENT_NOTIFICATION_TIMEOUT_MILLIS;
    // We want to receive accessibility events only from certain packages.
    // info.packageNames = PACKAGE_NAMES;
    setServiceInfo(info);
}

private boolean isInfrastructureInitialized = false;

@Override
public void onServiceConnected()
{   
    if (isInfrastructureInitialized) return;

    // Claim the events with which to listen to.
    setServiceInfo(AccessibilityServiceInfo.FEEDBACK_ALL_MASK);

    // We are in an initialized state now.
    isInfrastructureInitialized = true;
}

出典:個人的な経験

于 2012-06-23T03:58:34.743 に答える
0

インテントを構築するアクティビティを作成し、それを使用してサービスを開始します。

このようなものがアクティビティ内のコードになります。

Intent i = new Intent(YourActivity.this, MyAccessibilityService.class);
startService(i);

マニフェストで、アクティビティのインテントフィルターにMAINとLAUNCHERを含めて、ユーザー(またはadb)がアプリを起動したときに実行されるアクティビティになるようにします。その後、アクティビティによってサービスが開始されます。

編集:あなたがリンクした投稿からこのメモを見たと思います。そして、あなたは2.2でこれを試していませんか?

注:これはAndroid 2.2では機能しませんでした(Toastをキャッチしていないようです)が、Android4.0では機能しました。

于 2012-06-15T19:24:34.127 に答える
0

まず第一に、これはトーストを画面に表示する非同期呼び出しであり、タイミングに応じて画面にとどまるため、トーストをキャッチしようとしないでください。アプリケーションを離れても、トースト登場。これは無関係なので、乾杯がいつ行われるかは気にしないでください。トーストを使用する必要があるのは、進行中/完了した特定のプロセスに関する情報、または単なる情報をユーザーに提供するためだけです。あなたがやろうとしていることを意図したものではありません。

内部ブロードキャストをアプリケーションに送信し、インテント フィルターを介してキャッチし、そのブロードキャストを受信したら、サービスを開始する必要があります。

于 2012-06-15T20:19:56.320 に答える