0

I have a ImageButton, when I click it it gives me an AlertDialog to add an image to my Imagebutton. When I add an image, the app becomes very slow and laggy. If I want to reselect an image then the app crashes. Can someone help me out with this?

Code:

public class MainActivity extends Activity {

private final int SELECT_FILE = 1;
private final int REQUEST_CAMERA = 0;
private ImageButton btnImg;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    btnImg = (ImageButton) findViewById(R.id.btnAddThumbnail);

    btnImg.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            selectImage();
        }
    });
}

private void selectImage() {
    final CharSequence[] items = { "Take Photo", "Choose from gallery",
            "Cancel" };

    AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
    builder.setTitle("Add Photo!");

    builder.setItems(items, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int item) {
            if (items[item].equals("Take Photo")) {
                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                File f = new File(android.os.Environment.getExternalStorageDirectory(), "temp.jpg");
                intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
                startActivityForResult(intent, REQUEST_CAMERA);
            }

            else if (items[item].equals("Choose from gallery")) {
                Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                intent.setType("image/*");
                startActivityForResult(Intent.createChooser(intent, "Select File"), SELECT_FILE);
            }

            else if (items[item].equals("Cancel")) {
                dialog.dismiss();
            }
        }
    });
    builder.show();
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK) {
        if (requestCode == REQUEST_CAMERA) {
            File f = new File(Environment.getExternalStorageDirectory().toString());
            for (File temp : f.listFiles()) {
                if (temp.getName().equals("temp.jpg")) {
                    f = temp;
                    break;
                }
            }
            try {
                Bitmap bm;
                BitmapFactory.Options btmapOptions = new BitmapFactory.Options();

                bm = BitmapFactory.decodeFile(f.getAbsolutePath(),btmapOptions);

                // bm = Bitmap.createScaledBitmap(bm, 70, 70, true);
                btnImg.setImageBitmap(bm);
                btnImg.setScaleType(ScaleType.CENTER_INSIDE);

                String path = android.os.Environment.getExternalStorageDirectory() + File.separator + "Phoenix" + File.separator + "default";
                f.delete();
                OutputStream fOut = null;
                File file = new File(path, String.valueOf(System.currentTimeMillis()) + ".jpg");
                try {
                    fOut = new FileOutputStream(file);
                    bm.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
                    fOut.flush();
                    fOut.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (requestCode == SELECT_FILE) {
            Uri selectedImageUri = data.getData();

            String tempPath = getPath(selectedImageUri, MainActivity.this);
            Bitmap bm;
            BitmapFactory.Options btmapOptions = new BitmapFactory.Options();
            bm = BitmapFactory.decodeFile(tempPath, btmapOptions);
            btnImg.setImageBitmap(bm);
            btnImg.setScaleType(ScaleType.CENTER_INSIDE);
        }
    }
}

public String getPath(Uri uri, Activity activity) {
    String[] projection = { MediaColumns.DATA };
    Cursor cursor = activity.managedQuery(uri, projection, null, null, null);
    int column_index = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
}

}

Error after the crash:

05-04 20:45:02.890: W/dalvikvm(22576): threadid=1: thread exiting with uncaught exception (group=0x41d9f2a0) 05-04 20:45:02.895: E/AndroidRuntime(22576): FATAL EXCEPTION: main 05-04 20:45:02.895: E/AndroidRuntime(22576): java.lang.OutOfMemoryError 05-04 20:45:02.895: E/AndroidRuntime(22576): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) 05-04 20:45:02.895: E/AndroidRuntime(22576): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:650) 05-04 20:45:02.895: E/AndroidRuntime(22576): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:389) 05-04 20:45:02.895: E/AndroidRuntime(22576): at com.example.spui.MainActivity.onActivityResult(MainActivity.java:95) 05-04 20:45:02.895: E/AndroidRuntime(22576): at android.app.Activity.dispatchActivityResult(Activity.java:5390) 05-04 20:45:02.895: E/AndroidRuntime(22576): at android.app.ActivityThread.deliverResults(ActivityThread.java:3178) 05-04 20:45:02.895: E/AndroidRuntime(22576): at android.app.ActivityThread.handleSendResult(ActivityThread.java:3225) 05-04 20:45:02.895: E/AndroidRuntime(22576): at android.app.ActivityThread.access$1100(ActivityThread.java:140) 05-04 20:45:02.895: E/AndroidRuntime(22576): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1275) 05-04 20:45:02.895: E/AndroidRuntime(22576): at android.os.Handler.dispatchMessage(Handler.java:99) 05-04 20:45:02.895: E/AndroidRuntime(22576): at android.os.Looper.loop(Looper.java:137) 05-04 20:45:02.895: E/AndroidRuntime(22576): at android.app.ActivityThread.main(ActivityThread.java:4898) 05-04 20:45:02.895: E/AndroidRuntime(22576): at java.lang.reflect.Method.invokeNative(Native Method) 05-04 20:45:02.895: E/AndroidRuntime(22576): at java.lang.reflect.Method.invoke(Method.java:511) 05-04 20:45:02.895: E/AndroidRuntime(22576): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006) 05-04 20:45:02.895: E/AndroidRuntime(22576): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773) 05-04 20:45:02.895: E/AndroidRuntime(22576): at dalvik.system.NativeStart.main(Native Method)

mXX
  • 3,595
  • 12
  • 44
  • 61

1 Answers1

3

The chances are the image is too large and you are running out of memory. Some devices record images at quite large image sizes with large dimensions, which in turn causes you to run into memory issues. The same thing happens when dealing with images downloaded from the web.

I would scale the Bitmap down using the API method Bitmap.createScaledBitmap to scale the Bitmap down before you set it.

There is a good SO post on this here Android: Resize a large bitmap file to scaled output file

I would also like to add that thanks to a great library AndroidQuery, you could make your life so much simpler! I added some code below to show how it works with your snippet. There is a full blog post here http://blog.androidquery.com/2011/05/down-sample-images-to-avoid-out-of.html

File file = new File(Environment.getExternalStorageDirectory().toString());       
//load image from file, down sample to target width of 300 pixels and set it to the Imageview
aq.id(R.id.avatar).image(file, 300);
Community
  • 1
  • 1
Graham Smith
  • 25,627
  • 10
  • 46
  • 69