How to send a custom event to AccessibilityService?

故事扮演 提交于 2019-12-23 03:42:17

问题


My program purpose: trigger the BACK button in a service

I tried many ways, no one can achieve this purpose, finally I discovered AccessibilityService, it may be the most possible ways to implement this function.

I created this AccessibilityService, and tested it is work

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" />

And then I tried to move performGlobalAction to service, but it does not perform the action.

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);
    }
}

I also tried to send a custom event in different way, but no one can send to 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);
}

How can I send a custom event or message to MyAccessibilityService, so that I can recognize the event and message to perform the action?


回答1:


You can't run an Accessibility service the way in which you are attempting. Accessibility services can only be run as accessibility services. The reason here is obvious, if you understand the capabilities of accessibility services. Things they can do:

  • Track keyboard events
  • Investigate contents of text fields
  • arbitrarily send action events

These can be easily used for malicious purposes. Allowing an application, or even a standard service, to launch a process that can do such things would be terrible security. As such only the system can launch an accessibility service, with all of the relevant permissions. The only place it does this is from the accessibility settings menu. This way users know, at least, when an accessibility service is running, and can be more cautious about the types of these services that they run.

This also leads to the overall answer: You can't. At least not without running an actual accessibility service, and then sending intents directly to that. But the user would have to separately launch your service themselves.




回答2:


1 Create a static field of your service

public static MyAccessibilityService instance;

2 then initialize it in onServiceConnected()

    @Override
    protected void onServiceConnected() {
    super.onServiceConnected();
    instance = this;
}

3 don't foget to clear it in onUnbind()

    @Override
    public boolean onUnbind(Intent intent) {
    instance = null;
    return super.onUnbind(intent);
}

onServiceConnected() is called by the System when user gives permission to your app in device Settings

onUnbind() is when users revokes that permission

4 Use your instance everywhere you want

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



回答3:


I am not sure if this is the correct way to go but it will get your work done. Have a broadcast receiver registered within your Accessibility service method onServiceConnected() like below.

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

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

And your broadcast receiver within your accessibility service

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);
        }
}

Instead of creating an event, send a broadcast like below to perform back action:

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


来源:https://stackoverflow.com/questions/35739334/how-to-send-a-custom-event-to-accessibilityservice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!