如何获取从FileProvider类获取的图像文件的方向? [英] How to get orientation of image file, which was taken from FileProvider class?
问题描述
Targeting API 24或更高版本,开发人员需要使用FileProvider(或他们自己的ContentProvider),而不是使用简单的"Uri.fromFile"命令,才能让其他应用访问该应用的文件.
Targeting API 24 or above, instead of using a simple "Uri.fromFile" command, developers need to use FileProvider (or their own ContentProvider), in order to let other apps to access the app's files.
我尝试使用以下代码打开相机应用程序,使其将文件保存到应用程序的私有存储中:
I try to open a camera app to let it save a file into my app's private storage, using this code:
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>
启动相机应用程序后,这开始就很好,但是在返回的结果中,我无法使用以前可以正常运行的代码来获取图像文件的方向:
This starts fine, as the camera app is launched, but in the returned result, I fail to get the orientation of the image file using code that previously worked fine:
@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;
}
这将崩溃,因为运行此代码时光标没有任何列.
This will crash, because the cursor doesn't have any columns while running this code.
不仅如此,即使回退功能(在更改代码以使用它时)也不起作用,因为它在文件路径中添加了另一部分(在这种情况下为外部").
Not only that, but even the fallback function (when changing the code to use it) doesn't work, as it adds an additional part to the path of the file ("external" in this case).
似乎contentResolver在这里使用的是FileProvider,而不是以前版本的Android中使用的文件.
It seems that the contentResolver uses the FileProvider here, instead of what was used on previous versions of Android.
问题是,我需要此URI的ContentProvider才能授予相机应用访问该文件的权限...
Thing is, I need the ContentProvider of this URI in order to grant the camera app permission to access this file...
如何使用新的FileProvider Uri使用以上代码(甚至更好的代码)来获得方向?也许我可以强制ContentResolver使用以前的ContentProvider来获取光标所需的列数据?
How do I get the orientation using the above code (or even a better code), using the new FileProvider Uri ? Maybe I can force the ContentResolver to use the previously ContentProvider to get the needed column's data of the cursor?
我真的必须在这里创建自己的ContentProvider吗?
Do I really have to create my own ContentProvider here?
推荐答案
Uri
不是文件.您正在Uri
上调用getPath()
并将其视为文件路径.仅当Uri
中的方案为file
时,这才有效.就您而言,事实并非如此.
A Uri
is not a file. You are calling getPath()
on a Uri
and are treating it as if it were a file path. That only works if the scheme in the Uri
is file
. In your case, it is not.
您已经有一个File
对象指向该文件.它称为photoFile
.保留活动区域中的内容,然后将其保存为已保存实例状态Bundle
(因为在照相机应用程序处于前台时,您的过程可能会终止).然后,使用photoFile
.不过请不要使用内置的ExifInterface
,因为
You already have a File
object pointing to the file. It is called photoFile
. Hold onto that in a field of your activity, and save it in the saved instance state Bundle
(as your process might get terminated while the camera app is in the foreground). Then, use photoFile
. Don't use the built-in ExifInterface
though, as it has security flaws.
如何使用新的FileProvider Uri使用上面的代码(甚至更好的代码)来获得方向?
How do I get the orientation using the above code (or even a better code), using the new FileProvider Uri ?
你不知道.使用photoFile
.
也许我可以强制ContentResolver使用以前的ContentProvider来获取光标所需的列数据?
Maybe I can force the ContentResolver to use the previously ContentProvider to get the needed column's data of the cursor?
我不知道为什么您会期望使用Uri
的getOrientation()
起作用.您正在查询MediaStore
以获得与Uri
无关的数据.
I have no idea why you would expect the getOrientation()
that takes a Uri
to work. You are querying the MediaStore
for data about a Uri
that does not come from the MediaStore
.
我真的必须在这里创建自己的ContentProvider吗?
Do I really have to create my own ContentProvider here?
否,因为FileProvider
不是您的问题.您将有与自己的ContentProvider
相同的有缺陷的getOrientation()
方法.
No, because FileProvider
is not your problem. You would have the same flawed getOrientation()
methods with your own ContentProvider
.
这篇关于如何获取从FileProvider类获取的图像文件的方向?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!