Android中的FileProvider路径创建和BitmapFactory.decodefile问题

i_o*_*i_o 6 android uri android-intent bitmapfactory android-fileprovider

我正在尝试使用BitmapFactory.decodefile()来创建相机照片的缩小版本,并将其设置为我的framelayout中的imageview.遵循Android开发人员的以下说明:https: //developer.android.com/training/camera/photobasics.html 在这些说明中,文件创建并存储在fileprovider中,该文件提供程序包含一些以xml格式化的元数据文件.不知何故,BitmapFactory.decodefile()似乎无法访问此文件,该文件存储内容uri驻​​留在fileprovider中的图片.fileprovider是在androidmanifest文件中创建的,如下所示:

<provider
android:authorities="mypackagename.fileprovider"
android:name="android.support.v4.content.FileProvider"
android:exported="false" android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"  >
</meta-data>
</provider>
Run Code Online (Sandbox Code Playgroud)

file_paths xml文件如下所示:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images"            path="Android/data/mypackagename/files/Pictures/" />
</paths>
Run Code Online (Sandbox Code Playgroud)

通过以下方法生成图片所在的文件名:

private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(imageFileName,".jpg",storageDir);

// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
Log.d("absolute",""+image.getAbsolutePath());
return image;
}
Run Code Online (Sandbox Code Playgroud)

代码启动一个意图,以便使用startactivityforresult()拍照,如下所示:

Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (i.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File

}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile  (this,"mypackagename.fileprovider",photoFile);

i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(i,TAKE_PICTURE);
}
}
Run Code Online (Sandbox Code Playgroud)

现在,onActivityForResult()方法启动,但如果我设置我的if语句if(requestCode == TAKE_PICTURE && resultCode == RESULT_OK)它不起作用.我不知道为什么.通过阅读fileprovider类上的android参考文档,我发现我必须打开photoUri,它在我的意图中作为额外的传递.根据文档,我必须使用ContentResolver.openFileDescriptor打开它,它将返回一个ParcelFileDescriptor.不知何故,这就是相机刚刚拍摄的照片.不知何故,我需要从这个ParcelFileDescriptor对象访问文件名并将其传递给BitmapFactory.decode文件,以缩小图片位图并将其设置在我的imageview上.我不知道怎么回事

当我尝试缩放图片位图时,我有以下代码返回-1,这意味着"根据用于BitmapFactory类的android参考文档""解码文件时出现问题".我不知道为什么会有问题.这是返回-1的代码:

BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);

int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
Run Code Online (Sandbox Code Playgroud)

photoW和photoH都返回-1.请记住,变量mCurrentPhotoPath在方法CreateImageFile()中初始化,一直在这个问题的顶部.

我也尝试过,

BitmapFactory.decodeFile(photoFile.getAbsolutePath(), bmOptions);
Run Code Online (Sandbox Code Playgroud)

但结果仍然相同,实际上mCurrentPhotoPath和photoFile.getAbsolutePath()是相等的字符串.

我认为以某种方式,fileprovider及其元数据xml文件以某种方式隐藏了来自BitmapFactory.decodefile()的文件路径.

我测试应用程序时拍摄的照片也存储在手机图片库中.

请提供任何建议或建议,因为我需要继续使用tess-two库并使用相机中的图片执行OCR.

谢谢你的建议

小智 6

我遇到了完全相同的问题,这就是我如何处理它:首先i.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 按照上面的建议设置,然后启动相机.然后,不要使用该BitmapFactory.decodeFile()方法,因为它只适用于file:///使用的Uris类型Uri.fromFile(),但不能使用content://检索到的Uris类型,FileProvider.getUriForFile()这是API> = 24的必需方式.

而是使用ContentResolver打开InputStream并解码图像,如下所示:

BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
ContentResolver cr = getActivity().getContentResolver();
InputStream input = null;
InputStream input1 = null;
try {
    input = cr.openInputStream(photoUri);
    BitmapFactory.decodeStream(input, null, bmOptions);
    if (input != null) {
        input.close();
    }
} catch (Exception e) {
    e.printStackTrace();
}

int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
try {
    input1 = cr.openInputStream(photoUri);
    Bitmap takenImage = BitmapFactory.decodeStream(input1);                
    if (input1 != null) {
        input1.close();
    }
} catch (Exception e) {
    e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)

注意,为了获得Bitmap,您必须打开第二个输入流,因为第一个输入流不能重复使用.