Android 14+ 适配图片权限选择

在Android14+以上,申请 Manifest.permission.READ_MEDIA_IMAGES 权限时,会弹出以下权限框。

权限申请

这是在Android 14新增的细化权限,参考链接:Google

当用户选择“选择照片和视频”而不是“全部允许”时,会丢失 READ_MEDIA_IMAGES 权限,因此在适配安卓14时,需要检测 READ_MEDIA_IMAGES READ_MEDIA_VISUAL_USER_SELECTED 权限,第二个是用户选择“选择照片和视频”时会授权的。

按照谷歌的建议,可以使用Photo Picker 来获取图片或视频文件Uri。

public void init(){
ActivityResultLauncher<PickVisualMediaRequest> launcher = ((AppCompatActivity) mContext).registerForActivityResult(new ActivityResultContracts.PickVisualMedia(), new androidx.activity.result.ActivityResultCallback<Uri>() {
            @Override
            public void onActivityResult(Uri result) {
                LogUtils.e("result:" + result);
            }
        });
}
public void show(){
  PickVisualMediaRequest.Builder builder = new PickVisualMediaRequest.Builder()
                .setMediaType(ActivityResultContracts.PickVisualMedia.ImageOnly.INSTANCE);
        launcher.launch(builder.build());
}

如果需要解析成 Bitmap 或者 File ,可以参考以下代码

public void toBitmap(Uri uri){
  ImageDecoder.Source source = ImageDecoder.createSource(mContext.getContentResolver(), uri);
  Bitmap bitmap = ImageDecoder.decodeBitmap(source);
}

public boolean saveBitmap(Bitmap bitmap, File imageFile) {
        boolean success = false;
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(imageFile);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            fos.flush();
            saveImageInfo(imageFile);
            success = true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return success;
    }
   /**
     * 把视频保存到ContentProvider,在选择上传的时候能找到
     */
    private void saveImageInfo(File file) {
        try {
            String fileName = file.getName();
            long currentTimeMillis = System.currentTimeMillis();
            ContentValues values = new ContentValues();
            values.put(MediaStore.MediaColumns.TITLE, fileName);
            values.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
            values.put(MediaStore.MediaColumns.DATE_MODIFIED, currentTimeMillis);
            values.put(MediaStore.MediaColumns.DATE_ADDED, currentTimeMillis);
            values.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
            values.put(MediaStore.MediaColumns.SIZE, file.length());
            values.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
            CommonAppContext.sInstance.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

参考文档:

https://developer.honor.com/cn/docs/11100/guides/google_u_compatibility_adaptation_guide#%E5%85%BC%E5%AE%B9%E6%80%A7%E5%BD%B1%E5%93%8D

https://developer.android.com/training/data-storage/shared/photopicker?hl=zh-cn

https://developer.android.com/about/versions/14/changes/partial-photo-video-access?hl=zh-cn

git删除某个文件的提交记录

发现不小心提交了包含密码的文件,所以记录下删除该文件及记录的方法

git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch src/main/resources/application.properties' --prune-empty --tag-name-filter cat -- --all

src/main/resources/application.properties为该文件,替换成需要的文件即可。

如果提示:Cannot rewrite branches: Your index contains uncommitted changes.

则需要:

git stash

最后提交到git:

git push origin --force --all

Kotlin笔记

  1. by lazy :赖加载,在调用时才会初始化
  2. 单例模式、初始化、带参构造方法: git
  3. 初始化ViewModel时
ViewModelProvider.of(this).get(CrimeListViewModel::class.java)

该方法在lifecycle升级到2.x以后已被抛弃使用,可改为 (git):

       ViewModelProvider.AndroidViewModelFactory.getInstance(context?.applicationContext as Application).create(CrimeListViewModel::class.java)

4.set和get使用就是在方法/变量下直接使用get()和set() : git