python accessibilityservice_Android无障碍辅助功能(AccessibilityService)学习

本文介绍了Android AccessibilityService的使用方法,包括配置服务、工具类封装,以及如何通过文字和ID进行点击和长按操作。同时提供了一个简单的MyAccessibilityService示例,展示了如何在服务中响应无障碍事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.Android Accessibility 简介

对于那些失明或低视力,色盲,耳聋或听力受损,以及运动技能受限的用户,Android提供了Accessibility(辅助功能/无障碍)更加简单地操作设备,包括文字转语音、触觉反馈、手势操作、轨迹球和手柄操作等。

二.简单使用

1.在你的AndroidManifest中:

android:name=".MyAccessibilityService"

android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">

android:name="android.accessibilityservice"

android:resource="@xml/accessibility_service_config"/>

2.在你的@xml/accessibility_service_config中:

xmlns:tools="http://schemas.android.com/tools"

android:accessibilityEventTypes="typeAllMask"

android:accessibilityFeedbackType="feedbackGeneric"

android:accessibilityFlags="flagDefault"

android:canPerformGestures="true"

android:canRetrieveWindowContent="true"

android:description="@string/accessibility_doc"

android:notificationTimeout="100"

tools:ignore="UnusedAttribute" />

3.创建MyAccessibilityService 继承自 AccessibilityService

@SuppressLint("Registered")

public class MyAccessibilityService extends AccessibilityService {

@Override

public void onAccessibilityEvent(AccessibilityEvent event) {

}

@Override

public void onInterrupt() {

}

}

三.工具类封装

1.工具类AccessibilityServiceUtil封装

abstract public class AccessibilityUtil {

//开关

public static boolean isService = false;

//判断服务是否开启

public static boolean isService(Context context, Class service) {

int enable = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, 0);

if (enable != 1) return false;

String services = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);

if (!TextUtils.isEmpty(services)) {

TextUtils.SimpleStringSplitter split = new TextUtils.SimpleStringSplitter(':');

split.setString(services);

while (split.hasNext()) {

if (split.next().equalsIgnoreCase(context.getPackageName() + "/" + service.getName()))

return true;

}

}

return false;

}

//通过文字点击指定项

public static boolean clickText(AccessibilityService service, String string, int location) {

AccessibilityNodeInfo accessibilityNodeInfo = service.getRootInActiveWindow();

if (accessibilityNodeInfo == null) return false;

List nodeInfoByText = accessibilityNodeInfo.findAccessibilityNodeInfosByText(string);

List nodeInfoList = new ArrayList<>();

if (nodeInfoByText != null && !nodeInfoByText.isEmpty()) {

for (AccessibilityNodeInfo nodeInfo : nodeInfoByText) {

if (nodeInfo != null && (nodeInfo.getText().equals(string) || nodeInfo.getContentDescription().equals(string))) {

nodeInfoList.add(nodeInfo);

}

}

}

if (nodeInfoList.isEmpty()) return false;

if (nodeInfoList.size() > location) {

return click(nodeInfoList.get(location));

} else {

return click(nodeInfoList.get(0));

}

}

//通过文字点击第一项

public static boolean clickText(AccessibilityService service, String string) {

AccessibilityNodeInfo accessibilityNodeInfo = service.getRootInActiveWindow();

if (accessibilityNodeInfo == null) return false;

List nodeInfoByText = accessibilityNodeInfo.findAccessibilityNodeInfosByText(string);

if (nodeInfoByText != null && !nodeInfoByText.isEmpty()) {

for (AccessibilityNodeInfo nodeInfo : nodeInfoByText) {

if (nodeInfo != null && (nodeInfo.getText().equals(string) || nodeInfo.getContentDescription().equals(string))) {

return click(nodeInfo);

}

}

}

return false;

}

//通过文字长按指定项

public static boolean longClickText(AccessibilityService service, String string, int location) {

AccessibilityNodeInfo accessibilityNodeInfo = service.getRootInActiveWindow();

if (accessibilityNodeInfo == null) return false;

List nodeInfoByText = accessibilityNodeInfo.findAccessibilityNodeInfosByText(string);

List nodeInfoList = new ArrayList<>();

if (nodeInfoByText != null && !nodeInfoByText.isEmpty()) {

for (AccessibilityNodeInfo nodeInfo : nodeInfoByText) {

if (nodeInfo != null && (nodeInfo.getText().equals(string) || nodeInfo.getContentDescription().equals(string))) {

nodeInfoList.add(nodeInfo);

}

}

}

if (nodeInfoList.isEmpty()) return false;

if (nodeInfoList.size() > location) {

return longClick(nodeInfoList.get(location));

} else {

return longClick(nodeInfoList.get(0));

}

}

//通过文字长按第一项

public static boolean longClickText(AccessibilityService service, String string) {

AccessibilityNodeInfo accessibilityNodeInfo = service.getRootInActiveWindow();

if (accessibilityNodeInfo == null) return false;

List nodeInfoByText = accessibilityNodeInfo.findAccessibilityNodeInfosByText(string);

if (nodeInfoByText != null && !nodeInfoByText.isEmpty()) {

for (AccessibilityNodeInfo nodeInfo : nodeInfoByText) {

if (nodeInfo != null && (nodeInfo.getText().equals(string) || nodeInfo.getContentDescription().equals(string))) {

return longClick(nodeInfo);

}

}

}

return false;

}

//通过ID点击指定项

public static boolean clickId(AccessibilityService service, String id, int location) {

AccessibilityNodeInfo accessibilityNodeInfo = service.getRootInActiveWindow();

if (accessibilityNodeInfo == null) return false;

List infoByViewId = accessibilityNodeInfo.findAccessibilityNodeInfosByViewId(id);

List nodeInfoList = new ArrayList<>();

if (infoByViewId != null && !infoByViewId.isEmpty()) {

for (AccessibilityNodeInfo nodeInfo : infoByViewId) {

if (nodeInfo != null) {

nodeInfoList.add(nodeInfo);

}

}

}

if (nodeInfoList.isEmpty()) return false;

if (nodeInfoList.size() > location) {

return click(nodeInfoList.get(location));

} else {

return click(nodeInfoList.get(0));

}

}

//通过ID点击第一项

public static boolean clickId(AccessibilityService service, String id) {

AccessibilityNodeInfo accessibilityNodeInfo = service.getRootInActiveWindow();

if (accessibilityNodeInfo == null) return false;

List infoByViewId = accessibilityNodeInfo.findAccessibilityNodeInfosByViewId(id);

if (infoByViewId != null && !infoByViewId.isEmpty()) {

for (AccessibilityNodeInfo nodeInfo : infoByViewId) {

if (nodeInfo != null) {

return click(nodeInfo);

}

}

}

return false;

}

//通过ID长按指定项

public static boolean longClickId(AccessibilityService service, String id, int location) {

AccessibilityNodeInfo accessibilityNodeInfo = service.getRootInActiveWindow();

if (accessibilityNodeInfo == null) return false;

List infoByViewId = accessibilityNodeInfo.findAccessibilityNodeInfosByViewId(id);

List nodeInfoList = new ArrayList<>();

if (infoByViewId != null && !infoByViewId.isEmpty()) {

for (AccessibilityNodeInfo nodeInfo : infoByViewId) {

if (nodeInfo != null) {

nodeInfoList.add(nodeInfo);

}

}

}

if (nodeInfoList.isEmpty()) return false;

if (nodeInfoList.size() > location) {

return longClick(nodeInfoList.get(location));

} else {

return longClick(nodeInfoList.get(0));

}

}

//通过ID长按第一项

public static boolean longClickid(AccessibilityService service, String id) {

AccessibilityNodeInfo accessibilityNodeInfo = service.getRootInActiveWindow();

if (accessibilityNodeInfo == null) return false;

List infoByViewId = accessibilityNodeInfo.findAccessibilityNodeInfosByViewId(id);

if (infoByViewId != null && !infoByViewId.isEmpty()) {

for (AccessibilityNodeInfo nodeInfo : infoByViewId) {

if (nodeInfo != null) {

return longClick(nodeInfo);

}

}

}

return false;

}

//通过坐标点击

public static boolean coordinatesClick(AccessibilityService service, int x, int y) {

Path path = new Path();

path.moveTo(x, y);

GestureDescription.Builder builder = new GestureDescription.Builder();

GestureDescription gestureDescription = builder.addStroke(new GestureDescription.StrokeDescription(path, 0, 200)).build();

return service.dispatchGesture(gestureDescription, new AccessibilityService.GestureResultCallback() {

@Override

public void onCompleted(GestureDescription gestureDescription) {

super.onCompleted(gestureDescription);

}

}, null);

}

//通过坐标长按

public static boolean coordinatesLongClick(AccessibilityService service, int x, int y) {

Path path = new Path();

path.moveTo(x, y);

GestureDescription.Builder builder = new GestureDescription.Builder();

GestureDescription gestureDescription = builder.addStroke(new GestureDescription.StrokeDescription(path, 0, 1000)).build();

return service.dispatchGesture(gestureDescription, new AccessibilityService.GestureResultCallback() {

@Override

public void onCompleted(GestureDescription gestureDescription) {

super.onCompleted(gestureDescription);

}

}, null);

}

//自定义滑动

public static boolean coordinateSliding(AccessibilityService service, int x0, int y0, int x1, int y1, int ms) {

Path path = new Path();

path.moveTo(x0, y0);

path.lineTo(x1, y1);

GestureDescription.Builder builder = new GestureDescription.Builder();

GestureDescription gestureDescription = builder.addStroke(new GestureDescription.StrokeDescription(path, 0, ms)).build();

return service.dispatchGesture(gestureDescription, new AccessibilityService.GestureResultCallback() {

@Override

public void onCompleted(GestureDescription gestureDescription) {

super.onCompleted(gestureDescription);

}

}, null);

}

//点击

private static boolean click(AccessibilityNodeInfo node) {

if (node == null) return false;

if (node.isClickable()) {

return node.performAction(AccessibilityNodeInfo.ACTION_CLICK);

} else {

click(node.getParent());

}

return false;

}

//长按

private static boolean longClick(AccessibilityNodeInfo node) {

if (node == null) return false;

if (node.isLongClickable()) {

return node.performAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);

} else {

longClick(node.getParent());

}

return false;

}

//输入

@SuppressLint("ObsoleteSdkInt")

public static boolean InputText(AccessibilityService service, AccessibilityNodeInfo nodeInfo, String text) {

if (service == null) return false;

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

Bundle arguments = new Bundle();

arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);

return nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);

} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {

ClipboardManager clipboard = (ClipboardManager) service.getSystemService(Context.CLIPBOARD_SERVICE);

ClipData clip = ClipData.newPlainText("label", text);

if (clipboard != null) {

clipboard.setPrimaryClip(clip);

}

nodeInfo.performAction(AccessibilityNodeInfo.ACTION_FOCUS);

nodeInfo.performAction(AccessibilityNodeInfo.ACTION_PASTE);

}

return false;

}

//返回

@SuppressLint("ObsoleteSdkInt")

public static boolean Back(AccessibilityService service) {

if (service == null) return false;

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {

try {

Thread.sleep(200);

} catch (InterruptedException e) {

e.printStackTrace();

}

return service.performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);

} else {

return false;

}

}

//主页

@SuppressLint("ObsoleteSdkInt")

public static boolean Home(AccessibilityService service) {

if (service == null) return false;

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {

try {

Thread.sleep(200);

} catch (InterruptedException e) {

e.printStackTrace();

}

return service.performGlobalAction(AccessibilityService.GLOBAL_ACTION_HOME);

} else {

return false;

}

}

//上滑

public static boolean ScrollForward(AccessibilityNodeInfo node) {

if (node == null || !node.isScrollable()) return false;

return node.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);

}

//下滑

public static boolean ScrollBackward(AccessibilityNodeInfo node) {

if (node == null || !node.isScrollable()) return false;

return node.performAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);

}

//暂停

public static void Sleep(long millis) {

try {

Thread.sleep(millis);

} catch (Exception e) {

System.exit(0);

}

}

}

2.使用AccessibilityServiceUtil,例如:

public class MyAccessibilityService extends AccessibilityService {

@Override

public void onAccessibilityEvent(AccessibilityEvent event) {

//在服务正常的情况控制服务,isService默认为false,可在Activity中设置为true即可

if (AccessibilityUtil.isService) {

//通过坐标点击屏幕中的(500,500)位置直到成功

while (!AccessibilityUtil.coordinatesClick(this, 500, 500)) ;

//关闭服务,设置中仍然开启

AccessibilityUtil.isService = false;

}

}

@Override

public void onInterrupt() {

System.out.print("已停止服务");

}

}

3.十七岁辣鸡少年正在学习...,大佬轻拍,有兴趣加微互相交流…下方评论吐槽一下吧,转载请标记出处

7443d4a3cb08

AceCode

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值