Как передать изображение в другое приложение или процесс в Android
Что проверяют
Знаете ли вы, как в современном Android одно приложение даёт другому доступ к файлу без общих разрешений на хранилище. Следом почти всегда спрашивают, почему нельзя просто положить Bitmap в Intent и что делать, если картинку нужно передать своему же сервису в отдельном процессе.
Как отвечать
Ключевая мысль: передаётся не картинка, а content:// URI с временным правом на чтение.
FileProvider: объявляется в манифесте сandroid:exported="false"иandroid:grantUriPermissions="true", а вres/xmlописывается, какие каталоги можно раздавать (<cache-path>,<files-path>). Файл сохраняете, например, вcacheDir, URI получаете черезFileProvider.getUriForFile(context, authority, file);Intent.ACTION_SEND:setType("image/jpeg"), URI вEXTRA_STREAM, флагFLAG_GRANT_READ_URI_PERMISSION, запуск черезIntent.createChooser. Для нескольких картинокACTION_SEND_MULTIPLEи список URI;- своя граница процессов: если сервис того же приложения живёт в
android:process, картинку тоже передают через файл илиContentProvider, а большие объёмы черезParcelFileDescriptorилиSharedMemoryв AIDL-интерфейсе; MediaStore: если картинка должна остаться в галерее, её пишут вMediaStore.Images, на Android 10+ для этого не нужно разрешение на запись.
Отдельно объясните, почему не Bitmap в extras: всё, что идёт через Binder, упирается в буфер транзакций около 1 МБ на процесс, и крупная картинка роняет приложение с TransactionTooLargeException.
Где спотыкаются
Отдают file:// URI. При targetSdk 24 и выше это сразу FileUriExposedException, а принимающее приложение всё равно не имело бы доступа к вашей приватной папке.
Забывают флаг FLAG_GRANT_READ_URI_PERMISSION. Получатель видит URI, но при открытии ловит SecurityException, и ошибка всплывает только у него.
Просят READ_EXTERNAL_STORAGE «на всякий случай». Для отправки через FileProvider разрешения не нужны, а при targetSdk 33 и выше это разрешение вообще заменено на READ_MEDIA_IMAGES.