从相机返回的onActivityResult,Intent为空。

19

我按照Android开发网站上的相机指南进行操作。

我仅仅是启动了相机意图,而非构建自己的相机。

拍摄照片后处理返回结果的示例代码如下。

 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            // Image captured and saved to fileUri specified in the Intent
            Toast.makeText(this, "Image saved to:\n" +
                    data.getData(), Toast.LENGTH_LONG).show();
        } else if (resultCode == RESULT_CANCELED) {
            // User cancelled the image capture
        } else {
            // Image capture failed, advise user
        }
    }

    if (requestCode == CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            // Video captured and saved to fileUri specified in the Intent
            Toast.makeText(this, "Video saved to:\n" +
                    data.getData(), Toast.LENGTH_LONG).show();
        } else if (resultCode == RESULT_CANCELED) {
            // User cancelled the video capture
        } else {
            // Video capture failed, advise user
        }
    }
}
< p > resultCode 是OK的,但是data总是为NULL,导致了NPE。我查看了SD卡,照片确实保存在那里。有什么提示吗?非常感谢。

更新:按要求提供logcat信息:

   01-28 19:39:00.547: ERROR/AndroidRuntime(24315): FATAL EXCEPTION: main
    java.lang.RuntimeException: Unable to resume activity {com.example.CameraTest/com.example.CameraTest.MyCamera}: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=100, result=-1, data=null} to activity {com.example.CameraTest/com.example.CameraTest.MyCamera}: java.lang.NullPointerException
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2455)
    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2483)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1997)
    at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3362)
    at android.app.ActivityThread.access$700(ActivityThread.java:127)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1162)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4511)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:980)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:747)
    at dalvik.system.NativeStart.main(Native Method)
    Caused by: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=100, result=-1, data=null} to activity {com.example.CameraTest/com.example.CameraTest.MyCamera}: java.lang.NullPointerException
    at android.app.ActivityThread.deliverResults(ActivityThread.java:2991)
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2442)
    ... 13 more
    Caused by: java.lang.NullPointerException
    at com.example.CameraTest.MyCamera.onActivityResult(MyCamera.java:71)
    at android.app.Activity.dispatchActivityResult(Activity.java:4654)
    at android.app.ActivityThread.deliverResults(ActivityThread.java:2987)
    ... 14 more                                                                                      

2
你使用了MediaStore.EXTRA_OUTPUT吗? - Blackbelt
请展示一下你是如何在Intent中传递图片路径的? - GrIsHu
1
`private void fireCameraForImage(int requestCode){ Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); startActivityForResult(intent, requestCode); }` - EyeQ Tech
1
@TungMaiLe 只需使用 fileUri 获取图像路径。如果您想获取默认路径的数据路径,请不要放置 MediaStore.EXTRA_OUTPUT - Sieryuu
4
谢谢,Sieryuu。但是为什么意图(Intent)中的“data”为空? - EyeQ Tech
显示剩余2条评论
7个回答

27

你的代码存在这个问题:

data.getData()

这个调用没有从返回的Intent中获取键为"data"的额外数据。它从返回的Intent中获取字段data,该字段可能是null

您需要像这样从返回的Intent中获取额外数据:

data.getExtras().get("data");

其他答案中有些已经指出了这一点,但是它们被嵌入了大量的其他代码中,这使得实际上很难看到问题所在。


7
我遇到了同样的错误,此时data参数为空,因此在你的答案中执行data.getExtras()仍会导致NPE异常。 - KJ50
我有同样的问题。在一些三星设备上,我得到了数据参数为空的情况。因此,我无法继续进行。 - Jignesh M. Mehta
1
@JigneshM.Mehta,你看到KJ50关于三星手机的回答了吗? - David Wasser
@David Wasser:尽管有KJ50的答案,但我仍然得到了fileUri.toString()为空的结果.. :( - Jignesh M. Mehta
1
@JigneshM.Mehta 请开一个新的问题,发布您的问题、代码等等,也许有人可以帮助您。这不是寻求帮助的正确地方(在回答的评论中)。 - David Wasser

8
这里有一个类似问题的答案,链接在这里:https://dev59.com/U1TTa4cB1Zd3GeqPrEw4#4989163。看起来可能是三星手机的问题。
如果你有以下这样的代码创建了一个Intent: 像这样的代码
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name

// start the image capture Intent
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);

然后,在onActivityResult中,将data.getData()替换为fileUri.toString(),这样就可以解决您的问题。

有时候我会得到文件URI为空的情况。 - Darpan
fileUri.toString()对三星手机也不起作用。:'( - Amit Upadhyay
谢谢你 => 永远 (真的) - McLan
顺带一提,在三星手机之外,还可以添加Nexus-7平板电脑(以及Cyanogenmod操作系统)。 - McLan

3
使用@KJ50的解决方案,使用“savedInstanceState”确保不会得到空值。
/**
     * Here we store the file url as it will be null after returning from camera
     * app
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        // save file url in bundle as it will be null on screen orientation
        // changes
        outState.putParcelable("file_uri", fileUri);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        // get the file url
        fileUri = savedInstanceState.getParcelable("file_uri");
    }

2

尝试以下代码:

 Button m_btnCamera;
  ImageView m_ivCaptureImage;
  String m_curentDateandTime;
  String m_imagePath;
  Bitmap m_bitmap;

   //Start camera to caputre image.
 Intent m_intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  m_intent.putExtra(MediaStore.EXTRA_OUTPUT, getImageUri());
  startActivityForResult(m_intent, TAKE_PHOTO_CODE);

 private Uri getImageUri() throws CustomException
    {
    Uri m_imgUri = null;
    File m_file;
    try
    {
        SimpleDateFormat m_sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
        m_curentDateandTime = m_sdf.format(new Date());
        m_imagePath = File.getPath() + File.separator + m_curentDateandTime + ".jpg";
        m_file = new File(m_imagePath);
        m_imgUri = Uri.fromFile(m_file);
    }
    catch (Exception p_e)
    {}      
    return m_imgUri;        
}

 @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data)
  {
  super.onActivityResult(requestCode, resultCode, data);
 if (requestCode == TAKE_PHOTO_CODE && resultCode == RESULT_OK)
    {
        m_bitmap = ImageHelper.scaleImage(m_imagePath, 200, 200);
            m_bitmap = ImageHelper.rotateImage(m_bitmap, true, m_rotate);
            m_ivCaptureImage.setImageBitmap(m_bitmap);
    }
  }
}

24
catch (Exception p_e){} 看得我眼睛流血。 - m0skit0
2
捕获所有类型的异常,然后忽略它们(不记录日志或其他任何操作)肯定会降低代码的健壮性 :-( - David Wasser

0

这段代码将会帮助你

如果Android版本高于M,getData()方法将返回数据,否则将返回null结果。

if (resultCode == Activity.RESULT_OK) {

                //Check Android version, as intent.getData() will return data only if v is above or equal to M otherwise the data will be null
                if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M) {
                    Uri selectedImageURI = imageReturnedIntent.getData();
                    Toast.makeText(getActivity(), "URI Path:" + selectedImageURI, Toast.LENGTH_LONG).show();
                } else {
                    Bitmap photo = (Bitmap) imageReturnedIntent.getExtras().get("data");
                    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
                    photo.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
                    String path = MediaStore.Images.Media.insertImage(getActivity().getContentResolver(), photo, "Title", null);
                    Uri selectedImageURI = Uri.parse(path);
                    Toast.makeText(getActivity(), "URI Path:" + selectedImageURI, Toast.LENGTH_LONG).show();
                }
            }

0

试试这个

public void onActivityResult(int requestCode, int resultCode, Intent data) {

    switch (requestCode) {
        case PICK_IMAGE_ID:

            Bitmap bitmap = ImagePicker.getImageFromResult(this.getActivity(), resultCode, data);

            if(data!=null){
                //set image view
            }
            break;
        default:
            super.onActivityResult(requestCode, resultCode, data);
            break;
    }
}

-1

尝试下面的代码.....

btn_capture.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {

            Intent cameraIntent = new  Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
            startActivityForResult(cameraIntent, CAMERA_REQUEST); 
        }
    });
 protected void onActivityResult(int requestCode, int resultCode, Intent data){


             if (requestCode == CAMERA_REQUEST && resultCode == RESULT_OK) {  
                 Bitmap photo = (Bitmap) data.getExtras().get("data"); 
                 img.setImageBitmap(photo);
             } 
          }

    }

最后,您需要将以下代码添加到您的清单文件中

   <uses-feature android:name="android.hardware.camera"></uses-feature> 

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