Reputation: 3425
I'd like to be able to know in a AccessibilityService when the user presses any system key, specifically the back key. I've overwritten the onKeyEvent method, but it doesn't respond at all, yet I get all the events from onAccessibilityEvent.
@Override
public boolean onKeyEvent(KeyEvent event) {
Log.e(TAG, "------------------- onKeyEvent ----------------------------");
return super.onKeyEvent(event);
}
Following are my configuration files, I'm monitoring the AccessibilityService package (a subproject) and the actual application package.
Manifest.xml for the subproject containing the AccessibilityService.
<?xml version="1.0" encoding="utf-8"?>
...
<service android:name="com.foo.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/accessibilityservice" />
</service>
accessibilityservice.xml file is as follows:
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
xmlns:tools="http://schemas.android.com/tools"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagIncludeNotImportantViews"
xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/emachine_accessibility_service_description"
android:settingsActivity="com.foo.services.MyAccessibilityService"
tools:ignore="UnusedAttribute"
android:canRetrieveWindowContent="true"
android:canRequestFilterKeyEvents="true"
android:canRequestTouchExplorationMode="true"/>
And Yes the com.foo.services.MyAccessibilityService is 'On' under the system Accessibility Settings.
Added
android:canRequestFilterKeyEvents="true"
android:canRequestTouchExplorationMode="true"
to accessibility.xml in above, and the equivalent in the onServiceConnected was added programmatically.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
info.flags |= AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS;
info.flags |= AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS;
info.flags |= AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT;
}
with no positive outcome
Upvotes: 3
Views: 2875
Reputation: 18880
I suspect that you are trying to intercept these events from a soft keyboard that is not sending them. Key Events are only reliably sent from hardware keyboards. In fact, manually sending the events from a software input method service is discouraged, and in prior versions of the OS lead to potentially malicious effects. From the Android KeyEvent documentation:
As soft input methods can use multiple and inventive ways of inputting text, there is no guarantee that any key press on a soft keyboard will generate a key event: this is left to the IME's discretion, and in fact sending such events is discouraged. You should never rely on receiving KeyEvents for any key on a soft input method. In particular, the default software keyboard will never send any key event to any application targetting Jelly Bean or later, and will only send events for some presses of the delete and return keys to applications targetting Ice Cream Sandwich or earlier. Be aware that other software input methods may never send key events regardless of the version. Consider using editor actions like IME_ACTION_DONE if you need specific interaction with the software keyboard, as it gives more visibility to the user as to how your application will react to key presses.
A cheap bluetooth keyboard is your best bet. Or emulators with the proper configuration.
EDIT:
Alternatively you may have an error in your configuration file. In your accessibilityservice.xml, replace this line:
android:accessibilityFlags="flagIncludeNotImportantViews"
With this:
android:accessibilityFlags="flagIncludeNotImportantViews|flagRequestFilterKeyEvents"
You can also acheive the same in your accessibility service code.
protected void onServiceConnected() {
super.onServiceConnected();
AccessibilityServiceInfo tempInfo = getServiceInfo();
tempInfo.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
tempInfo.flags |= AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS;
setServiceInfo(tempInfo);
}
Upvotes: 1