Image Uri to bytesarray

I currently have two activities. One for pulling the image from the SD card and one for Bluetooth connection.

I have utilized a Bundle to transfer the Uri of the image from activity 1.

Now what i wish to do is get that Uri in the Bluetooth activity to and convert it into a transmittable state via Byte Arrays i have seen some examples but i can't seem to get them to work for my code!!

Bundle goTobluetooth = getIntent().getExtras();
    test = goTobluetooth.getString("ImageUri");

is what i have to pull it across. What would be the next step?


Solution 1:

From Uri to get byte[] I do the following things,

InputStream iStream =   getContentResolver().openInputStream(uri);
byte[] inputData = getBytes(iStream);

and the getBytes(InputStream) method is:

public byte[] getBytes(InputStream inputStream) throws IOException {
      ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
      int bufferSize = 1024;
      byte[] buffer = new byte[bufferSize];

      int len = 0;
      while ((len = inputStream.read(buffer)) != -1) {
        byteBuffer.write(buffer, 0, len);
      }
      return byteBuffer.toByteArray();
    }

Solution 2:

Kotlin is very concise here:

@Throws(IOException::class)
private fun readBytes(context: Context, uri: Uri): ByteArray? = 
    context.contentResolver.openInputStream(uri)?.buffered()?.use { it.readBytes() }

In Kotlin, they added convenient extension functions for InputStream like buffered,use , and readBytes.

  • buffered decorates the input stream as BufferedInputStream
  • use handles closing the stream
  • readBytes does the main job of reading the stream and writing into a byte array

Error cases:

  • IOException can occur during the process (like in Java)
  • openInputStream can return null. If you call the method in Java you can easily oversee this. Think about how you want to handle this case.

Solution 3:

Java best practice: never forget to close every stream you open! This is my implementation:

/**
 * get bytes array from Uri.
 * 
 * @param context current context.
 * @param uri uri fo the file to read.
 * @return a bytes array.
 * @throws IOException
 */
public static byte[] getBytes(Context context, Uri uri) throws IOException {
    InputStream iStream = context.getContentResolver().openInputStream(uri);
    try {
        return getBytes(iStream);
    } finally {
        // close the stream
        try {
            iStream.close();
        } catch (IOException ignored) { /* do nothing */ }
    }
}



 /**
 * get bytes from input stream.
 *
 * @param inputStream inputStream.
 * @return byte array read from the inputStream.
 * @throws IOException
 */
public static byte[] getBytes(InputStream inputStream) throws IOException {

    byte[] bytesResult = null;
    ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
    int bufferSize = 1024;
    byte[] buffer = new byte[bufferSize];
    try {
        int len;
        while ((len = inputStream.read(buffer)) != -1) {
            byteBuffer.write(buffer, 0, len);
        }
        bytesResult = byteBuffer.toByteArray();
    } finally {
        // close the stream
        try{ byteBuffer.close(); } catch (IOException ignored){ /* do nothing */ }
    }
    return bytesResult;
}

Solution 4:

Syntax in kotlin

val inputData = contentResolver.openInputStream(uri)?.readBytes()