从API级别11开始,通过adb shell设置剪贴板文本

时间:2023-01-30 09:43:33

Before API level 11, it was possible to set the content of the clipboard by using the service program on the adb shell:

在API级别11之前,可以使用adb shell上的服务程序设置剪贴板的内容:

service call SERVICE CODE [i32 INT | s16 STR] ...
Options:
    i32: Write the integer INT into the send parcel.
    s16: Write the UTF-16 string STR into the send parcel.

There were three integer codes to define the methods:

有三个整数代码来定义方法:

1 TRANSACTION_getClipboardText
2 TRANSACTION_setClipboardText
3 TRANSACTION_hasClipboardText

For instance this command

例如这个命令

$ adb shell service call clipboard 2 i32 1 i32 1 s16 "Hello Android!"

set the clipboard's content to "Hello Android!". As of API level 11 the listed methods are deprecated and the new ones take ClipData as an argument. How do you set the clipboard content now via adb shell?

将剪贴板的内容设置为“Hello Android!”。从API级别11开始,不推荐使用列出的方法,新的方法将ClipData作为参数。你如何通过adb shell设置剪贴板内容?

1 个解决方案

#1


9  

You've asked two different questions here. The service calls are not related to the API functions.

你在这里问了两个不同的问题。服务调用与API函数无关。

Android is in general overly-aggressive about marking APIs as deprecated. In this case, it only means that there are new functions with more functionality. The functionality of getText(), hasText(), and setText() still exists and those functions will continue to work, but they are now implemented as trivial wrappers around the newer functions.

对于将API标记为已弃用,Android通常过于激进。在这种情况下,它只意味着有更多功能的新功能。 getText(),hasText()和setText()的功能仍然存在,并且这些功能将继续工作,但它们现在被实现为围绕较新功能的普通包装器。

As far as the service calls go, those are an internal implementation detail and as you've noticed are not guaranteed to work across Android versions. If you peer into the Android source code, you'll find these transactions currently defined:

对于服务调用,这些是内部实现细节,并且您已经注意到不能保证在Android版本中工作。如果您查看Android源代码,您会发现当前定义的这些事务:

TRANSACTION_setPrimaryClip = 1
TRANSACTION_getPrimaryClip = 2
TRANSACTION_getPrimaryClipDescription = 3
TRANSACTION_hasPrimaryClip = 4
TRANSACTION_addPrimaryClipChangedListener = 5
TRANSACTION_removePrimaryClipChangedListener = 6
TRANSACTION_hasClipboardText = 7

The source code also indicates what parameters these transactions require. Unfortunately, TRANSACTION_setPrimaryClip requires a ClipData, which is not an i32 or an s16 and thus is not compatible with service call. We have bigger problems than that however; these transactions require the calling package name as a parameter, and the clipboard service validates that the specified package name matches the calling uid. When using the adb shell, the calling uid is either UID_ROOT or UID_SHELL, neither of which owns any packages, so there is no way to pass that check. Simply put, the new clipboard service cannot be used this way.

源代码还指出了这些事务所需的参数。不幸的是,TRANSACTION_setPrimaryClip需要一个ClipData,它不是i32或s16,因此与服务调用不兼容。然而,我们遇到了更大的问题;这些事务需要将调用包名称作为参数,剪贴板服务验证指定的包名称是否与调用uid匹配。使用adb shell时,调用uid是UID_ROOT或UID_SHELL,它们都不拥有任何包,因此无法通过该检查。简单地说,新的剪贴板服务不能以这种方式使用。

What can you do about all this? You can create your own service for manipulating the clipboard from the commandline and install it onto your device. I don't know if there's any way to extend service call, but you can use am startservice as a suitable replacement. If you've created and installed that custom clipboard service, then you could invoke it as:

你能做些什么呢?您可以创建自己的服务,以便从命令行操作剪贴板并将其安装到您的设备上。我不知道是否有任何方法可以扩展服务调用,但您可以使用am startservice作为合适的替代品。如果您已创建并安装了该自定义剪贴板服务,则可以将其调用为:

am startservice -a MySetClipboard -e text "clipboard text"

The code to implement this service could look like this:

实现此服务的代码可能如下所示:

public MyService extends Service {
    public int onStartCommand(Intent intent, int flags, int startId) {
        String text = intent.getStringExtra("text");
        ClipboardManager.setText(text);
        stopSelf();
        return START_NOT_STICKY;
    }
}

The service should have an intent-filter that declares it capable of handling the MySetClipboard intent action.

该服务应该有一个intent-filter,声明它能够处理MySetClipboard意图操作。

#1


9  

You've asked two different questions here. The service calls are not related to the API functions.

你在这里问了两个不同的问题。服务调用与API函数无关。

Android is in general overly-aggressive about marking APIs as deprecated. In this case, it only means that there are new functions with more functionality. The functionality of getText(), hasText(), and setText() still exists and those functions will continue to work, but they are now implemented as trivial wrappers around the newer functions.

对于将API标记为已弃用,Android通常过于激进。在这种情况下,它只意味着有更多功能的新功能。 getText(),hasText()和setText()的功能仍然存在,并且这些功能将继续工作,但它们现在被实现为围绕较新功能的普通包装器。

As far as the service calls go, those are an internal implementation detail and as you've noticed are not guaranteed to work across Android versions. If you peer into the Android source code, you'll find these transactions currently defined:

对于服务调用,这些是内部实现细节,并且您已经注意到不能保证在Android版本中工作。如果您查看Android源代码,您会发现当前定义的这些事务:

TRANSACTION_setPrimaryClip = 1
TRANSACTION_getPrimaryClip = 2
TRANSACTION_getPrimaryClipDescription = 3
TRANSACTION_hasPrimaryClip = 4
TRANSACTION_addPrimaryClipChangedListener = 5
TRANSACTION_removePrimaryClipChangedListener = 6
TRANSACTION_hasClipboardText = 7

The source code also indicates what parameters these transactions require. Unfortunately, TRANSACTION_setPrimaryClip requires a ClipData, which is not an i32 or an s16 and thus is not compatible with service call. We have bigger problems than that however; these transactions require the calling package name as a parameter, and the clipboard service validates that the specified package name matches the calling uid. When using the adb shell, the calling uid is either UID_ROOT or UID_SHELL, neither of which owns any packages, so there is no way to pass that check. Simply put, the new clipboard service cannot be used this way.

源代码还指出了这些事务所需的参数。不幸的是,TRANSACTION_setPrimaryClip需要一个ClipData,它不是i32或s16,因此与服务调用不兼容。然而,我们遇到了更大的问题;这些事务需要将调用包名称作为参数,剪贴板服务验证指定的包名称是否与调用uid匹配。使用adb shell时,调用uid是UID_ROOT或UID_SHELL,它们都不拥有任何包,因此无法通过该检查。简单地说,新的剪贴板服务不能以这种方式使用。

What can you do about all this? You can create your own service for manipulating the clipboard from the commandline and install it onto your device. I don't know if there's any way to extend service call, but you can use am startservice as a suitable replacement. If you've created and installed that custom clipboard service, then you could invoke it as:

你能做些什么呢?您可以创建自己的服务,以便从命令行操作剪贴板并将其安装到您的设备上。我不知道是否有任何方法可以扩展服务调用,但您可以使用am startservice作为合适的替代品。如果您已创建并安装了该自定义剪贴板服务,则可以将其调用为:

am startservice -a MySetClipboard -e text "clipboard text"

The code to implement this service could look like this:

实现此服务的代码可能如下所示:

public MyService extends Service {
    public int onStartCommand(Intent intent, int flags, int startId) {
        String text = intent.getStringExtra("text");
        ClipboardManager.setText(text);
        stopSelf();
        return START_NOT_STICKY;
    }
}

The service should have an intent-filter that declares it capable of handling the MySetClipboard intent action.

该服务应该有一个intent-filter,声明它能够处理MySetClipboard意图操作。