Android 9(API 28)调用TakePicture拍照时相机停止运行如何解决?
问题根因
你代码的核心错误是调用ActivityResultContracts.TakePicture()启动相机时,传入了null作为照片存储的目标Uri。系统相机获取到空的输出路径后,无法保存拍摄结果,才触发了空指针异常崩溃。由于崩溃发生在系统相机进程而非你的应用进程,所以最初在你应用的日志面板中无法抓到堆栈。
你后续抓取的
com.android.camera2进程日志也验证了这一点:相机在保存照片的环节尝试对传入的Uri做非空检查失败,直接抛出了空指针异常。
修复方案
Android 7.0及以上版本禁止直接使用本地文件路径跨应用传递,需要通过FileProvider生成合法的Content Uri提供给相机使用,完整修复步骤如下:
- 第一步:配置FileProvider(未配置过的前提下)
先在AndroidManifest.xml的<application>标签内添加provider配置:
再在<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>res/xml目录下创建file_paths.xml文件,配置允许共享的文件路径:<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 配置应用专属图片目录为可共享路径 --> <external-files-path name="profile_images" path="Pictures" /> </paths> - 第二步:修改拍照逻辑,提前生成合法存储Uri
调整后的代码如下:fun initCameraClick(activity: UserProfileActivity) { var uri: Uri? = null val takePicture = activity.registerForActivityResult(ActivityResultContracts.TakePicture()) { success: Boolean -> if (success) { uri?.let { Log.i("camerauri", it.toString()) this.profilepic.setImageURI(it) } } } this.cameraButton.setOnClickListener { // 生成存储照片的本地文件 val photoFile = File( activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES), "profile_${System.currentTimeMillis()}.jpg" ) // 通过FileProvider生成合法的Content Uri uri = FileProvider.getUriForFile( activity, "${activity.packageName}.fileprovider", photoFile ) // 传入非空Uri启动相机 takePicture.launch(uri) } } - 第三步:检查权限配置
在AndroidManifest.xml中添加必要的相机权限声明:<uses-permission android:name="android.permission.CAMERA" /> <!-- 若应用不强制要求设备有相机,设置required为false --> <uses-feature android:name="android.hardware.camera" android:required="false" />
内容的提问来源于stack exchange,提问作者qwerty_99
相关产品推荐
相关产品推荐

