Android 8.0 调取系统摄像头和相册选择图片

本文总结了在Android 8.0及以上版本中调用系统摄像头和相册选择图片时遇到的问题,包括FileUriExposedException异常的解决方法。在Android 6.0后需要动态申请权限,而在7.0之后,直接使用Uri.fromFile(file)会抛出异常,需要使用FileProvider进行适配。文中给出了在清单文件中添加权限和配置FileProvider的步骤,并提供了适配7.0以上系统的代码示例。同时,文章还介绍了如何处理回调并使用图片压缩框架。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近做了几个商城,发现个人中心那,头像修改都是统一一种模式,调取系统摄像头和相册上传头像.就写个总结,以后就直接拿来用,顺便总结遇到的问题.

  1. 6.0之后敏感权限动态申请
  2. 7.0之后 使用本地真实的Uri路径不安全,直接使用Uri.fromFile(file);会报FileUriExposedException异常
android.os.FileUriExposedException: file:///storage/emulated/0/Pictures/nbinpic/UserIcon.png exposed beyond app through ClipData.Item.getUri()

安卓更新越来越快了啊,9.0都已经出来了.

    不想看过程的同学可以直接看最后代码了.还不行的话,我将demo上传到github了.

首先6.0之后,权限需要动态申请,对,只是申请,首先还是需要我们在清单文件AndroidManifest.xml中加上

<!-- 写sd卡权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 这个可写可不写
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />-->
    <!-- 调取摄像头权限 -->
<uses-permission android:name="android.permission.CAMERA" />

因为变成组合式权限,我们只是写上 写SD卡 权限,android会自动将 读SD卡的权限也给你了.
然后,在我们点击照相的地方动态申请权限

//"点击了照相";
//  6.0之后动态申请权限 摄像头调取权限,SD卡写入权限
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
        && ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(MainActivity.this,
            new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE},
            MY_ADD_CASE_CALL_PHONE);
} else {
    try {
    //有权限,去打开摄像头
        takePhoto();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

有个调取摄像头回调

    /**
     * 申请权限回调
     *
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

        if (requestCode == MY_ADD_CASE_CALL_PHONE) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                try {
                //有权限,去调取摄像头
                    takePhoto();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                //"权限拒绝");
                // TODO: 2018/12/4 这里可以给用户一个提示,请求权限被拒绝了
            }
        }


        if (requestCode == MY_ADD_CASE_CALL_PHONE2) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //有权限,去打开系统图库
                choosePhoto();
            } else {
                //"权限拒绝");
                // TODO: 2018/12/4 这里可以给用户一个提示,请求权限被拒绝了
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

打开系统图库

    /**
     * 打开相册
     */
    private void choosePhoto() {
        //这是打开系统默认的相册(就是你系统怎么分类,就怎么显示,展示分类列表)
        Intent picture = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        startActivityForResult(picture, 2);
    }

打开摄像头

private void takePhoto() throws IOException {
    Intent intent = new Intent();
    intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
    // 获取文件
    File file = createFileIfNeed("UserIcon.png");
    //拍照后原图回存入此路径下
    Uri uri;
    uri = Uri.fro
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值