0

First of all I would like to say, that loading big images strategy is described here. I am aware of the obligation to resize the image to omit OutOfMemoryError. I would like to get bytes from the image to be able to send it through Internet.

public byte[] getAttachment(Context context, String fullFilePath) {
    byte[] fileBytes = mFileUtil.readFileAsBytes(fullFilePath);
    if (fileBytes == null) {
        Logger.i("Unable to get bytes, trying through content resolver");
        try {
            fileBytes = mFileUtil.readFileFromContentResolver(context, fullFilePath);
        } catch (OutOfMemoryError e) {
            Uri imageUri = Uri.parse(fullFilePath);
            if (checkIfFileIsImage(context, imageUri)) {
                try {
                    InputStream stream = context.getContentResolver().openInputStream(imageUri);
                    if (stream == null) {
                        return null;
                    }
                    BitmapFactory.Options options = getOptions(stream, 2000, 2000);
                    stream.close();
                    stream = context.getContentResolver().openInputStream(imageUri);
                    if (stream == null) {
                        return null;
                    }
                    Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);
                    bitmap = rotateBitmap(context, imageUri, bitmap);
                    stream.close();
                    fileBytes = convertBitmapToArray(bitmap);
                } catch (Exception e1) {
                    Logger.e("Unable to get bytes using fallback method, attachment " +
                            "will not be added");
                } catch (OutOfMemoryError e2) {
                    Logger.e("Unable to get bytes using fallback method, because " +
                            "attachment is too big. Attachment will not be added");
                }
            }
            System.gc();
        }
    }
    return fileBytes;
}

FileUtil.class

public byte[] readFileAsBytes(String fileName) {
    File originalFile = new File(fileName);
    byte[] bytes = null;
    try {
        FileInputStream fileInputStreamReader = new FileInputStream(originalFile);
        bytes = new byte[(int) originalFile.length()];
        fileInputStreamReader.read(bytes);
    } catch (IOException e) {
    }
    return bytes;
}

public byte[] readFileFromContentResolver(Context context, String fileName) {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    InputStream is = null;
    InputStream inputStream = null;
    try {
        inputStream = context.getContentResolver().openInputStream(Uri.parse(fileName));
        is = new BufferedInputStream(inputStream);
        byte[] data = new byte[is.available()];
        is.read(data);
        bos.write(data);
    } catch (Exception e) {

    } finally {
        try {
            if (is != null) {
                is.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
        } catch (IOException e1) {
        }
    }
    return bos.toByteArray();
}

As you can see the aim of this code is to get byte[] from Bitmap unlike here. It works without problems in almost any case. However it is especially error prone on low-end devices with older Android systems (but also very rarely).

I don't like the idea of setting largeHeap inside AndroidManifest.xml as this is just masking the problem rather than cope with it. I also would not like to send even smaller images.

Could this piece of code be improved in any other way in order to get rid of OutOfMemoryError?

Community
  • 1
  • 1
R. Zagórski
  • 20,020
  • 5
  • 65
  • 90
  • Why are you fiddling around wit Bitmap and BitmapFactory? If you can read bytes from the content resolver then you can send those bytes directly to you server. Dont change a file! – greenapps Jul 29 '16 at 13:06
  • If You look at the line `fileBytes = mFileUtil.readFileFromContentResolver(context, fullFilePath);` You might see it is sorrounded by `try` `catch` closure catching `OutOfMemoryError`. Is means, that I can't just get bytes of very big images, need to resize it first. – R. Zagórski Jul 29 '16 at 13:09
  • No. Just make a loop where you read chunks of bytes from the content resolver and write those chunks directly to an output stream of the server. – greenapps Jul 29 '16 at 15:02

0 Answers0