使用android相机捕获图像后的空指针

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20536603/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 02:59:37  来源:igfitidea点击:

Null pointer after capturing image using android camera

androidnullpointerexceptionimage-capture

提问by bohr

in my application,i am using android devices camera to capture an image. for some devices it works fine but some are not. I just tested it on LG nexus 4 E960, after i captured the image my application went crash without able to save the result. this is my code:

在我的应用程序中,我使用 android 设备相机来捕获图像。对于某些设备,它可以正常工作,但有些则不能。我刚刚在 LG nexus 4 E960 上对其进行了测试,在我捕获图像后,我的应用程序崩溃而无法保存结果。这是我的代码:

//Using intent to open camera
  Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  startActivityForResult(intent,CAMERA_CAPTURE); 

in the activityResult :

在活动结果中:

protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if(resultCode==RESULT_OK)
    {
        if(requestCode==CAMERA_CAPTURE)
        {   
            Bitmap pictTaken = null ;
            Bundle extras = data.getExtras();
            if(extras.keySet().contains("data"))
            {
                pictTaken = (Bitmap) extras.get("data");
                picUri = getIntent().getData();
            }
                    else{
                     picUri = getIntent().getData();
                try {
                    pictTaken = decodeUri(picUri);
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                     }
            Intent cropIntent= new Intent (this, Crop.class);
            cropIntent.putExtra("data", picUri.toString());
            cropIntent.putExtra("pict", pictTaken);
            cropIntent.putExtra("code","camera");
            startActivity(cropIntent);
            }
        }

after captured and save it, the image show in next activity called Crop.class here is my logcat

捕获并保存后,下一个名为 Crop.class 的活动中显示的图像是我的 logcat

     12-12 13:26:36.340: E/AndroidRuntime(23575): FATAL EXCEPTION: main
 12-12 13:26:36.340: E/AndroidRuntime(23575): Process: com.example.cobaandroid, PID: 23575
 12-12 13:26:36.340: E/AndroidRuntime(23575): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { act=inline-data (has extras) }} to activity {com.example.cobaandroid/com.example.cobaandroid.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.toString()' on a null object reference
 12-12 13:26:36.340: E/AndroidRuntime(23575):   at android.app.ActivityThread.deliverResults(ActivityThread.java:3368)
 12-12 13:26:36.340: E/AndroidRuntime(23575):   at android.app.ActivityThread.handleSendResult(ActivityThread.java:3411)
 12-12 13:26:36.340: E/AndroidRuntime(23575):   at android.app.ActivityThread.access00(ActivityThread.java:138)
 12-12 13:26:36.340: E/AndroidRuntime(23575):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1247)
 12-12 13:26:36.340: E/AndroidRuntime(23575):   at android.os.Handler.dispatchMessage(Handler.java:102)
 12-12 13:26:36.340: E/AndroidRuntime(23575):   at android.os.Looper.loop(Looper.java:136)
 12-12 13:26:36.340: E/AndroidRuntime(23575):   at android.app.ActivityThread.main(ActivityThread.java:5050)
 12-12 13:26:36.340: E/AndroidRuntime(23575):   at java.lang.reflect.Method.invoke(Native Method)
 12-12 13:26:36.340: E/AndroidRuntime(23575):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
 12-12 13:26:36.340: E/AndroidRuntime(23575):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
 12-12 13:26:36.340: E/AndroidRuntime(23575): Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.toString()' on a null object reference
 12-12 13:26:36.340: E/AndroidRuntime(23575):   at com.example.cobaandroid.MainActivity.onActivityResult(MainActivity.java:226)
 12-12 13:26:36.340: E/AndroidRuntime(23575):   at android.app.Activity.dispatchActivityResult(Activity.java:5433)
 12-12 13:26:36.340: E/AndroidRuntime(23575):   at android.app.ActivityThread.deliverResults(ActivityThread.java:3364)
 12-12 13:26:36.340: E/AndroidRuntime(23575):   ... 9 more

I got a problem to open/use the camera that work at most android devices, the main goal of this project is heavily depend on the use of the camera. please hand me your help, thank you..

我在打开/使用适用于大多数 android 设备的相机时遇到问题,这个项目的主要目标在很大程度上取决于相机的使用。请把你的帮助交给我,谢谢..

回答by Melbourne Lopes

try below code,

试试下面的代码,

        Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);

        File file=getOutputMediaFile(1);
        picUri = Uri.fromFile(file); // create
        i.putExtra(MediaStore.EXTRA_OUTPUT,picUri); // set the image file

        startActivityForResult(i, CAPTURE_IMAGE);

where getOutputMediaFile(int) will be,

getOutputMediaFile(int) 将在哪里,

/** Create a File for saving an image */
private  File getOutputMediaFile(int type){
    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
              Environment.DIRECTORY_PICTURES), "MyApplication");

    /**Create the storage directory if it does not exist*/
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            return null;
        }
    }

    /**Create a media file name*/
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File mediaFile;
    if (type == 1){
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
        "IMG_"+ timeStamp + ".png");
    } else {
        return null;
    }

    return mediaFile;
}

and finally,

最后,

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == Activity.RESULT_OK) {
        Intent i;
        switch (requestCode) {
        case CAPTURE_IMAGE:
            //THIS IS YOUR Uri
            Uri uri=picUri; 
            break;
        }
    }   
}

Cheers....:)

干杯....:)

回答by Buddy

For those who couldn't solve this issue with any of the answers here, here is the way.

对于那些无法通过此处的任何答案解决此问题的人,这里是方法。

You have a member picUriin which you save the temporary image file URI before the startActivityForResultis called for launching the Camera app.

您有一个成员picUri,您可以在startActivityForResult调用 启动相机应用程序之前将临时图像文件 URI 保存在其中。

When the app pauses, this information might get lost (as in my case) and you will find it as nullwhen you return to activity to use it to get the saved image from camera.

当应用程序暂停时,此信息可能会丢失(就像我的情况一样),null当您返回活动以使用它从相机获取保存的图像时,您会发现它。

Then, you will get NullPointerException.

然后,您将获得NullPointerException.

The proper way to keep picUriis to save it onSaveInstanceState(Bundle)and restore it onRestoreInstanceState(Bundle)to prevent information loss.

正确的picUri保存方式是保存onSaveInstanceState(Bundle)并恢复onRestoreInstanceState(Bundle),防止信息丢失。

Here is how to do it:

这是如何做到的:

// Save the activity state when it's going to stop.
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    outState.putParcelable("picUri", picUri);
}

// Recover the saved state when the activity is recreated.
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);

    picUri= savedInstanceState.getParcelable("picUri");

}

Gave me a headache for two hours.

让我头疼了两个小时。

回答by Alok

See I've done one more thing may be it will save your time. The thing is that the data object in onActivityResult() is the main content to look upon. The data object is being null when it comes to operate the p=code for the next move. What you'll do is to just put if-else condition on that and run your project.

看我又做了一件事,可能会节省你的时间。问题是 onActivityResult() 中的数据对象是要查看的主要内容。在为下一步操作 p=code 时,数据对象为空。你要做的就是在上面加上 if-else 条件并运行你的项目。

protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if(data !=null){
  if(resultCode==RESULT_OK)
    {
        if(requestCode==CAMERA_CAPTURE)
        {   
            Bitmap pictTaken = null ;
            Bundle extras = data.getExtras();
            if(extras.keySet().contains("data"))
            {
                pictTaken = (Bitmap) extras.get("data");
                picUri = getIntent().getData();
            }
                    else{
                     picUri = getIntent().getData();
                try {
                    pictTaken = decodeUri(picUri);
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                     }
            Intent cropIntent= new Intent (this, Crop.class);
            cropIntent.putExtra("data", picUri.toString());
            cropIntent.putExtra("pict", pictTaken);
            cropIntent.putExtra("code","camera");
            startActivity(cropIntent);
            }
        }
}else{
   //on cancel event or something else you want to do
}
}

Check this out, it is easy and will do your work in a go.

看看这个,它很容易,并且可以快速完成您的工作。

回答by AZorrozua

I have the same issue in my app. The problem is that when onActivityResult is executed, data is null so you can't get anything from the camera Activity. There should be another way to solve this rather than using the Application class, because it gets really complicate when you handle more than one photo.

我的应用程序中有同样的问题。问题是当 onActivityResult 被执行时,数据为空,所以你不能从相机活动中得到任何东西。应该有另一种方法来解决这个问题,而不是使用 Application 类,因为当您处理多张照片时,它会变得非常复杂。

回答by Gopal Gopi

replace

代替

picUri = getIntent().getData();

with

picUri = data.getData();

and try once...

并尝试一次...

回答by Sagar Maiyad

You have to tell camera for saving image path like below:

您必须告诉相机保存图像路径,如下所示:

Uri picUri;

   Intent intentAmbil = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
   String imageFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() +          "/picture.jpg";  
   File imageFile = new File(imageFilePath); 
   picUri = Uri.fromFile(imageFile); // convert path to Uri        
   intentAmbil.putExtra( MediaStore.EXTRA_OUTPUT,  picUri );
   startActivityForResult(intentAmbil, REQUEST_MAKE_PHOTO);


@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
    switch (requestCode) {
        case REQUEST_MAKE_PHOTO:
            if (resultCode == Activity.RESULT_OK) {
                // do something with mMakePhotoUri
            }
            return;
        default: // do nothing
            super.onActivityResult(requestCode, resultCode, data);
    }
}

回答by NagarjunaReddy

Try this one

试试这个

if (resultCode != RESULT_CANCELED) {
            if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {

                if (requestCode == CAMERA_REQUEST) {
                    if (data != null) {
                        Bitmap photo = (Bitmap) data.getExtras().get("data");
                        imageView.setImageBitmap(photo);
                    }
                }
            }            
            Drawable drawable = imageView.getDrawable();
            if (drawable instanceof BitmapDrawable) {
                BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
                bitmap1 = bitmapDrawable.getBitmap();
            }
        }
    }

    if (bitmap1 != null) {          
        bitmap1 = Bitmap.createScaledBitmap(bitmap1, 512, 512, false);
        imageView.setImageBitmap(bitmap1);
        @SuppressWarnings("unused")
        String path = SaveImage_Sta(bitmap1, "stat");
    } else {
        Log.i("bitmap............", "bitmap1 is null");
    }

回答by Aromal Sasidharan

in some devices onActivityResult is called not on activity resume instead the activity is restarted after callback from camera intent, so picurl can be null again - we can use the application class to keep reference of the variable

在某些设备中 onActivityResult 不是在活动恢复时调用,而是在从相机意图回调后重新启动活动,因此 picurl 可以再次为空 - 我们可以使用应用程序类来保持变量的引用

We can create our own application class

我们可以创建自己的应用程序类

1.in android manifest we have to Specify the application classwe are going to use

1.在android manifest中,我们必须指定我们将要使用的应用程序类

  <application android:name=".MyApplication" 
  >
 <activity
        ........         
        >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
      </activity> 
      <activity> 
          ....
      </activity>
        ....
  </application>

2.Create the Application Class

2.创建应用类

public class MyApplication extends Application {
   private Uri picUri;
   public void getPicUri()
   {
     return picUri;
   } 
   public void setPictUri(Uri auri)
   {
     picUri = aUri;
   } 
}

3.Inside the Activity use

3.在Activity里面使用

  //call the camera intent and pass the created a tempfile uri and use the tempfile uri
  MyApplication myApplication = (MyApplication)getApplication();
  myApplication.setPictUri(aUri);
  ....
 ....
 public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
switch (requestCode) {
    case REQUEST_MAKE_PHOTO:
        if (resultCode == Activity.RESULT_OK) {
            // do something with mMakePhotoUri
            MyApplication myApplication = (MyApplication)getApplication();
            myApplication.getPicUri();// use the pic uri
        }
        return;
    default: // do nothing
        super.onActivityResult(requestCode, resultCode, data);
   }  

 }