Whenever I try to set an image i get an OOM error.
My EditProfileFragment.java
package org.text.me.actionBar.edit.fragments;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.quickblox.core.QBCallback;
import com.quickblox.core.result.Result;
import org.text.me.R;
import org.text.me.actionBar.definitions.Queries;
import org.text.me.actionBar.edit.activity.ChangeNameActivity;
import org.text.me.actionBar.edit.activity.ChangePasswordActivity;
import org.text.me.actionBar.gallery.activity.GalleryActivity;
import org.text.me.actionBar.holder.DataHolder;
import org.text.me.actionBar.utils.bitmap.BitmapUtility;
import static android.widget.ImageView.ScaleType.FIT_CENTER;
import static org.text.me.actionBar.definitions.Constants.TAG;
import static org.text.me.actionBar.preferences.SharedConstants.PROFILE_PICTURE_PATH;
import static org.text.me.actionBar.preferences.SharedConstants.SIGN_IN_USER_FULL_NAME;
import static org.text.me.actionBar.preferences.SharedPrefs.getStringPrefs;
public class EditProfileFragment extends Fragment implements View.OnClickListener, QBCallback {
private View editProfileView;
private ImageView ivProfilePicture;
private TextView tvFullName;
private ImageButton ibPassword;
private ImageButton ibName;
private ProgressDialog progressDialog;
private String fullName = null;
private Bitmap DEFAULT_PROFILE_PICTURE = null;
private Bitmap PROFILE_PICTURE = null;
private int GALLERY = 1;
private static int DEFAULT_WIDTH = 300;
private static int DEFAULT_HEIGHT = 250;
private static final int DEFAULT_COMPRESS_QUALITY = 100;
private static final Bitmap.CompressFormat DEFAULT_COMPRESS_FORMAT = Bitmap.CompressFormat.PNG;
private static final boolean fileIsPublic = false;
private static final String FOLDER_NAME = "Text Me";
private static final String SUB_FOLDER_NAME = "Profile Pictures";
private static String FILE_NAME = null;
public static EditProfileFragment getInstance () {
return new EditProfileFragment ();
}
@Override
public void onCreate (Bundle savedInstanceState) {
super.onCreate ( savedInstanceState );
setHasOptionsMenu ( false );
}
@Override
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
editProfileView = inflater.inflate ( R.layout.fragment_edit_profile, container, false );
setupUi ();
setupProgressDialog ();
return editProfileView;
}
private void setupUi () {
tvFullName = (TextView) editProfileView.findViewById ( R.id.tvName );
ivProfilePicture = (ImageView) editProfileView.findViewById ( R.id.ivEditProfilePicture );
ibPassword = (ImageButton) editProfileView.findViewById ( R.id.ibPassword );
ibName = (ImageButton) editProfileView.findViewById ( R.id.ibName );
tvFullName.setText ( getStringPrefs ( getActivity (), SIGN_IN_USER_FULL_NAME ) );
if ( getStringPrefs ( getActivity (), PROFILE_PICTURE_PATH ).equals ( null ) || getStringPrefs ( getActivity
(),
PROFILE_PICTURE_PATH ).equals ( "path" ) )
setupDefaultProfilePicture ();
else
setupProfilePicture ();
ibName.setOnClickListener ( this );
ibPassword.setOnClickListener ( this );
ivProfilePicture.setOnClickListener ( this );
}
private void setupProgressDialog () {
progressDialog = new ProgressDialog ( this.getActivity () );
progressDialog.setMessage ( getResources ().getString ( R.string.loading ) );
progressDialog.setCancelable ( false );
}
private void setupDefaultProfilePicture () {
DEFAULT_PROFILE_PICTURE = BitmapUtility.decodeSampledBitmapFromResource (
getResources (),
R.drawable.action_people,
DEFAULT_WIDTH,
DEFAULT_HEIGHT );
ivProfilePicture.setScaleType ( FIT_CENTER );
ivProfilePicture.setImageBitmap ( DEFAULT_PROFILE_PICTURE );
}
private void setupProfilePicture () {
if ( PROFILE_PICTURE != null ) PROFILE_PICTURE.recycle ();
BitmapFactory.Options options = new BitmapFactory.Options ();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inInputShareable = true;
options.inPurgeable = true;
PROFILE_PICTURE = BitmapFactory.decodeFile ( getStringPrefs ( getActivity (), PROFILE_PICTURE_PATH ),
options );
Log.w ( TAG, PROFILE_PICTURE.toString () );
ivProfilePicture.setImageBitmap ( PROFILE_PICTURE );
}
@Override
public void onClick (View v) {
switch ( v.getId () ) {
case R.id.ibPassword:
startActivity ( new Intent ( this.getActivity (), ChangePasswordActivity.class ) );
break;
case R.id.ibName:
startActivity ( new Intent ( this.getActivity (), ChangeNameActivity.class ) );
break;
case R.id.ivEditProfilePicture:
Intent intent = new Intent ( getActivity (), GalleryActivity.class );
startActivity ( intent );
break;
}
}
@Override
public void onComplete (Result result) {
}
@Override
public void onComplete (Result result, Object query) {
Queries queryType = (Queries) query;
if ( result.isSuccess () ) {
switch ( queryType ) {
case QUERY_UPDATE_USER_INFO:
DataHolder.getDataHolder ().getSignInUser ().setFullName ( fullName );
progressDialog.dismiss ();
Toast.makeText ( this.getActivity (), getResources ().getString ( R.string
.action_edit_successful ),
Toast.LENGTH_SHORT ).show ();
break;
}
} else {
progressDialog.hide ();
Toast.makeText ( this.getActivity (), result.getErrors ().get ( 0 ).toString (),
Toast.LENGTH_SHORT ).show ();
Log.e ( TAG, result.getErrors ().toString () );
}
}
}
My GalleryActivity.java
package org.text.me.actionBar.gallery.activity;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.util.TypedValue;
import android.widget.GridView;
import org.text.me.R;
import org.text.me.actionBar.gallery.adapter.GalleryAdapter;
import org.text.me.actionBar.gallery.helper.GalleryUtils;
import java.util.ArrayList;
import static org.text.me.actionBar.gallery.helper.GalleryConstants.GRID_PADDING;
import static org.text.me.actionBar.gallery.helper.GalleryConstants.NUM_OF_COLS;
public class GalleryActivity extends ActionBarActivity {
private ActionBar actionBar;
private ArrayList<String> imagePaths = new ArrayList<String> ();
private GalleryAdapter mAdapter;
private GridView gvGallery;
private int colWidth;
private GalleryUtils galleryUtils;
@Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate ( savedInstanceState );
setContentView ( R.layout.activity_grid_view_gallery );
setupActionBar ();
setupGallery ();
}
private void setupActionBar () {
actionBar = getSupportActionBar ();
actionBar.setDisplayHomeAsUpEnabled ( true );
actionBar.setTitle ( "Gallery" );
}
private void setupGallery () {
gvGallery = (GridView) findViewById ( R.id.gvGallery );
galleryUtils = new GalleryUtils ( this );
initialiseGridView ();
imagePaths = galleryUtils.getFilePaths ();
mAdapter = new GalleryAdapter ( GalleryActivity.this, imagePaths, colWidth );
gvGallery.setAdapter ( mAdapter );
}
private void initialiseGridView () {
Resources resources = getResources ();
float padding = TypedValue.applyDimension ( TypedValue.COMPLEX_UNIT_DIP, GRID_PADDING,
resources.getDisplayMetrics () );
colWidth = (int) ( ( galleryUtils.getScreenWidth () - ( ( NUM_OF_COLS + 1 ) * padding ) ) / NUM_OF_COLS );
gvGallery.setNumColumns ( NUM_OF_COLS );
gvGallery.setColumnWidth ( colWidth );
gvGallery.setStretchMode ( GridView.NO_STRETCH );
gvGallery.setPadding ( (int) padding, (int) padding, (int) padding, (int) padding );
gvGallery.setHorizontalSpacing ( (int) padding );
gvGallery.setVerticalSpacing ( (int) padding );
}
}
My GalleryAdapter.class
package org.text.me.actionBar.gallery.adapter;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import org.text.me.actionBar.gallery.activity.FullScreenImageActivity;
import org.text.me.actionBar.utils.bitmap.BitmapUtility;
import java.util.ArrayList;
import static org.text.me.actionBar.definitions.Constants.IMAGE_PATH;
import static org.text.me.actionBar.preferences.SharedConstants.PROFILE_PICTURE_PATH;
import static org.text.me.actionBar.preferences.SharedPrefs.setStringPrefs;
public class GalleryAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<String> filePaths = new ArrayList<String> ();
private int imageWidth;
public GalleryAdapter (Activity activity, ArrayList<String> filePaths, int imageWidth) {
this.activity = activity;
this.filePaths = filePaths;
this.imageWidth = imageWidth;
}
@Override
public int getCount () {
return this.filePaths.size ();
}
@Override
public Object getItem (int position) {
return this.filePaths.get ( position );
}
@Override
public long getItemId (int position) {
return position;
}
@Override
public View getView (int position, View convertView, ViewGroup parent) {
ImageView imageView;
if ( convertView == null ) imageView = new ImageView ( activity );
else imageView = (ImageView) convertView;
Bitmap image = BitmapUtility.decodeFileForGallery ( filePaths.get ( position ), imageWidth,
imageWidth );
imageView.setScaleType ( ImageView.ScaleType.CENTER_CROP );
imageView.setLayoutParams ( new GridView.LayoutParams ( imageWidth, imageWidth ) );
imageView.setImageBitmap ( image );
imageView.setOnClickListener ( new onImageClickListener ( position ) );
return imageView;
}
class onImageClickListener implements View.OnClickListener {
int position;
public onImageClickListener (int position) {
this.position = position;
}
@Override
public void onClick (View v) {
Intent intent = new Intent ( activity, FullScreenImageActivity.class );
intent.putExtra ( IMAGE_PATH, filePaths.get ( position ) );
setStringPrefs ( activity.getApplicationContext (), PROFILE_PICTURE_PATH,
filePaths.get ( position ) );
activity.startActivity ( intent );
}
}
}
My FullScreenImageActivity.class
package org.text.me.actionBar.gallery.activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import org.text.me.R;
import org.text.me.actionBar.gallery.helper.GalleryUtils;
import org.text.me.actionBar.main.activity.MainActionBarActivity;
import static org.text.me.actionBar.definitions.Constants.IMAGE_PATH;
public class FullScreenImageActivity extends ActionBarActivity implements View.OnClickListener {
private ActionBar actionBar;
private GalleryUtils galleryUtils;
private String imagePosition = null;
private ImageView ivFullScreen;
private Button bApplyImage;
private Bitmap bitmap;
@Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate ( savedInstanceState );
setContentView ( R.layout.activity_full_screen_image );
setupActionBar ();
setupUi ();
setupImage ();
}
private void setupActionBar () {
actionBar = getSupportActionBar ();
actionBar.setDisplayHomeAsUpEnabled ( true );
}
private void setupUi () {
ivFullScreen = (ImageView) findViewById ( R.id.ivFullScreen );
bApplyImage = (Button) findViewById ( R.id.bApplyImage );
bApplyImage.setOnClickListener ( this );
}
private void setupImage () {
galleryUtils = new GalleryUtils ( this );
Intent intent = getIntent ();
imagePosition = intent.getStringExtra ( IMAGE_PATH );
BitmapFactory.Options options = new BitmapFactory.Options ();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inInputShareable = true;
options.inPurgeable = true;
bitmap = BitmapFactory.decodeFile ( imagePosition, options );
ivFullScreen.setImageBitmap ( bitmap );
}
@Override
public void onClick (View v) {
switch ( v.getId () ) {
case R.id.bApplyImage:
startActivity ( new Intent ( FullScreenImageActivity.this, MainActionBarActivity.class ) );
finish ();
break;
}
}
}
When I navigate from FullScreenImageActivity to the EditProfileFragment class I get the following error:
01-23 03:58:59.607 9655-9655/org.text.me E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:470)
at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:284)
at org.text.me.actionBar.gallery.activity.FullScreenImageActivity.setupImage(FullScreenImageActivity.java:58)
at org.text.me.actionBar.gallery.activity.FullScreenImageActivity.onCreate(FullScreenImageActivity.java:34)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1626)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1678)
at android.app.ActivityThread.access$1500(ActivityThread.java:118)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:932)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3698)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:875)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:633)
at dalvik.system.NativeStart.main(Native Method)
But when I reopen my app, it sets the image. How can I avoid OOM while setting up the image the first time? Please help me with the code asap.
May be the error is occuring because I'm trying the set the image in MainActionBarActivity.java that was opened in the FullScreenImageActivity.java class. And I think when the FullScreenImageActivity.java class closes, the VM heap is not recycled or something and the app crashes while loading the image in the MainActionbarActivity.java class.
Here is my code for MainActionBarActivity.java class:
package org.text.me.actionBar.edit.fragments;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.quickblox.core.QBCallback;
import com.quickblox.core.QBCallbackImpl;
import com.quickblox.core.result.Result;
import com.quickblox.module.content.QBContent;
import com.quickblox.module.content.model.QBFile;
import com.quickblox.module.content.result.QBFileUploadTaskResult;
import com.quickblox.module.users.QBUsers;
import com.quickblox.module.users.model.QBUser;
import org.text.me.R;
import org.text.me.actionBar.definitions.Queries;
import org.text.me.actionBar.edit.activity.ChangeNameActivity;
import org.text.me.actionBar.edit.activity.ChangePasswordActivity;
import org.text.me.actionBar.gallery.activity.GalleryActivity;
import org.text.me.actionBar.holder.DataHolder;
import org.text.me.actionBar.utils.bitmap.BitmapUtility;
import org.text.me.actionBar.utils.external_storage.ExternalStorageUtils;
import java.io.File;
import static android.widget.ImageView.ScaleType.FIT_CENTER;
import static org.text.me.actionBar.definitions.Constants.TAG;
import static org.text.me.actionBar.preferences.SharedConstants.*;
import static org.text.me.actionBar.preferences.SharedPrefs.*;
public class EditProfileFragment extends Fragment implements View.OnClickListener, QBCallback {
private View editProfileView;
private ImageView ivProfilePicture;
private TextView tvFullName;
private ImageButton ibPassword;
private ImageButton ibName;
private ProgressDialog progressDialog;
private String fullName = null;
private Bitmap DEFAULT_PROFILE_PICTURE = null;
private Bitmap PROFILE_PICTURE = null;
private static int DEFAULT_WIDTH = 300;
private static int DEFAULT_HEIGHT = 250;
private static final int DEFAULT_COMPRESS_QUALITY = 100;
private static final Bitmap.CompressFormat DEFAULT_COMPRESS_FORMAT = Bitmap.CompressFormat.PNG;
private static final boolean fileIsPublic = false;
public static EditProfileFragment getInstance () {
return new EditProfileFragment ();
}
@Override
public void onCreate (Bundle savedInstanceState) {
super.onCreate ( savedInstanceState );
setHasOptionsMenu ( false );
}
@Override
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
editProfileView = inflater.inflate ( R.layout.fragment_edit_profile, container, false );
setupUi ();
setupProgressDialog ();
return editProfileView;
}
private void setupUi () {
tvFullName = (TextView) editProfileView.findViewById ( R.id.tvName );
ivProfilePicture = (ImageView) editProfileView.findViewById ( R.id.ivEditProfilePicture );
ibPassword = (ImageButton) editProfileView.findViewById ( R.id.ibPassword );
ibName = (ImageButton) editProfileView.findViewById ( R.id.ibName );
tvFullName.setText ( getStringPrefs ( getActivity (), SIGN_IN_USER_FULL_NAME ) );
if ( getStringPrefs ( getActivity (), PROFILE_PICTURE_PATH ).equals ( null ) )
setupDefaultProfilePicture ();
else
setupProfilePicture ();
ibName.setOnClickListener ( this );
ibPassword.setOnClickListener ( this );
ivProfilePicture.setOnClickListener ( this );
}
private void setupProgressDialog () {
progressDialog = new ProgressDialog ( this.getActivity () );
progressDialog.setMessage ( getResources ().getString ( R.string.loading ) );
progressDialog.setCancelable ( false );
}
private void setupDefaultProfilePicture () {
DEFAULT_PROFILE_PICTURE = BitmapUtility.decodeSampledBitmapFromResource (
getResources (),
R.drawable.action_people,
DEFAULT_WIDTH,
DEFAULT_HEIGHT );
ivProfilePicture.setScaleType ( FIT_CENTER );
ivProfilePicture.setImageBitmap ( DEFAULT_PROFILE_PICTURE );
}
private void setupProfilePicture () {
if ( PROFILE_PICTURE != null ) PROFILE_PICTURE.recycle ();
BitmapFactory.Options options = new BitmapFactory.Options ();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inInputShareable = true;
options.inPurgeable = true;
PROFILE_PICTURE = BitmapFactory.decodeFile ( getStringPrefs ( getActivity (), PROFILE_PICTURE_PATH ),
options );
ivProfilePicture.setImageBitmap ( PROFILE_PICTURE );
if ( !getBooleanPrefs ( getActivity (), IS_PROFILE_UPLOADED ) && !getStringPrefs ( getActivity (),
PROFILE_PICTURE_PATH )
.equals ( null ) ) {
File profilePicture = ExternalStorageUtils.saveBitmapToFile ( PROFILE_PICTURE, DEFAULT_COMPRESS_FORMAT,
DEFAULT_COMPRESS_QUALITY,
String.valueOf ( getIntPrefs ( getActivity
(),
SIGN_IN_USER_ID ) ) );
QBContent.uploadFileTask ( profilePicture, fileIsPublic, new QBCallbackImpl () {
@Override
public void onComplete (Result result) {
if ( result.isSuccess () ) {
//Get the uploaded file
QBFileUploadTaskResult taskResult = (QBFileUploadTaskResult) result;
QBFile file = taskResult.getFile ();
int uploadedFileId = file.getId ();
//Connect image to user
QBUser user = new QBUser ();
user.setId ( getIntPrefs ( getActivity (), SIGN_IN_USER_ID ) );
user.setFileId ( uploadedFileId );
QBUsers.updateUser ( user, new QBCallbackImpl () {
@Override
public void onComplete (Result result) {
if ( result.isSuccess () ) {
Toast.makeText ( getActivity (), getResources ().getString ( R.string
.action_edit_successful ), Toast.LENGTH_SHORT ).show ();
setBooleanPrefs ( getActivity (), IS_PROFILE_UPLOADED, true );
} else {
Toast.makeText ( getActivity (), result.getErrors ().get ( 0 ).toString (),
Toast.LENGTH_SHORT ).show ();
Log.e ( TAG, result.getErrors ().toString () );
}
}
} );
} else {
Toast.makeText ( getActivity (), result.getErrors ().get ( 0 ).toString (),
Toast.LENGTH_SHORT ).show ();
Log.e ( TAG, result.getErrors ().toString () );
}
}
} );
}
}
@Override
public void onClick (View v) {
switch ( v.getId () ) {
case R.id.ibPassword:
startActivity ( new Intent ( this.getActivity (), ChangePasswordActivity.class ) );
break;
case R.id.ibName:
startActivity ( new Intent ( this.getActivity (), ChangeNameActivity.class ) );
break;
case R.id.ivEditProfilePicture:
Intent intent = new Intent ( getActivity (), GalleryActivity.class );
startActivity ( intent );
break;
}
}
@Override
public void onComplete (Result result) {
}
@Override
public void onComplete (Result result, Object query) {
Queries queryType = (Queries) query;
if ( result.isSuccess () ) {
switch ( queryType ) {
case QUERY_UPDATE_USER_INFO:
DataHolder.getDataHolder ().getSignInUser ().setFullName ( fullName );
progressDialog.dismiss ();
Toast.makeText ( this.getActivity (), getResources ().getString ( R.string
.action_edit_successful ),
Toast.LENGTH_SHORT ).show ();
break;
}
} else {
progressDialog.hide ();
Toast.makeText ( this.getActivity (), result.getErrors ().get ( 0 ).toString (),
Toast.LENGTH_SHORT ).show ();
Log.e ( TAG, result.getErrors ().toString () );
}
}
}