0

i have make a android app for capture image and add a title on image. the app working properly when i use from camera of mobile, but when i use back camera the application has been crashed with error java.lang.outofmemory my code is here

public class MainActivity extends AppCompatActivity {

private ImageView imageResult;
Bitmap processedBitmap;
String photoName;
Uri source1;
private String pictureImagePath = "";
File imgFile;

/**
 * ATTENTION: This was auto-generated to implement the App Indexing API.
 * See https://g.co/AppIndexing/AndroidStudio for more information.
 */
private GoogleApiClient client;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    imageResult = (ImageView) this.findViewById(R.id.imageView1);
    Button takePicture = (Button) this.findViewById(R.id.btnTakePic);
    Button renamePicture = (Button) this.findViewById(R.id.btnRename);
    Button savePicture = (Button) this.findViewById(R.id.btnSave);
    final File myDir=new File("/sdcard/saved_images");
    myDir.mkdirs();
    File myDirTemp = new File("/sdcard/saved_images/Temp");
    myDirTemp.mkdirs();

    takePicture.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
            String imageFileName = timeStamp + ".jpg";
            File storageDir = new File("/sdcard/saved_images/Temp");
            pictureImagePath = storageDir.getAbsolutePath() + "/" + imageFileName;
            File file = new File(pictureImagePath);
            Uri outputFileUri = Uri.fromFile(file);
            Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
            startActivityForResult(cameraIntent, 1);


        }
    });
    renamePicture.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            if(source1!=null){
                AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
                final EditText input = new EditText(MainActivity.this);
                input.setInputType(InputType.TYPE_CLASS_NUMBER);
                LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT,
                        LinearLayout.LayoutParams.MATCH_PARENT);
                input.setLayoutParams(lp);
                dialog.setView(input);
                dialog.setCancelable(false);
                dialog.setTitle("Rename Photo");
                dialog.setMessage("Enter Photo Name");
                dialog.setPositiveButton("Save", null);
                dialog.setNegativeButton("cancel", null);

                final AlertDialog alertdialog = dialog.create();
                alertdialog.setOnShowListener(new DialogInterface.OnShowListener() {

                    @Override
                    public void onShow(DialogInterface dialog) {
                        // TODO Auto-generated method stub
                        Button b = alertdialog.getButton(AlertDialog.BUTTON_POSITIVE);
                        Button c = alertdialog.getButton(AlertDialog.BUTTON_NEGATIVE);

                        b.setOnClickListener(new View.OnClickListener() {

                            @Override
                            public void onClick(View v) {
                                // TODO Auto-generated method stub
                                String SpinName = input.getText().toString();
                                if(SpinName.length()==0){
                                    Toast.makeText(MainActivity.this, "Enter Photo Name", Toast.LENGTH_LONG).show();
                                }else{
                                    photoName = input.getText().toString();
                                    processedBitmap = ProcessingBitmap();
                                    if(processedBitmap != null){
                                        imageResult.setImageBitmap(processedBitmap);
                                     }
                                }
                                alertdialog.dismiss();

                            }
                        });
                        c.setOnClickListener(new View.OnClickListener() {

                            @Override
                            public void onClick(View v) {
                                // TODO Auto-generated method stub
                                alertdialog.dismiss();
                            }
                        });
                    }
                });alertdialog.show();}
            else{
                Toast.makeText(MainActivity.this, "Take Image First", Toast.LENGTH_LONG).show();
            }
        }
    });


    savePicture.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(source1!=null){
            String fname = photoName +".jpg";
            File file = new File (myDir, fname);
            if (file.exists ()) file.delete ();
            try {
                FileOutputStream out = new FileOutputStream(file);
                processedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
                out.flush();
                out.close();

                AlertDialog.Builder aldialog = (new AlertDialog.Builder(MainActivity.this));
                aldialog.setTitle("saved");
                aldialog.setMessage("Image Saved Successfully");
                aldialog.setPositiveButton("OK", new DialogInterface.OnClickListener(){
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        imageResult.setImageResource(0);
                        source1 = null;
                    }
                });aldialog.show();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        else{
            Toast.makeText(MainActivity.this, "Take Image First", Toast.LENGTH_LONG).show();
        }
        }
    });
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == 1) {
        imgFile = new  File(pictureImagePath);
        if(imgFile.exists()){
            source1 = Uri.fromFile(imgFile);
            Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
            imageResult.setImageBitmap(myBitmap);


        }
    }

}

private Bitmap ProcessingBitmap() {
    Bitmap bm1 =  null;
    Bitmap newBitmap = null;
    try{
        bm1 = BitmapFactory.decodeStream(getContentResolver().openInputStream(Uri.fromFile(imgFile)));

        Bitmap.Config config = bm1.getConfig();
        if(config==null){
            config = Bitmap.Config.ARGB_8888;
        }
        newBitmap = Bitmap.createBitmap(bm1.getWidth(), bm1.getHeight(),config);
        Canvas newCanvas = new Canvas(newBitmap);
        newCanvas.drawBitmap(bm1,0,0,null);

        if(photoName!= null){
            Paint paintText =  new Paint(Paint.ANTI_ALIAS_FLAG);
            paintText.setColor(Color.WHITE);
            paintText.setTextSize(120);
            paintText.setShadowLayer(10f,10f,10f, Color.BLACK);
            Rect rectText = new Rect();
            paintText.getTextBounds(photoName, 0, photoName.length(), rectText);
            newCanvas.drawText(photoName, 0, bm1.getHeight()- rectText.height(), paintText);
            //newCanvas.drawText(photoName,bm1.getWidth()-rectText.left,bm1.getWidth()-rectText.top, paintText);


            Toast.makeText(MainActivity.this, "done", Toast.LENGTH_LONG).show();}
        else{
            Toast.makeText(MainActivity.this, "undone", Toast.LENGTH_LONG).show();}
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    return newBitmap;
}
}

Please tell some suggestion. exception log here

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.surveyphotoapp, PID: 24765 java.lang.OutOfMemoryError at android.graphics.Bitmap.nativeCreate(Native Method) at android.graphics.Bitmap.createBitmap(Bitmap.java:822) at android.graphics.Bitmap.createBitmap(Bitmap.java:799) at android.graphics.Bitmap.createBitmap(Bitmap.java:766) at com.surveyphotoapp.MainActivity.ProcessingBitmap(MainActivity.java:214) at com.surveyphotoapp.MainActivity.access$100(MainActivity.java:44) at com.surveyphotoapp.MainActivity$2$1$1.onClick(MainActivity.java:127) at android.view.View.performClick(View.java:4444) at android.view.View$PerformClick.run(View.java:18440) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5052) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:796) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:612) at dalvik.system.NativeStart.main(Native Method)

1 Answers1

0

The back camera has higher image resolution than the front camera. Therefore, direct creation of Bitmap from the byte stream may fail with OutOfMemoryError, especially on devices with small VM heap sizes.

To avoid the error on small VM heap sizes, you can catch the OutOfMemoryError while decoding the bitmap, and if it happens, reduce the image size and try again.

public static Bitmap getBitmapFromStream(Context context, InputStream istr) {
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    final int REQUIRED_SIZE = display.getWidth();

    istr.mark(Integer.MAX_VALUE);
    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true; 
    BitmapFactory.decodeStream(istr, null, o);
    int width_tmp = o.outWidth, height_tmp = o.outHeight;
    int scale = 1;
    while (true){
        if (width_tmp / 2 < REQUIRED_SIZE)
            break;
        width_tmp /= 2;
        height_tmp /= 2;
        scale *= 2;
    }

    while (true) {
        try {
            istr.reset();
            o = new BitmapFactory.Options();
            o.inSampleSize = scale;
            return BitmapFactory.decodeStream(istr, null, o);
        } catch (OutOfMemoryError ex) {
            scale *= 2;
            if (scale >= 32) {
                // Failed
                return null;
            }
        } catch (IOException ex) {
            ex.printStackTrace();
            return null;
        }
    }
}
vmayorow
  • 630
  • 5
  • 15
  • the error comes when i trying to add text over image click by rename button – svicc computers Nov 20 '16 at 04:57
  • It seems that the app has enough memory to keep one bitmap (when you create bm1), but there's not enough memory to keep two bitmaps of same size at once (the second bitmap creation fails with OutOfMemoryError). Consider to reduce the size of the first bitmap before creating a copy of it. Also, try to follow this suggestion: [link](http://stackoverflow.com/questions/14232440/how-to-increase-android-virtual-device-max-heap-size) – vmayorow Nov 20 '16 at 07:23
  • dear, is any way to compress both bitmap – svicc computers Nov 20 '16 at 09:36
  • You can reduce the bitmap size by using the attribute BitmapFactory.Options.inSampleSize while decoding the stream, see my code above. – vmayorow Nov 20 '16 at 10:16