When I run my code on API22 it works just fine, pasting the "Testing Testing" in my required EditText
in the app that initiated the AccessibilityEvent
. But when I run it on API 17, it does not work. It copies the data to clip but is unable to paste it. I require the mechanism to work on API 16 and above.
This is my code so far:
public class MyAccessibilityService extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
AccessibilityNodeInfo nodeInf = null;
AccessibilityNodeInfo nodeInfo = null;
final int eventType = event.getEventType();
String eventText = null;
switch(eventType) {
case AccessibilityEvent.TYPE_VIEW_CLICKED:
eventText = "Clicked: ";
nodeInf = this.getRootInActiveWindow();
Log.d("AccessibilityNodeInfo", ""+ nodeInf.getChildCount());
nodeInf.recycle();
break;
case AccessibilityEvent.TYPE_VIEW_FOCUSED:
AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event);
AccessibilityNodeInfoCompat source = record.getSource();
ClipboardManager clipboard = (ClipboardManager) this.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("label", "TESTING TESTING");
clipboard.setPrimaryClip(clip);
source.performAction(AccessibilityNodeInfoCompat.ACTION_PASTE);
//}
Log.d("AccessibilityNodeInfo", ""+ source.getClassName());
Intent intent = new Intent(MyAccessibilityService.this, TestActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
startActivity(intent);
break;
}
eventText = eventText + event.getText();
// Do something nifty with this text, like speak the composed string
// back to the user.
Log.d("Information", eventText);
Toast.makeText(getApplicationContext(), eventText + " " + android.os.Build.VERSION.SDK_INT,
Toast.LENGTH_LONG).show();
}
}
Unfortunately AccessibilityNodeInfo.ACTION_PASTE is added in API level 18, for this reason it doesn't work with API 17 and lower. AccessibilityNodeInfoCompat
is only a wrapper to existing features, it doesn't provide a custom implementation of missing features.
The sources of the v4 support library are pretty clear:
When you call performAction
in AccessibilityNodeInfoCompat
the support library calls IMPL.performAction
[1]
public boolean performAction(int action) {
return IMPL.performAction(mInfo, action);
}
IMPL
is AccessibilityNodeInfoJellybeanImpl
when API level is 16 and 17 [2]
if (Build.VERSION.SDK_INT >= 22) {
IMPL = new AccessibilityNodeInfoApi22Impl();
} else if (Build.VERSION.SDK_INT >= 21) {
IMPL = new AccessibilityNodeInfoApi21Impl();
} else if (Build.VERSION.SDK_INT >= 19) { // KitKat
IMPL = new AccessibilityNodeInfoKitKatImpl();
} else if (Build.VERSION.SDK_INT >= 18) { // JellyBean MR2
IMPL = new AccessibilityNodeInfoJellybeanMr2Impl();
} else if (Build.VERSION.SDK_INT >= 16) { // JellyBean
IMPL = new AccessibilityNodeInfoJellybeanImpl();
} else if (Build.VERSION.SDK_INT >= 14) { // ICS
IMPL = new AccessibilityNodeInfoIcsImpl();
} else {
IMPL = new AccessibilityNodeInfoStubImpl();
}
This is performAction
in AccessibilityNodeInfoJellybeanImpl
[3]
public static boolean performAction(Object info, int action, Bundle arguments) {
return ((AccessibilityNodeInfo) info).performAction(action, arguments);
}
As you can see the the support library call performAction
of the standard android.view.accessibility.AccessibilityNodeInfo
, so if the system doesn't support ACTION_PASTE
also the v4 support library doesn't support ACTION_PASTE
.
You can check if ACTION_PASTE
is supported with this code:
AccessibilityNodeInfoCompat source = record.getSource();
int supportedActions = source.getActions();
boolean isSupported = (supportedActions & AccessibilityNodeInfoCompat.ACTION_PASTE) == AccessibilityNodeInfoCompat.ACTION_PASTE;
Log.d(TAG, String.format("AccessibilityNodeInfoCompat.ACTION_PASTE %1$s supported", isSupported ? "is" : "is NOT"));
Perhaps you should improve your answer and add some more details about your imports.
Pasting: As you mentioned in your comment, it's more about getting the thing from the clipboard again?
As of the Android Copy and Paste Documentation you can get the copied content as text like this:
// Examines the item on the clipboard. If getText() does not return null, the clip item contains the
// text. Assumes that this application can only handle one item at a time.
ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);
// Gets the clipboard as text.
pasteData = item.getText();
// If the string contains data, then the paste operation is done
if (pasteData != null) {
return;
// The clipboard does not contain text. If it contains a URI, attempts to get data from it
} else {
Uri pasteUri = item.getUri();
// If the URI contains something, try to get text from it
if (pasteUri != null) {
// calls a routine to resolve the URI and get data from it. This routine is not
// presented here.
pasteData = resolveUri(Uri);
return;
} else {
// Something is wrong. The MIME type was plain text, but the clipboard does not contain either
// text or a Uri. Report an error.
Log.e("Clipboard contains an invalid data type");
return;
}
}
Copying:
There are two different variants of the ClipBoardManager
. The new one was introduced with Honeycomb. You have to make sure that your code is using the correct variant.
Look at this code sample:
int sdk = android.os.Build.VERSION.SDK_INT;
if(sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText("text to clip");
} else {
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
android.content.ClipData clip = android.content.ClipData.newPlainText("text label","text to clip");
clipboard.setPrimaryClip(clip);
}
This is just an assumption as the question misses some information.
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