Приложение может не только отправлять данные в другие приложения, но и получать их. Подумайте, как пользователи взаимодействуют с вашим приложением и какие типы данных вы хотите получать из других приложений. Например, приложение социальной сети может быть заинтересовано в получении текстового контента, такого как интересный веб-URL, из другого приложения.
В приложении, использующем Compose Navigation, получение данных, отправленных другим приложением, представляет собой трехэтапный процесс:
Объявите
<intent-filter>в манифесте. Вам по-прежнему нужно добавить фильтр intent в действие в файлеAndroidManifest.xml. Это сообщает ОС Android, что ваше приложение способно получать определенные действия (например,ACTION_SEND) и MIME-типы (например,text/plain).Определите
navDeepLinkв графе Navigation Compose. ПрикрепитеnavDeepLink, соответствующий действию и MIME-типу, непосредственно к composable-функции, которая должна показывать контент.NavControllerавтоматически перехватывает входящий интент и направляет пользователя прямо на этот экран.Извлеките полезную нагрузку входящих данных. На целевом экране получите доступ к дополнительным данным intent (например,
EXTRA_TEXTилиEXTRA_STREAM), чтобы извлечь общий контент и обновить состояние пользовательского интерфейса.
Цели прямого обмена – это ссылки на контент в приложении, которые часто представляют собой пользователя или группу и показываются на панели "Поделиться". Например, мессенджер может предлагать в качестве цели для прямой отправки пользователя, со ссылкой на контент, ведущей прямо в чат с ним. Подробные инструкции вы найдете в статье Как указать цели для прямого обмена.
Поддерживаемые MIME-типы
В идеале приложение должно поддерживать как можно больше MIME-типов.
Например, мессенджер, предназначенный для отправки текста, изображений и видео, должен поддерживать получение text/*, image/* и video/*. Вот несколько распространенных MIME-типов для отправки и получения данных в Android.
| Регистрация получателей для | Отправители отправляют |
|---|---|
text/* |
|
image/* |
|
video/* |
|
| Поддерживаемые расширения имени файла | application/pdf |
Ознакомьтесь с официальным реестром MIME-типов IANA.
Создавайте удобные цели для отправки контента
Когда пользователи нажимают на цель, связанную с определенным действием, дайте им возможность подтвердить и отредактировать контент, прежде чем приложение его использует. Это особенно важно для текстовых данных.
Как получать данные в приложении
Чтобы получать общие данные в приложении, созданном с помощью Compose, нужно объявить фильтры интентов в манифесте, направить входящие интенты на нужный экран с помощью ссылок на контент и извлечь полезную нагрузку из интента, чтобы обновить интерфейс.
Обновите манифест
Фильтры интентов сообщают системе, какие интенты принимает компонент приложения. Подобно тому, как вы создавали интент с действием ACTION_SEND на уроке Отправка данных в другие приложения, вы создаете фильтры интентов для получения интентов с этим действием. Фильтр интентов определяется в манифесте с помощью элемента <intent-filter>. Например, если ваше приложение обрабатывает текстовый контент, манифест, включающий одно или несколько изображений любого типа, будет выглядеть следующим образом:
<activity android:name=".ui.MyActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
Когда другое приложение пытается поделиться чем-либо из этого, создавая намерение и передавая его в startActivity(), ваше приложение указывается в качестве варианта на панели "Поделиться" или в средстве разрешения намерений. Если пользователь выберет ваше приложение, запустится соответствующее действие (в примере выше это .ui.MyActivity). После этого вы можете обработать контент в коде и интерфейсе.
Как определить ссылку на контент в графе навигации
В Compose Navigation прикрепите navDeepLink непосредственно к composable-функции назначения, которая должна отображать контент. Когда другое приложение передает данные, соответствующие вашему фильтру интентов, Compose Navigation направляет пользователя непосредственно к этому пункту назначения:
composable( route = "incoming_share", deepLinks = listOf( navDeepLink { action = Intent.ACTION_SEND mimeType = "text/plain" }, navDeepLink { action = Intent.ACTION_SEND mimeType = "image/*" }, navDeepLink { action = Intent.ACTION_SEND_MULTIPLE mimeType = "image/*" } ) ) { SharesheetHandler() }
navDeepLink сопоставляет действие и MIME-тип входящего намерения, чтобы перейти к нужному экрану. После этого обработчик проверяет намерение, чтобы определить, какие полезные данные были получены (например, одно изображение или несколько), и извлекает соответствующие дополнительные данные.
Обработка входящего контента
Чтобы получить контент, доставленный Intent, прочитайте текущее действие из LocalActivity.current в composable-функции, а затем изучите намерение, чтобы определить, что делать дальше. Если это действие можно запустить из других частей системы (например, из панели запуска), учтите это при проверке намерения.
Будьте особенно внимательны при проверке входящих данных: может быть задан неправильный MIME-тип или отправляемое изображение может быть слишком большим. Обрабатывайте двоичные данные или выполняйте тяжелые операции I/O (например, декодирование больших изображений или запись файлов) асинхронно с помощью сопрограмм (например, Dispatchers.IO), а не в основном потоке UI.
@Composable fun SharesheetHandler() { val activity = LocalActivity.current val intent = activity?.intent when (intent?.action) { Intent.ACTION_SEND -> { if (intent.type == "text/plain") { handleSendText(intent) // Handle text being sent } else if (intent.type?.startsWith("image/") == true) { handleSendImage(intent) // Handle single image being sent } } Intent.ACTION_SEND_MULTIPLE -> { if (intent.type?.startsWith("image/") == true) { handleSendMultipleImages(intent) // Handle multiple images being sent } } else -> { // Handle other intents, such as being started from the home screen } } } private fun handleSendText(intent: Intent) { intent.getStringExtra(Intent.EXTRA_TEXT)?.let { // Update UI state with the shared text } } private fun handleSendImage(intent: Intent) { val imageUri = IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java) imageUri?.let { // Update UI state with the shared image } } private fun handleSendMultipleImages(intent: Intent) { val imageUris = IntentCompat.getParcelableArrayListExtra(intent, Intent.EXTRA_STREAM, Uri::class.java) imageUris?.let { // Update UI state with the shared images } }
При извлечении двоичных данных или URI из дополнительных данных намерения (например, EXTRA_STREAM) используйте IntentCompat.getParcelableExtra() или IntentCompat.getParcelableArrayListExtra() из библиотеки AndroidX Core, как показано в функциях handleSendImage и handleSendMultipleImages выше. В Android 13 (уровень API 33) метод Intent.getParcelableExtra(String) без параметров заменен типобезопасными методами, которые принимают ожидаемый тип класса.
Обновление интерфейса после получения данных может быть как простым, например обновление состояния для заполнения TextField, так и сложным, например применение фильтра к изображению. Дальнейшие действия зависят от приложения.
Как поделиться URL скриншота
Когда вы делаете скриншот, вы можете поделиться им и связанным с ним URL.
Это делает приложение более удобным для пользователей. При получении URL обязательно извлеките поле EXTRA_TEXT из намерения, как показано в примере ниже.
IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java).let { // Handle the EXTRA_TEXT as well val extraText = intent.getCharSequenceExtra(Intent.EXTRA_TEXT) // Update UI state with the shared image and the EXTRA_TEXT if available }
Помогите пользователям узнавать ваше приложение
Приложение представлено значком и ярлыком на панели "Поделиться" и в окне выбора намерения. Оба этих параметра определены в манифесте. Чтобы предоставить больше контекста, можно задать ярлыки фильтров действий или намерений.
Начиная с Android 10 (уровень API 29), на панели "Поделиться" используются только значки, заданные в манифесте в теге application. Android игнорирует значки, заданные в тегах intent-filter и activity.
Получение расширенного контента
Намерения ACTION_SEND позволяют получать данные из панели "Поделиться" и средства разрешения намерений на уровне действия или навигации. Кроме того, приложения могут получать расширенные сведения (например, изображения, видео, аудиофайлы и форматированный текст) через прямое взаимодействие с интерфейсом. К ним относятся:
- Вставка из буфера обмена (меню, которое открывается при нажатии и удержании).
- вставка медиафайлов, например стикеров или GIF-изображений, непосредственно с виртуальной клавиатуры (IME);
- перетаскивание контента из другого приложения в режиме разделения экрана или многооконном режиме;
В интерфейсах на основе представлений в Android 12 (уровень API 31) и AndroidX Core 1.7 появился унифицированный API OnReceiveContentListener. Этот прослушиватель объединяет обработку контента из буфера обмена, клавиатуры и перетаскивания в один обратный вызов. Подробные инструкции по реализации этого в представлениях можно найти в статье Получение расширенного контента.
В Jetpack Compose вы можете обрабатывать получение расширенного контента, вставленного в компоненты пользовательского интерфейса (например, текстовые поля), с помощью модификатора Modifier.contentReceiver или модификаторов перетаскивания.