Our Android app has a new feature using the camera to take photos. We can split the feature into two tasks, taking a photo and reviewing a photo by pan-and-zoom.
Take a Photo
To take a photo, we found two methods. The first method uses an
Intent to launch the camera app. The second method uses the Camera API to access the hardware directly. For simplicity in our project, we chose the
Intent method. Using the
Intent to call the camera reduces the amount of time needed to develop taking a photo. By using the
Intent approach, we can leverage all the built-in functionality provided by the OS layer.
To start we need to set permission to get access to the camera in the
android:required="true" lets the Google Play Store detect if the app should be installed or not, this is optional. If the attribute
android:required="true" is omitted, then the app has to check for the feature at runtime. Otherwise, the app will crash when it attempts to access the camera when one does not exist:
The first part of checks that the device has a camera, which may return true even though there is none, and the next part checks for the number of cameras the device has.
Intent to call an existing camera app:
CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE can be any number.
The return from the
By checking if the data is null 1 prevents the following error when the user press the back button or cancels:
Pan and Zoom to Review a Photo
To review a photo afterward, we came across several issues to overcome. These issues included out of memory and image pan-and-zoom.
Memory issues encountered using
ImageView were the limited amount of RAM in a phone, i.e. Nexus S with 384 MB of available RAM out of 512 MB2.
The following setup prevents an OutOfMemory exception.
To prevent running out of memory with Nexus S, use a byte array to store the image and use
BitmapFactory.decodeByteArray to store the photo as a
Bitmap. This is recommended over reading the file directly into a
Once the byte array is loaded, it can be stored as a
The bitmap also needs to be scale down before sending it to
ImageView to prevent the following error message:
While the original bitmap is still in memory, this is solved by following the solution mentioned in Stack Overflow:
ImageView does not provide the ability to zoom into a image. One option is to use
ZoomControls widget and listen to
OnTouch events. Another option is to show the image in a
WebView. A third option is to use Michael Ortiz TouchImageView 8. We choose
TouchImageView because it offered an easy way to get zoom functionality without too much extra coding.
TouchImageView in the layout xml do, the following:
Without setting an image in the layout xml but programmatically as discussed above, the following error will show:
After investigating why this happens, we found that
TouchImageView has the following code:
getDrawable() is called it returns
null. The conditional check causes the app to crash.
The solution was to include an image source in the layout xml. A blank PNG image did the trick.
The ability to swap out
TouchImageView in code is an advantage. There is no visible or noticeable lag when zooming in and out.