0

In my application there is a button to "upload a picture": taking a photo from camera or choosing from gallery.

On both options, there are 2 problems:

  1. When clicking again to upload another picture - the application crashes.

  2. On the first "upload", the picture is rotated on the side (90 degrees counterclockwise).

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.app.Fragment;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import entities.Order;

public class SellABookFragment extends Fragment implements View.OnClickListener {

    private ImageView ivBookPicture;
    private EditText etBookName, etBookAuthor, etBookGenre, etBookPublishing, etQuantity, etBookPrice, etBookDetails;
    private Button bUploadPicture, bAddBook;

    public SellABookFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_sell_a_book, container, false);
        ivBookPicture = (ImageView) view.findViewById(R.id.ivBook_Picture);
        etBookName = (EditText) view.findViewById(R.id.etBook_Name);
        etBookAuthor = (EditText) view.findViewById(R.id.etAuthor_Name);
        etBookGenre = (EditText) view.findViewById(R.id.etGenre);
        etBookPublishing = (EditText) view.findViewById(R.id.etPublishing_Year);
        etQuantity = (EditText) view.findViewById(R.id.etBook_Quantity);
        etBookPrice = (EditText) view.findViewById(R.id.etBook_Price);
        etBookDetails = (EditText) view.findViewById(R.id.etBook_Details);
        bUploadPicture = (Button) view.findViewById(R.id.bUpload_Picture);
        bAddBook = (Button) view.findViewById(R.id.bAdd_Book);

        bUploadPicture.setOnClickListener(this);
        bAddBook.setOnClickListener(this);
        return view;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bUpload_Picture:
                selectPicture();
                break;
            case R.id.bAdd_Book:
                addBook();
                break;
        }
    }

    private void addBook() {
        try {
            HomeActivity.backEnd.addOrder(new Order(HomeActivity.LoggedUser.getID(),
                    etBookGenre.getText().toString(),
                    etBookName.getText().toString(),
                    Integer.parseInt(etBookPublishing.getText().toString()),
                    etBookAuthor.getText().toString(),
                    Double.parseDouble(etBookPrice.getText().toString()),
                    (Integer) ivBookPicture.getTag()));
        } catch (Exception e) {
            Toast.makeText(getActivity().getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
        }
    }

    private void selectPicture() {
        final CharSequence[] options = {
                getResources().getString(R.string.take_photo),
                getResources().getString(R.string.gallery_choose),
                getResources().getString(R.string.cancel)};
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle(getResources().getString(R.string.upload_picture));
        builder.setItems(options, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int item) {
                if (options[item].equals(getResources().getString(R.string.take_photo))) {
                    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    File f = new File(android.os.Environment.getExternalStorageDirectory(), "tmp.jpg");
                    intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
                    startActivityForResult(intent, 1);
                } else if (options[item].equals(getResources().getString(R.string.gallery_choose))) {
                    Intent intent = new Intent(Intent.ACTION_PICK,
                            MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                    startActivityForResult(intent, 2);
                } else
                    dialog.dismiss();
            }
        });
        builder.show();
    }

    Bitmap bitmap;

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        OutputStream outFile;
        String path = android.os.Environment.getExternalStorageDirectory()
                + File.separator
                + "MyApp";
        File file;
        if (resultCode == Activity.RESULT_OK) {
            if (bitmap != null) {
                ivBookPicture.setImageBitmap(null);
                bitmap.recycle();
                bitmap = null;
            }
            try {
                if (requestCode == 1) {
                    File f = new File(Environment.getExternalStorageDirectory().toString());
                    for (File tmp : f.listFiles()) {
                        if (tmp.getName().equals("tmp.jpg")) {
                            f = tmp;
                            break;
                        }
                    }
                    BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
                    bitmap = BitmapFactory.decodeFile(f.getAbsolutePath(), bitmapOptions);
                    ivBookPicture.setImageBitmap(bitmap);
                    if (f.delete()) {
                        file = new File(path, String.valueOf(System.currentTimeMillis()) + ".jpg");
                        try {
                            outFile = new FileOutputStream(file);
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        }
                    }
                } else if (requestCode == 2) {
                    Uri selectedImage = data.getData();
                    String[] filePath = {MediaStore.Images.Media.DATA};
                    Cursor c = getActivity().getContentResolver().query(selectedImage, filePath, null, null, null);
                    c.moveToFirst();
                    int columnIndex = c.getColumnIndex(filePath[0]);
                    String picturePath = c.getString(columnIndex);
                    c.close();
                    bitmap = (BitmapFactory.decodeFile(picturePath));
                    Log.w("image path", picturePath);
                    ivBookPicture.setImageBitmap(bitmap);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

The ImageView which contains the uploaded picture:

<ImageView
    android:id="@+id/ivBook_Picture"
    android:layout_width="@dimen/sell_a_book_picture_size"
    android:layout_height="@dimen/sell_a_book_picture_size"
    android:src="@mipmap/ic_launcher" />

Thanks!

I attached the error log when taking a picture twice. About the rotation problem I have nothing to add but the code above.

E/AndroidRuntime: FATAL EXCEPTION: main
E/AndroidRuntime: java.lang.OutOfMemoryError
E/AndroidRuntime:     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
E/AndroidRuntime:     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:623)
E/AndroidRuntime:     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:378)
E/AndroidRuntime:     at com.example.amit.java5776_7546_8412.SellABookFragment.onActivityResult(SellABook
E/AndroidRuntime:     at android.app.Activity.dispatchActivityResult(Activity.java:5567)
E/AndroidRuntime:     at android.app.ActivityThread.deliverResults(ActivityThread.java:3496)
E/AndroidRuntime:     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2906)
E/AndroidRuntime:     at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2948)
E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2354)
E/AndroidRuntime:     at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3877)
E/AndroidRuntime:     at android.app.ActivityThread.access$800(ActivityThread.java:159)
E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1322)
E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:176)
E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5419)
E/AndroidRuntime:     at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:525)
E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
E/AndroidRuntime:     at dalvik.system.NativeStart.main(Native Method)
Dylan Wheeler
  • 6,928
  • 14
  • 56
  • 80
Nick
  • 499
  • 4
  • 11
  • 25

1 Answers1

0

App is crashing because picture is using a lot of memory.

You need to resize the bitmap first to a smaller size (around 200dp X 200dp) and then set it to the ImageView.

Use this answer here to resize the bitmap:

UPDATE: also, you must call the resize function from inside an AsyncTask and set the bitmap to ImageView using activity.runOnUiThread

Community
  • 1
  • 1
penduDev
  • 4,743
  • 35
  • 37
  • But the app crushes only after the second selection, even if I choose the same picture twice. So why it does not crush at the first time if it's a memory issue? – Nick Dec 18 '15 at 11:41
  • it happens because when you call bitmap = BitmapFactory.decodeFile(f.getAbsolutePath(), bitmapOptions);...then a new bitmap is created before assigning it to the old variable....so it takes 2xMemoryOfBitmap...try calling bitmap=null just before decodeFile line...maybe it'll solve the prob...however a cleaner solution will be resizing your bitmap – penduDev Dec 18 '15 at 11:46