#android #kotlin #camera #image-gallery #android-camera-intent
#Android #kotlin #камера #изображение-галерея #android-камера-намерение
Вопрос:
Я потратил часы на изучение этой проблемы, и я не нашел решения (в StackOverflow или иным образом). Мое приложение нацелено на API 30, а minSskVersion равна 29. Я следую этому руководству:https://developer.android.com/training/camera/photobasics
У меня есть кнопка в моей активности, которая открывает камеру, используя намерение:
fun takePhoto() {
Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
takePictureIntent.resolveActivity(packageManager)?.also {
startActivityForResult(takePictureIntent, CAMERA_REQUEST)
}
}
}
Но я также хочу сохранить изображение в галерее устройства. Итак, я изменил свой takePhoto()
метод на:
fun takePhoto() {
Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
takePictureIntent.resolveActivity(packageManager)?.also {
val photoFile: File? = try {
createImageFile()
} catch (ex: IOException) {
ex.printStackTrace()
null
}
photoFile?.also {
try {
val photoURI: Uri = FileProvider.getUriForFile(
this,
"net.filiperamos.photogrid.provider",
it
)
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
} catch (ex: IllegalArgumentException) {
Log.d(TAG, "Could not get file URI.")
ex.printStackTrace()
}
startActivityForResult(takePictureIntent, CAMERA_REQUEST)
}
}
}
}
и добавлен createImageFile()
метод:
private fun createImageFile(): File {
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date())
val filename = "image_$timeStamp"
val storageDir: File? = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
return File.createTempFile(filename, ".jpg", storageDir).apply {
currentPhotoPath = absolutePath // Save path for later use
}
}
В моем манифесте есть разрешение на использование камеры и внешнюю запись:
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Я добавил независимый поставщик в тег приложения:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
и я создал file_paths.xml
:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path
name="my_images"
path="Android/data/net.ramos.photos/files/Pictures/" />
</paths>
Когда я запускаю этот код на своем устройстве, я получаю исключение при запуске FileProvider.getUriForFile()
:
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/net.ramos.photos/files/Pictures/image_20200823_1415398042919497737944663.jpg
И если я изменю свой file_paths.xml
файл, заменив external-files-path
на external-path
, ошибка исчезнет, но изображение нигде не сохраняется.
Чего я не понимаю?
Комментарии:
1. «и я создал file_paths.xml :» — замените свое
path
значение простоPictures/
. «ни одно изображение нигде не хранится» — как вы его ищете? Он не будет отображаться вMediaStore
, поскольку изображения, хранящиеся в этом месте, больше не подлежат индексации. Приложения в стиле галереи вряд ли в результате получат изображение.2. Спасибо, теперь ошибка исчезла. Но я хочу, чтобы фотографии, сделанные с помощью моего приложения, были доступны другим приложениям. Как я могу сделать его доступным у системного медиа-провайдера?
3. В течение следующего года или около того используйте
android:requestLegacyExternalStorage="true"
общедоступное местоположение и записывайте в него, например, вPictures/
каталог верхнего уровня, а не в конкретное местоположение приложения, как вы используете сейчас. На данный момент, учитывая весь беспорядок в области хранения и ограничения наACTION_IMAGE_CAPTURE
, я понятия не имею, каким будет план для желаемой функции через год.
Ответ №1:
Добавьте следующую строку в свой файл манифеста в качестве атрибута тега ‘application’,
android:requestLegacyExternalStorage="true"
это должно решить проблему, с которой вы столкнулись, и исключение должно исчезнуть.
Комментарии:
1. Это не сработало: если я сохраню,
external-files-path
я все равно увижу ошибку, и если я изменю ее наexternal-path
, я не увижу ошибки, но я также не увижу сохраненное изображение. Хотя, похоже, согласно @CommonsWare, я ищу фотографию не в том месте…