在API级别11之前,可以使用service
上的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.
有三个整数代码来定义方法:
1 TRANSACTION_getClipboardText
2 TRANSACTION_setClipboardText
3 TRANSACTION_hasClipboardText
例如这个命令
$ adb shell service call clipboard 2 i32 1 i32 1 s16 "Hello Android!"
将剪贴板的内容设置为"Hello Android!"
。从API级别11开始,列出的方法为deprecated,新的方法以ClipData为参数。如何通过adb shell
设置剪贴板内容?
答案 0 :(得分:10)
你在这里问了两个不同的问题。服务调用与API函数无关。
对于将API标记为已弃用,Android一般过于激进。在这种情况下,它只意味着有更多功能的新功能。 getText()
,hasText()
和setText()
的功能仍然存在,并且这些功能将继续有效,但它们现在可以作为较新功能的简单包装实现。
就服务调用而言,这些是内部实现细节,并且您已经注意到不能保证在Android版本中工作。如果您查看Android source code,您会发现当前定义的这些交易:
TRANSACTION_setPrimaryClip = 1
TRANSACTION_getPrimaryClip = 2
TRANSACTION_getPrimaryClipDescription = 3
TRANSACTION_hasPrimaryClip = 4
TRANSACTION_addPrimaryClipChangedListener = 5
TRANSACTION_removePrimaryClipChangedListener = 6
TRANSACTION_hasClipboardText = 7
源代码还指出了这些事务需要的参数。不幸的是,TRANSACTION_setPrimaryClip需要一个ClipData
,它不是i32或s16,因此与service call
不兼容。然而,我们遇到了更大的问题;这些事务需要将调用包名称作为参数,剪贴板服务验证指定的包名称是否与调用uid匹配。使用adb shell时,调用uid是UID_ROOT或UID_SHELL,它们都不拥有任何包,因此无法通过该检查。简单地说,新的剪贴板服务不能以这种方式使用。
你能做些什么呢?您可以创建自己的服务,以便从命令行操作剪贴板并将其安装到您的设备上。我不知道是否有任何方法可以扩展service call
,但您可以使用am startservice
作为合适的替代品。如果您已创建并安装了该自定义剪贴板服务,则可以将其调用为:
am startservice -a MySetClipboard -e text "clipboard text"
实现此服务的代码可能如下所示:
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;
}
}
该服务应该有一个intent-filter,声明它能够处理MySetClipboard
意图操作。
答案 1 :(得分:0)
我找到了一种使用 com.tengu.sharetoclipboard 执行此操作的方法。您使用 F-Droid 安装它,然后使用以下参数以 am
超过 adb
启动它:
adb shell am start-activity \
-a android.intent.action.SEND \
-e android.intent.extra.TEXT <sh-escaped-text> \
-t 'text/plain' \
com.tengu.sharetoclipboard
<sh-escaped-text>
是安卓剪贴板的新内容。请注意,此文本必须进行转义,以便远程端的 sh
不会对其进行特殊解释。实际上,这意味着用单引号将其括起来并用 '\''
替换所有单引号。例如,如果本地 shell 是 fish,这会正常工作:
adb shell am start-activity \
-a android.intent.action.SEND \
-e android.intent.extra.TEXT '\'I\'\\\'\'m pretty sure $HOME is set.\'' \
-t 'text/plain' \
com.tengu.sharetoclipboard
fish 解析后,参数为 'I'\''m pretty sure $HOME is set.'
。 sh解析后,参数为I'm pretty sure $HOME is set.
。
这里有一个 Python 脚本来简化这个过程:
#!/usr/bin/env python
import sys
import os
def shsafe(s):
return "'" + s.replace("'", "'\\''") + "'"
def exec_adb(text):
os.execvp('adb', [
'adb', 'shell', 'am', 'start-activity',
'-a', 'android.intent.action.SEND',
'-e', 'android.intent.extra.TEXT', shsafe(text),
'-t', 'text/plain',
'com.tengu.sharetoclipboard',
])
if sys.stdin.isatty():
if len(sys.argv) == 2:
exec_adb(sys.argv[1])
else:
sys.stderr.write(
'''Send something to the android clipboard over ADB. Requires
com.tengu.sharetoclipboard.
acb <text>
<some command> | acb''')
exit(1)
else:
exec_adb(sys.stdin.read())