Set clipboard text via adb shell as of API level 11 Set clipboard text via adb shell as of API level 11 android android

Set clipboard text via adb shell as of API level 11


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

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.

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:

TRANSACTION_setPrimaryClip = 1TRANSACTION_getPrimaryClip = 2TRANSACTION_getPrimaryClipDescription = 3TRANSACTION_hasPrimaryClip = 4TRANSACTION_addPrimaryClipChangedListener = 5TRANSACTION_removePrimaryClipChangedListener = 6TRANSACTION_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.

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 -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.


I found a way to do this using com.tengu.sharetoclipboard. You install it with F-Droid, then you start it with am over adb with the following arguments:

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> is the new contents of the android clipboard. Note that this text must be escaped so that it is not interpreted specially by sh on the remote end. In practice, that means surrounding it with single quotes and replacing all single quotes with '\''. For instance, this would work fine if the local shell is 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

After fish parses it, the argument is 'I'\''m pretty sure $HOME is set.'. After sh parses it, the argument is I'm pretty sure $HOME is set..

Here's a python script to simplify this process:

#!/usr/bin/env pythonimport sysimport osdef 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. Requirescom.tengu.sharetoclipboard.acb <text><some command> | acbacb <some_text_file.txt''')        exit(1)else:    exec_adb(sys.stdin.read())