Android AccessibilityService:如何记录和重放视图点击?
我正在尝试实现一个AccessibilityService,该服务记录用户的操作(此时仅单击事件)并存储它们,以便可以在稍后的时间点重播它们 为此,我注册了Android AccessibilityService:如何记录和重放视图点击?,android,accessibility,Android,Accessibility,我正在尝试实现一个AccessibilityService,该服务记录用户的操作(此时仅单击事件)并存储它们,以便可以在稍后的时间点重播它们 为此,我注册了AccessibilityEvent。键入\u VIEW\u CLICKED事件,并检查我是否可以稍后通过使用两种策略恢复它们(当我所拥有的只是对活动的窗口/根节点的引用时): 获取单击视图的id并在根节点的树中查找该id 获取单击视图的文本,并在根节点的树中查找该文本 我已经在各种应用程序和Android系统的不同部分进行了测试,结果非常混
AccessibilityEvent。键入\u VIEW\u CLICKED
事件,并检查我是否可以稍后通过使用两种策略恢复它们(当我所拥有的只是对活动的窗口/根节点的引用时):
public class RecorderService extends AccessibilityService {
private static final String TAG = "RecorderService";
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
switch (event.getEventType()) {
case AccessibilityEvent.TYPE_VIEW_CLICKED:
AccessibilityNodeInfo node = event.getSource();
if (node == null) {
Log.i(TAG, "node is null");
return;
}
AccessibilityNodeInfo root = getRootInActiveWindow();
if (root == null) {
Log.i(TAG, "root is null");
return;
}
// Strategy #1: locate node via its id
String id = node.getViewIdResourceName();
if (id == null) {
Log.i(TAG, "id is null");
} else {
List<AccessibilityNodeInfo> rootNodes = root.findAccessibilityNodeInfosByViewId(id);
if (rootNodes.size() == 1) {
Log.i(TAG, "success (via id)");
return;
} else {
Log.i(TAG, "multiple nodes with that id");
}
}
// Strategy #2: locate node via its text
CharSequence text = node.getText();
if (text == null) {
Log.i(TAG, "text is null");
} else {
List<AccessibilityNodeInfo> rootNodes = root.findAccessibilityNodeInfosByText(text.toString());
if (rootNodes.size() == 1) {
Log.i(TAG, "success (via text)");
return;
}
}
Log.i(TAG, "failed, node was not recoverable");
}
}
@Override
protected boolean onKeyEvent(KeyEvent event) {
Log.i("Key", event.getKeyCode() + "");
return true;
// return super.onKeyEvent(event);
}
@Override
public void onInterrupt() {
}
}
公共类记录器服务扩展了AccessibilityService{
私有静态最终字符串TAG=“RecorderService”;
@凌驾
AccessibilityEvent上的公共无效(AccessibilityEvent事件){
开关(event.getEventType()){
案例可访问性事件类型\视图\单击:
AccessibilityNodeInfo节点=event.getSource();
if(node==null){
Log.i(标记“node is null”);
返回;
}
AccessibilityNodeInfo root=getRootInActiveWindow();
if(root==null){
Log.i(标记“root为null”);
返回;
}
//策略#1:通过其id定位节点
String id=node.getViewIdResourceName();
if(id==null){
Log.i(标记“id为null”);
}否则{
List rootNodes=root.findAccessibilityNodeInfosByViewId(id);
if(rootNodes.size()==1){
Log.i(标记“成功(通过id)”);
返回;
}否则{
i(标记“具有该id的多个节点”);
}
}
//策略2:通过文本定位节点
CharSequence text=node.getText();
if(text==null){
Log.i(标记“文本为空”);
}否则{
List rootNodes=root.findAccessibilityNodeInfosByText(text.toString());
if(rootNodes.size()==1){
Log.i(标记“成功(通过文本)”);
返回;
}
}
Log.i(标记“失败,节点不可恢复”);
}
}
@凌驾
受保护的布尔onKeyEvent(KeyEvent事件){
Log.i(“Key”,event.getKeyCode()+”);
返回true;
//返回super.onKeyEvent(事件);
}
@凌驾
在中断时的公共无效(){
}
}
我在SDK版本21(棒棒糖)上开发了这个软件,并在HTC Nexus M8和三星Galaxy Note2上进行了测试,两者都显示了类似的结果。是的,这差不多是你所能做到的。您也可以尝试使用祖先视图ID和子索引作为唯一标识符,尽管这对ListView之类的东西没有多大帮助(尽管在那里您可以依赖CollectionItemInfo)。我尝试在源节点上使用getParent()并结合getChild(…)来检查子节点是否可以通过父节点恢复,但是后者经常返回null,我不明白为什么。