I'm writing an acessibility service in Android which relies on getting the view id of the currently selected view, however on some devices (Nexus 6P 6.0.1, Samsung Galaxy S6 edge+ 5 + 6.0.1) I get no view id through and on others (HTC One M8 5.0.1) it comes through fine. Because it works fine on some devices, I'm sure there's not a problem with my code, however I've posted a minimal test case below.
Can anyone can help me get my service reporting ids across all devices?
The A11y service
public class ViewIdLoggingAccessibilityService extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
AccessibilityNodeInfo source = event.getSource();
if (source == null) {
Log.d("onAccessibilityEvent", "source was null for: " + event);
} else {
String viewIdResourceName = source.getViewIdResourceName();
Log.d("onAccessibilityEvent", "viewid: " + viewIdResourceName);
}
}
@Override
public void onInterrupt() {
Log.d("!# onInterrupt", "called");
}
}
The AndroidManifest.xml
<manifest package="com.example.a11yservice"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
>
<service
android:name=".ViewIdLoggingAccessibilityService"
android:label="@string/view_id_logging_service_label"
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/serviceconfig"
/>
</service>
</application>
</manifest>
serviceconfig.xml
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeViewClicked|typeViewFocused"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagReportViewIds"
android:canRetrieveWindowContent="true"
android:notificationTimeout="100" />
It's known issue and was posted to AOSP issue tracker some time ago. You can check status of issue here: "Accessibility Issue: flagReportViewIds has no effect on real devices in Android M".
Unfortunately issue exists even on latest Android 7.0 but I found simple workaround. You can call refresh()
method on AccessibilityNodeInfo
object to refresh it and collect all missed data including id.
Something like that:
public void onAccessibilityEvent(AccessibilityEvent event) {
AccessibilityNodeInfo ani = event.getSource();
if (ani != null) {
ani.refresh(); // to fix issue with viewIdResName = null on Android 6+
}
}
I found that if the viewId isn't available, querying the focused element seems to work:
AccessibilityNodeInfo source = findFocus(AccessibilityNodeInfo.FOCUS_INPUT);
viewIdResourceName = source.getViewIdResourceName();
returns the correct view id
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With