0

i really stuck when load an image from gallery to my imageview. i already followed this tutorial http://developer.android.com/training/displaying-bitmaps/manage-memory.html and also this one Strange out of memory issue while loading an image to a Bitmap object. when i used samsung tab it works fine but when i deploy it to galaxy note and other device, my app crash and got error out of memory. here is my code

package com.example.cobaandroid;



import java.io.InputStream;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException; 
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {

final int PICTURE_GALLERY = 0;
final int CAMERA_CAPTURE = 1;
final int PIC_CROP = 2;
public static final int MEDIA_IMAGE = 3;
private Uri picUri;
@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    tampilkanUserManual();
    Button ambilGambar = (Button)findViewById(R.id.ambil_gambar);
    Button gallery = (Button) findViewById(R.id.ambilGallery);
    ambilGambar.setOnClickListener(this);
    gallery.setOnClickListener(this);
    if(!supportCamera())
    {
        Toast.makeText(getApplicationContext(), "Maaf device anda tidak mendukung penggunaan kamera", Toast.LENGTH_LONG).show();
        finish();
    }
    Button exit = (Button)findViewById(R.id.exit);
    exit.setOnClickListener(this);
}

//Cek apakah device memiliki kamera
private Boolean supportCamera()
{
    if(getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA))
    {
        return true;
    }
    else return false;
}

// Button onClick 
public void onClick(View v)
{
    if(v.getId()==R.id.ambil_gambar)
    {
        try
        {
            //Intent untuk menggunakan kamera
            Intent intentAmbil = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(intentAmbil,CAMERA_CAPTURE);
        }
        catch(ActivityNotFoundException activity)
        {
            String errorMessage = "ga support kamera";
            Toast toast = Toast.makeText(this, errorMessage, Toast.LENGTH_SHORT);
            toast.show();
        }
    }
    else if(v.getId()==R.id.ambilGallery)
    {
        try
        {
            //intent untuk ngambil gambar di galeri
            Intent ambilGallery = new Intent(Intent.ACTION_PICK,MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            ambilGallery.setType("image/*");
            startActivityForResult(ambilGallery, PICTURE_GALLERY);
        }
        catch(ActivityNotFoundException activity)
        {
            String errorMessage = "Tidak dapat mengambil gambar dari galeri";
            Toast toast = Toast.makeText(this, errorMessage, Toast.LENGTH_SHORT);
            toast.show();
        }
    }
    else if(v.getId()==R.id.exit)
    {
        try
        {
            Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_HOME);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        }
        catch(ActivityNotFoundException ac)
        {
            Toast.makeText(getApplicationContext(), "Tidak dapat menutup aplikasi", Toast.LENGTH_LONG).show();
        }
    }
}

protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if(resultCode==RESULT_OK)
    {
        if(requestCode==CAMERA_CAPTURE)
        {

            BitmapFactory.Options option = new BitmapFactory.Options();
            //option.inSampleSize = 8;
            option.inJustDecodeBounds = true;
            Bitmap hasilPoto = (Bitmap) data.getExtras().get("data");
            if(hasilPoto==null)
            {
                Toast.makeText(getApplicationContext(), "bitmap null", Toast.LENGTH_LONG).show();
            }
            picUri = data.getData();
            Toast.makeText(getApplicationContext(), picUri.getPath(), Toast.LENGTH_LONG).show();

            Intent cropIntent= new Intent (this, Crop.class);
            cropIntent.putExtra("data", picUri.toString());
            cropIntent.putExtra("gambar", hasilPoto);
            cropIntent.putExtra("kode","kamera");
            startActivity(cropIntent);
        }
        else if(requestCode==PICTURE_GALLERY)
        {
            // Resize gambar dari galeri
            Uri galeriUri = data.getData();
            String[] path = {MediaStore.Images.Media.DATA};
            Cursor cursor = getContentResolver().query(galeriUri,path,null,null,null);
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(path[0]);
            String gambarPath = cursor.getString(columnIndex);
            cursor.close();
            BitmapFactory.Options opt = new BitmapFactory.Options();
            opt.inJustDecodeBounds = true;
            opt.inSampleSize = calculateInSampleSize(opt, 50, 50);

            //Bitmap hasilPoto = BitmapFactory.decodeFile(gambarPath);
            Bitmap hasilPoto = BitmapFactory.decodeFile(gambarPath, opt);
            //hasilPoto = scaleDown(hasilPoto, 100, getApplicationContext());
            Intent cropIntents = new Intent(this,Crop.class);
            cropIntents.putExtra("data", galeriUri.toString());
            cropIntents.putExtra("kode","galeri");
            cropIntents.putExtra("gambar",hasilPoto);
            startActivity(cropIntents);
        }
    }
}

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth,int reqHeight)
{
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;
    if(height > reqHeight || width > reqWidth)
    {
        final int halfHeight = height/2;
        final int halfWidth = width/2;
        while((halfHeight/inSampleSize)>reqHeight && (halfWidth/inSampleSize)>reqWidth)
        {
            inSampleSize*=2;
        }
        long totalPixels = width*height/inSampleSize;
        final long totalReqPixelsCap = reqWidth*reqHeight*2;
        while(totalPixels > totalReqPixelsCap)
        {
            inSampleSize*=2;
            totalPixels/=2;
        }
    }
    return inSampleSize;
}
//fungsi untuk scaling gambar
private Bitmap scaleDown(Bitmap photo, int newHeight,Context contex)
{
    final float densityMultiplier = contex.getResources().getDisplayMetrics().density;
    int h = (int) (newHeight*densityMultiplier);
    int w = (int) (h*photo.getWidth()/(double)photo.getHeight());
    photo = Bitmap.createScaledBitmap(photo, w, h, true);
    return photo;
}

//tampilkan userManual
private void tampilkanUserManual()
{
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    LayoutInflater inflater = this.getLayoutInflater();
    View view = inflater.inflate(R.layout.activity_usermanual, null);
    builder.setView(view);
    builder.setPositiveButton("Ok", null);
    AlertDialog dialog = builder.create();
    dialog.show();
}

} here is the logcat

12-05 14:09:23.238: E/AndroidRuntime(6697): FATAL EXCEPTION: main
12-05 14:09:23.238: E/AndroidRuntime(6697): java.lang.OutOfMemoryError
12-05 14:09:23.238: E/AndroidRuntime(6697):     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
12-05 14:09:23.238: E/AndroidRuntime(6697):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:587)
12-05 14:09:23.238: E/AndroidRuntime(6697):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:389)
12-05 14:09:23.238: E/AndroidRuntime(6697):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:418)
12-05 14:09:23.238: E/AndroidRuntime(6697):     at com.example.cobaandroid.MainActivity.onActivityResult(MainActivity.java:150)
12-05 14:09:23.238: E/AndroidRuntime(6697):     at android.app.Activity.dispatchActivityResult(Activity.java:4654)
12-05 14:09:23.238: E/AndroidRuntime(6697):     at android.app.ActivityThread.deliverResults(ActivityThread.java:2987)
12-05 14:09:23.238: E/AndroidRuntime(6697):     at android.app.ActivityThread.handleSendResult(ActivityThread.java:3034)
12-05 14:09:23.238: E/AndroidRuntime(6697):     at android.app.ActivityThread.access$1100(ActivityThread.java:127)
12-05 14:09:23.238: E/AndroidRuntime(6697):     at  android.app.ActivityThread$H.handleMessage(ActivityThread.java:1188)
12-05 14:09:23.238: E/AndroidRuntime(6697):     at android.os.Handler.dispatchMessage(Handler.java:99)
12-05 14:09:23.238: E/AndroidRuntime(6697):     at android.os.Looper.loop(Looper.java:137)
12-05 14:09:23.238: E/AndroidRuntime(6697):     at android.app.ActivityThread.main(ActivityThread.java:4511)
12-05 14:09:23.238: E/AndroidRuntime(6697):     at java.lang.reflect.Method.invokeNative(Native Method)
12-05 14:09:23.238: E/AndroidRuntime(6697):     at java.lang.reflect.Method.invoke(Method.java:511)
12-05 14:09:23.238: E/AndroidRuntime(6697):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:980)
12-05 14:09:23.238: E/AndroidRuntime(6697):     at  com.android.internal.os.ZygoteInit.main(ZygoteInit.java:747)
12-05 14:09:23.238: E/AndroidRuntime(6697):     at dalvik.system.NativeStart.main(Native Method)

i also have another problem, when i open camera using intent and captured any, my app always crash when i press ok or save button to save the image. Can you all help me ? I really desperate :( Thanks all...

Community
  • 1
  • 1
bohr
  • 631
  • 2
  • 9
  • 29

2 Answers2

0

You need to use BitmapFactory.Options to reduce the size of displayed images, try this method that returns a bitmap that you can display in your imageview.

private Bitmap shrinkmethod(String file, int width, int height) {
    BitmapFactory.Options bitopt = new BitmapFactory.Options();
    bitopt.inJustDecodeBounds = true;
    Bitmap bit = BitmapFactory.decodeFile(file, bitopt);

    int h = (int) Math.ceil(bitopt.outHeight / (float) height);
    int w = (int) Math.ceil(bitopt.outWidth / (float) width);

    if (h > 1 || w > 1) {
        if (h > w) {
            bitopt.inSampleSize = h;

        } else {
            bitopt.inSampleSize = w;
        }
    }
    bitopt.inJustDecodeBounds = false;
    bit = BitmapFactory.decodeFile(file, bitopt);

    return bit;

}

I got that method from somewhere, but i cant quite recall. Anyways, i don't take credit for it.

Hope it helps

Mushroomzier
  • 108
  • 6
0

For what I can see is that you dont seem to call the method that scales down the image in the first if-else-block - that is *if(requestCode==CAMERA_CAPTURE)* Instead I see you have done the following:

//option.inSampleSize = 8;

shouldnt you call the method calculateInSampleSize here?

Then when you are done with scaling down the bitmap you should set the injustdecodebounds to false, that is

 option.inJustDecodeBounds = false;

You could also try to reduce the size of the images by setting the config to RGB565 that is

 opt.inPreferredConfig = Config.RGB_565;
Björn Hallström
  • 3,775
  • 9
  • 39
  • 50