62

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?

Ryan M
  • 18,333
  • 31
  • 67
  • 74
user1314243
  • 639
  • 1
  • 5
  • 7

8 Answers8

119

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();
    }
user370305
  • 108,599
  • 23
  • 164
  • 151
  • getContentResolver().openInputStream(test); is receiving an error saying that it is not applicable for arguments for string!! In reference to my code above its states the the uri is in string form how do i change this to coincide with the code you have stated above! – user1314243 Apr 24 '12 at 12:05
  • test is a string variable you have to pass Uri. Make Uri from test and then pass it to method.. – user370305 Apr 24 '12 at 12:06
  • Still getting an error saying uri can't be resolved to variable!! – user1314243 Apr 24 '12 at 12:18
  • 1
    You have to write this line, InputStream iStream = getContentResolver().openInputStream(Uri.parse(test)); – user370305 Apr 24 '12 at 12:20
  • Actually instead of passing string Uri from activity 1 you have to get byte[] from it in that activity and then you have to just pass the byte[] using intent to activity 2. – user370305 Apr 24 '12 at 12:28
  • i just need to now get the byte array to work within my transmission phase now. It used to send txt messages need to change it to the array just created: Thread.sleep(1000); OutputStream outStream; outStream = BT_Socket.getOutputStream(); byte[] ByteArray = ; outStream.write(ByteArray); outStream.flush(); Thread.sleep(1500); – user1314243 Apr 24 '12 at 12:35
  • i just need to get the byte array into the transmission code i stated above. it keeps coming up with errors when i try and include it in byte[] ByteArray = inputdata; etc – user1314243 Apr 24 '12 at 12:44
  • If the above answer works for you then accept it as a correct answer and make a new question on your current problem. – user370305 Apr 24 '12 at 12:49
  • this can cause an OutOfMemory error and crash at `while ((len = inputStream.read(buffer)) != -1) ` if the image/video/file is too large. have a different solution? – CQM Feb 24 '15 at 16:22
  • 3
    `InputStream iStream =...` line gives me `FileNotFoundException` – mrid Oct 04 '17 at 13:12
  • @mrid just hit Alt+Enter and surround with try/catch. – DJTano Apr 10 '19 at 18:23
25

Kotlin is very concise here:

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

Kotlin has 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.
Peter F
  • 3,633
  • 3
  • 33
  • 45
  • 2
    I think it's better to do `context.contentResolver.openInputStream(uri)?.use { it.buffered().readBytes() }` instead, this way you can ensure the stream is closed even if the buffer fails somehow (although improbable). – rtsketo Jul 29 '22 at 06:47
  • @rtsketo I agree with your suggestion. I updated the answer accordingly. Thanks! – Peter F Jun 05 '23 at 08:24
8

Syntax in kotlin

val inputData = contentResolver.openInputStream(uri)?.readBytes()
Lúcio Aguiar
  • 191
  • 1
  • 3
  • 6
  • 1
    This isn't completely correct, you need to always close `openInputStream(..)` after reading. You can use `use { }` for auto-closing it. Check Peter's [answer](https://stackoverflow.com/a/54250792/2115403). – rtsketo Jul 29 '22 at 06:30
5

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;
}
ahmed_khan_89
  • 2,755
  • 26
  • 49
1

use getContentResolver().openInputStream(uri) to get an InputStream from a URI. and then read the data from inputstream convert the data into byte[] from that inputstream

Try with following code

public byte[] readBytes(Uri uri) throws IOException {
          // this dynamically extends to take the bytes you read
        InputStream inputStream = getContentResolver().openInputStream(uri);
          ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();

          // this is storage overwritten on each iteration with bytes
          int bufferSize = 1024;
          byte[] buffer = new byte[bufferSize];

          // we need to know how may bytes were read to write them to the byteBuffer
          int len = 0;
          while ((len = inputStream.read(buffer)) != -1) {
            byteBuffer.write(buffer, 0, len);
          }

          // and then we can return your byte array.
          return byteBuffer.toByteArray();
        }

Refer this LINKs

Shankar Agarwal
  • 34,573
  • 7
  • 66
  • 64
0

This code works for me

Uri selectedImage = imageUri;
            getContentResolver().notifyChange(selectedImage, null);
            ImageView imageView = (ImageView) findViewById(R.id.imageView1);
            ContentResolver cr = getContentResolver();
            Bitmap bitmap;
            try {
                 bitmap = android.provider.MediaStore.Images.Media
                 .getBitmap(cr, selectedImage);

                imageView.setImageBitmap(bitmap);
                Toast.makeText(this, selectedImage.toString(),
                        Toast.LENGTH_LONG).show();
                finish();
            } catch (Exception e) {
                Toast.makeText(this, "Failed to load", Toast.LENGTH_SHORT)
                        .show();

                e.printStackTrace();
            }
png
  • 4,368
  • 7
  • 69
  • 118
0
public void uriToByteArray(String uri)
    {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(new File(uri));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        byte[] buf = new byte[1024];
        int n;
        try {
            while (-1 != (n = fis.read(buf)))
                baos.write(buf, 0, n);
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] bytes = baos.toByteArray();
    }
IntelliJ Amiya
  • 74,896
  • 15
  • 165
  • 198
0

Use the following method to create a bytesArray from a URI in Android studio.

public byte[] getBytesArrayFromURI(Uri uri) {
    try {
        InputStream inputStream = getContentResolver().openInputStream(uri);
        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();

    }catch(Exception e) {
        Log.d("exception", "Oops! Something went wrong.");
    }
    return null;
}
Codemaker2015
  • 12,190
  • 6
  • 97
  • 81