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

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了。


利用系统自带语音助手打开第三方应用就实现了。



  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
使用 AccessibilityService 来监听第三方应用播放的音乐,你需要先创建一个继承自 AccessibilityService 的服务类,并在 AndroidManifest.xml 文件中声明该服务类。在服务类中,你需要重写 onAccessibilityEvent() 方法,并在该方法中获取当前活动的窗口信息,判断当前是否有音乐播放器应用正在运行,并获取该应用的包名。 接下来,你可以通过使用 MediaSessionManager 来获取当前正在播放的媒体信息,例如音乐名称、歌手、专辑等。在获取到这些信息后,你可以将它们发送到你的服务器或进行其他处理。 以下是一个示例代码,用于监听第三方应用播放的音乐: ```java public class MusicAccessibilityService extends AccessibilityService { private MediaSessionManager mMediaSessionManager; private MediaController mMediaController; @Override protected void onServiceConnected() { super.onServiceConnected(); mMediaSessionManager = (MediaSessionManager) getSystemService(Context.MEDIA_SESSION_SERVICE); } @Override public void onAccessibilityEvent(AccessibilityEvent event) { if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { String packageName = event.getPackageName().toString(); if (isMusicPlayerApp(packageName)) { List<MediaController> controllers = mMediaSessionManager.getActiveSessions(null); for (MediaController controller : controllers) { if (controller != null && controller.getMetadata() != null) { String title = controller.getMetadata().getString(MediaMetadata.METADATA_KEY_TITLE); String artist = controller.getMetadata().getString(MediaMetadata.METADATA_KEY_ARTIST); String album = controller.getMetadata().getString(MediaMetadata.METADATA_KEY_ALBUM); // 将获取到的媒体信息发送到服务器或进行其他处理 } } } } } private boolean isMusicPlayerApp(String packageName) { // 判断是否为音乐播放器应用 return packageName.equals("com.android.music") || packageName.equals("com.google.android.music"); } @Override public void onInterrupt() { } } ``` 需要注意的是,使用 AccessibilityService 来监听第三方应用播放的音乐需要用户授权才能正常工作。你需要在启动服务时请求用户授权,并在用户同意授权后才能正常工作。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值