相机结果总是返回 RESULT_CANCELED

Posted

技术标签:

【中文标题】相机结果总是返回 RESULT_CANCELED【英文标题】:Camera Result always returns RESULT_CANCELED 【发布时间】:2016-05-18 06:41:03 【问题描述】:

我想用我的相机拍照。我只是暂时需要它们,所以我执行以下操作:

private void takePicture() 
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

    if (intent.resolveActivity(this.getActivity().getPackageManager()) != null) 
        try 
            this.imageFile = File.createTempFile("CROP_SHOT", ".jpg", this.getActivity().getCacheDir());

            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(this.imageFile));
            intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);

            this.startActivityForResult(intent, Globals.REQUEST_TAKE_PHOTO);
         catch (IOException e) 
            e.printStackTrace();
        
    

不幸的是我的onActivityResult中的结果代码RESULT_CANCELED

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) 
    Log.v("PictureEdit", "onActivityResult");

    super.onActivityResult(requestCode, resultCode, data);

    if(resultCode == Activity.RESULT_OK) 
        if(requestCode == Globals.REQUEST_TAKE_PHOTO) 
            Log.v("PictureEdit", "onActivityResult take photo");

            this.startCropImage(Uri.fromFile(this.imageFile));
         else if (requestCode == Globals.REQUEST_PICK_PHOTO) 
            Log.v("PictureEdit", "onActivityResult pick photo");

            this.startCropImage(data.getData());
         else if (requestCode == Globals.REQUEST_CROP_PHOTO) 
            Log.v("PictureEdit", "onActivityResult crop photo");

            this.imageEncoded = data.getStringExtra(Globals.KEY_IMAGE_ENCODED);

            this.imageView.setImageBitmap(Images.decodeImage(imageEncoded));
            this.buttonSave.setEnabled(true);
         else 
            Log.v("PictureEdit", "onActivityResult requestCode: " + requestCode + ", result: " + resultCode);
        
     else 
        Log.v("PictureEdit", "onActivityResult resultCode is not ok: " + resultCode);
    

到目前为止,我在 *** 和网络上找到的每个解决方案都没有解决我的问题。我使用缓存目录来创建临时文件:

File.createTempFile("CROP_SHOT", ".jpg", this.getActivity().getCacheDir());

而且我拥有正确的权限:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

从我的智能手机中挑选图像总是可以正常工作:

private void pickPicture() 
    Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

    this.startActivityForResult(intent, Globals.REQUEST_PICK_PHOTO);

那么为什么相机总是返回RESULT_CANCELED

它出现在搭载 Android 6.0 的 Nexus 4 和搭载 Android 4.2 的三星 Galaxy S III 上。

【问题讨论】:

【参考方案1】:

我使用缓存目录来创建临时文件:

首先,第三方相机应用无权使用您应用在internal storage 上的私有缓存目录。

其次,您不应该创建文件。相机应用程序应该创建文件。某些相机应用程序可能会感到困惑并拒绝覆盖您的文件。

因此,创建一个 File 对象,指向 external storage 上的某个位置(例如,getExternalCacheDir()),但不要创建文件。使用 File 对象作为 EXTRA_OUTPUT 值的基础。

还要注意MediaStore.EXTRA_VIDEO_QUALITY是用来录制视频的;它对ACTION_IMAGE_CAPTURE 没有任何意义。

【讨论】:

同意不应创建新文件。不知道为什么谷歌培训文档会在创建将由相机应用程序通过 FileProvider 使用的 URI 之前创建一个临时文件。 developer.android.com/training/camera/… 只是简单地实例化一个指向外部缓存目录的文件并没有帮助。当我们点击使用图片时,股票凸轮没有响应。【参考方案2】:

@CommonsWare 提到的是正确的,但是如果您仍然想遵循官方文档所说的内容,我所做的是授予那些能够处理您的意图的 3rd 方应用程序临时读写 URI 权限:

List<ResolveInfo> resolvedIntentActivities = getContext().getPackageManager().queryIntentActivities(takePhotoIntent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolvedIntentInfo : resolvedIntentActivities) 
    String packageName = resolvedIntentInfo.activityInfo.packageName;
    getContext().grantUriPermission(packageName, photoURI, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);

上面的代码 sn-p 应该插入你的startActivityForResult()之前。

【讨论】:

【参考方案3】:

更好的解决方案是使用 FileProvider。因此,您的应用不需要任何权限即可写入外部存储,并且您的应用可以授予相机写入权限

以使用应用文件夹的权限启动相机:

Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
camera.putExtra(MediaStore.EXTRA_OUTPUT, getPhotoFile(context));
camera.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
camera.addFlags(FLAG_GRANT_WRITE_URI_PERMISSION);

public static Uri getPhotoFile(Context context) 
    File file = new File(context.getExternalCacheDir(), "camera.jpg");
    return FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider.files", file);

【讨论】:

以上是关于相机结果总是返回 RESULT_CANCELED的主要内容,如果未能解决你的问题,请参考以下文章

Android - 相机意图,返回空结果

从相机返回结果时也会调用 onCreate 方法

活动结果相机意图在三星 s4 中返回 null

无法打开相机意图。 queryIntentActivities 在 api 级别 30 返回一个空列表,但在级别 29 中找到结果。发生了啥变化?

Android相机应用程序(图片仅在重启后显示)

从 ExifInterface 获取旋转总是返回 0