Androidx Exifinterface аварийно завершает работу при попытке сохранить атрибуты. Ошибка записи: EBADF (неверный дескриптор файла)
При попытке сохранить любое изображение JPEG с помощью androidx моя программа вылетает с ошибкой «ошибка записи: EBADF (плохой дескриптор файла)»
Я могу воспроизвести ошибку, начиная с нового проекта. Я использую Android Studio:
new project
->
Empty Activity
. Использую для тестирования эмулятор.
Ниже приведен полный код с единственными изменениями, которые я внес в новый шаблон Empty Activity.
Использование androidx
Exifinterface
, этот код может правильно получать атрибуты Exif. Однако вылетает каждый раз:
- вылетает независимо от того, если я сначала
setAttribute()
или нет. - Какая картинка используется, не имеет значения. Вылетает для каждой картинки, которую я пробовал.
- Я использую изображения в формате JPEG. Я не тестировал другие типы пантомимы.
-
saveAttributes()
выдает: «Не удалось сохранить новый файл. Исходный файл хранится в ...»
Я хочу установить атрибуты Exif изображения и сохранить их в исходный файл изображения. Как правильно?
[Это сообщение должно быть помечено
androidx-interface
. Но этого тега не существует, и у меня нет репутации, чтобы добавить тег. Итак, я использовал тег
android-interface
, который существует].
build.gradle (: приложение)
implementation "androidx.exifinterface:exifinterface:1.3.2"
AndroidManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
MainActivity.kt:
package com.example.test_exif_save
import android.content.ContentUris
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import androidx.core.app.ActivityCompat
import androidx.exifinterface.media.ExifInterface
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Simple method for PERMISSIONS just for quick testing
val permissions = arrayOf(
android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
android.Manifest.permission.ACCESS_MEDIA_LOCATION,
)
ActivityCompat.requestPermissions(this, permissions, 0)
val contentUri: Uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
// id of arbitrary picture saved in Pictures/
// The picture chosen does not matter. The same crash occurs for every picture.
val picture_id: Long = 32
val uri = ContentUris.withAppendedId(contentUri, picture_id)
contentResolver.openInputStream(uri)?.use { stream ->
val exifData = ExifInterface(stream)
// Check that ExifInterface getAttribute works correctly
val attr_model = exifData.getAttribute(ExifInterface.TAG_MODEL)
val attr_datetime_original = exifData.getAttribute(ExifInterface.TAG_DATETIME_ORIGINAL)
val attr_image_width = exifData.getAttribute(ExifInterface.TAG_IMAGE_WIDTH)
Log.i("ExifData", "Model: $attr_model")
Log.i("ExifData", "Datetime original: $attr_datetime_original")
Log.i("ExifData", "Width: $attr_image_width")
// Try to save
// Causes fatal exception. Error: ErrnoException: write failed: EBADF (Bad file descriptor)
exifData.saveAttributes()
}
}
}
Трассировка стека:
com.example.test_exif_save E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.test_exif_save, PID: 12188
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.test_exif_save/com.example.test_exif_save.MainActivity}: java.io.IOException: Failed to save new file. Original file is stored in /data/user/0/com.example.test_exif_save/cache/temp1652156935871844716tmp
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.io.IOException: Failed to save new file. Original file is stored in /data/user/0/com.example.test_exif_save/cache/temp1652156935871844716tmp
at androidx.exifinterface.media.ExifInterface.saveAttributes(ExifInterface.java:4783)
at com.example.test_exif_save.MainActivity.onCreate(MainActivity.kt:44)
at android.app.Activity.performCreate(Activity.java:8000)
at android.app.Activity.performCreate(Activity.java:7984)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.io.IOException: write failed: EBADF (Bad file descriptor)
at libcore.io.IoBridge.write(IoBridge.java:540)
at java.io.FileOutputStream.write(FileOutputStream.java:398)
at androidx.exifinterface.media.ExifInterface.copy(ExifInterface.java:8087)
at androidx.exifinterface.media.ExifInterface.saveAttributes(ExifInterface.java:4779)
at com.example.test_exif_save.MainActivity.onCreate(MainActivity.kt:44)
at android.app.Activity.performCreate(Activity.java:8000)
at android.app.Activity.performCreate(Activity.java:7984)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: android.system.ErrnoException: write failed: EBADF (Bad file descriptor)
at libcore.io.Linux.writeBytes(Native Method)
at libcore.io.Linux.write(Linux.java:293)
at libcore.io.ForwardingOs.write(ForwardingOs.java:240)
at libcore.io.BlockGuardOs.write(BlockGuardOs.java:418)
at libcore.io.ForwardingOs.write(ForwardingOs.java:240)
at libcore.io.IoBridge.write(IoBridge.java:535)
at java.io.FileOutputStream.write(FileOutputStream.java:398)
at androidx.exifinterface.media.ExifInterface.copy(ExifInterface.java:8087)
at androidx.exifinterface.media.ExifInterface.saveAttributes(ExifInterface.java:4779)
at com.example.test_exif_save.MainActivity.onCreate(MainActivity.kt:44)
at android.app.Activity.performCreate(Activity.java:8000)
at android.app.Activity.performCreate(Activity.java:7984)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
2 ответа
У меня такая же проблема. Исправлено путем создания ExifInterface из FileDescriptor вместо InputStream. Заменять
val exifData = ExifInterface(stream)
С
val exifData = ExifInterface(context.contentResolver.openFile(new, "rw", null)!!.fileDescriptor)
(Обработка обнуляемости FileDescriptor на ваш вкус).
Я никогда не кодирую для Android, но просто быстро взглянув на код, похоже, что вы передаете входной поток в интерфейс exif. Вам нужно настроить отдельный выходной поток для записи контента? имеет смысл, почему вы можете читать, но тогда при записи возникает ошибка плохого дескриптора файла.
не могли бы вы попробовать запустить exifinterface для статического файла, а не для потока? посмотрим, изменится ли это что-нибудь.