Friday, January 14, 2011

Adding suport for Android SDK <2.2

 Making your application work across multiple Android SDK versions can be non-trivial if you are using features that depend on newly introduced API. One such example is the YuvImage class in SDK v2.2 (Froyo). We use YuvImage.compressToJpeg method to convert YUV data obtained from the Android camera, to a Jpeg image which you can save to disk, dispatch over the network, pickle it, or what you will. However, for API version <2.2, we need to do something else:

int[] rgb = new int[previewWidth * previewHeight]; 
// This method decodes YUV to RGB.
// imageData is byte[] obtained from the Camera.
decodeYUV(rgb, imageData, previewWidth, previewHeight);
Bitmap bm = Bitmap.createBitmap(rgb, previewWidth, previewHeight, Config.RGB_565);
bm.compress(Bitmap.CompressFormat.JPEG, mPreviewQuality, out);

However, to produce an app that works across different platform versions, this is not enough. We still want to use the speed of native Jpeg compression done by YuvImage in 2.2+ SDK. With the target SDK version of the app set to 2.1, we need to use reflection in order to use the YuvImage class.

Class<?>[] yuvArgsClass = new Class[] {
  byte[].class, int.class, int.class, int.class, int[].class };
Class<?> yuvParamTypes[] = new Class[] { Rect.class, int.class, OutputStream.class};
Class<?> c = Class.forName("android.graphics.YuvImage");
Constructor<?> yuvImageConstructor = c.getConstructor(yuvArgsClass);
Object[] args = new Object[] {
  imageData, previewFormat, previewWidth, previewHeight, null};
Object yuvImage = yuvImageConstructor.newInstance(args);
Object params[] = new Object[] {previewRect, mPreviewQuality, out};
Method compress = c.getMethod("compressToJpeg", yuvParamTypes);
compress.invoke(yuvImage, params);

In the above code, imageData is the byte[] data obtained from the Camera. previewFormat, previewWidth, and previewHeight are obtained from Camera.getParameters().
previewRect = new Rect(0, 0, previewWidth, previewHeight);

We were unable to get the Java-based YUV -> Bitmap conversion to work on the G1 phones due to OutOfMemory problems. G1 phones have a 16 MB heap which seems to run out pretty quick.

No comments:

Post a Comment