バリアフリーサービスでAccessibilityNodeInfoがクリックできない問題の解決方法

1548 ワード

最近実習して、仕事を受けて、微信の自動返信のような機能を実現させました.その時、分からなかったと思います.第一の考えは、パケットをつかんでデータフォーマットを判断し、返信をシミュレートすることですか.これは気持ち悪いでしょう.あとで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秒程度遅くなりますので、自動スクリプトを書くときは必ず十分な遅延を設定してください.