Null pointer after capturing image using android camera

27.8k views Asked by At

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:

//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

     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.access$1300(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..

8

There are 8 answers

2
Melbourne Lopes On BEST ANSWER

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,

/** 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....:)

1
Gopal Gopi On

replace

picUri = getIntent().getData();

with

picUri = data.getData();

and try once...

3
Sagar Maiyad On

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);
    }
}
0
NagarjunaReddy On

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");
    }
1
Aromal Sasidharan On

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

We can create our own application class

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

  <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

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

  //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);
   }  

 }
0
azorrozua On

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.

1
Buddy On

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

You have a member picUri in which you save the temporary image file URI before the startActivityForResult is called for launching the Camera app.

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

Then, you will get NullPointerException.

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

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.

0
Alok On

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.

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.