You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ActivityResultLauncher<Intent>返回Activity前提前返回结果码问题

问题现象
  • 从当前Activity拉起第三方OpenCamera应用,相机可以正常启动,但启动后立刻返回结果码,未定位到根因
  • 日志打印返回的结果码值为0,即Activity.RESULT_CANCELED
  • 疑问:若目标相机仅完成拍照操作、不返回任何数据,是否需要调整现有实现逻辑
  • 原有实现代码:
private void cameraOpen() {
        Intent cam = getContext().getPackageManager().getLaunchIntentForPackage("net.sourceforge.opencamera");
        postCamera.launch(cam);
    }

    ActivityResultLauncher<Intent> postCamera = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> {
        if (result.getResultCode() == Activity.RESULT_OK) {
            Log.i("SAKEGA", "WAK");
            dispatchTakePictureIntent();
        } else {
            Log.i("SAKEGA", String.valueOf(result.getResultCode()));
        }
    });
问题根因

返回0和相机是否返回数据无关,核心是拉起逻辑写错了:
getLaunchIntentForPackage获取的是应用的桌面入口Intent,和用户手动点桌面图标启动应用的行为完全一致,这种启动方式没有携带任何拍照请求的参数,OpenCamera识别到这不是外部发起的拍照调用,不会停留在拍照页面等待用户操作,会直接走普通启动流程后返回取消结果。

修复方案
  1. 不要用普通桌面启动Intent发起拍照请求,必须使用Android标准的拍照Action MediaStore.ACTION_IMAGE_CAPTURE构造Intent,如果需要固定拉起OpenCamera,单独给Intent设置包名即可。
  2. 不要等相机返回Intent里携带的图片数据,几乎所有第三方相机都不会直接在返回结果中放Bitmap(很容易触发跨进程传输数据过大的崩溃),正确做法是提前创建好图片存储文件,生成FileProvider Uri后通过MediaStore.EXTRA_OUTPUT参数传给相机,相机会直接把拍摄的图片写入你指定的路径。
  3. 给Intent添加FLAG_GRANT_WRITE_URI_PERMISSION权限,保证相机有权限写入你指定的文件路径。
  4. 修正后的代码参考:
// 全局存储拍照输出路径的Uri
private Uri photoOutputUri;

private void cameraOpen() {
    Intent cam = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    // 指定拉起OpenCamera,去掉该行则会弹出应用选择器让用户选可用相机
    cam.setPackage("net.sourceforge.opencamera");
    
    // 提前创建拍照存储文件
    File photoFile = new File(
            getExternalFilesDir(Environment.DIRECTORY_PICTURES),
            "camera_shot_" + System.currentTimeMillis() + ".jpg"
    );
    // 生成对应FileProvider的访问Uri,注意替换成你自己的FileProvider配置的authority
    photoOutputUri = FileProvider.getUriForFile(
            getContext(),
            getContext().getPackageName() + ".fileprovider",
            photoFile
    );
    
    // 给相机授予临时写入权限
    cam.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    // 传入输出路径
    cam.putExtra(MediaStore.EXTRA_OUTPUT, photoOutputUri);
    
    // 提前判断是否有可处理该意图的相机应用,避免ActivityNotFound崩溃
    if (cam.resolveActivity(getContext().getPackageManager()) != null) {
        postCamera.launch(cam);
    }
}

ActivityResultLauncher<Intent> postCamera = registerForActivityResult(
        new ActivityResultContracts.StartActivityForResult(),
        result -> {
            if (result.getResultCode() == Activity.RESULT_OK) {
                Log.i("SAKEGA", "拍照成功,图片已写入photoOutputUri对应路径");
                // 直接使用全局的photoOutputUri做后续图片处理即可,不需要从result中取数据
                dispatchTakePictureIntent();
            } else {
                Log.i("SAKEGA", "拍照失败/用户取消,结果码:" + result.getResultCode());
            }
        }
);
注意事项
  • 上述实现需要你提前在AndroidManifest.xml中配置FileProvider,否则生成Uri时会抛出异常。
  • 按照Android相机Intent的标准规范,配置了EXTRA_OUTPUT参数后,相机返回的Intent通常是空值,这是正常设计,不是相机实现错误。

内容的提问来源于stack exchange,提问作者shiho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 17:09:17