当前位置:   article > 正文

安卓14更换头像相册使用若干问题包含权限问题以及系统裁剪报错Mutation of _data is not allowed解决并兼容各个版本_android14 相册权限

android14 相册权限

最近发现再安卓14的系统上,用户无法正常使用相册图片更换头像
问题一
相册空白(权限问题)
解决方案
添加关键动态权限READ_MEDIA_VISUAL_USER_SELECTED
mainfest仍然需要添加权限

<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    <uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED"
        android:minSdkVersion="34" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
        android:maxSdkVersion="32" />
  • 1
  • 2
  • 3
  • 4
  • 5

权限动态代码(此处用谷歌EasyPermissions框架,其它框架用法类似,回调省略。。。)

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
            String[] perms32 = {
                    Manifest.permission.READ_MEDIA_IMAGES,
                    Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED
            };
            if (!EasyPermissions.hasPermissions(this, perms32)){
                EasyPermissions.requestPermissions(this, getString(R.string.permission_request),
                        READ_MEDIA_IMAGES, perms32);
            }
        } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.TIRAMISU) {
            //录音下一个版本在开发
            String[] perms32 = {
                    Manifest.permission.READ_MEDIA_IMAGES
            };
            if (!EasyPermissions.hasPermissions(this, perms32)){
                EasyPermissions.requestPermissions(this, getString(R.string.permission_request),
                        READ_MEDIA_IMAGES, perms32);
            }
        } else {
            String[] perms = {
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE};
            if (!EasyPermissions.hasPermissions(this, perms)){
                EasyPermissions.requestPermissions(this, getString(R.string.permission_request),
                        READ_EXTERNAL_STORAGE, perms);
                        //以上代码兼容各个版本,已经不需要单独兼容安卓11,故以下代码废弃
//            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
//                Uri uri = Uri.parse("package:" + getPackageName());
//                startActivity(new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, uri));
//            }
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

此处就是当选择图片以后 进入系统裁剪
特别说明 Global.setCropPhotoFilePath(imgFile.getAbsolutePath());
全局保存图片的路径,系统裁剪完成之后这个路径就是裁剪后的图片。
此处可以自行优化,安卓13以后,外部存储已经指定了的图片存储位置,只需要知道图片名,即可找到文件

 //支持安卓各种版本的裁剪功能
    public static void startIconPhotoCrop(Activity context, Uri sourceUri) {
        File imgFile;
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.putExtra("crop", "true");
        intent.putExtra("aspectX", 1);    //X方向上的比例
        intent.putExtra("aspectY", 1);    //Y方向上的比例
        intent.putExtra("outputX", 256);  //裁剪区的宽
        intent.putExtra("outputY", 256); //裁剪区的高
        intent.putExtra("scale ", true);  //是否保留比例
        intent.putExtra("return-data", false);
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        intent.setDataAndType(sourceUri, "image/*"); //设置数据源
        Uri uri;
        try {
//            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
            String uuid = AndroidUtil.getUUID().replace("-","");
            String fileName = "CROP_"+ uuid +".jpg";
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                imgFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + fileName);
                ContentValues values = new ContentValues();
                values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
                values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
                values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);
                Uri externalUri = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
                uri = context.getContentResolver().insert(externalUri, values);
            } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R) {
                imgFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + fileName);
                // 通过 MediaStore API 插入file 为了拿到系统裁剪要保存到的uri(因为App没有权限不能访问公共存储空间,需要通过 MediaStore API来操作)
                ContentValues values = new ContentValues();
                //安卓13起不能使用MediaStore.Images.Media.DATA否则会报错Mutation of _data is not allowed
                values.put(MediaStore.Images.Media.DATA, imgFile.getAbsolutePath());
                values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
                values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
                uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
            } else {
                imgFile = FileManager.ofMedia(fileName);
                uri = Uri.fromFile(imgFile);
            }
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
            Global.setCropPhotoFilePath(imgFile.getAbsolutePath());
            context.startActivityForResult(intent, Constant.RESULT_ZOOM);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/902578
推荐阅读
相关标签
  

闽ICP备14008679号