AccessibilityService也叫andriod辅助服务。这个服务提供了增强的用户界面,目的是为了帮助残障人士。它一般提供了页面元素查找功能和元素点击功能。
使用科大讯飞asr语音能力,实现语音控制点击界面。
方案一:派生服务
原理参考:辅助模式最终考验的是想象力,先来看看怎么用!| Accessibility - 简书 (jianshu.com)
基本框架参考百度搜索:java AccessibilityService派生两个服务,参考搜索结果。
1、java代码创建派生服务
需要重写onAccessibilityEvent(AccessibilityEvent event)
方法来处理事件,以及onInterrupt()
方法来处理服务中断的情况
打开微信,触发点击、打开新页面等操作,就可以在onAccessibilityEvent接收到事件。
所以百度搜索“java使用requestFocus()方法来设置控件的焦点来触发无障碍服务”。
// 假设你有一个EditText控件
EditText editText = findViewById(R.id.edit_text);
// 请求焦点
editText.requestFocus();
// 通过无障碍服务来模拟点击操作
if (editText.isFocused()) {
// 获取系统的无障碍管理器
AccessibilityManager accessibilityManager = (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
// 如果无障碍服务正在运行
if (accessibilityManager.isEnabled()) {
// 发送一个触发事件
editText.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
}
}
event分发原理的源码解析可参考(新人建议跳过):
【Android】AccessibilityService事件分发原理_onaccessibilityevent-CSDN博客
使用科大讯飞的asr识别能力,把语音转化出来的字符串作为输入如何触发?
实现细节可参考方案二的链接。
基本思路:每次界面变化,都刷新容器accessibilityNodeInfoSet
asr语音输入字符串,直接遍历匹配accessibilityNodeInfoSet容器中的每一个NodeInfo的text。
2、在AndroidManifest.xml中配置系统权限
<uses-permission
android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"
tools:ignore="ProtectedPermissions" />
注册服务
<manifest ... >
<application ... >
<service
android:name=".MySecondAccessibilityService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service_config_second_service" />
</service>
</application>
</manifest>
3、增加对应的xml文件。
xml的配置需要根据具体情况,可以先按照下面默认配置
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagReportViewIds"
android:canRetrieveWindowContent="true"
android:canRequestFilterKeyEvents="true"
android:packageNames="com.example.helloworld"
android:description="@string/app_name"
android:notificationTimeout="2000">
</accessibility-service>
用到的几个配置参数解释如下:
android:accessibilityFeedbackType="feedbackGeneric"
表示当访问性事件发生时,会提供一般性的反馈,例如声音提示或者触觉反馈。
android:accessibilityFlags="flagRequestFilterKeyEvents"
是用来设置可访问性标志的,这个标志用于请求过滤键盘事件。
当你在自定义的View中设置这个标志时,你的View将接收所有的按键事件,包括系统导航键(如回退键、Home键、菜单键)。
android:accessibilityFlags="flagReportViewIds"
是Android中的一个属性,用于定义无障碍服务的行为。在无障碍服务中,flagReportViewIds
这个标志用于指示无障碍服务在事件中包含视图的ID。
canRetrieveWindowContent
:表示该服务能否访问活动窗口中的内容,也就是说如果希望在服务中获取窗体的内容,则需要设置其值为true。
android:canRequestFilterKeyEvents="true"
。这个属性的含义是,标签内的视图(通常是一个EditText或者是一个自定义的视图)可以过滤键事件。
在Android中,键事件是指用户通过键盘或者其他输入设备进行的操作,例如按键、滑动等。有时候,我们可能需要对这些事件进行过滤或者拦截,以满足特定的需求。
方案二:派生Receiver
参考实现:
android可见即可说实现方案_android 可见即可说-CSDN博客
参考原理:
在Android中注册一个广播接收器(Receiver)以监听无障碍服务状态变化,可以通过继承BroadcastReceiver类并重写其onReceive()方法来实现。
这个方式通过监听无障碍服务被关闭、监听设备的重启事件,保证无障碍服务一直处于开启状态。
首先,创建一个继承自BroadcastReceiver的类,例如命名为AccessibilityServiceReceiver,并重写onReceive()方法。在这个方法中,通过检查传入的Intent的动作(action)来判断无障碍服务是否被启用或禁用。如果无障碍服务被禁用,则通过启动一个新的Intent来重新开启它。
其次,为了监听设备的重启事件,可以在BroadcastReceiver类中添加对Intent.ACTION_BOOT_COMPLETED的处理。这样,当设备重启后,广播接收器能够接收到重启完成的广播,从而确保无障碍服务在设备启动后立即启动。
最后,在AndroidManifest.xml文件中注册这个自定义的广播接收器,并为其配置相应的IntentFilter,以便它能接收到相关的广播。例如,为了监听无障碍服务的启用和禁用事件,需要在IntentFilter中添加对应的动作,如Intent.ACTION_ACCESSIBILITY_SERVICE_ENABLED和Intent.ACTION_ACCESSIBILITY_SERVICE_DISABLED。
通过上述步骤,可以确保无障碍服务在Android设备上的持续运行,即使在设备重启或无障碍服务被用户禁用的情况下也能及时恢复。
点评:
用onReceive是为了通过下面adb命令模拟asr热词命中,用MutableLiveData.observeForever的方式来触发。代码感觉是写复杂了,没有必要加一个vrSpeechService。
adb shell am broadcast -a com.saicmotor.voiceservice.hotword -n com.saicmotor.voiceservice/.model.HotWordReceiver --es hotWord “sound”