携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第二十五天,[点击查看活动详情](juejin.cn/post/712312…
Android小技巧之AccessibilityService(无障碍)
前言
本文章收录Android小技巧系列,该系列是在日常工作用不上但是该功能可以实现一些比较好玩的app。该文章的主角是AccessibilityService(无障碍),该功能可以实现模拟用户操作手机,有这个这个就可以实现一些,重复度较高的操作,比如:办公软件的打卡,抢红包,自动回复等相关操作。
AccessibilityService
AccessibilityService是Android提供的开发人员实现无障碍模式的一个服务类,如果我们要实现无障碍的功能,我们就要继承与AccessibilityService类,但是光继承还是远远不够的,那么我们就来看看,使用一个AccessibilityService需要那些步骤:
继承 AccessibilityService
我们声明一个类继承与AccessibilityService
class AccessibilityDemoService : AccessibilityService(){
//无障碍服务链接的时候回调
override fun onServiceConnected() {
super.onServiceConnected()
ToastUtils.showLong("onServiceConnected")
}
//无障碍服务监听事件回调
override fun onAccessibilityEvent(event: AccessibilityEvent?) {
ToastUtils.showLong("onAccessibilityEvent")
}
//无障碍服务断开的时候回调
override fun onInterrupt() {
ToastUtils.showLong("onInterrupt")
}
}
解析:
当我们继承AccessibilityService的时候onAccessibilityEvent和onInterrupt是必须重写,onServiceConnected也很重要,我们重写一些,可以进行一些初始化的操作,细心的你会发现我们在每个回调显示了Toast,每个回调都是在主线程所以Toast不会报错,也就是不能做耗时操作,要不然会出先ARN。
在AccessibilityService里只能加Log或者加Toast来看数据,加了断点也不停
AndroidManifest.xml配置
我们创建了AccessibilityDemoService还需要在清单文件里,声明一下:
<service
//在无障碍设置显示的名字
android:label="@string/app_name"
//自己声明的类
android:name=".AccessibilityDemoService"
//支持其它应用调用当前组件
android:exported="true"
//需要指定BIND_ACCESSIBILITY_SERVICE权限,这是4.0以上的系统要求的
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
//运行的进程
android:process=":BackgroundService">
//必须声明这个为无障碍服务,声明了才设置里显示
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<!-- 通过xml文件完成辅助功能相关配置,也可以在onServiceConnected中动态配置-->
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_config" />
</service>
解析:
和普通的Service配置有点区别,我们也了解这个配置的作用,最后两个配置是一定要配置的,要不然就启动不起无障碍服务,我们还发现最后要配置一个 android:resource的xml文件,这个配置也可以在之前说的onServiceConnected方法中设置,提供两种配置,一个静态,一个动态,我们先看一下静态的配置。
配置文件
- 配置文件配置
我们直接看accessibility_config.xml的内容:
<accessibility-service
android:accessibilityEventTypes="typeViewClicked|typeViewFocused"
android:packageNames="com.example.android.myFirstApp, com.example.android.mySecondApp"
android:accessibilityFeedbackType="feedbackSpoken"
android:notificationTimeout="100"
android:settingsActivity="com.example.android.apis.accessibility.TestBackActivity"
android:canRetrieveWindowContent="true"
/>
解析:
上面只写了一部分的属性,全部属性和属性详情如下表:
| 属性 | 介绍 |
|---|---|
| android:accessibilityEventTypes | 此服务希望接收的事件类型,如 AccessibilityEvent. |
| android:accessibilityFeedbackType | 此服务提供的反馈类型在 中指定 AccessibilityServiceInfo |
| android:accessibilityFlags | 中指定的附加标志 AccessibilityServiceInfo |
| android:canRequestEnhancedWebAccessibility | 属性可访问性服务是否希望能够请求增强的 Web 可访问性增强 |
| android:canRequestFilterKeyEvents | 属性无障碍服务是否希望能够请求过滤关键事件 |
| android:canRequestTouchExplorationMode | 属性无障碍服务是否希望能够请求触摸探索模式,在该模式中,大声说出触摸的项目并且可以通过手势探索 UI |
| android:canRetrieveWindowContent | 属性无障碍服务是否希望能够检索活动窗口内容 |
| android:canTakeScreenshot | 属性无障碍服务是否希望能够截屏 |
| android:description | 无障碍服务使用、可用性或限制的描述 |
| android:interactiveUiTimeout | 建议的超时时间(以毫秒为单位),用于 为交互式控件返回合适的值。 android.view.accessibility.AccessibilityManager.getRecommendedTimeoutMillis(int, int) |
| android:intro | 无障碍服务目的或行为的详细介绍。 |
| android:nonInteractiveUiTimeout | 建议的超时时间(以毫秒为单位),用于 为不包含交互式控件的 UI 返回合适的值。 android.view.accessibility.AccessibilityManager.getRecommendedTimeoutMillis(int, int) |
| android:notificationTimeout | 两个相同类型的可访问性事件之间的最小时间间隔(以毫秒为单位)被发送到此服务 |
| android:packageNames | 逗号分隔的包名称,该服务希望从中接收事件(省略所有包 |
| android:settingsActivity | 允许用户修改此服务设置的活动的完全限定类名。 |
| android:summary | 无障碍服务目的或行为的简要总结。 |
| android:tileService | 的完全限定类名TileService与此可访问性服务相关联,以进行一对一映射 |
- 代码配置
override fun onServiceConnected() {
val serviceInfo = AccessibilityServiceInfo().apply {
eventTypes = AccessibilityEvent.TYPES_ALL_MASK
feedbackType = AccessibilityServiceInfo.FEEDBACK_ALL_MASK
packageNames = arrayOf("com.eg.android.AlipayGphone")//支付宝包名,可以多个
notificationTimeout = 10
}
setServiceInfo(serviceInfo)
}
我们需要在onServiceConnected方法中设置,上面代码只设置了部分
运行
上面的步骤我们就完成了无障碍的基本流程,但是现在你运行app还不会运行,因为我们需要在设置里开启app的无障碍,我们使用代码跳转:
try {
startActivity( Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
}
catch (e: Exception){
startActivity( Intent(Settings.ACTION_SETTINGS));
}
然后我们在选我们的应用打开,就会跳转到无障碍设置界面,我们开启我们的应用就可以,你就会看到我们的Toast,效果图吐下:
常用的操作
我们启动了无障碍,那么我们就可以做一下模拟用户操作,所有操作我们在onAccessibilityEvent方法中进行操作:
- 锁屏
override fun onAccessibilityEvent(event: AccessibilityEvent?) {
event ?: return
performGlobalAction(GLOBAL_ACTION_LOCK_SCREEN)
}
- 打开通知栏
override fun onAccessibilityEvent(event: AccessibilityEvent?) {
event ?: return
performGlobalAction(GLOBAL_ACTION_NOTIFICATIONS)
}
我们就简单介绍两个的代码展示,更多请看performGlobalAction的使用
总结
到这里我们就简单的使用一下Android的无障碍功能,无障碍功能可以做很多功能,下一篇我们来实战,使用无障碍来实现企业微信的打开功能。