mirror of
https://github.com/SimpleMobileTools/Simple-Camera.git
synced 2025-02-17 03:40:38 +01:00
couple more updates of the Preview class
This commit is contained in:
parent
1095ed56e5
commit
0cfebacd01
@ -12,16 +12,21 @@ import android.net.Uri
|
|||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.*
|
import android.view.ScaleGestureDetector
|
||||||
|
import android.view.SurfaceHolder
|
||||||
|
import android.view.SurfaceView
|
||||||
|
import android.view.ViewGroup
|
||||||
import com.simplemobiletools.camera.activities.MainActivity
|
import com.simplemobiletools.camera.activities.MainActivity
|
||||||
import com.simplemobiletools.commons.extensions.scanPaths
|
import com.simplemobiletools.camera.extensions.config
|
||||||
|
import com.simplemobiletools.commons.extensions.needsStupidWritePermissions
|
||||||
|
import com.simplemobiletools.commons.extensions.scanPath
|
||||||
import com.simplemobiletools.commons.extensions.toast
|
import com.simplemobiletools.commons.extensions.toast
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class Preview : ViewGroup, SurfaceHolder.Callback, View.OnTouchListener, View.OnClickListener, MediaScannerConnection.OnScanCompletedListener {
|
class Preview : ViewGroup, SurfaceHolder.Callback, MediaScannerConnection.OnScanCompletedListener {
|
||||||
companion object {
|
companion object {
|
||||||
val PHOTO_PREVIEW_LENGTH = 1000
|
val PHOTO_PREVIEW_LENGTH = 1000
|
||||||
private val TAG = Preview::class.java.simpleName
|
private val TAG = Preview::class.java.simpleName
|
||||||
@ -32,31 +37,31 @@ class Preview : ViewGroup, SurfaceHolder.Callback, View.OnTouchListener, View.On
|
|||||||
lateinit var mActivity: MainActivity
|
lateinit var mActivity: MainActivity
|
||||||
lateinit var mCallback: PreviewListener
|
lateinit var mCallback: PreviewListener
|
||||||
lateinit var mScreenSize: Point
|
lateinit var mScreenSize: Point
|
||||||
|
lateinit var config: Config
|
||||||
private var mCamera: Camera? = null
|
private var mCamera: Camera? = null
|
||||||
private var mSupportedPreviewSizes: List<Camera.Size>? = null
|
private var mSupportedPreviewSizes: List<Camera.Size>? = null
|
||||||
private var mPreviewSize: Camera.Size? = null
|
private var mPreviewSize: Camera.Size? = null
|
||||||
private var mParameters: Camera.Parameters? = null
|
private var mParameters: Camera.Parameters? = null
|
||||||
private var mRecorder: MediaRecorder? = null
|
private var mRecorder: MediaRecorder? = null
|
||||||
private var mCurrVideoPath: String? = null
|
|
||||||
private var mTargetUri: Uri? = null
|
private var mTargetUri: Uri? = null
|
||||||
private var mScaleGestureDetector: ScaleGestureDetector? = null
|
private var mScaleGestureDetector: ScaleGestureDetector? = null
|
||||||
private var mZoomRatios: List<Int>? = null
|
private var mZoomRatios: List<Int>? = null
|
||||||
private var mConfig: Config? = null
|
|
||||||
|
|
||||||
private var mCanTakePicture: Boolean = false
|
private var mCurrVideoPath = ""
|
||||||
private var mIsFlashEnabled: Boolean = false
|
private var mCanTakePicture = false
|
||||||
private var mIsRecording: Boolean = false
|
private var mIsFlashEnabled = false
|
||||||
private var mIsVideoMode: Boolean = false
|
private var mIsRecording = false
|
||||||
private var mIsSurfaceCreated: Boolean = false
|
private var mIsVideoMode = false
|
||||||
private var mSwitchToVideoAsap: Boolean = false
|
private var mIsSurfaceCreated = false
|
||||||
private var mSetupPreviewAfterMeasure: Boolean = false
|
private var mSwitchToVideoAsap = false
|
||||||
private val mForceAspectRatio: Boolean = false
|
private var mSetupPreviewAfterMeasure = false
|
||||||
private var mWasZooming: Boolean = false
|
private val mForceAspectRatio = false
|
||||||
private var mLastClickX: Int = 0
|
private var mWasZooming = false
|
||||||
private var mLastClickY: Int = 0
|
private var mLastClickX = 0
|
||||||
private var mInitVideoRotation: Int = 0
|
private var mLastClickY = 0
|
||||||
private var mCurrCameraId: Int = 0
|
private var mInitVideoRotation = 0
|
||||||
private var mMaxZoom: Int = 0
|
private var mCurrCameraId = 0
|
||||||
|
private var mMaxZoom = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(context: Context) : super(context)
|
constructor(context: Context) : super(context)
|
||||||
@ -69,15 +74,31 @@ class Preview : ViewGroup, SurfaceHolder.Callback, View.OnTouchListener, View.On
|
|||||||
mSurfaceHolder.addCallback(this)
|
mSurfaceHolder.addCallback(this)
|
||||||
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS)
|
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS)
|
||||||
mCanTakePicture = false
|
mCanTakePicture = false
|
||||||
mSurfaceView.setOnTouchListener(this)
|
|
||||||
mSurfaceView.setOnClickListener(this)
|
|
||||||
mIsFlashEnabled = false
|
mIsFlashEnabled = false
|
||||||
mIsVideoMode = false
|
mIsVideoMode = false
|
||||||
mIsSurfaceCreated = false
|
mIsSurfaceCreated = false
|
||||||
mSetupPreviewAfterMeasure = false
|
mSetupPreviewAfterMeasure = false
|
||||||
mCurrVideoPath = ""
|
mCurrVideoPath = ""
|
||||||
mScreenSize = Utils.getScreenSize(mActivity)
|
config = activity.config
|
||||||
|
mScreenSize = Utils.getScreenSize(activity)
|
||||||
initGestureDetector()
|
initGestureDetector()
|
||||||
|
|
||||||
|
mSurfaceView.setOnTouchListener { view, event ->
|
||||||
|
mLastClickX = event.x.toInt()
|
||||||
|
mLastClickY = event.y.toInt()
|
||||||
|
|
||||||
|
if (mMaxZoom > 0)
|
||||||
|
mScaleGestureDetector!!.onTouchEvent(event)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
mSurfaceView.setOnClickListener {
|
||||||
|
if (!mWasZooming)
|
||||||
|
focusArea(false)
|
||||||
|
|
||||||
|
mWasZooming = false
|
||||||
|
mSurfaceView.isSoundEffectsEnabled = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun trySwitchToVideo() {
|
fun trySwitchToVideo() {
|
||||||
@ -95,7 +116,7 @@ class Preview : ViewGroup, SurfaceHolder.Callback, View.OnTouchListener, View.On
|
|||||||
newCamera = Camera.open(cameraId)
|
newCamera = Camera.open(cameraId)
|
||||||
mCallback.setIsCameraAvailable(true)
|
mCallback.setIsCameraAvailable(true)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Utils.showToast(mActivity, R.string.camera_open_error)
|
mActivity.toast(R.string.camera_open_error)
|
||||||
Log.e(TAG, "setCamera open " + e.message)
|
Log.e(TAG, "setCamera open " + e.message)
|
||||||
mCallback.setIsCameraAvailable(false)
|
mCallback.setIsCameraAvailable(false)
|
||||||
return false
|
return false
|
||||||
@ -132,7 +153,6 @@ class Preview : ViewGroup, SurfaceHolder.Callback, View.OnTouchListener, View.On
|
|||||||
Log.e(TAG, "setCamera setPreviewDisplay " + e.message)
|
Log.e(TAG, "setCamera setPreviewDisplay " + e.message)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mCallback.setFlashAvailable(Utils.hasFlash(mCamera))
|
mCallback.setFlashAvailable(Utils.hasFlash(mCamera))
|
||||||
@ -207,7 +227,7 @@ class Preview : ViewGroup, SurfaceHolder.Callback, View.OnTouchListener, View.On
|
|||||||
mParameters.setPictureSize(maxSize.width, maxSize.height);*/
|
mParameters.setPictureSize(maxSize.width, maxSize.height);*/
|
||||||
mParameters!!.setRotation(rotation % 360)
|
mParameters!!.setRotation(rotation % 360)
|
||||||
|
|
||||||
if (mConfig!!.isSoundEnabled) {
|
if (config.isSoundEnabled) {
|
||||||
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||||
val volume = audioManager.getStreamVolume(AudioManager.STREAM_SYSTEM)
|
val volume = audioManager.getStreamVolume(AudioManager.STREAM_SYSTEM)
|
||||||
if (volume != 0) {
|
if (volume != 0) {
|
||||||
@ -227,7 +247,7 @@ class Preview : ViewGroup, SurfaceHolder.Callback, View.OnTouchListener, View.On
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val takePictureCallback = Camera.PictureCallback { data, cam ->
|
private val takePictureCallback = Camera.PictureCallback { data, cam ->
|
||||||
if (mConfig!!.isShowPreviewEnabled) {
|
if (config.isShowPreviewEnabled) {
|
||||||
Handler().postDelayed({ resumePreview() }, PHOTO_PREVIEW_LENGTH.toLong())
|
Handler().postDelayed({ resumePreview() }, PHOTO_PREVIEW_LENGTH.toLong())
|
||||||
} else {
|
} else {
|
||||||
resumePreview()
|
resumePreview()
|
||||||
@ -237,19 +257,15 @@ class Preview : ViewGroup, SurfaceHolder.Callback, View.OnTouchListener, View.On
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun resumePreview() {
|
private fun resumePreview() {
|
||||||
if (mCamera != null) {
|
mCamera?.startPreview()
|
||||||
mCamera!!.startPreview()
|
|
||||||
}
|
|
||||||
|
|
||||||
mCanTakePicture = true
|
mCanTakePicture = true
|
||||||
}
|
}
|
||||||
|
|
||||||
val supportedVideoSizes: List<Camera.Size>
|
fun getSupportedVideoSizes(): List<Camera.Size> {
|
||||||
get() {
|
return if (mParameters!!.supportedVideoSizes != null) {
|
||||||
if (mParameters!!.supportedVideoSizes != null) {
|
mParameters!!.supportedVideoSizes
|
||||||
return mParameters!!.supportedVideoSizes
|
|
||||||
} else {
|
} else {
|
||||||
return mParameters!!.supportedPreviewSizes
|
mParameters!!.supportedPreviewSizes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,22 +313,16 @@ class Preview : ViewGroup, SurfaceHolder.Callback, View.OnTouchListener, View.On
|
|||||||
|
|
||||||
fun releaseCamera() {
|
fun releaseCamera() {
|
||||||
stopRecording()
|
stopRecording()
|
||||||
|
mCamera?.stopPreview()
|
||||||
if (mCamera != null) {
|
mCamera?.release()
|
||||||
mCamera!!.stopPreview()
|
|
||||||
mCamera!!.release()
|
|
||||||
mCamera = null
|
mCamera = null
|
||||||
}
|
|
||||||
|
|
||||||
cleanupRecorder()
|
cleanupRecorder()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun surfaceCreated(holder: SurfaceHolder) {
|
override fun surfaceCreated(holder: SurfaceHolder) {
|
||||||
mIsSurfaceCreated = true
|
mIsSurfaceCreated = true
|
||||||
try {
|
try {
|
||||||
if (mCamera != null) {
|
mCamera?.setPreviewDisplay(mSurfaceHolder)
|
||||||
mCamera!!.setPreviewDisplay(mSurfaceHolder)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mSwitchToVideoAsap)
|
if (mSwitchToVideoAsap)
|
||||||
initRecorder()
|
initRecorder()
|
||||||
@ -332,10 +342,7 @@ class Preview : ViewGroup, SurfaceHolder.Callback, View.OnTouchListener, View.On
|
|||||||
|
|
||||||
override fun surfaceDestroyed(holder: SurfaceHolder) {
|
override fun surfaceDestroyed(holder: SurfaceHolder) {
|
||||||
mIsSurfaceCreated = false
|
mIsSurfaceCreated = false
|
||||||
if (mCamera != null) {
|
mCamera?.stopPreview()
|
||||||
mCamera!!.stopPreview()
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanupRecorder()
|
cleanupRecorder()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,23 +421,12 @@ class Preview : ViewGroup, SurfaceHolder.Callback, View.OnTouchListener, View.On
|
|||||||
|
|
||||||
if (mSetupPreviewAfterMeasure) {
|
if (mSetupPreviewAfterMeasure) {
|
||||||
mSetupPreviewAfterMeasure = false
|
mSetupPreviewAfterMeasure = false
|
||||||
if (mCamera != null)
|
mCamera?.stopPreview()
|
||||||
mCamera!!.stopPreview()
|
|
||||||
|
|
||||||
setupPreview()
|
setupPreview()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTouch(v: View, event: MotionEvent): Boolean {
|
|
||||||
mLastClickX = event.x.toInt()
|
|
||||||
mLastClickY = event.y.toInt()
|
|
||||||
|
|
||||||
if (mMaxZoom > 0)
|
|
||||||
mScaleGestureDetector!!.onTouchEvent(event)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun enableFlash() {
|
fun enableFlash() {
|
||||||
mParameters!!.flashMode = Camera.Parameters.FLASH_MODE_TORCH
|
mParameters!!.flashMode = Camera.Parameters.FLASH_MODE_TORCH
|
||||||
mCamera!!.parameters = mParameters
|
mCamera!!.parameters = mParameters
|
||||||
@ -481,7 +477,7 @@ class Preview : ViewGroup, SurfaceHolder.Callback, View.OnTouchListener, View.On
|
|||||||
mRecorder!!.setAudioSource(MediaRecorder.AudioSource.DEFAULT)
|
mRecorder!!.setAudioSource(MediaRecorder.AudioSource.DEFAULT)
|
||||||
|
|
||||||
mCurrVideoPath = Utils.getOutputMediaFile(mActivity, false)
|
mCurrVideoPath = Utils.getOutputMediaFile(mActivity, false)
|
||||||
if (mCurrVideoPath!!.isEmpty()) {
|
if (mCurrVideoPath.isEmpty()) {
|
||||||
mActivity.toast(R.string.video_creating_error)
|
mActivity.toast(R.string.video_creating_error)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -492,10 +488,10 @@ class Preview : ViewGroup, SurfaceHolder.Callback, View.OnTouchListener, View.On
|
|||||||
cpHigh.videoFrameHeight = videoSize.height;
|
cpHigh.videoFrameHeight = videoSize.height;
|
||||||
mRecorder.setProfile(cpHigh);*/
|
mRecorder.setProfile(cpHigh);*/
|
||||||
|
|
||||||
if (Utils.needsStupidWritePermissions(context, mCurrVideoPath!!)) {
|
if (mActivity.needsStupidWritePermissions(mCurrVideoPath)) {
|
||||||
if (mConfig!!.treeUri.isEmpty()) {
|
if (config.treeUri.isEmpty()) {
|
||||||
mActivity.toast(R.string.save_error_internal_storage)
|
mActivity.toast(R.string.save_error_internal_storage)
|
||||||
mConfig!!.savePhotosFolder = Environment.getExternalStorageDirectory().toString()
|
config.savePhotosFolder = Environment.getExternalStorageDirectory().toString()
|
||||||
releaseCamera()
|
releaseCamera()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -569,11 +565,10 @@ class Preview : ViewGroup, SurfaceHolder.Callback, View.OnTouchListener, View.On
|
|||||||
try {
|
try {
|
||||||
toggleShutterSound(true)
|
toggleShutterSound(true)
|
||||||
mRecorder!!.stop()
|
mRecorder!!.stop()
|
||||||
val paths = arrayListOf<String>(mCurrVideoPath!!)
|
mActivity.scanPath(mCurrVideoPath) {}
|
||||||
mActivity.scanPaths(paths) {}
|
|
||||||
} catch (e: RuntimeException) {
|
} catch (e: RuntimeException) {
|
||||||
toggleShutterSound(false)
|
toggleShutterSound(false)
|
||||||
File(mCurrVideoPath!!).delete()
|
File(mCurrVideoPath).delete()
|
||||||
mActivity.toast(R.string.video_saving_error)
|
mActivity.toast(R.string.video_saving_error)
|
||||||
Log.e(TAG, "stopRecording " + e.message)
|
Log.e(TAG, "stopRecording " + e.message)
|
||||||
mRecorder = null
|
mRecorder = null
|
||||||
@ -586,26 +581,18 @@ class Preview : ViewGroup, SurfaceHolder.Callback, View.OnTouchListener, View.On
|
|||||||
mRecorder = null
|
mRecorder = null
|
||||||
mIsRecording = false
|
mIsRecording = false
|
||||||
|
|
||||||
val file = File(mCurrVideoPath!!)
|
val file = File(mCurrVideoPath)
|
||||||
if (file.exists() && file.length() == 0L) {
|
if (file.exists() && file.length() == 0L) {
|
||||||
file.delete()
|
file.delete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun toggleShutterSound(mute: Boolean?) {
|
private fun toggleShutterSound(mute: Boolean?) {
|
||||||
if (!mConfig!!.isSoundEnabled) {
|
if (!config.isSoundEnabled) {
|
||||||
(mActivity.getSystemService(Context.AUDIO_SERVICE) as AudioManager).setStreamMute(AudioManager.STREAM_SYSTEM, mute!!)
|
(mActivity.getSystemService(Context.AUDIO_SERVICE) as AudioManager).setStreamMute(AudioManager.STREAM_SYSTEM, mute!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(v: View) {
|
|
||||||
if (!mWasZooming)
|
|
||||||
focusArea(false)
|
|
||||||
|
|
||||||
mWasZooming = false
|
|
||||||
mSurfaceView.isSoundEffectsEnabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onScanCompleted(path: String, uri: Uri) {
|
override fun onScanCompleted(path: String, uri: Uri) {
|
||||||
mCallback.videoSaved(uri)
|
mCallback.videoSaved(uri)
|
||||||
toggleShutterSound(false)
|
toggleShutterSound(false)
|
||||||
|
@ -9,8 +9,6 @@ import android.graphics.Point
|
|||||||
import android.hardware.Camera
|
import android.hardware.Camera
|
||||||
import android.support.v4.content.ContextCompat
|
import android.support.v4.content.ContextCompat
|
||||||
import android.view.Surface
|
import android.view.Surface
|
||||||
import com.simplemobiletools.commons.extensions.getFileDocument
|
|
||||||
import com.simplemobiletools.commons.extensions.needsStupidWritePermissions
|
|
||||||
import com.simplemobiletools.commons.extensions.toast
|
import com.simplemobiletools.commons.extensions.toast
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
@ -102,10 +100,6 @@ class Utils {
|
|||||||
|
|
||||||
fun hasAudioPermission(cxt: Context) = ContextCompat.checkSelfPermission(cxt, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED
|
fun hasAudioPermission(cxt: Context) = ContextCompat.checkSelfPermission(cxt, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED
|
||||||
|
|
||||||
fun needsStupidWritePermissions(context: Context, path: String) = context.needsStupidWritePermissions(path)
|
|
||||||
|
|
||||||
fun getFileDocument(context: Context, path: String, treeUri: String) = context.getFileDocument(path, treeUri)
|
|
||||||
|
|
||||||
fun getRotationDegrees(activity: Activity): Int {
|
fun getRotationDegrees(activity: Activity): Int {
|
||||||
return when (activity.windowManager.defaultDisplay.rotation) {
|
return when (activity.windowManager.defaultDisplay.rotation) {
|
||||||
Surface.ROTATION_0 -> 0
|
Surface.ROTATION_0 -> 0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user