registerForActivityResult调用相机返回resultCode为0如何解决
registerForActivityResult启动相机返回resultCode恒为0问题
问题现象
使用registerForActivityResult实现拍照功能时,回调返回的resultCode始终为0,无法从相机Activity获取正常返回结果。该段代码上月可正常运行,近期使用时突发异常,初步排查代码未发现明显编写错误。
相关代码
相机调用函数
private fun UseCamera() { val takePictureIntent = Intent (MediaStore.ACTION_IMAGE_CAPTURE) val imagePath = File(Environment.getExternalStorageDirectory(), "Pictures") val photoFile = File(imagePath, "my_picture.jpg") FilePath = FileProvider.getUriForFile(this, FILE_AUTHORITY, photoFile ) Log.w("FilePath",FilePath.toString()) takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, FilePath) takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION) getPreviewImage.launch(takePictureIntent) Log.w("UseCamera","Successful") }
ActivityResult注册与回调逻辑
getPreviewImage = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> Log.e("Preview Image", result.resultCode.toString()) if (result.resultCode == RESULT_OK) { if (!forfood){ Log.i("File Path", FilePath.toString()) val SelectedImage = FilePath val PicRef = StorageRef.child(preferences.getValue("username").toString()) .child("kiosk_pic/" + ImageID) PicRef.putFile(SelectedImage).addOnSuccessListener { Toast.makeText(this, "Uploaded", Toast.LENGTH_SHORT).show() PicRef.downloadUrl.addOnSuccessListener { preferences.setValue("kiosk_pic", it.toString()) ref.child(preferences.getValue("username").toString()).child("kiosk_picture").setValue(it.toString()) setKioskImage(preferences.getValue("kiosk_pic").toString(),ImageID) } } .addOnFailureListener { Toast.makeText(this, "Upload Fail", Toast.LENGTH_SHORT).show() } .addOnProgressListener { Toast.makeText(this, "Uploading", Toast.LENGTH_SHORT).show() } } else { Log.i("File Path",FilePath.toString()) val SelectedImage = FilePath if (add){ iv_addimage.setImageURI(SelectedImage) }else{ iv_changeimage.setImageURI(SelectedImage) } } }
调试日志
每次调用相机输出日志如下,结果码固定为0:
W/UseCamera: Successfull D/OpenGLRenderer: endAllActiveAnimators on 0xea49f7f0 (AlertController$RecycleListView) with handle 0xc1acc9b0 E/Preview Image: 0
补充日志中存在的警告信息:
W/InputEventReceiver: Attempted to finish an input event but the input event receiver has already been disposed.
原因排查与修复
resultCode=0对应系统常量RESULT_CANCELED,说明相机Activity启动后未完成拍照流程就异常返回,上述InputEventReceiver警告是页面异常销毁时的附带日志,不是问题根因。按以下优先级排查修复:
- 存储路径权限不兼容(最高概率)
代码中直接使用Environment.getExternalStorageDirectory()公共目录创建拍照文件,安卓11及以上版本启用分区存储后,应用即使申请了旧版外部存储权限,也无权在公共根目录下直接创建、修改文件,相机应用拿到对应Uri后没有写入权限,会直接取消拍照返回。
修复方式:将拍照临时文件的存储路径改为应用私有外部存储目录,不需要额外申请存储权限,FileProvider可正常完成授权:// 替换原有imagePath定义 val imagePath = File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "") // 目录不存在时提前创建 if (!imagePath.exists()) { imagePath.mkdirs() } - FileProvider配置校验
确认常量FILE_AUTHORITY的值和AndroidManifest.xml中FileProvider节点配置的android:authorities属性完全一致,同时确认FileProvider的路径配置文件中,已经包含你存放拍照文件的目录,避免相机应用无权限访问目标Uri。 - 权限Flag补全
部分厂商定制ROM需要同时授予读写权限才能正常写入拍照文件,给Intent补充读权限Flag:takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION) - Intent可用性校验
启动相机前先校验设备上是否存在可响应拍照Intent的相机应用,避免因相机应用被禁用、卸载导致直接返回取消结果:if (takePictureIntent.resolveActivity(packageManager) != null) { getPreviewImage.launch(takePictureIntent) }
内容的提问来源于stack exchange,提问作者MadsterMIZE
相关产品推荐
相关产品推荐

