在onActivityResult(..)中拍照总是返回RESULT_CANCELED(0)

3
我正在尝试使用Firebase存储示例应用程序构建{{link1:存储应用程序}},但是当我拍照时,在onActivityResult(..)中总是得到RESUL_CANCELED。 以下是代码:
@AfterPermissionGranted(RC_STORAGE_PERMS)
private void launchCamera() {
    Log.d(LOG_TAG, "launchCamera");

    // Check that we have permission to read images from external storage.
    String perm = Manifest.permission.WRITE_EXTERNAL_STORAGE;
    if (!EasyPermissions.hasPermissions(this, perm)) {
        EasyPermissions.requestPermissions(this, getString(R.string.rationale_storage),
                RC_STORAGE_PERMS, perm);
        return;
    }

    // Choose file storage location, must be listed in res/xml/file_paths.xml
    File externalDir = Environment.getExternalStorageDirectory();
    File file = new File(externalDir, "photos/" + UUID.randomUUID().toString() + ".jpg");

    // Create content:// URI for file, required since Android N
    // See: https://developer.android.com/reference/android/support/v4/content/FileProvider.html
    mFileUri = FileProvider.getUriForFile(this,
           "com.google.firebase.quickstart.firebasestorage.fileprovider", file);

    // Create and launch the intent
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mFileUri);

    startActivityForResult(takePictureIntent, RC_TAKE_PICTURE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Log.d(LOG_TAG, "onActivityResult:" + requestCode + ":" + resultCode + ":" + data);
    if (requestCode == RC_TAKE_PICTURE) {
        if (resultCode == RESULT_OK) {
            if (mFileUri != null) {
                uploadFromUri(mFileUri);
            } else {
                Log.w(LOG_TAG, "File URI is null");
            }
        } else {
            Toast.makeText(this, "Taking picture failed.", Toast.LENGTH_SHORT).show();
        }
    }
}

日志:onActivityResult:101:0:意图 { }

尝试使用其他相机应用程序。ACTION_IMAGE_CAPTURE 的实现存在一系列的错误。此外,不要忘记将 mFileUri 放入保存的实例状态 Bundle 中,因为在相机应用程序处于前台时,您的进程可能会被终止。 - CommonsWare
@CommonsWare 谢谢,那就是问题所在。所以这取决于 Android 的版本? - madim
1
@madim,到底是什么问题?我在安卓12、三星Galaxy S21和OneUI 4.0上也遇到了同样的问题。是需要保存实例状态还是相机应用程序出了问题? - Ovi Trif
2个回答

7

那么这取决于Android的版本吗?

这取决于您的意思以及错误是什么。

正如我在评论中指出的那样,ACTION_IMAGE_CAPTURE 实现存在许多错误。有很多这样的错误,并不一定与Android操作系统版本有关。

然而,您的代码采用了一个有趣的方法来处理EXTRA_OUTPUT:使用位于外部存储上的FileProvider。从长远来看,FileProvider是一个很好的选择,因为Android N开始禁止使用file: Uri。然而,许多相机应用程序会出现问题,因为这些相机应用程序的开发人员没有预料到content: Uri值。例如,截至几个月前,Google自己的相机应用程序无法处理ACTION_VIDEO_CAPTURE中的content: Uri值,但对于ACTION_IMAGE_CAPTURE则没有问题。
更糟糕的是,应用程序无法为额外信息广告支持的方案。使用 Intent 的“data”属性,可以向外部广告支持的方案,但不能用于 extras。因此,当您在 EXTRA_OUTPUT 中调用 ACTION_IMAGE_CAPTURE 时,相机应用程序不限于支持 content: Uri 值的相机应用程序。您可能需要将 targetSdkVersion 暂时降低到 24 以下,然后使用 Uri.fromFile(file) 而非 FileProvider.getUriForFile(...),并观察结果。如果原始相机应用程序正常工作,则该应用程序不正确地支持 content: Uri 值,并导致了原始问题。

总的来说,我建议使用ACTION_IMAGE_CAPTURE的开发者将targetSdkVersion保持在24以下,并在未来几年内使用file:Uri值,直到更高比例的用户安装了支持content:Uri值的相机应用。或者,通过ACTION_IMAGE_CAPTURE为您的用户提供现有相机应用的选择,以及您自己应用中构建的一些相机功能(例如使用我的库),增加某种程度上的可行性。


0
只是添加了一些代码,调用了一个平滑的解决方案,添加到@CommonsWare。 检查API并适当处理效果很好。
   private void startCamera() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
        File photoFile = null;
        try {
            photoFile = ImgUtils.createTempImageFile(this);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        if (photoFile != null) {
            mTempPhotoPath = photoFile.getAbsolutePath();
            if(Build.VERSION.SDK_INT < 24) {

            //create Uri with 'file://' prefix 
                tempImgUri = Uri.fromFile(photoFile);
            }else{

            //create Uri with 'content://' prefix 
                tempImgUri = FileProvider.getUriForFile(this,
                        FILE_PROVIDER_AUTHORITY,
                        photoFile);
            }
            mImgUriString = tempImgUri.toString();

            // Add the URI so the camera can store the image
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, tempImgUri);
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接