【问题标题】:Image captured from the camera is not showing (OnActivityResult)从相机捕获的图像未显示(OnActivityResult)
【发布时间】:2012-10-30 01:13:16
【问题描述】:

我无法检索刚刚拍摄的照片。我相信我的 OnActivityResult 有问题,案例 CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE。按案例 1 从相册中检索照片效果很好。请善意的建议。

源代码:

    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
        super.onActivityResult(requestCode, resultCode, data); 
        if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
           if(resultCode == RESULT_OK){     
             Uri targetUri = (data != null) ? data.getData() : null;
             if (targetUri == null) {
                 targetUri = fileUri;
             }
             imageView.setImageURI(targetUri);
           }
           if(resultCode == RESULT_CANCELED){   
             Uri targetUri = (data != null) ? data.getData() : null;
             if (targetUri == null) {
                 targetUri = fileUri;
             }
             imageView.setImageURI(targetUri);
           }
           else{  ; 
             Uri targetUri = (data != null) ? data.getData() : null;
             if (targetUri == null) {
                 targetUri = fileUri;
             }
             imageView.setImageURI(targetUri);
           }
    }   
    else if(requestCode == 1) {
        if(resultCode == RESULT_OK){  
            Uri selectedImage = data.getData();
            imageView.setImageURI(selectedImage);
        }
    }
}

}

【问题讨论】:

  • 您是否收到任何错误或警告?
  • 不。没有错误。我不确定这是否是我的案例代码的问题。我试过在箱子里烤面包,也没有显示

标签: android android-layout android-intent android-emulator android-widget


【解决方案1】:

不幸的是,您是否获得图像取决于手机的制造商。每个 Android 版本和每个制造商的行为似乎都略有不同。有时 URL 在结果中作为“数据”参数提供(这就是你正在做的),但有时它只是空的。我什至得到了一部返回 RESULT_CANCEL 的手机,尽管它运行良好。

似乎没有办法实现各种不同的后备。这是我目前在我们的一个项目中使用的代码。成员变量mTargetUri需要设置为您提供的输出文件名作为Intent参数MediaStore.EXTRA_OUTPUTmCaptureTime应该在启动Intent之前设置为Sytem.currentTimeMillis()

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            Log.v(LOG_TAG, "Camera intent succeeded");
        }
        else if (resultCode == RESULT_CANCELED) {
            Log.i(LOG_TAG, "Camera intent aborted");
        }
        else {
            Log.e(LOG_TAG, "Camera intent failed with result code: " + resultCode);
        }

        // Regardless of the resultCode we're going to check if a new photo has been
        // created on the phone. At least on the Samsung Galaxy S3 the behavior
        // could be observed that although the result code was "0" the camera app
        // created two (!) files on the SD card.

        // Image captured and saved to fileUri specified in the Intent
        Uri targetUri = (data != null) ? data.getData() : null;
        if (targetUri == null) {
            Log.w(LOG_TAG, "Camera intent returned empty result.");
            targetUri = mTargetUri;
        }

        if (targetUri != null) {
            String targetFilePath = targetUri.getPath();
            File targetFile = new File(targetFilePath);
            if (targetFile.exists()) {
                Log.i(LOG_TAG, "Image saved to: " + targetUri.toString());

                // Fix for issue reported here: http://code.google.com/p/android/issues/detail?id=22822
                // and here: http://code.google.com/p/android/issues/detail?id=19268
                // We're following the proposed solution from https://stackoverflow.com/questions/8450539/
                int rotation = -1;
                long fileSize = targetFile.length();
                Cursor mediaCursor = getContentResolver().query(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
                        new String[] { 
                            MediaStore.Images.ImageColumns.ORIENTATION, 
                            MediaStore.MediaColumns.SIZE,
                            MediaStore.MediaColumns.DATA }, 
                        MediaStore.MediaColumns.DATE_ADDED + ">=?", 
                        new String[] { String.valueOf(mCaptureTime/1000 - 1)}, 
                        MediaStore.MediaColumns.DATE_ADDED + " desc");

                if ((mediaCursor != null) && (mCaptureTime != 0)) {
                    if (mediaCursor.moveToFirst()) {
                        do {
                            long size = mediaCursor.getLong(1);
                            Uri uri = Uri.parse(mediaCursor.getString(2));
                            // Extra check to make sure that we are getting the orientation from the proper file
                            if (size == fileSize && !uri.equals(targetUri.toString())) {
                                rotation = mediaCursor.getInt(0);
                                break;
                            }
                        } while (mediaCursor.moveToNext());
                    }
                    mediaCursor.close();
                }

                if (rotation == -1) {
                    // It seems that there has been no duplication and no rotation issue so far. This means we can
                    // add our newly created file to the media library.
                    // TODO
                }
                else {
                    // Looks like the picture already exists in the media library. This indicates we got a duplicate.
                    Log.w(LOG_TAG, "Duplicate image found for " + targetUri.toString() + " in media library. Deleting the copy.");
                    if (!targetFile.delete()) {
                        Log.e(LOG_TAG, "Failed to delete duplicate image.");
                    }
                }
            }
            }
    }
}

代码来自 Stackoverflow 和其他网站上的不同来源。基本思想是我们

  1. 忽略结果代码(RESULT_OKRESULT_CANCELED),因为它们并不表示照片是否已拍摄并存储在 SD 卡上。上面的代码只是记录值,但无论如何都会继续。
  2. 然后我们检查是否有意图结果提供的 URI。如果我们得到一个 URI,那么可以安全地假设它实际上会指向新拍摄的照片。但是,尽管一切都非常成功,但我们不会得到这样的 URI。为了处理这种情况,我们只需使用我们最初提供给相机活动 (mTargetUri) 的 URI,希望我们能在那里找到新文件。
  3. 在一些较新的设备上,相机应用程序会自动将新照片添加到媒体库,然后按照我们最初在 targetUri 中指定的方式创建第二个副本名称。这种方法的问题是我们最终会得到重复的图像。为了解决这个问题,我们遵循源自以下 Stackoverflow 问题的逻辑:Images taken with ACTION_IMAGE_CAPTURE always returns 1 for ExifInterface.TAG_ORIENTATION on some newer devices。我不会在这里详细介绍(只需点击链接以获得更好的理解),但基本想法是我们查询 Android 媒体商店并通过比较时间戳检查它是否已经包含我们的新照片(mCaptureTime 已设置到 System.currentTimeMillis() 当捕获意图最初开始时)。
  4. 如果我们在媒体存储中找到了一个条目,我们只需删除副本即可。

这个逻辑应该适用于几乎所有的 Android 设备。到目前为止,我们已经在十几种不同的设备和 Android 版本上对其进行了测试,没有出现其他问题。

【讨论】:

  • 嗨安德烈,我可以知道 mCaptureTime 的用途是什么,它的设置是什么?另外,您的意思是我只需将 onActvityResult 的代码更改为上述代码?所以在我的情况下 targetUri = fileUri?
  • 另外,就我而言,这不是 resultcode 的问题,因为我添加了相同的代码以产生 ok 并取消了结果。我相信它没有输入 requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE 的 if 语句。我可以知道这是为什么吗?
  • 关于捕获时间和检查旋转的基本逻辑源自以下 Stackoverflow 响应:stackoverflow.com/a/8864367/1510185。它还解释了它背后的想法。在我的测试中,我总是从被调用的活动中得到正确的请求代码。所以我希望这在所有平台上都能按设计工作。但是,结果代码和附加内容在设备之间存在很大差异。稍后我将更新我的答案以更详细地解释这一点。
  • 您可以安全地使用 MediaStore.Images.Media._ID 而不是检查 mCaptureTime。捕获时间在模拟器上有错误。感谢@Emil Davtyan
【解决方案2】:

我遇到了同样的问题,一旦检查你有没有放任何与历史相关的标签?​​

不要将android:noHistory="true"标签放在清单中

如果您在清单内的活动中使用android:noHistory="true",它将 停止后从堆栈中删除。

注意:如果你正在使用标签活动,那么你也不应该使用android:noHistory="true"

或者简单地将android:noHistory="false" 放在清单内的活动中。

【讨论】:

    【解决方案3】:

    尝试转动相机并在横向模式下拍照。 Mediastore Camera Intent 似乎只拍摄风景照片。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-08
      • 1970-01-01
      • 2011-08-24
      • 2019-07-09
      • 1970-01-01
      相关资源
      最近更新 更多