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

标签 android android-intent uri bitmapfactory android-fileprovider

我正在尝试使用 BitmapFactory.decodefile() 来创建按比例缩小的文件 相机照片的版本并将其设置为我的框架布局中的 ImageView 。 我正在按照 Android 开发人员的以下说明进行操作: https://developer.android.com/training/camera/photobasics.html 在这些说明中,文件被创建并存储在一个文件提供程序中,该文件提供程序包含一些以 xml 格式设置的元数据文件。不知何故,BitmapFactory.decodefile() 似乎无法访问此文件,该文件存储其内容 uri 驻留在文件提供程序中的图片。 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>

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>

图片所在位置的文件名是通过此方法生成的:

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;
}

代码启动一个 intent 以便使用 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);
}
}

现在,onActivityForResult() 方法开始了,但是如果我像这样设置我的 if 语句 如果(requestCode == TAKE_PICTURE && resultCode == RESULT_OK) 它不起作用。 我不知道为什么。 通过阅读关于 fileprovider 类的 android 引用文档,我看到了 我必须打开 photoUri,它在我的 Intent 中作为额外传递。 根据文档,我必须使用 ContentResolver.openFileDescriptor 打开它,它将返回一个 ParcelFileDescriptor。不知何故,这就是相机刚刚拍摄的照片所在的位置。 我需要以某种方式从这个 ParcelFileDescriptor 对象访问文件名并将其传递给 BitmapFactory.decodefile 以缩小图片位图并将其设置在我的 ImageView 上。我不知道该怎么做

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

BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);

int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;

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

我也试过,

BitmapFactory.decodeFile(photoFile.getAbsolutePath(), bmOptions);

但还是一样的结果,其实mCurrentPhotoPath和photoFile.getAbsolutePath()是相等的字符串。

我认为带有元数据 xml 文件的文件提供者以某种方式隐藏了 BitmapFactory.decodefile() 的文件路径。

这张照片是我在测试应用程序时拍摄的,也存储在我的手机图片库中。

请提供任何意见或建议,因为我需要继续使用 tess-two 库并对来自相机的图片进行 OCR。

感谢您的建议

最佳答案

我遇到了完全相同的问题,这就是我处理它的方式:首先按照上面的建议设置 i.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);,然后再启动相机。然后,不要使用 BitmapFactory.decodeFile() 方法,因为它仅适用于使用 Uri.fromFile() 检索的 file:/// 类型的 Uris ,但不是使用 FileProvider.getUriForFile() 检索的 content:// 类型的 Uris,这是 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();
}

请注意,为了获得位图,您必须打开第二个输入流,因为第一个输入流无法重复使用。

关于android - Android 中的 FileProvider 路径创建和 BitmapFactory.decodefile 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41481614/

相关文章:

在 SDK rev 18 更新中找不到基于 Android x86 的系统镜像

java - 如何点击Android中的Recyclerview并获取另一个像play store这样的数据Activity?

Android内容提供者随机排序

android - 是否可以将 Amazon EC2 用于 Android 同步到云后端

c# - 如何在 Google Cardboard Unity3D 中找到头部的旋转?

android - 打开蓝牙并等待 Intent ?

ruby - 如何安全地加入相对 url 段?

android - 从 MediaStore.Images.Media.DATA 获取图像的方向

android - ButterKnife 中 R2.java 中的最后一个字段

android - PendingIntents 保持缓存相同的对象