尝试使用saveAttributes()
from androidxExifinterface
保存任何 JPEG 图片时,我的程序崩溃并出现错误“写入失败:EBADF(错误文件描述符)”
我可以从新项目重新开始复制错误。我正在使用 Android Studio: new project
-> Empty Activity
。我正在使用模拟器进行测试。
以下是我对新的 Empty Activity 模板所做的唯一更改的完整代码。
使用androidxExifinterface
,此代码能够正确获取 Exif 属性。但是,saveAttributes()
每次都崩溃:
saveAttributes()
无论我是否先崩溃,都会崩溃setAttribute()
。- 使用哪张图片无关紧要。我尝试过的每张照片都会崩溃。
- 我正在使用JPEG图片。我没有测试过其他 mime 类型。
saveAttributes()
抛出:“无法保存新文件。原始文件存储在...”
我想设置图片的Exif属性并保存到原始图像文件中。正确的方法是什么?
[这篇文章应该被标记androidx-interface
。但是那个标签不存在,而且我没有添加标签的声誉。所以我使用了 tag android-interface
,它确实存在]。
build.gradle (:app)
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)