辅助功能事件未在Activity启动时被服务捕获

时间:2015-03-25 16:57:24

标签: android android-service accessibility

当用户启动活动时,我试图让我的应用向我的自定义AccessibilityService宣布一些信息。我有一个TextView在活动开始时调用requestFocus(),然后我发送一个AccessibilityEvent让AccessibilityService读取TextView的内容描述。我已将问题分解为一个小应用程序。

这是主要活动:

package com.example.ttstest;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        View v = findViewById(R.id.textView1);
        v.requestFocus();
        v.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT);
    }
}

布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.ttstest.MainActivity" >

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:contentDescription="Secondarily focused text view"
        android:text="@string/hello_world" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView2"
        android:layout_marginLeft="54dp"
        android:layout_marginTop="145dp"
        android:layout_toRightOf="@+id/textView2"
        android:contentDescription="Initially focused text view"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:text="Initially focused text view" />

</RelativeLayout>

AccessibilityService:

package com.example.ttstest;

import android.accessibilityservice.AccessibilityService;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;

public class TextToSpeechService extends AccessibilityService {
    private static TextToSpeech textToSpeech = null;
    private static boolean ttsReady = false;

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        Log.e("TextToSpeechService", "Got to onServiceConnected()");
        textToSpeech = new TextToSpeech(this.getApplicationContext(), new OnInitListener() {
            @Override
            public void onInit(int status) {
                if(status == TextToSpeech.SUCCESS) {
                    ttsReady = true;
                }
            }
        });
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        Log.e("TextToSpeechService", "Entering onAccessibilityEvent().");
        Log.e("TextToSpeechService", "Event type: " + event.getEventType() + ", from class " + event.getClassName());
        if(event.getContentDescription() != null) {
            Log.e("TextToSpeechService", "" + event.getContentDescription());
        }
        if(textToSpeech != null && ttsReady == true) {
            if(event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
                CharSequence contentDescription = event.getContentDescription();
                if(contentDescription != null) {
                    String say = contentDescription.toString();
                    textToSpeech.speak(say, TextToSpeech.QUEUE_FLUSH, null);
                }
            } else if (event.getEventType() == AccessibilityEvent.TYPE_ANNOUNCEMENT) {
                CharSequence contentDescription = event.getContentDescription();
                if(contentDescription != null) {
                    textToSpeech.speak(event.getContentDescription().toString(), TextToSpeech.QUEUE_FLUSH, null);
                }
            }
        }
        Log.e("TextToSpeechService", "Exiting onAccessibilityEvent().");
    }

    @Override
    public void onInterrupt() {
        Log.e("TextToSpeechService", "Entering onInterrupt()");
        if(textToSpeech != null && ttsReady == true) {
            textToSpeech.stop();
        }
    }
}

这已添加到我的AndroidManifest.xml中的适当位置:

<service android:name="com.example.ttstest.TextToSpeechService"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" >
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>

    <meta-data android:name="android.accessibilityservice"
        android:resource="@xml/accessibilityservice"/>
</service>

我的accessibilityservice.xml设置:

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeAllMask"
    android:notificationTimeout="100"
    android:accessibilityFeedbackType="feedbackSpoken"
    android:accessibilityFlags="flagDefault"
    android:canRetrieveWindowContent="true"
    android:packageNames="com.example.ttstest"/>

最后,问题。当我第一次启动应用程序时,TextView从requestFocus()获得焦点或者调用sendAccessibilityEvent()实际上都没有向AccessibilityService发送任何内容。如果我通过附加物理键盘来浏览TextViews,则会收到焦点事件 。我确保在设置中打开AccessibilityService,并且我从我创建此示例的应用程序中得到证据,即在调用requestFocus()和sendAccessibilityEvent()时启用了AccessibilityService。这没有用。似乎首次启动Activity时,这些方法都不会向AccessibilityService发送任何内容。我也试过调用announceForAccessibility()并得到类似的结果。

我这样做错了吗?我该如何解决它,或者至少绕过它?具体来说,我想在活动首次启动时向我的AccessibilityService发送一个事件。

更多信息:我尝试将requestFocus()和sendAccessibilityEvent()调用移动到onStart()和onWindowFocusChanged();这些都不起作用。

1 个答案:

答案 0 :(得分:0)

我可能会弄错,但是在调用onResume()之前“UI”还没有准备就绪,这可能就是问题了吗?