从 AccessibilityService 粘贴在 API22 中有效在 API17 中无效
Paste from AccessibilityService works in API22 does not work in API17
当我 运行 我在 API22 上的代码时,它工作正常,将 "Testing Testing" 粘贴到启动 [=12 的应用程序中所需的 EditText
=].但是当我 运行 它在 API 17 时,它不起作用。它将数据复制到剪辑但无法粘贴。我需要该机制在 API 16 及更高版本上工作。
到目前为止,这是我的代码:
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();
}
}
也许您应该改进您的答案并添加更多关于导入的详细信息。
正在粘贴:
正如您在评论中提到的,更多的是再次从剪贴板中获取内容?
从 Android Copy and Paste Documentation 开始,您可以像这样将复制的内容作为文本获取:
// 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;
}
}
正在复制:
ClipBoardManager
有两种不同的变体。新的是用 Honeycomb 引入的。您必须确保您的代码使用了正确的变体。
看看这个代码示例:
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);
}
这只是一个假设,因为问题遗漏了一些信息。
不幸的是,AccessibilityNodeInfo.ACTION_PASTE 被添加到 API 级别 18 中,因此它不适用于 API 17 及更低级别。 AccessibilityNodeInfoCompat
只是现有功能的包装器,它不提供缺失功能的自定义实现。
v4 支持库的来源非常清楚:
当您在 AccessibilityNodeInfoCompat
中调用 performAction
时,支持库会调用 IMPL.performAction
[1]
public boolean performAction(int action) {
return IMPL.performAction(mInfo, action);
}
IMPL
当 API 级别为 16 和 17 时 AccessibilityNodeInfoJellybeanImpl
[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();
}
这是 performAction
在 AccessibilityNodeInfoJellybeanImpl
[3]
public static boolean performAction(Object info, int action, Bundle arguments) {
return ((AccessibilityNodeInfo) info).performAction(action, arguments);
}
如您所见,标准 android.view.accessibility.AccessibilityNodeInfo
的支持库调用 performAction
,因此如果系统不支持 ACTION_PASTE
,v4 支持库也不支持ACTION_PASTE
.
您可以检查此代码是否支持 ACTION_PASTE
:
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"));
当我 运行 我在 API22 上的代码时,它工作正常,将 "Testing Testing" 粘贴到启动 [=12 的应用程序中所需的 EditText
=].但是当我 运行 它在 API 17 时,它不起作用。它将数据复制到剪辑但无法粘贴。我需要该机制在 API 16 及更高版本上工作。
到目前为止,这是我的代码:
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();
}
}
也许您应该改进您的答案并添加更多关于导入的详细信息。
正在粘贴: 正如您在评论中提到的,更多的是再次从剪贴板中获取内容?
从 Android Copy and Paste Documentation 开始,您可以像这样将复制的内容作为文本获取:
// 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;
}
}
正在复制:
ClipBoardManager
有两种不同的变体。新的是用 Honeycomb 引入的。您必须确保您的代码使用了正确的变体。
看看这个代码示例:
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);
}
这只是一个假设,因为问题遗漏了一些信息。
不幸的是,AccessibilityNodeInfo.ACTION_PASTE 被添加到 API 级别 18 中,因此它不适用于 API 17 及更低级别。 AccessibilityNodeInfoCompat
只是现有功能的包装器,它不提供缺失功能的自定义实现。
v4 支持库的来源非常清楚:
当您在 AccessibilityNodeInfoCompat
中调用 performAction
时,支持库会调用 IMPL.performAction
[1]
public boolean performAction(int action) {
return IMPL.performAction(mInfo, action);
}
IMPL
当 API 级别为 16 和 17 时 AccessibilityNodeInfoJellybeanImpl
[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();
}
这是 performAction
在 AccessibilityNodeInfoJellybeanImpl
[3]
public static boolean performAction(Object info, int action, Bundle arguments) {
return ((AccessibilityNodeInfo) info).performAction(action, arguments);
}
如您所见,标准 android.view.accessibility.AccessibilityNodeInfo
的支持库调用 performAction
,因此如果系统不支持 ACTION_PASTE
,v4 支持库也不支持ACTION_PASTE
.
您可以检查此代码是否支持 ACTION_PASTE
:
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"));