blob: 187b55e2ace0fa2e3dc6d314b934b677fed5c307 [file] [log] [blame]
/*
* Copyright 2017 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.SurfaceHolder
import android.view.SurfaceView
import com.example.android.system.runtimepermissions.extensions.calculatePreviewOrientation
import java.io.IOException
/**
* Camera preview that displays a [Camera].
*
*
* Handles basic lifecycle methods to display and stop the preview.
*
*
* Implementation is based directly on the documentation at
* http://developer.android.com/guide/topics/media/camera.html
*
*
* Using deprecated android.hardware.Camera API in order to support {14 < API < 21}.
*/
class CameraPreview @JvmOverloads constructor(
context: Context,
private val camera: Camera? = null,
private val cameraInfo: Camera.CameraInfo? = null,
private val displayOrientation: Int = 0
) : SurfaceView(context), SurfaceHolder.Callback {
private var surfaceHolder: SurfaceHolder? = null
init {
// Do not initialise if no camera has been set
if (camera != null && cameraInfo != null) {
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
surfaceHolder = holder.apply {
addCallback(this@CameraPreview)
}
}
}
override fun surfaceCreated(holder: SurfaceHolder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
camera?.run {
setPreviewDisplay(holder)
startPreview()
Log.d(TAG, "Camera preview started.")
}
} catch (e: IOException) {
Log.d(TAG, "Error setting camera preview: " + e.message)
}
}
override fun surfaceDestroyed(holder: SurfaceHolder) {
// Empty. Take care of releasing the Camera preview in your activity.
}
override fun surfaceChanged(holder: SurfaceHolder, format: Int, w: Int, h: Int) {
// 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 (surfaceHolder?.surface == null) {
// preview surface does not exist
Log.d(TAG, "Preview surface does not exist")
return
}
// stop preview before making changes
try {
camera?.run {
stopPreview()
Log.d(TAG, "Preview stopped.")
}
} catch (e: Exception) {
// ignore: tried to stop a non-existent preview
Log.d(TAG, "Error starting camera preview: " + e.message)
}
try {
camera?.run {
cameraInfo?.run {
setDisplayOrientation(calculatePreviewOrientation(displayOrientation))
}
setPreviewDisplay(surfaceHolder)
startPreview()
Log.d(TAG, "Camera preview started.")
}
} catch (e: Exception) {
Log.d(TAG, "Error starting camera preview: " + e.message)
}
}
companion object {
private const val TAG = "CameraPreview"
}
}