Android 14中申请READ_MEDIA_VISUAL_USER_SELECTED后PhotoPicker仍显示全量媒体
Android 14 READ_MEDIA_VISUAL_USER_SELECTED权限与PhotoPicker适配问题
问题背景
Android 14新增了READ_MEDIA_VISUAL_USER_SELECTED权限,该权限可提供对用户照片和视频的部分临时访问权限,权限申请弹窗包含「选择照片和视频」「允许全部」「不允许」三个选项。官方文档提到,若应用已使用PhotoPicker则无需额外操作适配该权限,但测试时遇到如下问题:
测试步骤
- 申请
READ_MEDIA_IMAGES和READ_MEDIA_VISUAL_USER_SELECTED权限; - 在权限弹窗中选择「选择照片和视频」,选中少量照片后点击允许;
- 打开PhotoPicker时,发现其仍显示设备中的全部媒体内容,而非仅用户授权的媒体。
代码实现
Case 1 使用Intent实现
public class MainActivity extends AppCompatActivity { ImageView imageView; Button takePictureButton; int RESULT_CODE = 0; int REQUEST_CODE = 1; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = findViewById(R.id.img); takePictureButton = findViewById(R.id.btn_take_picture); takePictureButton.setOnClickListener(view -> { if (android.os.Build.VERSION.SDK_INT == 34) { int result14 = this.checkSelfPermission(READ_MEDIA_VISUAL_USER_SELECTED); boolean hasReadMediaPermissionAndroid14 = PackageManager.PERMISSION_GRANTED == result14; if (hasReadMediaPermissionAndroid14) { Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); intent.setType("image/*"); startActivityForResult(intent, RESULT_CODE); } else { requestPermissions(new String[] {READ_MEDIA_IMAGES, READ_MEDIA_VISUAL_USER_SELECTED}, REQUEST_CODE); } } }); } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (data != null) { imageView.setImageURI(data.getData()); } } }
Case 2 遵循官方PhotoPicker文档实现
public class MainActivity extends AppCompatActivity { ImageView imageView; Button takePictureButton; int REQUEST_CODE = 1; ActivityResultLauncher<PickVisualMediaRequest> pickMedia = registerForActivityResult(new ActivityResultContracts.PickVisualMedia(), uri -> { if (uri != null) { imageView.setImageURI(uri); Log.d("PhotoPicker", "Selected URI: " + uri); } else { Log.d("PhotoPicker", "No media selected"); } }); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = findViewById(R.id.img); takePictureButton = findViewById(R.id.btn_take_picture); takePictureButton.setOnClickListener(view -> { if (android.os.Build.VERSION.SDK_INT == 34) { int result14 = this.checkSelfPermission(READ_MEDIA_VISUAL_USER_SELECTED); boolean hasReadMediaPermissionAndroid14 = PackageManager.PERMISSION_GRANTED == result14; if (hasReadMediaPermissionAndroid14) { pickMedia.launch(new PickVisualMediaRequest.Builder() .setMediaType(ActivityResultContracts.PickVisualMedia.ImageOnly.INSTANCE) .build()); } else { requestPermissions(new String[]{READ_MEDIA_IMAGES, READ_MEDIA_VISUAL_USER_SELECTED}, REQUEST_CODE); } } } ); } }
AndroidManifest.xml配置
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
activity_main.xml布局
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <ImageView android:id="@+id/img" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHeight_percent="0.5" app:layout_constraintVertical_bias="0" android:src="@drawable/img" tools:ignore="ContentDescription" /> <Button android:id="@+id/btn_take_picture" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="take picture" app:layout_constraintTop_toBottomOf="@id/img" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" android:layout_marginTop="20dp"/> </androidx.constraintlayout.widget.ConstraintLayout>
问题现象
选择「选择照片和视频」并授权部分照片后,打开PhotoPicker仍展示设备内全部媒体内容,未过滤到仅授权的媒体。
疑问
请问是我对权限机制理解有误,还是代码存在问题?该权限的实际预期行为是什么?我应如何处理此问题?
内容的提问来源于stack exchange,提问作者Khuê Nguyễn
相关产品推荐
相关产品推荐

