如何获取从 FileProvider class 获取的图像文件的方向?
How to get orientation of image file, which was taken from FileProvider class?
背景
针对API 24或以上,而不是使用简单的"Uri.fromFile"命令,开发者需要使用FileProvider(或他们自己的ContentProvider),以让其他应用程序访问应用程序的文件.
问题
我尝试打开一个相机应用程序,让它将文件保存到我的应用程序的私有存储中,使用以下代码:
final Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
final File photoFile = FileHelper.generateTempCameraFile(this);
mCameraCachedImageURI = FileProvider.getUriForFile(this, getPackageName()+ ".provider", photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCameraCachedImageURI);
takePictureIntent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(takePictureIntent, REQ_CODE_PICK_IMAGE_FROM_CAMERA);
provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="."/>
</paths>
清单文件
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
这开始很好,因为相机应用程序已启动,但在返回的结果中,我无法使用以前工作正常的代码获取图像文件的方向:
@Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
int orientation = getOrientation(this,mCameraCachedImageURI );
...
public static int getOrientation(final Context context, final Uri photoUri) {
Cursor cursor = null;
try {
cursor = context.getContentResolver().query(photoUri,
new String[]{MediaStore.Images.ImageColumns.ORIENTATION}, null, null, null);
} catch (final Exception ignored) {
}
if (cursor == null) {
// fallback
return getOrientation(photoUri.getPath());
}
int result = 0;
if (cursor.getCount() > 0) {
cursor.moveToFirst();
result = cursor.getInt(0);
}
cursor.close();
return result;
}
public static int getOrientation(final String filePath) {
if (TextUtils.isEmpty(filePath))
return 0;
try {
final ExifInterface exifInterface = new ExifInterface(filePath);
final int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
int rotate = 0;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
return rotate;
} catch (final IOException ignored) {
}
return 0;
}
这会崩溃,因为游标在 运行 这段代码时没有任何列。
不仅如此,甚至回退功能(当更改代码以使用它时)也不起作用,因为它向文件路径添加了一个附加部分(在本例中为 "external") .
我发现了什么
contentResolver 似乎在这里使用了 FileProvider,而不是以前版本 Android 中使用的。
事实是,我需要此 URI 的 ContentProvider 才能授予相机应用访问此文件的权限...
问题
如何使用新的 FileProvider Uri 使用上述代码(或更好的代码)获取方向?也许我可以强制 ContentResolver 使用以前的 ContentProvider 来获取游标所需的列数据?
我真的必须在这里创建自己的 ContentProvider 吗?
A Uri
不是文件。您在 Uri
上调用 getPath()
并将其视为文件路径。仅当 Uri
中的方案为 file
时才有效。在你的情况下,它不是。
您已经有一个指向该文件的 File
对象。它被称为photoFile
。在 activity 的字段中保留它,并将其保存在已保存的实例状态 Bundle
中(因为当相机应用程序在前台时,您的进程可能会终止)。然后,使用 photoFile
。但是不要使用内置 ExifInterface
,因为 it has security flaws.
How do I get the orientation using the above code (or even a better code), using the new FileProvider Uri ?
你不知道。使用 photoFile
.
Maybe I can force the ContentResolver to use the previously ContentProvider to get the needed column's data of the cursor?
我不知道为什么您会期望 getOrientation()
需要 Uri
才能工作。您在 MediaStore
中查询有关 Uri
的数据,但该数据并非来自 MediaStore
。
Do I really have to create my own ContentProvider here?
不,因为 FileProvider
不是你的问题。您将使用自己的 ContentProvider
方法来使用同样有缺陷的 getOrientation()
方法。
背景
针对API 24或以上,而不是使用简单的"Uri.fromFile"命令,开发者需要使用FileProvider(或他们自己的ContentProvider),以让其他应用程序访问应用程序的文件.
问题
我尝试打开一个相机应用程序,让它将文件保存到我的应用程序的私有存储中,使用以下代码:
final Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
final File photoFile = FileHelper.generateTempCameraFile(this);
mCameraCachedImageURI = FileProvider.getUriForFile(this, getPackageName()+ ".provider", photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCameraCachedImageURI);
takePictureIntent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(takePictureIntent, REQ_CODE_PICK_IMAGE_FROM_CAMERA);
provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="."/>
</paths>
清单文件
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
这开始很好,因为相机应用程序已启动,但在返回的结果中,我无法使用以前工作正常的代码获取图像文件的方向:
@Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
int orientation = getOrientation(this,mCameraCachedImageURI );
...
public static int getOrientation(final Context context, final Uri photoUri) {
Cursor cursor = null;
try {
cursor = context.getContentResolver().query(photoUri,
new String[]{MediaStore.Images.ImageColumns.ORIENTATION}, null, null, null);
} catch (final Exception ignored) {
}
if (cursor == null) {
// fallback
return getOrientation(photoUri.getPath());
}
int result = 0;
if (cursor.getCount() > 0) {
cursor.moveToFirst();
result = cursor.getInt(0);
}
cursor.close();
return result;
}
public static int getOrientation(final String filePath) {
if (TextUtils.isEmpty(filePath))
return 0;
try {
final ExifInterface exifInterface = new ExifInterface(filePath);
final int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
int rotate = 0;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
return rotate;
} catch (final IOException ignored) {
}
return 0;
}
这会崩溃,因为游标在 运行 这段代码时没有任何列。
不仅如此,甚至回退功能(当更改代码以使用它时)也不起作用,因为它向文件路径添加了一个附加部分(在本例中为 "external") .
我发现了什么
contentResolver 似乎在这里使用了 FileProvider,而不是以前版本 Android 中使用的。
事实是,我需要此 URI 的 ContentProvider 才能授予相机应用访问此文件的权限...
问题
如何使用新的 FileProvider Uri 使用上述代码(或更好的代码)获取方向?也许我可以强制 ContentResolver 使用以前的 ContentProvider 来获取游标所需的列数据?
我真的必须在这里创建自己的 ContentProvider 吗?
A Uri
不是文件。您在 Uri
上调用 getPath()
并将其视为文件路径。仅当 Uri
中的方案为 file
时才有效。在你的情况下,它不是。
您已经有一个指向该文件的 File
对象。它被称为photoFile
。在 activity 的字段中保留它,并将其保存在已保存的实例状态 Bundle
中(因为当相机应用程序在前台时,您的进程可能会终止)。然后,使用 photoFile
。但是不要使用内置 ExifInterface
,因为 it has security flaws.
How do I get the orientation using the above code (or even a better code), using the new FileProvider Uri ?
你不知道。使用 photoFile
.
Maybe I can force the ContentResolver to use the previously ContentProvider to get the needed column's data of the cursor?
我不知道为什么您会期望 getOrientation()
需要 Uri
才能工作。您在 MediaStore
中查询有关 Uri
的数据,但该数据并非来自 MediaStore
。
Do I really have to create my own ContentProvider here?
不,因为 FileProvider
不是你的问题。您将使用自己的 ContentProvider
方法来使用同样有缺陷的 getOrientation()
方法。