Пользователи любят изображения, видео и другой выразительный контент, но вставлять и перемещать этот контент в приложениях не всегда легко. Чтобы приложениям было проще получать разнообразный контент, в Android 12 (уровень API 31) представлен унифицированный API, который позволяет вашему приложению принимать контент из любого источника: буфера обмена, клавиатуры или перетаскивания.
Вы можете прикрепить интерфейс, например OnReceiveContentListener
, к компонентам пользовательского интерфейса и получать обратный вызов, когда контент вставляется с помощью любого механизма. Обратный вызов становится единственным местом, где ваш код обрабатывает получение всего контента: от простого и стилизованного текста до разметки, изображений, видео, аудиофайлов и т. д.
Для обратной совместимости с предыдущими версиями Android этот API также доступен в AndroidX, начиная с Core 1.7 и Appcompat 1.4 , которые мы рекомендуем использовать при реализации этой функциональности.
Обзор
В случае с другими существующими API каждый механизм пользовательского интерфейса, например меню касания и удержания или перетаскивание, имеет свой собственный соответствующий API. Это означает, что вам придется интегрироваться с каждым API отдельно, добавляя аналогичный код для каждого механизма вставки контента:
API OnReceiveContentListener
объединяет эти различные пути кода, создавая единый API для реализации, поэтому вы можете сосредоточиться на логике, специфичной для вашего приложения, и позволить платформе позаботиться обо всем остальном:
Этот подход также означает, что когда на платформу добавляются новые способы вставки контента, вам не нужно вносить дополнительные изменения в код, чтобы включить поддержку в вашем приложении. И если вашему приложению необходимо реализовать полную настройку для конкретного варианта использования, вы все равно можете использовать существующие API, которые продолжают работать так же.
Выполнение
API представляет собой интерфейс прослушивателя с одним методом OnReceiveContentListener
. Для поддержки более старых версий платформы Android мы рекомендуем использовать соответствующий интерфейс OnReceiveContentListener
в библиотеке AndroidX Core.
Чтобы использовать API, реализуйте прослушиватель, указав, какие типы контента может обрабатывать ваше приложение:
Котлин
object MyReceiver : OnReceiveContentListener { val MIME_TYPES = arrayOf("image/*", "video/*") // ... override fun onReceiveContent(view: View, payload: ContentInfoCompat): ContentInfoCompat? { TODO("Not yet implemented") } }
Ява
public class MyReceiver implements OnReceiveContentListener { public static final String[] MIME_TYPES = new String[] {"image/*", "video/*"}; // ... }
После указания всех типов MIME контента, которые поддерживает ваше приложение, реализуйте остальную часть прослушивателя:
Котлин
class MyReceiver : OnReceiveContentListener { override fun onReceiveContent(view: View, contentInfo: ContentInfoCompat): ContentInfoCompat { val split = contentInfo.partition { item: ClipData.Item -> item.uri != null } val uriContent = split.first val remaining = split.second if (uriContent != null) { // App-specific logic to handle the URI(s) in uriContent. } // Return anything that your app didn't handle. This preserves the // default platform behavior for text and anything else that you aren't // implementing custom handling for. return remaining } companion object { val MIME_TYPES = arrayOf("image/*", "video/*") } }
Ява
public class MyReceiver implements OnReceiveContentListener { public static final String[] MIME_TYPES = new String[] {"image/*", "video/*"}; @Override public ContentInfoCompat onReceiveContent(View view, ContentInfoCompat contentInfo) { Pairsplit = contentInfo.partition( item -> item.getUri() != null); ContentInfo uriContent = split.first; ContentInfo remaining = split.second; if (uriContent != null) { // App-specific logic to handle the URI(s) in uriContent. } // Return anything that your app didn't handle. This preserves the // default platform behavior for text and anything else that you aren't // implementing custom handling for. return remaining; } }
Если ваше приложение уже поддерживает совместное использование с намерениями, вы можете повторно использовать логику, специфичную для приложения, для обработки URI контента. Верните все оставшиеся данные, чтобы делегировать обработку этих данных платформе.
После реализации прослушивателя установите его в соответствующих элементах пользовательского интерфейса вашего приложения:
Котлин
class MyActivity : Activity() { public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... val myInput = findViewById(R.id.my_input) ViewCompat.setOnReceiveContentListener(myInput, MyReceiver.MIME_TYPES, MyReceiver()) } }
Ява
public class MyActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { // ... AppCompatEditText myInput = findViewById(R.id.my_input); ViewCompat.setOnReceiveContentListener(myInput, MyReceiver.MIME_TYPES, new MyReceiver()); } }
Разрешения URI
Разрешения на чтение предоставляются и освобождаются платформой автоматически для любых URI контента в полезных данных, передаваемых в OnReceiveContentListener
.
Обычно ваше приложение обрабатывает URI контента в службе или действии. Для длительной обработки используйте WorkManager . При реализации этого расширите разрешения для целевой службы или действия, передав содержимое с помощью Intent.setClipData
и установив флаг FLAG_GRANT_READ_URI_PERMISSION
.
Альтернативно вы можете использовать фоновый поток в текущем контексте для обработки содержимого. В этом случае вы должны сохранить ссылку на объект payload
, полученный прослушивателем, чтобы гарантировать, что разрешения не будут преждевременно отозваны платформой.
Пользовательские представления
Если ваше приложение использует пользовательский подкласс View
, позаботьтесь о том, чтобы OnReceiveContentListener
не был обойден.
Если ваш класс View
переопределяет метод onCreateInputConnection
, используйте Jetpack API InputConnectionCompat.createWrapper
для настройки InputConnection
.
Если ваш класс View
переопределяет метод onTextContextMenuItem
, делегируйте его суперу, когда пункт меню — R.id.paste
или R.id.pasteAsPlainText
.
Сравнение с API изображения клавиатуры
Вы можете думать об API OnReceiveContentListener
как о следующей версии существующего API изображения клавиатуры . Этот унифицированный API поддерживает функциональность API изображения клавиатуры, а также некоторые дополнительные функции. Совместимость устройств и функций зависит от того, используете ли вы библиотеку Jetpack или собственные API из Android SDK.
Действие или функция | Поддерживается API изображения клавиатуры. | Поддерживается унифицированным API |
---|---|---|
Вставка с клавиатуры | Да (уровень API 13 и выше) | Да (уровень API 13 и выше) |
Вставьте, используя вставку из меню касания и удержания. | Нет | Да |
Вставка с помощью перетаскивания | Нет | Да (уровень API 24 и выше) |
Действие или функция | Поддерживается API изображения клавиатуры. | Поддерживается унифицированным API |
---|---|---|
Вставка с клавиатуры | Да (уровень API 25 и выше) | Да (Android 12 и выше) |
Вставьте, используя вставку из меню касания и удержания. | Нет | |
Вставка с помощью перетаскивания | Нет |