Skip to content

spinaki/android-camera

Repository files navigation

android-camera

Lightweight Library for integrating the Camera sensor on your Android apps. The library internally takes care of invoking the correct API -- the deprecated android.hardware.Camera or the new android.hardware.Camera2. You get a generated image in the bitmap format which you can save (as JPEGs etc) or render in your apps. The returned bitmap is guaranteed to have the correct orientation and resolution.

Getting Started

V2 API

Add via

compile 'xyz.pinaki.android:camera:2.1.0'

In addition to stability and various bug fixes, this new API has the following additional features:

  • You can now choose a TextureView or SurfaceView as your preview surface. Deafult is the more performant SurfaceView. The options are CameraAPI.PreviewType.TEXTURE_VIEW and CameraAPI.PreviewType.SURFACE_VIEW which can be set in the CameraAPIClient. See example below.
  • You can add a desired aspect ratio as input parameters. Different cameras support different aspect ratio. So if your camera does not supper the desired aspect ratio -- it chooses one by default. Additionally, in a callback onAspectRatioAvailable you get to know all possible size/ aspect ratio choices for your front and back cameras. Note that these are likely to be different. After you are aware of the supported sizes, in the next invocation, you can choose one of the available sizes.
  • You can also set the maximum size of the smaller dimension of the JPEG image. The smaller dimension is typically the top of the phone if you hold it in portrait mode. The resultant bitmap will have max that size, without disturbing the aspect ratio.
  • Back button navigation should work.

Unfortunately, all this needed a major API change. We now have a CameraAPIClient See the MainActivity for detailed examples.

apiClient = new CameraAPIClient.Builder(this).
                previewType(CameraAPI.PreviewType.TEXTURE_VIEW).
                maxSizeSmallerDimPixels(1000).
                desiredAspectRatio(aspectRatio).
                build();

Start the camera by

apiClient.start(R.id.container, callback);

where Callback is an instance of CameraAPI.Callback

public interface Callback {
        void onCameraOpened();
        void onAspectRatioAvailable(AspectRatio desired, AspectRatio chosen, List<Size> availablePreviewSizes);
        void onCameraClosed();
        void onPhotoTaken(byte[] data);
        void onBitmapProcessed(Bitmap bitmap);
    }

V1 API

Add the library dependency to your build.gradle.

compile 'xyz.pinaki.android:camera:1.0.1'

The main entry point to this library is the singleton CameraController class. You can use the getInstance() method to get an instance object of the class. Start the camera using the launch method of this class which takes three arguments:

launch(AppCompatActivity activity, int containerID, Callback callback)
  • As the first arguement, pass the Activity from which this is launched.
  • The Camera is launched inside a Fragment. You will have to define a place in your layout file to launch the Fragment. The ID of this node in the layout file is the second argument. For instance, in the layout file within the demo app, we define a FrameLayout where the camera will be displayed.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_height="match_parent" android:layout_width="match_parent"
                android:orientation="vertical">
    <FrameLayout android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:id="@+id/container">
    </FrameLayout>
</LinearLayout>
  • The third argument is a callback object which notifies the caller about various lifecycle events of the Camera. It is an instance of the interface CAmeraController.Callback and you can add your own code in the object about what you wich to do when these lifecycle events are triggered.
public interface Callback {
    void onCameraOpened();
    void onCameraClosed();
    void onPhotoTaken(byte[] data);
    void onBitmapProcessed(Bitmap bitmap);
}

Checkout the example app built using this library app/src/main/java/xyz/pinaki/androidcamera/example

Why This Library

There are multiple issues with the camera libraries on Android.

  • The new Camera2 library is only supported by Android Lollipop (21) and higher. However, I have found in many post 21 devices, the camera sensor does not behave well when used with Camera2 library. In some cases, even if one of the cameras support it -- the other might not. The CameraCharacteristics store the hardware level support. This library includes the logic to choose the correct library.

    During my search, I was not able to find a lightweight library, which enables developer capture an image from either of the cameras with correct orientation and aspect ratios. Hence, I created this library.

  • Based on how the camera sensor is mounted on the device, we have to correct the preview image as well as the final bitmap. Else the orientation will be incorrect. Furthermore, based on how the user is holding the camera (portrait or landscape), the final image needs to be corrected. This library takes care of those scenarios.

  • This library enables easily switch between front and rear cameras. The images from the front camera are corrected so that they show up as mirror reflections.

  • Handling the camera callbacks correctly in background thread without blocking the UI thread.

  • Correct Aspect Ratio for the camera (the cameras only support some aspect ratios), the preview image (which are constrained by the display dimensions) and the final image.

The above points are explained in details below. To summarize, the goal behind this library is to let app developers integrate camera in their apps and take a picture (with either of the front and rear facing cameras) without delving too much into the details of how the camera libraries are implemented. The final bitmap has the correct aspect ration and orientation so they can either be save or uploaded to remote hosts like AWS S3.

Functionality of this library

  • Most examples for the android camera, used the main UI thread to open the camera. However, this is discouraged in the docs. The idea is to use a background thread to invoke it -- since this operation might take a while and block the UI thread. However, the caveat is all camera callbacks (e.g., preview, focus, photo capture) happen on the same thread where Camera.open was invoked. If the callback handling is not correctly implemented -- the android platform throws an exception that callbacks should be handled in the same thread as open. This library takes care of this using looper,message queue and handlers.
  • The preview size and aspect ratio: The camera library does not support arbitrary aspect ratios and sizes. The goal of this library to open up an API so that user can specify a size or an aspect ratio and the library can choose a size that best matches the query ratio.
  • Correct Orientation of the preview image: The orientation of the preview image (while recording) depends on multiple factors : natural orientation of the device, how the camera sensor is oriented in relation to the device, how the user holds while capturing a photo (portrait or landscape). Because of these factors, its easy to get the orientation of the preview image wrong. See here and here . This library takes care of such scenarios and generates the correct orientation of the preview image.
  • Even if you fix the orientation of the preview image -- the orientation of the final image which you want to display or save in the disk (JPEG etc) is still not fixed. The angle used in Camera.setDisplayOrientation can also be used in Camera.Parameters.setRotation. However, according to the Android docs there is no guarantee that the pixels returned from the library will be correctly oriented. It depends on the hardware manufacturer on how they interpret this value. This library takes care of this too.
  • Option to lock the orientation: In many camera libraries, if you change the orientation of the camera, the view is destroyed and regenerated. This creates a bad user experience since on most devices, one can see a lag. This library has an option to fix the orientation -- so that if orientation is changed -- the views are not regenerated.
  • SurfaceView instead of TextureView. In many libraries, e.g., the one from Google TextureView is used to render the live Camera preview. However, SurfaceView is much more efficient as mentioned in Android Docs and here . This library uses SurfaceView.
  • Work In Progress: Tap to focus.
  • Work In Progress: Pinch to Zoom.

About

Library for Android Camera and Camera2

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages