0

I'm attempting to load an image from the Gallery that is big (around 30MB-70MB). The issue I keep facing is:

FATAL EXCEPTION: main Process: com.parse.starter, PID: 29795
java.lang.OutOfMemoryError: Failed to allocate a 1866240012 byte allocation with 2323392 free bytes and 380MB until OOM at dalvik.system.VMRuntime.newNonMovableArray(Native Method) at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:635) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:611) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:649) at android.provider.MediaStore$Images$Media.getBitmap(MediaStore.java:867) at com.parse.starter.AddPhotosActivity.onActivityResult(AddPhotosActivity.java:151) at android.app.Activity.dispatchActivityResult(Activity.java:6428) at android.app.ActivityThread.deliverResults(ActivityThread.java:3695) at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742) at android.app.ActivityThread.-wrap16(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Here is my code (line 151 as stated above in crash log) has a comment right above it. Basically, the end goal is I want to detect right off the bat whether or not the selected image is greater than 10MB. If so, then send a Toast, if not, then proceed with saving out the image to the backend.

if (requestCode == SELECT_PHOTO && resultCode == RESULT_OK)
{
    Uri uri = data.getData();
    File f = new File(uri.getPath());

    try
    {
        // LINE BELOW IS THE LINE 151, ERROR CRASH
        Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
        if (bitmap.getByteCount() > 10485760)
        {
            Toast.makeText(AddPhotosActivity.this, "That file is too large to attach to a Grievance, please try again!", Toast.LENGTH_SHORT).show();
        }
        else
        {
            mImageOne.setImageBitmap(bitmap);
            SaveImageOne(bitmap);
        }

    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
}
Allan Pereira
  • 2,572
  • 4
  • 21
  • 28
Jamie22
  • 424
  • 4
  • 15
  • 1
    BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; Bitmap bm = BitmapFactory.decodeFile(picPath, options); try this – Nisarg Jul 05 '16 at 19:44
  • 1
    See this : https://developer.android.com/training/displaying-bitmaps/load-bitmap.html – marcinj Jul 05 '16 at 19:51
  • Please search for your exception next time, there are lots of questions related to this – tyczj Jul 05 '16 at 20:00
  • I did @tyczj, if you did, you will see most answers are deprecated or not accomplishing the same task. – Jamie22 Jul 05 '16 at 21:54
  • @Jamie22 sorry but you must not have read correctly because the good answers (ones with the most upvotes) are still correct. I specifically use this solution http://stackoverflow.com/a/3549021/599346 The accepted answer is also very correct and not deprecated – tyczj Jul 06 '16 at 13:22
  • telling the user that their photo is too large so they cant use it because you don't know how to load a large bitmap provides a very bad user experience and would probably cause many people to uninstall the app – tyczj Jul 06 '16 at 13:33

3 Answers3

0

java.lang.OutOfMemoryError happens in case of image loading. Because the phone memory has certain limitations. So instead of loading image directly use some kind of library like picasso, etc. And load the image according to the size you need not in the original dimensions, it will reduce memory consumption.

picasso

And replace

mImageOne.setImageBitmap(bitmap);

with

Picasso.with(context).load(uri).resize(50, 50).centerCrop().into(mImageOne);

// here 50,50 is new dimension, centercrop is scaletype

Shahbaz Hashmi
  • 2,631
  • 2
  • 26
  • 49
  • Thanks but that's not the line I'm having an issue with. – Jamie22 Jul 05 '16 at 21:57
  • Have you tried this ? Obviously this is not that line which causing the issue. But this is the code which loads your image in imageview. Before doing resizing or compressing. Therefore your phone memory get filled. That library is not only for resizing it also reuse views for memory optimisation. Did you notice your logcat. According to it there is no error in your code. But there is the code which is responsible for out of memory exception. – Shahbaz Hashmi Jul 05 '16 at 23:46
-1

you can test the file before with :

File file = new File(uri.getPath());

// Get length of file in bytes
long fileSizeInBytes = file.length();

//10485760 will work for your phone, but not for all
if (fileSizeInMB > 10485760) {
  ...
}¸

this way you don't have to use too much memory to transform your picture but a memory leak indicated an other problem. As Shahbaz Hashmi said you should consider something like picasso, or change the way you load your image.

I'm not sure what you wish to accomplish but if you want to load image from gallery or from the camera please check this tutorial :http://www.theappguruz.com/blog/android-take-photo-camera-gallery-code-sample

JCDecary
  • 557
  • 1
  • 7
  • 18
  • Simply just trying to make my app obtain the reference to an image selected through the Gallery and upload it. I had no issues or crashes until I started picking images that were 10mb+ – Jamie22 Jul 05 '16 at 21:58
-1

Based on inputs in question, seems like you first want to check the file size before you process it. You can simply do this by creating a File object, something like following:

File file = new File("<<Provide full file path>>");
long length = file.length();

if (length  > 10485760)
{
            Toast.makeText(AddPhotosActivity.this, "That file is too large to attach to a Grievance, please try again!", Toast.LENGTH_SHORT).show();
}

Read more about api at URL

Hope this helps.

Cheers !

Sachin Thapa
  • 3,559
  • 4
  • 24
  • 42
  • This is the one that makes most sense to me but how do I get the path from the uri? I tried something like this, with no luck. Uri uri = data.getData(); File file = new File(uri.getPath()); – Jamie22 Jul 05 '16 at 21:55
  • @Jamie22 - Where are the files located on device ? – Sachin Thapa Jul 07 '16 at 16:07