17

在 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 开始,不推荐使用列出的方法,新的方法将ClipData作为参数。您现在如何通过 设置剪贴板内容adb shell

4

2 回答 2

10

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

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

就服务调用而言,这些是内部实现细节,正如您所注意到的,不能保证跨 Android 版本工作。如果您查看 Android源代码,您会发现当前定义了这些事务:

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;
    }
}

服务应该有一个意图过滤器,声明它能够处理MySetClipboard意图操作。

于 2013-09-03T00:52:49.893 回答
1

我找到了一种使用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>是android剪贴板的新内容。请注意,此文本必须进行转义,以免sh在远程端对其进行特殊解释。实际上,这意味着用单引号将其括起来,并将所有单引号替换为'\''. 例如,如果本地 shell 是鱼,这将正常工作:

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(' '.join(sys.argv[1:]))
    else:
        sys.stderr.write(
'''Send something to the android clipboard over ADB. Requires
com.tengu.sharetoclipboard.
acb <text>
<some command> | acb
acb <some_text_file.txt''')
        exit(1)
else:
    exec_adb(sys.stdin.read())
于 2021-06-30T23:57:36.077 回答