/* * Copyright 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.system.runtimepermissions.camera; import android.content.Context; import android.hardware.Camera; import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import java.io.IOException; /** * Camera preview that displays a {@link Camera}. * * Handles basic lifecycle methods to display and stop the preview. * <p> * Implementation is based directly on the documentation at * http://developer.android.com/guide/topics/media/camera.html */ public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { private static final String TAG = "CameraPreview"; private SurfaceHolder mHolder; private Camera mCamera; private Camera.CameraInfo mCameraInfo; private int mDisplayOrientation; public CameraPreview(Context context, Camera camera, Camera.CameraInfo cameraInfo, int displayOrientation) { super(context); // Do not initialise if no camera has been set if (camera == null || cameraInfo == null) { return; } mCamera = camera; mCameraInfo = cameraInfo; mDisplayOrientation = displayOrientation; // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); } public void surfaceCreated(SurfaceHolder holder) { // The Surface has been created, now tell the camera where to draw the preview. try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); Log.d(TAG, "Camera preview started."); } catch (IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } public void surfaceDestroyed(SurfaceHolder holder) { // empty. Take care of releasing the Camera preview in your activity. } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // If your preview can change or rotate, take care of those events here. // Make sure to stop the preview before resizing or reformatting it. if (mHolder.getSurface() == null) { // preview surface does not exist Log.d(TAG, "Preview surface does not exist"); return; } // stop preview before making changes try { mCamera.stopPreview(); Log.d(TAG, "Preview stopped."); } catch (Exception e) { // ignore: tried to stop a non-existent preview Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } int orientation = calculatePreviewOrientation(mCameraInfo, mDisplayOrientation); mCamera.setDisplayOrientation(orientation); try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); Log.d(TAG, "Camera preview started."); } catch (Exception e) { Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } } /** * Calculate the correct orientation for a {@link Camera} preview that is displayed on screen. * * Implementation is based on the sample code provided in * {@link Camera#setDisplayOrientation(int)}. */ public static int calculatePreviewOrientation(Camera.CameraInfo info, int rotation) { int degrees = 0; switch (rotation) { case Surface.ROTATION_0: degrees = 0; break; case Surface.ROTATION_90: degrees = 90; break; case Surface.ROTATION_180: degrees = 180; break; case Surface.ROTATION_270: degrees = 270; break; } int result; if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = (info.orientation + degrees) % 360; result = (360 - result) % 360; // compensate the mirror } else { // back-facing result = (info.orientation - degrees + 360) % 360; } return result; } }