网站title keyword description,网站建设的美图,一个网站的二级目录在另一台服务器上_怎么做,西宁微网站建设多少钱原理#xff1a;
通过监听窗口改变事件#xff0c;监听目标应用#xff0c;通过视图ID#xff08;或文本、或描述、或其他如坐标之类的#xff09;找到目标视图#xff0c;使用无障碍动作点击方法点击它
无障碍服务实现#xff1a;
1、写一个自己的无障碍服务继承Acc…原理
通过监听窗口改变事件监听目标应用通过视图ID或文本、或描述、或其他如坐标之类的找到目标视图使用无障碍动作点击方法点击它
无障碍服务实现
1、写一个自己的无障碍服务继承AccessibilityService
public class AppWindowChangeService extends AccessibilityService {private static final String TAG MyAppWindowChangeService;Overridepublic void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {if (accessibilityEvent null || accessibilityEvent.getPackageName() null) return;CharSequence packageName accessibilityEvent.getPackageName();CharSequence className accessibilityEvent.getClassName();//监听当前窗口变化获取Packageif(accessibilityEvent.getEventType() AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED){Log.i(TAG, onAccessibilityEvent: packageName packageName, className className);} }Overridepublic void onInterrupt() {Log.e(TAG, onInterrupt);}}
2、AndroidManifest.xml声明这个服务
serviceandroid:name.AppWindowChangeServiceandroid:configChangeskeyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|fontScale|locale|uiModeandroid:enabledtrueandroid:exportedfalseandroid:permissionandroid.permission.BIND_ACCESSIBILITY_SERVICEintent-filteraction android:nameandroid.accessibilityservice.AccessibilityService//intent-filtermeta-dataandroid:nameandroid.accessibilityserviceandroid:resourcexml/detection_service_config//service
3、在xml新建一个配置资源做这个无障碍服务的相关配置
?xml version1.0 encodingutf-8?
accessibility-servicexmlns:androidhttp://schemas.android.com/apk/res/androidandroid:accessibilityEventTypestypeWindowStateChanged|typeViewClickedandroid:accessibilityFeedbackTypefeedbackGenericandroid:canRetrieveWindowContenttrueandroid:accessibilityFlagsflagIncludeNotImportantViews|flagReportViewIds|flagRetrieveInteractiveWindows /
这里监听类型我还多加了一个typeViewClicked后面可以用来找你点击的view的相关信息。 启用功能
自行找到系统设置的无障碍服务功能界面或者使用代码做跳转到无障碍服务界面
Intent intent new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);intent.setPackage(com.android.settings);startActivity(intent);
开启自己app的无障碍服务开关无障碍服务就会启动起来了。 实践
举个栗子监听美团外卖启动页的广告的跳过按钮
import android.accessibilityservice.AccessibilityService;
import android.os.Handler;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Toast;public class AppWindowChangeService extends AccessibilityService {private static final String TAG MyAppWindowChangeService;private static final String TARGET_PACKAGE_NAME com.sankuai.meituan.takeoutnew;private static final String TARGET_VIEW_ID com.sankuai.meituan.takeoutnew:id/ll_skip;private final Runnable runnable this::findAndClickTargetView;private final Handler handler new Handler();Overridepublic void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {if (accessibilityEvent null || accessibilityEvent.getPackageName() null) return;CharSequence packageName accessibilityEvent.getPackageName();CharSequence className accessibilityEvent.getClassName();//监听当前窗口变化获取Packageif(accessibilityEvent.getEventType() AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED){if (TARGET_PACKAGE_NAME.equals(packageName)) {Log.i(TAG, Target package opened: packageName);// 查找并点击目标视图handler.removeCallbacks(runnable);handler.postDelayed(runnable, 200);}} else if (accessibilityEvent.getEventType() AccessibilityEvent.TYPE_VIEW_CLICKED) {Log.i(TAG, onAccessibilityEvent: packageName packageName, className className);Log.e(TAG, onAccessibilityEvent: 点击view className);AccessibilityNodeInfo source accessibilityEvent.getSource();if (source ! null) {String viewId source.getViewIdResourceName();CharSequence text source.getText();CharSequence contentDescription source.getContentDescription();Log.e(TAG, View ID: viewId);Log.e(TAG, Text: text);Log.e(TAG, Content Description: contentDescription);source.recycle(); // 释放资源}}}private void findAndClickTargetView() {AccessibilityNodeInfo rootNode getRootInActiveWindow();Log.i(TAG, findAndClickTargetView: rootNode rootNode);if (rootNode ! null) {AccessibilityNodeInfo targetNode findNodeById(rootNode, TARGET_VIEW_ID);Log.i(TAG, findNodeById: targetNode targetNode);if (targetNode ! null) {Log.i(TAG, targetNode ! null, start click);performClick(targetNode);targetNode.recycle();}rootNode.recycle();}}private AccessibilityNodeInfo findNodeById(AccessibilityNodeInfo rootNode, String viewId) {if (rootNode.getViewIdResourceName() ! null rootNode.getViewIdResourceName().equals(viewId)) {return AccessibilityNodeInfo.obtain(rootNode);}for (int i 0; i rootNode.getChildCount(); i) {AccessibilityNodeInfo childNode rootNode.getChild(i);if (childNode ! null) {AccessibilityNodeInfo result findNodeById(childNode, viewId);if (result ! null) {return result;}childNode.recycle();}}return null;}private void performClick(AccessibilityNodeInfo node) {if (node ! null node.isClickable()) {node.performAction(AccessibilityNodeInfo.ACTION_CLICK);Log.i(TAG, Clicked on node: node);Toast.makeText(this, 自动点击, Toast.LENGTH_SHORT).show();} else {Log.i(TAG, Node is not clickable: node);}}Overridepublic void onInterrupt() {Log.e(TAG, onInterrupt);}}
目标包名和目标viewID是我通过点击的时候输出打印看到的给他倒推回去记录到代码当中。
查找view的动作需要做延时获取实测马上去获取是获取不到的。
实际实现中可以记录多个包名以及对应的需要点击的视图做李跳跳的效果。 Android高版本注意如果打开其他App之后日志不打印回到自己应用之后才会一次性把之前的动作日志打印出来的情况需要将应用的省电策略改为无限制这个问题网上都没有提到之前一直不生效困扰了我好久。