Установка текста буфера обмена через оболочку adb с уровня API 11

До уровня 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?

Ответы

Ответ 1

Вы задали здесь два разных вопроса. Сервисные вызовы не связаны с функциями 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 вызывающий 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.