如何将自定义事件发送到AccessibilityService?

时间:2016-03-02 05:40:01

标签: android android-service accessibilityservice accessibility-api android-accessibility

我的程序目的:触发服务中的BACK按钮

我尝试了很多方法,没有人能达到这个目的,最后我发现了AccessibilityService,它可能是实现这个功能的最可能的方法。

我创建了这个AccessibilityService,并测试了它是否正常工作

package com.accessibilityservice;

public class MyAccessibilityService extends AccessibilityService {
    public MyAccessibilityService() {
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {

        performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);

    }

    @Override
    public void onInterrupt() {

    }
}

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackSpoken"
    android:accessibilityFlags="flagDefault"
    android:canRetrieveWindowContent="true"
    android:description="desc"
    android:notificationTimeout="100"
    android:settingsActivity="com.example.android.accessibility.ServiceSettingsActivity" />

然后我尝试将performGlobalAction移至服务,但它不会执行操作。

public class MyService extends Service {

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        MyAccessibilityService mas=new MyAccessibilityService();
        mas.performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
    }
}

我还尝试以不同的方式发送自定义事件,但没有人可以发送到MyAccessibilityService

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    //method1
    AccessibilityEvent event = AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_CLICKED);
    event.setContentDescription("this is description");
    View view = new View(this);
    ViewParent parent = view.getParent();
    if (parent != null) {
        parent.requestSendAccessibilityEvent(view, event);
    }

    //method2
    AccessibilityManager manager = (AccessibilityManager) getApplicationContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
    AccessibilityEvent event = AccessibilityEvent.obtain();
    event.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
    event.setPackageName("p");
    event.setClassName("c");
    manager.sendAccessibilityEvent(event);
}

如何向MyAccessibilityService发送自定义事件或消息,以便我能识别事件和消息以执行操作?

3 个答案:

答案 0 :(得分:1)

您无法按照您尝试的方式运行辅助功能服务。辅助功能服务只能作为辅助功能服务运行。如果您了解辅助功能服务的功能,这里的原因很明显。他们可以做的事情:

  • 跟踪键盘事件
  • 调查文本字段的内容
  • 任意发送行动事件

这些可以很容易地用于恶意目的。允许应用程序甚至标准服务启动可以执行此类操作的进程将是非常糟糕的安全性。因此,只有系统可以启动具有所有相关权限的辅助功能服务。它执行此操作的唯一位置是辅助功能设置菜单。这样,用户至少知道可访问性服务何时运行,并且可以对他们运行的这些服务的类型更加谨慎。

这也导致了总体答案:你不能。至少没有运行实际的辅助功能服务,然后直接向其发送意图。但是用户必须自己单独启动服务。

答案 1 :(得分:1)

1创建服务的静态字段

public static MyAccessibilityService instance;

2然后在onServiceConnected()

中初始化它
    @Override
    protected void onServiceConnected() {
    super.onServiceConnected();
    instance = this;
}

3不要忘记在onUnbind()

中清除它
    @Override
    public boolean onUnbind(Intent intent) {
    instance = null;
    return super.onUnbind(intent);
}
当用户在设备设置

中授予您的应用权限时,系统会调用 onServiceConnected()

onUnbind()是指用户撤销该权限

4随时随地使用您的实例

if(MyAccessibilityService.instance != null)
    MyAccessibilityService.instance.performGlobalAction(....)

答案 2 :(得分:0)

我不确定这是否是正确的方法,但它会让你的工作完成。在您的辅助功能服务方法 onServiceConnected()中注册广播接收器,如下所示。

@Override
protected void onServiceConnected() {
    super.onServiceConnected();
    registerReceiver(listener, new IntentFilter("my_custom_event_listener));
}

@Override
public void onDestroy() {
    super.onDestroy();
    unregisterReceiver(listener);
}

您的无障碍服务中的广播接收器

private class MyCustomListener extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
       Bundle extras = intent.getExtras();
        if(extras != null){
            String action = extras.getString("action");
            if(action.equals("back")
                performGlobalAction(GLOBAL_ACTION_BACK);
        }
}

不是创建活动,而是发送如下的广播来执行回复操作:

Intent back = new Intent("my_custom_event_listener");
Bundle data = new Bundle();
data.putString("action", "back");
back.putExtras(data);
sendBroadcast(back);