11

I am using JNI code in an Android project in which the JNI native function requires a short[] argument. However, the original data is stored as a ByteBuffer. I'm trying the convert the data format as follows.

ByteBuffer rgbBuf = ByteBuffer.allocate(size);
...    
short[] shortArray = (short[]) rgbBuf.asShortBuffer().array().clone();

But I encounter the following problem when running the second line of code shown above:

E/AndroidRuntime(23923): Caused by: java.lang.UnsupportedOperationException
E/AndroidRuntime(23923): at Java.nio.ShortToByteBufferAdapter.protectedArray(ShortToByteBufferAdapter.java:169)

Could anyone suggest a means to implement the conversion?

bei
  • 221
  • 4
  • 7

2 Answers2

7

The method do this is a bit odd, actually. You can do it as below; ordering it is important to convert it to a short array.

short[] shortArray = new short[size/2];
rgbBuf.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shortArray);

Additionally, you may have to use allocateDirect instead of allocate.

Cat
  • 66,919
  • 24
  • 133
  • 141
  • Could you explain a bit more why using allocateDirect()? Since I don't find any hints from the android documentation. – bei Aug 13 '12 at 08:54
  • It's a hunch based on [a bug report](http://code.google.com/p/android/issues/detail?id=24327) that was filed. It may be unrelated, but I figured it was worth mentioning. – Cat Aug 13 '12 at 18:06
1

I had the same error with anything that used asShortBuffer(). Here's a way around it (adapted from 2 bytes to short java):

short[] shortArray = new short[rgbBuf.capacity() / 2]);
for (int i=0; i<shortArray.length; i++)
{   
    ByteBuffer bb = ByteBuffer.allocate(2);
    bb.order(ByteOrder.LITTLE_ENDIAN);
    bb.put(rgbBuf[2*i]);
    bb.put(rgbBuf[2*i + 1]);
    shortArray[i] = bb.getShort(0);
}
Community
  • 1
  • 1
Hari Honor
  • 8,677
  • 8
  • 51
  • 54