Tuesday, April 2, 2013

Handling OutOfMemory Exception When Sending or Uploading Large Images to the Server From Android Activity

This Post provides the solution for OutOfMemoryException for large image uploades or server requests as Base64 encoded String format.

The code as follows.

1) The image which I am picking from either camera or from gallery .

 Dialog for pick the image.


private void startDialog() {

AlertDialog.Builder myAlertDialog = new AlertDialog.Builder(this);
myAlertDialog.setTitle("Upload Pictures Option");
myAlertDialog.setMessage("How do you want to set your picture?");

myAlertDialog.setPositiveButton("Gallery",
new DialogInterface.OnClickListener() {

public void onClick(DialogInterface arg0, int arg1) {
pictureActionIntent = new Intent(
Intent.ACTION_GET_CONTENT, null);
pictureActionIntent.setType("image/*");
pictureActionIntent.putExtra("return-data", true);
// Intent intent = new Intent(Intent.ACTION_PICK,
// android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(Intent.createChooser(
pictureActionIntent, "Select Picture"),
GALLERY_PICTURE);
}
});

myAlertDialog.setNegativeButton("Camera",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {

pictureActionIntent = new Intent(
android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File f = null;
try {
f = setUpPhotoFile();
mCurrentPhotoPath = f.getAbsolutePath();
pictureActionIntent.putExtra(
MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));

} catch (IOException e) {
e.printStackTrace();
f = null;
mCurrentPhotoPath = null;
}
startActivityForResult(pictureActionIntent,
CAMERA_PICTURE);
}
});
myAlertDialog.show();
}



2)  Next I will set the image to image view in OnActivityresult() method as follows.



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

if (resultCode == RESULT_OK) {

switch (requestCode) {

case GALLERY_PICTURE:

Log.i(TAG, "INSIDE GALLERY PICTURE>>>>>>>>>>>>>>>>>>>>");
if (data != null) {

Uri imageUri = data.getData();

if(bitmap != null && !bitmap.isRecycled()){
attachImage.setImageBitmap(bitmap);
bitmap.isRecycled();
bitmap = null;
}
try {
bitmap = MediaStore.Images.Media.getBitmap(
this.getContentResolver(), imageUri);
attachImage.setImageBitmap(bitmap);
attachImage.setVisibility(View.VISIBLE);
// getImageByteAsString(bitmap);

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

}

break;

case CAMERA_PICTURE:
Log.i(TAG, "INSIDE CAMERAPICTURE>>>>>>>>>>>>>>>>>>>>");
if (mCurrentPhotoPath != null) {
setPic();
// galleryAddPic();

} else {
if (data != null) {
Uri imageUri = data.getData();
if(bitmap != null && !bitmap.isRecycled()){
attachImage.setImageBitmap(null);
bitmap.recycle();
bitmap = null;
}
try {
bitmap = MediaStore.Images.Media.getBitmap(
this.getContentResolver(), imageUri);
attachImage.setImageBitmap(bitmap);
attachImage.setVisibility(View.VISIBLE);
// getImageByteAsString(bMap);

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
break;
}
}
}

3) I will decode the bitmap as follows.


private void setPic() {

/* There isn't enough memory to open up more than a couple camera photos */
/* So pre-scale the target bitmap into which the file is decoded */

/* Get the size of the ImageView */
int targetW = 200;
int targetH = 200;

/* Get the size of the image */
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;

/* Figure out which way needs to be reduced less */
int scaleFactor = 1;
if ((targetW > 0) || (targetH > 0)) {
scaleFactor = Math.min(photoW / targetW, photoH / targetH);
}

/* Set bitmap options to scale the image decode target */
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;

if (bitmap != null && !bitmap.isRecycled()) {
attachImage.setImageBitmap(null);
bitmap.recycle();
bitmap = null;
}

/* Decode the JPEG file into a Bitmap */
bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);

/* Associate the Bitmap to the ImageView */
attachImage.setImageBitmap(bitmap);
attachImage.setVisibility(View.VISIBLE);

// getImageByteAsString(bitmap);
}


4) Scaling the Image to overcome the out of memory exception while converting Base64 encoding format.


call the below method as requst of your image bytes in the form of Base64 encoded string.


private String getImageByteAsString(Bitmap bitmap) {
String bitmapStr = null;
try {

Bitmap bmap = Bitmap.createScaledBitmap(bitmap, 100, 100, true);

ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] b = baos.toByteArray();

// here chance to get Out Of Memory Exception
bitmapStr = Base64.encodeToString(b, Base64.DEFAULT);

baos.close();
baos = null;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

return bitmapStr;
}


the above scaled and recycled bitmap will solves the issue.









5 comments:

  1. Best Article BUY ADDERALL ONLINE Excellent post. I appreciate this site. Stick with it! Because the admin of this web page is working, no doubt very quickly it will be well-known, due to its quality contents.This website was how do you say it? Relevant!! Finally, I’ve found something that helped me.

    ReplyDelete