您的位置:首页 > 移动开发 > Android开发

android Accessibility系统自带语音助手打开第三方应用

2016-07-15 14:16 381 查看
AccessibilityService是什么

某些用户由于视力、身体、年龄等问题致使他们不能使用触摸屏幕,为这些用户提供无障碍服务时应该更多的提供语音、触摸反馈、手势操作、模拟点击等。

为此android官方推出了AccessibilityService方便开发者为特殊用户服务。

更详细资料可以看android官方文档

AccessibilityService能做什么

AccessibilityService是一个辅助类,可以监听我们手机的焦点,窗口变化,按钮点击等,同时它还可以模拟点击。基本上等同于可以监听一切你想监听的内容。

如何使用AccessibilityService

AccessibilityService使用很简单:

1. 新建一个类继承AccessibilityService,并实现几个重要的重载方法;

2.在AndroidManifest中注册服务

3.配置AceessibilityService

通过这三步就可以创建自己的辅助类了,在 系统设置-》辅助功能中开启我们的服务就实现我们想要的功能了。

我们以利用系统自带语音助手打开第三方应用为例来实现。

1.新建MyAccessibilityService类并继承AccessibilityService

利用getRootInActivityWindow()方法可以获得当前界面的根节点node

然后通过findAccessibilityNodeInfosByText() 获取到我们想要的节点

public class MyAccessbilityService extends AccessibilityService {

private static final String TAG = "MyAccessbilityService";
//记录上一次识别结果,防止死循环
private String lastText = "";
/**
* 连接服务成功后调用
* 可选
*/
protected void onServiceConnected() {

Log.d(TAG, "onServiceConnected: success");
super.onServiceConnected();

}

/**
* 接受系统发来的accessibilityEvent
* 必须实现
*/
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {

AccessibilityNodeInfo nodes = getRootInActiveWindow();
if (nodes == null){
return;
}
// List<AccessibilityNodeInfo> nodeList =
// nodes.findAccessibilityNodeInfosByViewId(Config.viewId);
// 也可通过findAccessibilityNodeInfosByViewId 方式解决
List<AccessibilityNodeInfo> nodeInfoList =
nodes.findAccessibilityNodeInfosByText("芝麻开门");
for (int i = 0; i < nodeInfoList.size(); i++){

String text = nodeInfoList.get(i).getText().toString();
Log.d(TAG, "onAccessibilityEvent: result" + i +" = " + text);

if (!text.equals(lastText)){
dealText(text);
}
}
nodes.recycle();
Log.d(TAG, "onAccessibilityEvent: packageName = " + event.getPackageName());
Log.d(TAG, "onAccessibilityEvent: eventType = " + event.getEventType());
Log.d(TAG, "onAccessibilityEvent: windowId = " + event.getWindowId());
Log.d(TAG, "onAccessibilityEvent: -------------");
}
/**
* 中断服务
* 必须实现
*/
@Override
public void onInterrupt() {
}

/**
* 系统关闭服务时调用
* 可选
* @param intent
* @return
*/
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}

/**
* 打开第三方应用,这里以打开我们自己的Activity为例
* @param text 打开应用附带的消息
*/
private void openApp(String text){
Log.d(TAG, "open some app");
lastText = text;
Intent intent = new Intent(MyAccessbilityService.this, MainActivity.class);
intent.putExtra("str",text);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
/**
* 处理语音识别结果
* @param str
*/
private void dealText(String str){
if (str.contains(Config.mark)){
openApp(str);
}
}
}AccessibilityService中的重要方法

onServiceConnected() - 可选。系统会在成功连接上你的服务的时候调用这个方法,在这个方法里你可以做一下初始化工作,例如设备的声音震动管理,也可以调用setServiceInfo()进行配置工作。

onAccessibilityEvent() - 必须。通过这个函数可以接收系统发送来的AccessibilityEvent,接收来的AccessibilityEvent是经过过滤的,过滤是在配置工作时设置的。

onInterrupt() - 必须。这个在系统想要中断AccessibilityService返给的响应时会调用。在整个生命周期里会被调用多次。

onUnbind() - 可选。在系统将要关闭这个AccessibilityService会被调用。在这个方法中进行一些释放资源的工作。

2.在AndroidManifest中注册服务

在AndroidManifest下application标签中加入如下代码

<service android:name=".MyAccessbilityService"
android:description="@string/accessibility_description"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:label="@string/accessibility_label">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service_config"/>
</service>

label           为服务的名字
description 为服务的描述

<meta-data 下为配置文件的名称及资源路径,在后面会详细介绍。

这样我们的服务就成功注册了

3.配置AceessibilityService

有两种配置方式,一种是java代码配置,一种是使用xml文件配置。xml配置方式支持更多的参数,推荐使用这种方式配置。

xml文件配置方式

在res文件夹下新建一个xml文件夹

在xml文件夹中新建一个xml文件,取名跟meta-data中的name一致



xml文件代码

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/accessibility_description"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFlags="flagDefault"
android:accessibilityFeedbackType="feedbackGeneric"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"
android:packageNames="com.meizu.voiceassistant"
/>
packageNames中填入想要监听的包名,我的测试机是魅族MX3,语音助手的包名是com.meizu.voiceassistant ,可以替换成你需要的包名

java代码配置方式

需要new一个AccessibilityServiceInfo对象并设置相关参数

最后在MyaccessibilityService类中的onServiceConnected方法中配置参数。

在MyaccessibilityService中添加方法

private void setServiceInfo(int feedbackType) {
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
// We are interested in all types of accessibility events.
info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
// We want to provide specific type of feedback.
info.feedbackType = feedbackType;
// We want to receive events in a certain interval.
info.notificationTimeout = EVENT_NOTIFICATION_TIMEOUT_MILLIS;
// We want to receive accessibility events only from certain packages.
info.packageNames = PACKAGE_NAMES;
setServiceInfo(info);
}在onServiceConnect中调用该方法

protected void onServiceConnected() {
super.onServiceConnected();
setServiceInfo(AccessibilityServiceInfo.FEEDBACK_GENERIC);
}

经过以上三步我们的服务就编写完成了

编译运行就可以在    系统设置->辅助功能   中看到我们 的服务



打开服务,启动系统自带的语音助手,说出密令词 “芝麻开门”

就可以打开MainActivity了。

利用系统自带语音助手打开第三方应用就实现了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息