Search code examples
javaandroidaccessibilityservice

android AccessibilityService suddenly stopped triggerring events - check my code please


I have an AccessibilityService which was working fine but for some reason during development it stopped working. I can't seem to find that reason. Please have a look at my code and tell why it isn't working.

public class MyAccessibilityService extends AccessibilityService {

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {

    Toast.makeText(this, "event triggered", Toast.LENGTH_SHORT).show();
}

@Override
public void onServiceConnected() {
    AccessibilityServiceInfo config = new AccessibilityServiceInfo();
    config.eventTypes = AccessibilityEvent.TYPE_WINDOWS_CHANGED;
    config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;

    config.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;

    setServiceInfo(config);
    super.onServiceConnected();
}

Here's the relevant part of Manifest:

 <service
        android:name=".MyAccessibilityService"
        android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
        <intent-filter>
            <action android:name="android.accessibilityservice.AccessibilityService" />
        </intent-filter>

        <meta-data
            android:name="android.accessibilityservice"
            android:resource="@xml/myserviceconfig" />
    </service>

Here's myserviceconfig.xml:

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service android:accessibilityEventTypes="typeWindowsChanged"
android:notificationTimeout="100"
android:accessibilityFeedbackType="feedbackGeneric"
android:settingsActivity="com.example.android.apis.accessibility.TestBackActivity"
android:canRetrieveWindowContent="true"
xmlns:android="http://schemas.android.com/apk/res/android" />

The code attempts to detect when the user has started a new Activity of a third party app.


Solution

  • The function below is definitely problematic.

    @Override
    public void onServiceConnected() {
        AccessibilityServiceInfo config = new AccessibilityServiceInfo();
        config.eventTypes = AccessibilityEvent.TYPE_WINDOWS_CHANGED;
        config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
    
        config.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
    
        setServiceInfo(config);
        super.onServiceConnected();
    }
    

    The line: AccessibilityServiceInfo config = new AccessibilityServiceInfo();

    Is for sure innapropriate. By fetching a non initialized service config object, you have removed any of the configuration you did in your service config XML file. In fact, there is no reason to do any of your configuration programmatically, you should probably just remove this function, and change all of these settings in your service config. EITHER of the following solutions would work.

    Fetch you services current configuration, instead of instantiating a new one.

    @Override
    public void onServiceConnected() {
        AccessibilityServiceInfo config = getServiceInfo();//This IS A REALLY IMPORTANT CHANGE!!! 
        //By instantiating a new "AccessibilityServiceInfo" you have overwritten all of your XML Config changes, as well as any default settings internal to Android! 
        //DON'T instantiate your own ServiceConfig objects!!!! Just don't. In fact, do everything in XML instead!
    
        config.eventTypes = AccessibilityEvent.TYPE_WINDOWS_CHANGED;
        config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
    
        config.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
    
        setServiceInfo(config);
        super.onServiceConnected();
    }
    

    Just make all of these changes in your service config xml file.

    <?xml version="1.0" encoding="utf-8"?>
    <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
        android:accessibilityEventTypes="typeWindowsChanged"
        android:notificationTimeout="100"
        android:accessibilityFeedbackType="feedbackGeneric"
        android:accessibilityFlags="flagIncludeNotImportantViews"
        android:settingsActivity="com.example.android.apis.accessibility.TestBackActivity"
        android:canRetrieveWindowContent="true" />
    

    Notice that the flags you were adding in code are available in the service config file as well! Just use this, it's much easier. In this solution you should simply delete your onServiceConnected override function completely.

    Finally

    Development of Android Accessibility Services is quite finicky! Android Studio does not always handle crashes well, particularly as it pertains to getting crash data into LogCat in an identifiable reliable manner and/or crashing vocally. Tracking down runtime exceptions can be a pain. Make sure when you experience sudden inconsistency like this, that you don't filter LogCat by application! Check the entire Log at Error level for stack traces and exceptions! ALSO, try uninstalling your service and running it again AND THEN inspecting the entire LogCat output. Turning your device on and off can help as well. YEP, it's a pain!

    Between the solutions above, and these notes, you should be able to track down your problem.