On some devices (such as the Samsung ones), captured images in portrait mode are rotated 90
degrees; and on other devices (such as the Nexus devices), things seem to be just fine. You won't notice this if you have a look at the file using the Astro app, for example, but you will if you see the preview in the Facebook share dialog.
This is a well-known challenge for many Android developers. Images may contain metadata about the rotation degree, but apparently not every app respects that metadata. What is the best solution? Should you rotate the image every time you want to display it? Should you rotate the bitmap itself, which could be very time and processor consuming?
For this recipe, you need to have the previous recipe completed successfully. It would be ideal if you had multiple Android devices to test your app on. Otherwise, it would be great if you had at least a Samsung device available, as the orientation issue can be reproduced for most (if not all) models from this brand.
Let's take a look at how you can fix this orientation issue if it appears:
getRotationFromMetaData
method:private int getRotationFromMetaData(){ try { ExifInterface exif = new ExifInterface(mFile.getAbsolutePath()); int orientation = exif.getAttributeInt( ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_270: return 270; case ExifInterface.ORIENTATION_ROTATE_180: return 180;case ExifInterface.ORIENTATION_ROTATE_90: return 90; default: return 0; } } catch (IOException ex){ return 0; } }
rotateCaptureImageIfNeeded
method comes in.Here, we can safely rotate the bitmap in memory, because of the inSampleSet
value of 4
. If you rotate the original full-size bitmap, chances are that you will run out of memory. Either way, it is going to be time consuming and will result in a delay between capturing an image and displaying the sharing preview dialog:
private Bitmap rotateCapturedImageIfNeeded(Bitmap bitmap){ int rotate = getRotationFromMetaData(); Matrix matrix = new Matrix(); matrix.postRotate(rotate); bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); Bitmap mutableBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true); return mutableBitmap; }
sharePictureOnFacebook
method, right after you have retrieved the bitmap using the BitmapFactory
class , call the onRotateCaptureImageIfNeeded
method and pass the bitmap as a parameter:bitmap = rotateCapturedImageIfNeeded(bitmap);
These things are easy to implement and will improve the quality of your app, although they can also drive you nuts sometimes and make you wonder why one solution cannot just work on any device. Everything looks fine now, but what will it look like on a tablet or on a Huawei, LG, or HTC device? There's nothing that cannot be fixed, but since you do not have a drawerful of Android devices (or maybe you do), testing is hard.
It always is a good thing to test your app on as many devices as possible. Consider using a service for remote testing, for example, TestDroid. You can find their website at www.testdroid.com. In Chapter 8, Improving quality, this and other topics will be discussed, but first will we have a look at observables and content providers in the upcoming chapter.
Capturing video is even more fun to do. There is also a Camera2 API sample for video capturing available. You can examine the sample project through the Import sample option as well.