无障碍服务中AccessibilityNodeInfo无法点击问题的解决方法

最近实习,接了个活,让实现类似微信自动回复一类的功能,当时想不明白,第一想法是难道还要让人去抓包判断数据格式然后模拟回复?这也太恶心了吧。后来知道有AccessibilityService这个东西,瞬间觉得其实也没那么难嘛。

直奔主题,然而,不管通过什么方法获得了View的Id,如果不知道怎么获取viewId请参考这篇AccessibilityService 获取View的Id,正常情况下,只要这个view是clickable,就可以使用:

AccessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);

实现对view的点击,但万一不是clickable的咋办?
网上搜了半天,知道了大概是app重写了ontouch来实现的点击,然而并没有什么卵用。
通过参考这篇Android后台模拟点击探索(附源码)
得知解决方法是可以通过强行单击view所在的屏幕位置来解决。
这时我们需要一个root过的手机。因为只有获得了管理员权限的用户才可以使用shell命令。
然后通过获取Node的Bounds,就可以获得所在位置,再转换坐标传入命令即可:

private OutputStream os;
private void forceClick(AccessibilityNodeInfo nodeInfo) {
    Rect rect = new Rect();
    nodeInfo.getBoundsInScreen(rect);
    Log.d(TAG, "forceClick: " + rect.left + " " + rect.top + " " + rect.right + " " + rect.bottom);
    int x=(rect.left+rect.right)/2;
    int y = (rect.top + rect.bottom) / 2;
    String cmd = "input tap " + String.valueOf(x) + " " + String.valueOf(y);
    try {
        if (os == null) {
            os = Runtime.getRuntime().exec("su").getOutputStream();
        }
        os.write(cmd.getBytes());
        os.flush();//清空缓存
        os.close();//停止流
        os = null;
    } catch (Exception e) {
        Log.e(e.getMessage());
    }
}

就可以实现啦,但是需要注意的是,这个操作会比正常情况下的点击慢1秒左右,如果在写自动脚本的时候请务必设置足够的延时。

你可能感兴趣的:(Android)