首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >BitmapFactory:无法解码流: java.io.FileNotFoundException:open失败: Android q上的java.io.FileNotFoundException:open(权限被拒绝)

BitmapFactory:无法解码流: java.io.FileNotFoundException:open失败: Android q上的java.io.FileNotFoundException:open(权限被拒绝)
EN

Stack Overflow用户
提问于 2020-01-31 19:17:55
回答 2查看 11.2K关注 0票数 10

我授予了权限,但BitmapFactory.decodeFile()返回此错误:

代码语言:javascript
运行
复制
E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: /storage/emulated/0/DCIM/Camera/IMG_20200130_165131.jpg: open failed: EACCES (Permission denied)

我想从图片库获取最后一张图片,并将其保存到另一个文件中。我在安卓P测试设备上测试了它。但是它在android版本Q (API级别29)的android仿真器中返回此错误。这有什么问题吗?

以下是我的代码片段:

代码语言:javascript
运行
复制
writeStoragePermissionGranted();

BitmapFactory.Options options = null;
Bitmap bm = null;

String[] projection = new String[]{
            MediaStore.Images.ImageColumns._ID,
            MediaStore.Images.ImageColumns.DATA,
            MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
            MediaStore.Images.ImageColumns.DATE_TAKEN,
            MediaStore.Images.ImageColumns.MIME_TYPE,
            MediaStore.Images.ImageColumns.DISPLAY_NAME,
    };

    final Cursor cursor = this.getContentResolver()
            .query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null,
                    null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");
      if (cursor.moveToFirst()) {
        final ImageView imageView = (ImageView) findViewById(R.id.pictureView);
        String imageLocation = cursor.getString(1);
        File imageFile = new File(imageLocation);

        if (imageFile.exists()) {
            options = new BitmapFactory.Options();
            options.inSampleSize = 2;

            try {
                    bm = BitmapFactory.decodeFile(imageLocation, options);
            } catch(Exception e) {
                    e.printStackTrace();
            }
        }

        imageView.setImageBitmap(bm);



        try {
            saveImage(bm,"NAME" );
        } catch (IOException e) {
                e.printStackTrace();
        }
    }

writeStoragePermissionGranted()函数:

代码语言:javascript
运行
复制
 public void writeStoragePermissionGranted() {
       if (Build.VERSION.SDK_INT >= 23) {
           if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                   == PackageManager.PERMISSION_GRANTED) {
            startPeriodicRequest();
        } else {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, Constants.REQUEST_CODE_WRITE_EXTERNAL_STORAGE_PERMISSION);
        }
    } else {
        return;
    }
} 

和清单权限:

代码语言:javascript
运行
复制
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

我知道这方面有很多问题。但是没有人在android仿真器版本Q上工作。另一方面,这段代码在android饼(API级别28)上工作。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-31 20:21:02

在Android 10上,他们引入了“范围存储”的概念,这样,您就不能再使用它的路径打开图像了。你可以得到更多的信息,这里

所以现在您必须使用它的ParcelFileDescriptorUri来解码它。

您可以:

代码语言:javascript
运行
复制
final Cursor cursor = this.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        projection, null, null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");
if (cursor.moveToFirst()) {
    final ImageView imageView = (ImageView) findViewById(R.id.pictureView);


    if (Build.VERSION.SDK_INT >= 29) {
        // You can replace '0' by 'cursor.getColumnIndex(MediaStore.Images.ImageColumns._ID)'
        // Note that now, you read the column '_ID' and not the column 'DATA'
        Uri imageUri= ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, cursor.getInt(0));

        // now that you have the media URI, you can decode it to a bitmap
        try (ParcelFileDescriptor pfd = this.getContentResolver().openFileDescriptor(mediaUri, "r")) {
            if (pfd != null) {
                bitmap = BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
            }
        } catch (IOException ex) {

        }
    } else {
        // Repeat the code you already are using
    }
}
票数 15
EN

Stack Overflow用户

发布于 2021-07-26 15:13:56

只需将android:requestLegacyExternalStorage="true"添加到Manifest.xml中的Application标记即可。

希望下面的代码能帮你解决这个问题。

Manifest.xml

在清单文件中添加以下内容:

代码语言:javascript
运行
复制
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

还添加:

将此添加到报表中的应用程序标记中。

代码语言:javascript
运行
复制
android:requestLegacyExternalStorage="true"

开放画廊获取图像:

代码语言:javascript
运行
复制
private void openImagePicker() {
    MyDatePicker datePicker = new MyDatePicker();
    datePicker.show(getSupportFragmentManager(), "DATE PICK");
}

启动ActivityForResult:

onActivityResult --您将通过它获得结果对象--您将得到图像原始uri。

代码语言:javascript
运行
复制
ActivityResultLauncher<Intent> galleryResultLauncher = registerForActivityResult(
        new ActivityResultContracts.StartActivityForResult(),
        new ActivityResultCallback<ActivityResult>() {
            @Override
            public void onActivityResult(ActivityResult result) {
                if (result.getResultCode() == Activity.RESULT_OK) {
                    Intent data = result.getData();
                    imageURi = data.getData();
                    image.setVisibility(View.VISIBLE);
                    String path = getPath(imageURi);
                    File file = new File(path);
                    if (file.exists()) {
                        Bitmap myBitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
                        image.setImageBitmap(myBitmap);
                    }
                }
            }
        });

获取图像的绝对路径:

代码语言:javascript
运行
复制
public String getPath(Uri uri) {
    String[] projection = {MediaStore.Images.Media.DATA};
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    if (cursor != null) {
        int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    } else return null;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60010006

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档