Android 将EXIF数据写入使用DocumentFile类保存的图像
我需要从DocumentFile或Uri中获取一个具有正确方案的文件,而不是具有Android 将EXIF数据写入使用DocumentFile类保存的图像,android,storage-access-framework,documentfile,android-storage,Android,Storage Access Framework,Documentfile,Android Storage,我需要从DocumentFile或Uri中获取一个具有正确方案的文件,而不是具有content://com.android.externalstorage.documents/tree/primary:如果选择了设备的主存储器。 要获取图像的文件或绝对路径,我需要一个file:///storage/emulated/0 或storage/emulated/0,但我找不到一种方法来获取正确的Uri,以便构建一个将EXIF数据写入映像的文件 我的设想是: 用户选择一个路径来保存返回Uri为conte
content://com.android.externalstorage.documents/tree/primary:
如果选择了设备的主存储器。
要获取图像的文件或绝对路径,我需要一个file:///storage/emulated/0 或storage/emulated/0,但我找不到一种方法来获取正确的Uri,以便构建一个将EXIF数据写入映像的文件
我的设想是:
content://com.android.externalstorage.documents
onActivityResult()。我使用treeUri.toString()
将此路径保存到SharedReferences以供以后使用DocumentFile.fromtreeeuri(MainActivity.this,Uri.parse(uriString))保存图像代码>
file:///storage/emulated/
我可以使用file filePath=new file(Uri.create(saveDir.getUri().toString())将此Uri转换为文件代码>
Uri uri; // the URI you've received from the other app
InputStream in;
try {
in = getContentResolver().openInputStream(uri);
ExifInterface exifInterface = new ExifInterface(in);
// Now you can extract any Exif tag you want
// Assuming the image is a JPEG or supported raw format
} catch (IOException e) {
// Handle any errors
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ignored) {}
}
}
注意:ExiFinInterface将不适用于远程输入流,例如从HttpURLConnection返回的输入流。强烈建议仅将它们与content://或file://URI一起使用
显然,上面的代码段正在读取数据,因为它打开了一个InputStream来读取数据。我需要能够将EXIF数据写入JPEG文件。如果Api为24或更高,则使用
文件描述符将EXIF数据写入先前保存的图像,并使用已知的内容Uri
private void writeEXIFWithFileDescriptor(Uri uri) {
if (Build.VERSION.SDK_INT < 24) {
showToast("writeEXIFWithInputStream() API LOWER 24", Toast.LENGTH_SHORT);
return;
}
ParcelFileDescriptor parcelFileDescriptor = null;
try {
parcelFileDescriptor = mContext.getContentResolver().openFileDescriptor(uri, "rw");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
showToast("writeEXIFWithFileDescriptor(): " + fileDescriptor.toString(), Toast.LENGTH_LONG);
ExifInterface exifInterface = new ExifInterface(fileDescriptor);
// TODO Create Exif Tags class to save Exif data
exifInterface.saveAttributes();
} catch (FileNotFoundException e) {
showToast("File Not Found " + e.getMessage(), Toast.LENGTH_LONG);
} catch (IOException e) {
// Handle any errors
e.printStackTrace();
showToast("IOEXception " + e.getMessage(), Toast.LENGTH_LONG);
} finally {
if (parcelFileDescriptor != null) {
try {
parcelFileDescriptor.close();
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
}
}
这两种方法都可以用于将Exif数据写入保存到设备内存或SD卡的图像。您还可以使用Storage Access Framework中的有效Uri将图像保存到SD卡
我还发现了一种从内容Uri获取内存和SD卡的绝对路径的方法,但这与这个问题无关,并且鼓励使用Uri而不是绝对路径,并且不会导致未注意到的错误,我也无法使用绝对路径将图像保存到SD卡,只能从中读取
private boolean exportImageWithEXIF(Bitmap bitmap, DocumentFile documentFile) {
OutputStream outputStream = null;
File bufFile = new File(Environment.getExternalStorageDirectory(), "buffer.jpg");
long freeSpace = Environment.getExternalStorageDirectory().getFreeSpace() / 1048576;
double bitmapSize = bitmap.getAllocationByteCount() / 1048576d;
showToast("exportImageWithEXIF() freeSpace " + freeSpace, Toast.LENGTH_LONG);
showToast("exportImageWithEXIF() bitmap size " + bitmapSize, Toast.LENGTH_LONG);
try {
outputStream = new FileOutputStream(bufFile);
// Compress image from bitmap with JPEG extension
if (mCameraSettings.getImageFormat().equals(Constants.IMAGE_FORMAT_JPEG)) {
isImageSaved = bitmap.compress(CompressFormat.JPEG, mCameraSettings.getImageQuality(), outputStream);
showToast("isImageSaved: " + isImageSaved, Toast.LENGTH_SHORT);
}
if (isImageSaved) {
writeEXIFWithFile(bufFile);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
OutputStream os = null;
InputStream is = null;
try {
int len;
byte[] buf = new byte[4096];
os = mContext.getContentResolver().openOutputStream(documentFile.getUri());
is = new FileInputStream(bufFile);
while ((len = is.read(buf)) > 0) {
os.write(buf, 0, len);
}
os.close();
is.close();
if (bufFile != null) {
bufFile.delete();
bufFile = null;
}
} catch (IOException e) {
e.printStackTrace();
}
return isImageSaved;
}