使用谷歌新版多选照片选择器时ActivityResultCallback从未触发的问题
嘿,我看你在Fragment里尝试用谷歌新版Photo Picker替代READ_MEDIA_IMAGES权限时,遇到了ActivityResultCallback完全不触发的问题,这种情况我之前踩过坑,给你梳理几个大概率的原因和解决办法:
启动Launcher的方式不正确
很多人会在这里栽跟头,你得确保启动时传了正确的PickVisualMediaRequest参数,而不是随便传个空对象或者错误的配置。正确的启动代码应该是这样的:mPickPhotosActivityResult.launch(new PickVisualMediaRequest.Builder() .setMediaType(PickVisualMedia.ImageOnly.INSTANCE) .build());如果启动时没指定媒体类型,或者参数不符合要求,Photo Picker可能无法正常完成选择流程,自然不会触发回调。
Fragment生命周期注册时机不对
你是在Fragment里注册的registerForActivityResult,这个注册操作必须放在Fragment的onCreate(或者更早的onAttach)生命周期方法里,绝对不能放在onStart、onCreateView或者之后的方法里。如果注册时机太晚,Launcher无法和Fragment的生命周期正确绑定,就会导致回调丢失。检查系统兼容性和设备限制
Photo Picker是Android 13(API 33)开始原生支持的功能,如果你项目的targetSdkVersion低于33,部分设备可能会有兼容性问题。另外,也可以换几台不同Android版本的设备测试下,排除是某台设备的系统Photo Picker应用异常导致的问题。先确认回调是否真的没触发
有时候可能是回调里的代码抛出了异常,导致你误以为回调没执行。可以先在回调里加一行简单的日志输出:@Override public void onActivityResult(List<Uri> uris) { Log.d("PhotoPickerDebug", "回调触发了!选中图片数量:" + (uris == null ? 0 : uris.size())); // 原来的逻辑放在后面 }然后去Logcat里搜这个日志标签,看看是不是真的没触发,还是自己的业务逻辑有问题。
配置变更时的绑定问题
你的代码里已经用private final修饰了mPickPhotosActivityResult,这一点是对的——这样Fragment在配置变更(比如旋转屏幕)重建后,Launcher会自动重新绑定。如果你是动态创建的Launcher(比如在方法里临时创建),就很容易出现回调丢失的情况,保持现在的成员变量写法就好。
给你一个完整的可参考示例代码:
public class PhotoPickerFragment extends Fragment { // 注册最多选5张图片的Photo Picker Launcher private final ActivityResultLauncher<PickVisualMediaRequest> mPickPhotosActivityResult = registerForActivityResult(new ActivityResultContracts.PickMultipleVisualMedia(5), uris -> { if (uris == null || uris.isEmpty()) { Log.d("PhotoPicker", "没有选中任何图片"); return; } Log.d("PhotoPicker", "成功选中" + uris.size() + "张图片"); // 这里处理选中的图片Uri,比如加载显示、上传等 for (Uri uri : uris) { // 示例:用Glide加载图片到ImageView // Glide.with(this).load(uri).into(imageView); } }); @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 注册操作必须在这里完成,不能晚于这个生命周期 } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_photo_picker, container, false); Button pickButton = rootView.findViewById(R.id.btn_pick_photos); pickButton.setOnClickListener(v -> { // 点击按钮启动Photo Picker mPickPhotosActivityResult.launch(new PickVisualMediaRequest.Builder() .setMediaType(PickVisualMedia.ImageOnly.INSTANCE) .build()); }); return rootView; } }
备注:内容来源于stack exchange,提问作者Vitaly

