5

我的程序目的:触发服务中的 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 发送自定义事件或消息,以便我可以识别事件和消息以执行操作?

4

3 回答 3

2

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(....)
于 2016-10-31T15:00:29.577 回答
2

您无法以您尝试的方式运行辅助功能服务。无障碍服务只能作为无障碍服务运行。如果您了解无障碍服务的功能,这里的原因是显而易见的。他们可以做的事情:

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

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

这也导致了总体答案:你不能。至少在不运行实际的可访问性服务的情况下,然后直接向该服务发送意图。但是用户必须自己单独启动您的服务。

于 2016-03-02T14:44:44.507 回答
1

我不确定这是否是正确的方法,但它会完成你的工作。在您的辅助功能服务方法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);
于 2016-09-29T12:23:35.290 回答