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 CameraPreview(Context context, Camera camera, Camera.CameraInfo cameraInfo, int displayOrientation)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 surfaceCreated(SurfaceHolder holder)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 surfaceDestroyed(SurfaceHolder holder)73 public void surfaceDestroyed(SurfaceHolder holder) { 74 // empty. Take care of releasing the Camera preview in your activity. 75 } 76 surfaceChanged(SurfaceHolder holder, int format, int w, int h)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 */ calculatePreviewOrientation(Camera.CameraInfo info, int rotation)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