Showing posts with label Android Capture Image from Camera causes NullPointerException on Samsung phones. Show all posts
Showing posts with label Android Capture Image from Camera causes NullPointerException on Samsung phones. Show all posts

Friday 14 December 2012

Photo capture Intent causes NullPointerException on Samsung phones only

Hello Dorid Guys,

Yesterday, I came across  a weird situation . In my application ,I am capturing an image from camera and displaying it inside an imageview. I tested its functionality on many of android device and its working 
fine except "Samsung Galaxy Tab".
In Samsung device the capture intent will be "Null" and I am getting null pointer exception while capturing image from camera in android Samsung S2.

Following code I am using which running fine in all devices except Samsung :

For capturing Image from camera:

Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(captureIntent, CAMERA_CAPTURE);

For choosing an image from gallery:

Intent gallaryIntent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(gallaryIntent, RESULT_LOAD_IMAGE);


And finally the onActivityResult(int requestCode, int resultCode, Intent data) :

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
       
       if (requestCode == RESULT_LOAD_IMAGE) {
         picUri = data.getData();
         performCrop();
        }

       if (requestCode == CAMERA_CAPTURE) {
  // get the Uri for the captured image
  picUri = data.getData();
  if (picUri != null) {
   performCrop();
  }
 }
 // user is returning from cropping the image
  if (requestCode == PIC_CROP) {
  // get the returned data
  Bundle extras = data.getExtras();
  // get the cropped bitmap
  rectangleBitmap = extras.getParcelable("data");
  // retrieve a reference to the ImageView
  GraphicsUtil graphicsUtil = new GraphicsUtil();
  rectangleBitmap = graphicsUtil.getRoundedCornerBitmap(
  rectangleBitmap, 16);
  ImageView picView = (ImageView) findViewById(R.id.imgView);
  // display the returned cropped image
  picView.setImageBitmap(rectangleBitmap);
  btnMakeMotekon.setBackgroundDrawable(getResources()
                .getDrawable(R.drawable.make));
  btnMakeMotekon.setEnabled(true);
  btnNext.setEnabled(true);
 }
}
}

Now the crop image method, picking the image from gallery or camera and crop it.


private void performCrop() {
 // take care of exceptions
 try {
 // call the standard crop action intent (the user device may not support it)
 Intent cropIntent = new Intent("com.android.camera.action.CROP");
 // indicate image type and Uri
 cropIntent.setDataAndType(picUri, "image/*");
 // set crop properties
 cropIntent.putExtra("crop", "true");
 // indicate aspect of desired crop
 cropIntent.putExtra("aspectX", 1);
 cropIntent.putExtra("aspectY", 1);
 // indicate output X and Y
 cropIntent.putExtra("outputX", 256);
 cropIntent.putExtra("outputY", 256);
 // retrieve data on return
 cropIntent.putExtra("return-data", true);
 // start the activity - we handle returning in onActivityResult
 startActivityForResult(cropIntent, PIC_CROP);
 }catch (ActivityNotFoundException anfe) {
  // display an error message
  String errorMessage = "Whoops - your device doesn't support the 
                   crop action!";
  Toast toast = Toast.makeText(this, errorMessage,
                    Toast.LENGTH_SHORT);
  toast.show();
 }
}


The above code is working fine in most of the devices but when test it on Samsung S2 . I am getting the NullPointerException.
This is very tough time for me because my client wants to release the Application ASAP. And because of this issue he is delaying its time. 

After spending a full day and a night a found the fix for this problem, I added some extra code inside the
onActivityResult method.

The trick is:

if(picUri != null) {
    // do it the normal way
else {
    // do it the "Samsung" way
}



And it works :)
Here is my source code:


 protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
   super.onActivityResult(requestCode, resultCode, data);  
  if (resultCode == RESULT_OK) {  
  if (requestCode == RESULT_LOAD_IMAGE) {  
    picUri = data.getData();  
    performCrop();  
  }  
  if (requestCode == CAMERA_CAPTURE) {  
  // get the Uri for the captured image  
  picUri = data.getData();  
  /*  
  * In samsung , the picUri will be null and application will  
  * give runtime error In else part we are doing the code for  
  * samsung device  
  */  
  if (picUri != null) {  
    // do it the normal way  
    performCrop();  
  } else {  
   // Describe the columns you'd like to have returned.  
   // Selecting from the Thumbnails location gives you both the  
   // Thumbnail Image ID, as well as the original image ID  
   String[] projection = {  
     MediaStore.Images.Thumbnails._ID, // The columns we wANT  
  MediaStore.Images.Thumbnails.IMAGE_ID,  
  MediaStore.Images.Thumbnails.KIND,  
  MediaStore.Images.Thumbnails.DATA };  
   String selection = MediaStore.Images.Thumbnails.KIND + "=" + // Select  
                // only        // mini's  
     MediaStore.Images.Thumbnails.MINI_KIND;  
      String sort = MediaStore.Images.Thumbnails._ID + " DESC";  
      // At the moment, this is a bit of a hack, as I'm returning  
   // ALL images, and just taking the latest one. There is a  
   // better way to narrow this down I think with a WHERE  
   // clause which is currently the selection variable  
      Cursor myCursor = this.managedQuery(  
   MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,  
   projection, selection, null, sort);  
   long imageId = 0l;  
   long thumbnailImageId = 0l;  
   String thumbnailPath = "";  
   try {  
     myCursor.moveToFirst();  
     imageId = myCursor.getLong(myCursor   .getColumnIndexOrThrow(MediaStore.Images.Thumbnails.IMAGE_ID));  
         thumbnailImageId = myCursor.getLong(myCursor   .getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID));  
     thumbnailPath = myCursor  
  .getString(myCursor    .getColumnIndexOrThrow(MediaStore.Images.Thumbnails.DATA));  
   } finally {  
     myCursor.close();  
  }  
  // Create new Cursor to obtain the file Path for the large  
  // image  
  String[] largeFileProjection = {  
         MediaStore.Images.ImageColumns._ID,  
   MediaStore.Images.ImageColumns.DATA };  
  String largeFileSort = MediaStore.Images.ImageColumns._ID  
     + " DESC";  
  myCursor = this.managedQuery(  
   MediaStore.Images.Media.EXTERNAL_CONTENT_URI,  
   largeFileProjection, null, null, largeFileSort);  
   String largeImagePath = "";  
  try {  
    myCursor.moveToFirst();  
       // This will actually give yo uthe file path location of  
    // the image.  
    largeImagePath = myCursor  
   .getString(myCursor  
  .getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATA));  
  } finally {  
  myCursor.close();  
  }  
  // These are the two URI's you'll be interested in. They  
  // give you a handle to the actual images  
  Uri uriLargeImage = Uri.withAppendedPath(  
  MediaStore.Images.Media.EXTERNAL_CONTENT_URI,  
  String.valueOf(imageId));  
  Uri uriThumbnailImage = Uri.withAppendedPath(  
  MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,  
   String.valueOf(thumbnailImageId));  
  picUri = uriLargeImage;  
  performCrop();  
  }  
  }  
 }  

Hope this will helps Some one.
Enjoy Coding :)

 

Copyright @ 2013 Android Developers Blog.