如何使用语音访问应用程序等辅助功能服务执行其他应用程序列表项目?

时间:2017-08-31 12:21:19

标签: android accessibilityservice

我正在开发像VoiceAccess应用程序这样的应用程序。使用辅助功能服务,我可以执行顶级活动(第三方应用程序)上的所有点击。但我面临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屏幕。 enter image description here 当用户说出任何号码时,将执行特定项目点击。

我能够获得7,8,9,10个事件但是从11个开始我没有单独获得列表项目。我的代码只返回listview id。

提前致谢....

2 个答案:

答案 0 :(得分:1)

@steveenzoleko

我自己解决了这个问题。这里 AccessibilityNodeInfo始终不返回完整列表或列表大小。它返回VIEW。它可能是TextView,Button等...每个View都有多个方法,如getText(),getContentDescription(),getClassName(),getChildCount(),getViewIdResourceName()等...这里Voice Access应用检测所有视图并给它们一些数字。对于列表,在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()方法来了解textview,button,checkbox的文本。

getClassName()方法返回视图类型,如TextView,Button,ImageView,CheckBox等...

答案 1 :(得分:0)

也许您可以使用AccessibilityService API 7.0中的dispatchGesture。