使用expo-image-picker调用launchCameraAsync时相机无法激活异常
原本使用expo-image-picker的launchCameraAsync实现拍照功能一切正常,现在调用时相机无法激活,同时抛出未处理的Promise拒绝警告:
可能未处理的Promise拒绝(id: 0):
Error: Call to function 'ExponentImagePicker.launchCameraAsync' has been rejected.
→ Caused by: java.lang.RuntimeException: Can't create handler inside thread Thread[DefaultDispatcher-worker-2,5,main] that has not called Looper.prepare()
对应代码片段:
const permission = await ImagePicker.requestCameraPermissionsAsync(); if (permission.granted === false) //Error handeling console.log(permission); let result = await ImagePicker.launchCameraAsync({ base64: false, mediaTypes: ImagePicker.MediaTypeOptions.Images, allowsEditing: true, aspect: [3, 2], quality: 1, }); console.log(result); if (!result.cancelled) { console.log(result.uri); setImages({ ...images, document: result.uri }); }
使用的模块版本:
"expo": "~46.0.16", "expo-image-picker": "~13.3.1", "expo-updates": "~0.14.6",
推测可能是模块不兼容,但未更新或修改过应用中的模块,寻求解决办法。
解决方案
这个错误的核心是相机调用未在Android主线程执行,虽然Expo模块默认会处理线程调度,但特殊场景下会出现异常,可按以下步骤修复:
补全权限错误处理
权限未授予时直接终止后续逻辑,避免无效调用:const permission = await ImagePicker.requestCameraPermissionsAsync(); if (!permission.granted) { alert('需要相机权限才能使用拍照功能'); return; }强制主线程执行相机调用
用setTimeout将相机调用放入主线程消息队列,确保线程环境正确:// 替换原launchCameraAsync调用代码 setTimeout(async () => { const result = await ImagePicker.launchCameraAsync({ base64: false, mediaTypes: ImagePicker.MediaTypeOptions.Images, allowsEditing: true, aspect: [3, 2], quality: 1, }); if (!result.cancelled) { setImages({ ...images, document: result.uri }); } }, 0);清理缓存重建项目
运行expo r -c清理Expo缓存并重启项目,同时卸载设备上的旧应用后重新安装。排查模块冲突
暂时禁用非核心第三方模块,测试是否存在线程调度干扰;若无效,升级Expo 46到最新补丁版本(如46.0.21)修复已知bug。
内容的提问来源于stack exchange,提问作者Diego Andres Castillo Villalon

