阅读 552

Android 11 拍照适配填坑之旅

这是我参与新手入门的第1篇文章

1.背景

android沙盒机制已经出了好久,但是程序没对其做适配,最近收到了google发来的提示,使得适配不得不提上日程,开启了新一轮的采坑之旅。 Starting August 2021, new apps will be required to target API level 30 (Android 11) and use the Android App Bundle publishing format. Starting November 2021, all app updates will be required to target API level 30 (Android 11). Apps with a download size of more than 150 MB are now supported by Play Asset Delivery and Play Feature Delivery.

2.适配

  1. 修改目标版本和编译版本为30,buildTools可根据自己需要修改
compileSdkVersion 30
buildToolsVersion "30.0.3"
targetSdkVersion 30
复制代码

2.修改保存路径

public static String createJpgFilePath(Context context, String name) {
        return context == null ? "" : new StringBuilder(
                context.getExternalCacheDir().getAbsolutePath())
                .append(File.separator).append(name).append(".jpg").toString();
    }
复制代码

PS:

通过getExternalFilesDir()方法获取到的目录为 sdcard/Android/data/packageName/files/,一般存放长时间保存的数据.

通过getExternalCacheDir()方法获取到的目录为 sdcard/Android/data/packageName/cache/,一般存放临时缓存数据

使用上面的方法获取路径并使用,当应用在被卸载后,sdcard/Android/data/packageName/ 这个目录下所有的文件都会被删除。

3.调用相机

private void takePhoto() {
        mPhotoFile = new File(CommonUtil.createJpgFilePath(getContext(),
                TOKEN_PHOTO_NAME));

        if (mPhotoFile.exists()) {
            mPhotoFile.delete();
        }
        try {
            mPhotoFile.createNewFile();
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            }
            intent.putExtra(MediaStore.EXTRA_OUTPUT,
                    CommonUtil.getFileUri(getContext(), mPhotoFile));
            startActivityForResult(intent, REQ_CODE_CAMERA);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
复制代码

Android7.0以上需要将File转换为Uri

public static Uri getFileUri(Context context, File file) {
      Uri uri = null;
      if (file != null) {
          if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
              // 如果api大于Android api23 要替换获取文件Uri方式
              // 此方法第二个参数authority的值要用项目中的值来替换,
              // 可网上找Android 7.0 FileProvider相关介绍
              if (context != null) {
                  uri = FileProvider.getUriForFile(context,
                          context.getPackageName() + ".fileProvider", file);
              }
          } else {
              uri = Uri.fromFile(file);
          }
      }

      return uri;
  }
复制代码

然后在onActivityResult接受拍摄后的相片,至此拍照完成,后就是裁剪功能

3.调用系统裁剪功能

 private void cropPhoto(Uri uri) {
        mCroppedFile = new File(CommonUtil.createJpgFilePath(
                getContext(), CROPPED_PHOTO_NAME));

        if (mCroppedFile.exists()) {
            mCroppedFile.delete();
        }
        try {
            Intent intent = new Intent("com.android.camera.action.CROP");

            intent.setDataAndType(uri, "image/*");
            intent.putExtra("crop", "true");
            intent.putExtra("aspectX", mAspectX);
            intent.putExtra("aspectY", mAspectY);
            intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            }
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mCroppedFile));
            startActivityForResult(intent, REQ_CODE_CROP);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
复制代码

正常调用提示不能修改 Screenshot_20210706-210420.png 经查证发现SDK>=30 系统裁剪不能访问App的私有路径,如果想正常使用裁剪功能,两种实现方案

  1. 自己写一个裁剪功能
  2. 把保存路径送私有变为公共路径(如果存储到公共路径就得需要动态申请存储权限,拍摄头像完全可以只在私有的缓存路径中解决,希望可以有一个兼容方案)

开启沙盒迁移数据会过段时间领开一篇写出

文章分类
Android
文章标签