Android7.0 拍照 选择照片 权限 实现

本文介绍了在Android 7.0及以上版本中,由于运行时权限和File URI安全性的改变导致的问题,以及如何通过使用FileProvider来解决相机拍照和相册选择图片后无法正常共享的异常。详细步骤包括打开相机和相册获取图片的Uri,并对图片进行压缩。参考了优快云和简书上的相关文章,提供了具体的代码示例。

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

参考链接:

http://blog.youkuaiyun.com/hu5080126/article/details/53738625

http://www.jianshu.com/p/ba57444a7e69

在Android7.0以后,当app使用file:// url 共享给其他app时, 会抛出异常。

因为在android 6.0 + 权限需要 在运行时候检查, 其他app 可能没有读写文件的权限, 所以google在7.0的时候加上了这个限制。

官方推荐使用 FileProvider 解决这个问题。 

1.打开相机拍照获取照片Uri,然后对图片进行压缩
2.打开相册获取选取的图片Uri,然后对图片进行压缩

打开相机和相册是不会触发任何权限问题的,如果你想获取相机或相册的图片中的Uri,即file://URI开头的Uri离开了相机或相册应用,就会触发7.0文件uri权限 FileUriExposedException会触发FileUriExposedException权限异常。

现在将代码贴下来:

private static final int NEED_CAMERA = 200;
private static final int RESULT_PICK = 201;

/**
 * 从TakePhotoPopWin获取的onClickListener
 * 点击PopuWindow上的照相或者从相册中选取图片 功能1
 */
private View.OnClickListener onClickListener = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            //照相
            case R.id.btn_take_photo:
                //检测是否有相机和读写文件权限
                if (ContextCompat.checkSelfPermission(UIUtils.getContext(), Manifest.permission.CAMERA)
                        != PackageManager.PERMISSION_GRANTED
                        || ContextCompat.checkSelfPermission(UIUtils.getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
                        != PackageManager.PERMISSION_GRANTED) {
                    getActivity().requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, NEED_CAMERA);
                } else {
                    //打开相机获取图片
                    startCamera();
                }
                break;
            //从相册选择图片
            case R.id.btn_pick_photo:
                if (ContextCompat.checkSelfPermission(UIUtils.getContext(), Manifest.permission.READ_EXTERNAL_STORAGE)
                        != PackageManager.PERMISSION_GRANTED) {
                    getActivity().requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, RESULT_PICK);
                } else {
                    //选择图片
                    startPickPhoto();
                }
                break;
        }
    }
};
/**
 * date: 2017/7/5 10:59
 * autour: HelenChen
 * description: 选择图片
*/
 private void startPickPhoto() {
     Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
     startActivityForResult(Intent.createChooser(intent, "请选择图片"), RESULT_PICK);
     takePhotoPopWin.hiddPop();
 }

/**
 * 打开相机获取图片
 */
private void startCamera() {
    File imagePath = new File(Environment.getExternalStorageDirectory(), "images");
    if (!imagePath.exists()) imagePath.mkdirs();
    newFile = new File(imagePath, "point_image.jpg");

    //第二参数是在manifest.xml定义 provider的authorities属性
    contentUri = FileProvider.getUriForFile(UIUtils.getContext(), "com.example.administrator.im_demo.fileprovider", newFile);

    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    //兼容版本处理,因为 intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION) 只在5.0以上的版本有效
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        ClipData clip = ClipData.newUri(getActivity().getContentResolver(), "A photo", contentUri);
        intent.setClipData(clip);
        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    } else {
        List<ResolveInfo> resInfoList = getActivity().getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo resolveInfo : resInfoList) {
            String packageName = resolveInfo.activityInfo.packageName;
            getActivity().grantUriPermission(packageName, contentUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        }
    }
    intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
    startActivityForResult(intent, NEED_CAMERA);
    takePhotoPopWin.hiddPop();
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                       int[] grantResults) {
    switch (requestCode) {
        case NEED_CAMERA:
            // 如果权限被拒绝,grantResults 为空
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                //打开相机获取图片
                startCamera();
            } else {
                Toast.makeText(UIUtils.getContext(), "需要相机和读写文件权限", Toast.LENGTH_SHORT).show();
            }
            break;
        case RESULT_PICK:
            // 如果权限被拒绝,grantResults 为空
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                //选择图片
                startPickPhoto();
            } else {
                Toast.makeText(UIUtils.getContext(), "需要读取权限", Toast.LENGTH_SHORT).show();
            }
            break;

    }
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case NEED_CAMERA:
            ContentResolver contentProvider = getActivity().getContentResolver();
            ParcelFileDescriptor mInputPFD;
            try {
                //获取contentProvider图片
                mInputPFD = contentProvider.openFileDescriptor(contentUri, "r");
                FileDescriptor fileDescriptor = mInputPFD.getFileDescriptor();
                iv_company_bk.setImageBitmap(BitmapFactory.decodeFileDescriptor(fileDescriptor));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            break;
        //选择照片
        case RESULT_PICK:
            try {
                Uri uri = data.getData();
                //打开圆形裁剪图界面
                String path = Utils.getRealFilePathFromUri(getActivity().getApplicationContext(), uri);
                Bitmap bitmaps = BitmapUtil.decodeSampledBitmap(path, 720, 1280);
                iv_company_bk.setImageBitmap(bitmaps);
                /**
                 * 请求网络,将图片上传到服务器
                 */
                //upLoadImg(path);
            }catch (Exception e){
                e.printStackTrace();
            }
            break;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值