Home | History | Annotate | Download | only in camera
      1 /*
      2 * Copyright 2015 The Android Open Source Project
      3 *
      4 * Licensed under the Apache License, Version 2.0 (the "License");
      5 * you may not use this file except in compliance with the License.
      6 * You may obtain a copy of the License at
      7 *
      8 *     http://www.apache.org/licenses/LICENSE-2.0
      9 *
     10 * Unless required by applicable law or agreed to in writing, software
     11 * distributed under the License is distributed on an "AS IS" BASIS,
     12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 * See the License for the specific language governing permissions and
     14 * limitations under the License.
     15 */
     16 
     17 package com.example.android.system.runtimepermissions.camera;
     18 
     19 import android.content.Context;
     20 import android.hardware.Camera;
     21 import android.util.Log;
     22 import android.view.Surface;
     23 import android.view.SurfaceHolder;
     24 import android.view.SurfaceView;
     25 
     26 import java.io.IOException;
     27 
     28 /**
     29  * Camera preview that displays a {@link Camera}.
     30  *
     31  * Handles basic lifecycle methods to display and stop the preview.
     32  * <p>
     33  * Implementation is based directly on the documentation at
     34  * http://developer.android.com/guide/topics/media/camera.html
     35  */
     36 public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
     37 
     38     private static final String TAG = "CameraPreview";
     39     private SurfaceHolder mHolder;
     40     private Camera mCamera;
     41     private Camera.CameraInfo mCameraInfo;
     42     private int mDisplayOrientation;
     43 
     44     public CameraPreview(Context context, Camera camera, Camera.CameraInfo cameraInfo,
     45             int displayOrientation) {
     46         super(context);
     47 
     48         // Do not initialise if no camera has been set
     49         if (camera == null || cameraInfo == null) {
     50             return;
     51         }
     52         mCamera = camera;
     53         mCameraInfo = cameraInfo;
     54         mDisplayOrientation = displayOrientation;
     55 
     56         // Install a SurfaceHolder.Callback so we get notified when the
     57         // underlying surface is created and destroyed.
     58         mHolder = getHolder();
     59         mHolder.addCallback(this);
     60     }
     61 
     62     public void surfaceCreated(SurfaceHolder holder) {
     63         // The Surface has been created, now tell the camera where to draw the preview.
     64         try {
     65             mCamera.setPreviewDisplay(holder);
     66             mCamera.startPreview();
     67             Log.d(TAG, "Camera preview started.");
     68         } catch (IOException e) {
     69             Log.d(TAG, "Error setting camera preview: " + e.getMessage());
     70         }
     71     }
     72 
     73     public void surfaceDestroyed(SurfaceHolder holder) {
     74         // empty. Take care of releasing the Camera preview in your activity.
     75     }
     76 
     77     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
     78         // If your preview can change or rotate, take care of those events here.
     79         // Make sure to stop the preview before resizing or reformatting it.
     80 
     81         if (mHolder.getSurface() == null) {
     82             // preview surface does not exist
     83             Log.d(TAG, "Preview surface does not exist");
     84             return;
     85         }
     86 
     87         // stop preview before making changes
     88         try {
     89             mCamera.stopPreview();
     90             Log.d(TAG, "Preview stopped.");
     91         } catch (Exception e) {
     92             // ignore: tried to stop a non-existent preview
     93             Log.d(TAG, "Error starting camera preview: " + e.getMessage());
     94         }
     95 
     96         int orientation = calculatePreviewOrientation(mCameraInfo, mDisplayOrientation);
     97         mCamera.setDisplayOrientation(orientation);
     98 
     99         try {
    100             mCamera.setPreviewDisplay(mHolder);
    101             mCamera.startPreview();
    102             Log.d(TAG, "Camera preview started.");
    103         } catch (Exception e) {
    104             Log.d(TAG, "Error starting camera preview: " + e.getMessage());
    105         }
    106     }
    107 
    108     /**
    109      * Calculate the correct orientation for a {@link Camera} preview that is displayed on screen.
    110      *
    111      * Implementation is based on the sample code provided in
    112      * {@link Camera#setDisplayOrientation(int)}.
    113      */
    114     public static int calculatePreviewOrientation(Camera.CameraInfo info, int rotation) {
    115         int degrees = 0;
    116 
    117         switch (rotation) {
    118             case Surface.ROTATION_0:
    119                 degrees = 0;
    120                 break;
    121             case Surface.ROTATION_90:
    122                 degrees = 90;
    123                 break;
    124             case Surface.ROTATION_180:
    125                 degrees = 180;
    126                 break;
    127             case Surface.ROTATION_270:
    128                 degrees = 270;
    129                 break;
    130         }
    131 
    132         int result;
    133         if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
    134             result = (info.orientation + degrees) % 360;
    135             result = (360 - result) % 360;  // compensate the mirror
    136         } else {  // back-facing
    137             result = (info.orientation - degrees + 360) % 360;
    138         }
    139 
    140         return result;
    141     }
    142 }
    143