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?
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.
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(....)
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