如何使用语音访问应用程序等辅助功能服务执行其他应用程序列表项单击?
How to perform Other app list item click using accessibility service like Voice Access app?
我正在开发类似 VoiceAccess 应用程序的应用程序。使用可访问性服务,我能够执行位于顶部 activity(第 3 方应用程序)的所有点击。但我面临 ListItem 点击问题。我正在为 FaceBook 应用程序尝试此代码。下面是我的代码。谁能帮我解决这个问题。
public class MyService extends AccessibilityService {
/**/
private SharedPreferences S_PREF;
private SharedPreferences.Editor editor;
private static final String TAG = MyService.class
.getSimpleName();
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
clickPerform(getRootInActiveWindow(), 0);
}
public void clickPerform(AccessibilityNodeInfo nodeInfo, final int depth) {
if (nodeInfo == null) return;
List<AccessibilityNodeInfo> list = nodeInfo
.findAccessibilityNodeInfosByViewId("com.facebook.katana:id/bookmarks_tab");
for (AccessibilityNodeInfo node : list) {
Log.i(TAG, "ViewID-: bookmarks_tab " + node.getChild(0));
if (S_PREF.getBoolean("fb_menu", false)) {
editor.putBoolean("fb_menu", false);
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
List<AccessibilityNodeInfo> list2 = nodeInfo
.findAccessibilityNodeInfosByViewId("com.facebook.katana:id/bookmarks_list");
for (AccessibilityNodeInfo node2 : list2) {
if (node2.getChild(0) != null)
if (S_PREF.getBoolean("fb_scroll_down", false)) {
editor.putBoolean("fb_scroll_down", false);
node2.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
}
}
editor.commit();
for (int i = 0; i < nodeInfo.getChildCount(); ++i) {
clickPerform(nodeInfo.getChild(i), depth+1);
}
}
@Override
public void onInterrupt() {
}
protected void onServiceConnected() {
S_PREF = getSharedPreferences("S_PREF", Context.MODE_PRIVATE);
editor = S_PREF.edit();
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.flags = AccessibilityServiceInfo.DEFAULT;
info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
setServiceInfo(info);
Toast.makeText(getApplicationContext(), "onServiceConnected", Toast.LENGTH_SHORT).show();
}
}
下面是 VoiceAccess 屏幕。
当用户说出任何数字时,将执行特定项目点击。
我能够获得 7、8、9、10 个事件,但从 11 开始,我无法单独获得列表项。我的代码仅返回列表视图 ID。
提前致谢....
@steveenzoleko
我自己找到了这个问题的解决方案。这里
AccessibilityNodeInfo 始终不会 return 完整列表或列表大小。它 return 的视图。它可能是 TextView、Button 等...每个视图都有多种方法,如 getText()、getContentDescription()、getClassName()、getChildCount()、getViewIdResourceName() 等...这里语音访问应用程序检测所有视图并为它们提供一些数字。对于列表,在 for 循环中使用 getChildCount() 方法我们可以 getChildViews/listItems。例如:
AccessibilityNodeInfo node = getRootInActiveWindow();
if(node != null) {
for(int i = 0; i < node.getChildCount(); i++){
AccessibilityNodeInfo childNode = node.getChild(i);
if(childNode != null){
Log.i("childNode", "-----getText->"+childNode.getText()+"---getContentDescription-->"+childNode.getContentDescription() );
}
}
}
使用 getText() 和 getContentDescription() 方法了解文本视图、按钮、复选框的文本。
getClassName() 方法返回视图类型,如 TextView、Button、ImageView、CheckBox 等...
也许您可以使用 AccessibilityService API 7.0.
中的 dispatchGesture
我正在开发类似 VoiceAccess 应用程序的应用程序。使用可访问性服务,我能够执行位于顶部 activity(第 3 方应用程序)的所有点击。但我面临 ListItem 点击问题。我正在为 FaceBook 应用程序尝试此代码。下面是我的代码。谁能帮我解决这个问题。
public class MyService extends AccessibilityService {
/**/
private SharedPreferences S_PREF;
private SharedPreferences.Editor editor;
private static final String TAG = MyService.class
.getSimpleName();
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
clickPerform(getRootInActiveWindow(), 0);
}
public void clickPerform(AccessibilityNodeInfo nodeInfo, final int depth) {
if (nodeInfo == null) return;
List<AccessibilityNodeInfo> list = nodeInfo
.findAccessibilityNodeInfosByViewId("com.facebook.katana:id/bookmarks_tab");
for (AccessibilityNodeInfo node : list) {
Log.i(TAG, "ViewID-: bookmarks_tab " + node.getChild(0));
if (S_PREF.getBoolean("fb_menu", false)) {
editor.putBoolean("fb_menu", false);
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
List<AccessibilityNodeInfo> list2 = nodeInfo
.findAccessibilityNodeInfosByViewId("com.facebook.katana:id/bookmarks_list");
for (AccessibilityNodeInfo node2 : list2) {
if (node2.getChild(0) != null)
if (S_PREF.getBoolean("fb_scroll_down", false)) {
editor.putBoolean("fb_scroll_down", false);
node2.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
}
}
editor.commit();
for (int i = 0; i < nodeInfo.getChildCount(); ++i) {
clickPerform(nodeInfo.getChild(i), depth+1);
}
}
@Override
public void onInterrupt() {
}
protected void onServiceConnected() {
S_PREF = getSharedPreferences("S_PREF", Context.MODE_PRIVATE);
editor = S_PREF.edit();
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.flags = AccessibilityServiceInfo.DEFAULT;
info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
setServiceInfo(info);
Toast.makeText(getApplicationContext(), "onServiceConnected", Toast.LENGTH_SHORT).show();
}
}
下面是 VoiceAccess 屏幕。
我能够获得 7、8、9、10 个事件,但从 11 开始,我无法单独获得列表项。我的代码仅返回列表视图 ID。
提前致谢....
@steveenzoleko
我自己找到了这个问题的解决方案。这里 AccessibilityNodeInfo 始终不会 return 完整列表或列表大小。它 return 的视图。它可能是 TextView、Button 等...每个视图都有多种方法,如 getText()、getContentDescription()、getClassName()、getChildCount()、getViewIdResourceName() 等...这里语音访问应用程序检测所有视图并为它们提供一些数字。对于列表,在 for 循环中使用 getChildCount() 方法我们可以 getChildViews/listItems。例如:
AccessibilityNodeInfo node = getRootInActiveWindow();
if(node != null) {
for(int i = 0; i < node.getChildCount(); i++){
AccessibilityNodeInfo childNode = node.getChild(i);
if(childNode != null){
Log.i("childNode", "-----getText->"+childNode.getText()+"---getContentDescription-->"+childNode.getContentDescription() );
}
}
}
使用 getText() 和 getContentDescription() 方法了解文本视图、按钮、复选框的文本。
getClassName() 方法返回视图类型,如 TextView、Button、ImageView、CheckBox 等...
也许您可以使用 AccessibilityService API 7.0.
中的 dispatchGesture