|Bothie makes extensive use|
of the Camera APIs.
The Camera and Camera2 APIs are far from painless to use. If you've ever written an app that uses the camera (embedded in an activity or not), you've almost certainly come up against orientation issues, stretched previews, or weird quirks that change from manufacturer to manufacturer...
There are three good libraries out there that can save you from many common pitfalls:
- Google's (unofficial) CameraView library.
- Mark Murphy's CWAC-Cam2 library.
- Dylan McKintyre's CameraKit for Android library.
- If you want to capture photos in a full-screen preview, but you don't want to have to rely on the native camera app, then use CWAC-Cam2.
- If you want to embed a preview into your Activity, use CameraKit. It's forked from the CameraView library, and offers a few more features.
The original CWAC-Cam was superb at coping with the old Camera API and the hoops you had to jump through to outwit the (sometimes bizarre) quirks introduced by each manufacturer. When the Camera2 API came out, Mark released CWAC-Cam2 to support it - and the library is steadily improving. It supports a variety of features, including flash modes, focus modes, and orientation normalization. Image orientation is a source of frustration for many Android developers who work with the camera. More on that later...
The CameraView library is clean, tidy and works for most simple cases. It is limited to still photography at present. You can embed a CameraView into your layout, and use it there - with only a small amount of supporting code in your Activity class. The library takes care of the proportions of the view, to prevent a stretched preview, and orients it correctly too. (the Camera2 API is supposed to "just take care of that").
CameraKit was originally forked from CameraView and offers a few more features - including tap-to-focus, cropped output, and video capture.
There are a couple of issues with the CameraView library that will very likely also affect CameraKit. These are interesting edge cases that relate to doing things like:
- Stopping the CameraView and attempting to close the Activity. (This leads to the app crashing sometimes - as it seems that the CameraView needs time to close the Camera it's using safely.)
- Stopping one CameraView and starting another in quick succession. (This also sometimes leads to the app crashing, and seems to be again because the first Camera isn't released as the second CameraView tries to start - and so it cannot claim a Camera of its own.)
All three libraries are well maintained - although they're constantly playing catch-up, as each manufacturer manages to introduce some new utterly strange behaviour to their own camera. (Who remembers trying to understand why making a photo size request different to the preview size led to washed out images with no white-balance? Or which of the permitted preview sizes didn't lead to green static on certain phones?)
Make sure to grab a recent version of the library you choose when building your app, and update regularly.
A word of warning about orientation: When actually taking a photo, CameraView (and CameraKit) will return it oriented according to how the camera chip in the phone provided it - not how the preview was arranged. This can be confusing until you realise what's going on. You'll have to reorient the image yourself to get back on the road.
Your choices are:
- Read the orientation information from the image's EXIF data. Unfortunately, this is not always available. (In fact, on most phones I've worked with I don't remember being able to get that data.)
- Guess based on the orientation of the device itself when the photo was taken. This approach appears quite frequently in examples found online, and seems to be the preferred choice amongst developers.
- Fall back on educated guesswork. Take a look at the image in question - is it wider or taller than the preview's dimensions? If so, perhaps you should rotate it 90 degrees (or -90 degrees).
One final word: You may also find that photos taken through the front-facing camera are flipped around the vertical axis (left and right don't match the preview!) To flip it back, you could adjust the Matrix you're using: matrix.postScale(-1.0f, 1.0f); should mirror the image for you, although you'll also have to apply a matrix.postTranslate(imageWidth, 0.0f); to put it back to the same position.
I hope that's helpful!