我正在尝试让我的应用在用户启动Activity时向我的自定义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();上。这些都不起作用。
最佳答案
我可能会弄错,但是在调用onResume()之前“ UI”还没有准备好,所以也许这是问题所在吗?