mirror of
https://github.com/SimpleMobileTools/Simple-Camera.git
synced 2025-03-21 02:50:19 +01:00
updated Commons, min Android OS to 5, removed Camera One implementation
This commit is contained in:
parent
d7a9002076
commit
39aba65589
@ -3,13 +3,13 @@ apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion "27.0.3"
|
||||
compileSdkVersion 28
|
||||
buildToolsVersion "28.0.3"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.simplemobiletools.camera"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 27
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 28
|
||||
versionCode 63
|
||||
versionName "4.2.0"
|
||||
setProperty("archivesBaseName", "camera")
|
||||
@ -41,7 +41,7 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.simplemobiletools:commons:4.6.4'
|
||||
implementation 'com.simplemobiletools:commons:5.1.4'
|
||||
}
|
||||
|
||||
Properties props = new Properties()
|
||||
|
@ -102,7 +102,7 @@
|
||||
</receiver>
|
||||
|
||||
<provider
|
||||
android:name="android.support.v4.content.FileProvider"
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
|
@ -16,14 +16,12 @@ import com.bumptech.glide.request.RequestOptions
|
||||
import com.simplemobiletools.camera.BuildConfig
|
||||
import com.simplemobiletools.camera.R
|
||||
import com.simplemobiletools.camera.extensions.config
|
||||
import com.simplemobiletools.camera.extensions.getMyCamera
|
||||
import com.simplemobiletools.camera.extensions.navBarHeight
|
||||
import com.simplemobiletools.camera.helpers.*
|
||||
import com.simplemobiletools.camera.interfaces.MyCamera
|
||||
import com.simplemobiletools.camera.implementations.MyCameraImpl
|
||||
import com.simplemobiletools.camera.interfaces.MyPreview
|
||||
import com.simplemobiletools.camera.views.CameraPreview
|
||||
import com.simplemobiletools.camera.views.FocusCircleView
|
||||
import com.simplemobiletools.camera.views.PreviewCameraOne
|
||||
import com.simplemobiletools.camera.views.PreviewCameraTwo
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.models.Release
|
||||
@ -36,7 +34,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener {
|
||||
private lateinit var mOrientationEventListener: OrientationEventListener
|
||||
private lateinit var mFocusCircleView: FocusCircleView
|
||||
private lateinit var mFadeHandler: Handler
|
||||
private lateinit var mCameraImpl: MyCamera
|
||||
private lateinit var mCameraImpl: MyCameraImpl
|
||||
|
||||
private var mPreview: MyPreview? = null
|
||||
private var mPreviewUri: Uri? = null
|
||||
@ -116,7 +114,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener {
|
||||
mIsHardwareShutterHandled = false
|
||||
mCurrVideoRecTimer = 0
|
||||
mLastHandledOrientation = 0
|
||||
mCameraImpl = getMyCamera()
|
||||
mCameraImpl = MyCameraImpl(applicationContext)
|
||||
|
||||
if (config.alwaysOpenBackCamera) {
|
||||
config.lastUsedCamera = mCameraImpl.getBackCameraId().toString()
|
||||
@ -193,13 +191,10 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener {
|
||||
setContentView(R.layout.activity_main)
|
||||
initButtons()
|
||||
|
||||
camera_surface_view.beVisibleIf(!isLollipopPlus())
|
||||
camera_texture_view.beVisibleIf(isLollipopPlus())
|
||||
|
||||
(btn_holder.layoutParams as RelativeLayout.LayoutParams).setMargins(0, 0, 0, (navBarHeight + resources.getDimension(R.dimen.activity_margin)).toInt())
|
||||
|
||||
checkVideoCaptureIntent()
|
||||
mPreview = if (isLollipopPlus()) PreviewCameraTwo(this, camera_texture_view, mIsInPhotoMode) else PreviewCameraOne(this, camera_surface_view)
|
||||
mPreview = CameraPreview(this, camera_texture_view, mIsInPhotoMode)
|
||||
view_holder.addView(mPreview as ViewGroup)
|
||||
checkImageCaptureIntent()
|
||||
mPreview?.setIsImageCaptureIntent(isImageCaptureIntent())
|
||||
@ -373,7 +368,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener {
|
||||
mPreviewUri = Uri.withAppendedPath(uri, lastMediaId.toString())
|
||||
|
||||
runOnUiThread {
|
||||
if (!isActivityDestroyed()) {
|
||||
if (!isDestroyed) {
|
||||
val options = RequestOptions()
|
||||
.centerCrop()
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
@ -419,14 +414,6 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener {
|
||||
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LOW_PROFILE
|
||||
}
|
||||
|
||||
fun toggleTimer(show: Boolean) {
|
||||
if (show) {
|
||||
showTimer()
|
||||
} else {
|
||||
hideTimer()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showTimer() {
|
||||
video_rec_curr_timer.beVisible()
|
||||
setupTimer()
|
||||
@ -450,14 +437,10 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener {
|
||||
|
||||
private fun resumeCameraItems() {
|
||||
showToggleCameraIfNeeded()
|
||||
if (mPreview?.resumeCamera() == true) {
|
||||
hideNavigationBarIcons()
|
||||
hideNavigationBarIcons()
|
||||
|
||||
if (!mIsInPhotoMode) {
|
||||
initVideoButtons()
|
||||
}
|
||||
} else {
|
||||
toast(R.string.camera_switch_error)
|
||||
if (!mIsInPhotoMode) {
|
||||
initVideoButtons()
|
||||
}
|
||||
}
|
||||
|
||||
@ -470,7 +453,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener {
|
||||
private fun setupOrientationEventListener() {
|
||||
mOrientationEventListener = object : OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) {
|
||||
override fun onOrientationChanged(orientation: Int) {
|
||||
if (isActivityDestroyed()) {
|
||||
if (isDestroyed) {
|
||||
mOrientationEventListener.disable()
|
||||
return
|
||||
}
|
||||
@ -490,7 +473,6 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener {
|
||||
|
||||
animateViews(degrees)
|
||||
mLastHandledOrientation = currOrient
|
||||
mPreview?.deviceOrientationChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -555,7 +537,6 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener {
|
||||
fun drawFocusCircle(x: Float, y: Float) = mFocusCircleView.drawFocusCircle(x, y)
|
||||
|
||||
override fun mediaSaved(path: String) {
|
||||
mPreview?.imageSaved()
|
||||
rescanPaths(arrayListOf(path)) {
|
||||
setupPreviewImage(true)
|
||||
Intent(BROADCAST_REFRESH_MEDIA).apply {
|
||||
|
@ -10,7 +10,6 @@ import com.simplemobiletools.commons.dialogs.FilePickerDialog
|
||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.LICENSE_GLIDE
|
||||
import com.simplemobiletools.commons.helpers.isLollipopPlus
|
||||
import com.simplemobiletools.commons.models.FAQItem
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import kotlinx.android.synthetic.main.activity_settings.*
|
||||
@ -29,7 +28,6 @@ class SettingsActivity : SimpleActivity() {
|
||||
setupCustomizeColors()
|
||||
setupUseEnglish()
|
||||
setupAvoidWhatsNew()
|
||||
setupShowPreview()
|
||||
setupSound()
|
||||
setupFocusBeforeCapture()
|
||||
setupVolumeButtonsAsShutter()
|
||||
@ -111,15 +109,6 @@ class SettingsActivity : SimpleActivity() {
|
||||
return humanized.substringAfterLast("/", humanized)
|
||||
}
|
||||
|
||||
private fun setupShowPreview() {
|
||||
settings_show_preview_holder.beVisibleIf(!isLollipopPlus())
|
||||
settings_show_preview.isChecked = config.isShowPreviewEnabled
|
||||
settings_show_preview_holder.setOnClickListener {
|
||||
settings_show_preview.toggle()
|
||||
config.isShowPreviewEnabled = settings_show_preview.isChecked
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupSound() {
|
||||
settings_sound.isChecked = config.isSoundEnabled
|
||||
settings_sound_holder.setOnClickListener {
|
||||
|
@ -1,8 +1,8 @@
|
||||
package com.simplemobiletools.camera.dialogs
|
||||
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.simplemobiletools.camera.R
|
||||
import com.simplemobiletools.camera.activities.SimpleActivity
|
||||
import com.simplemobiletools.camera.extensions.config
|
||||
|
@ -4,9 +4,6 @@ import android.content.Context
|
||||
import android.graphics.Point
|
||||
import android.view.WindowManager
|
||||
import com.simplemobiletools.camera.helpers.Config
|
||||
import com.simplemobiletools.camera.implementations.MyCameraOneImpl
|
||||
import com.simplemobiletools.camera.implementations.MyCameraTwoImpl
|
||||
import com.simplemobiletools.commons.helpers.isLollipopPlus
|
||||
import java.io.File
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
@ -47,5 +44,3 @@ val Context.realScreenSize: Point
|
||||
}
|
||||
|
||||
val Context.navBarHeight: Int get() = realScreenSize.y - usableScreenSize.y
|
||||
|
||||
fun Context.getMyCamera() = if (isLollipopPlus()) MyCameraTwoImpl(applicationContext) else MyCameraOneImpl(applicationContext)
|
||||
|
@ -1,6 +0,0 @@
|
||||
package com.simplemobiletools.camera.extensions
|
||||
|
||||
import android.content.Context
|
||||
import android.hardware.Camera
|
||||
import com.simplemobiletools.camera.R
|
||||
|
@ -21,10 +21,6 @@ class Config(context: Context) : BaseConfig(context) {
|
||||
}
|
||||
set(path) = prefs.edit().putString(SAVE_PHOTOS, path).apply()
|
||||
|
||||
var isShowPreviewEnabled: Boolean
|
||||
get() = prefs.getBoolean(SHOW_PREVIEW, false)
|
||||
set(enabled) = prefs.edit().putBoolean(SHOW_PREVIEW, enabled).apply()
|
||||
|
||||
var isSoundEnabled: Boolean
|
||||
get() = prefs.getBoolean(SOUND, true)
|
||||
set(enabled) = prefs.edit().putBoolean(SOUND, enabled).apply()
|
||||
@ -73,10 +69,6 @@ class Config(context: Context) : BaseConfig(context) {
|
||||
get() = prefs.getInt(FRONT_VIDEO_RESOLUTION_INDEX, 0)
|
||||
set(frontVideoResIndex) = prefs.edit().putInt(FRONT_VIDEO_RESOLUTION_INDEX, frontVideoResIndex).apply()
|
||||
|
||||
var wasPhotoPreviewHintShown: Boolean
|
||||
get() = prefs.getBoolean(PHOTO_PREVIEW_HINT_SHOWN, false)
|
||||
set(wasPhotoPreviewHintShown) = prefs.edit().putBoolean(PHOTO_PREVIEW_HINT_SHOWN, wasPhotoPreviewHintShown).apply()
|
||||
|
||||
var keepSettingsVisible: Boolean
|
||||
get() = prefs.getBoolean(KEEP_SETTINGS_VISIBLE, false)
|
||||
set(keepSettingsVisible) = prefs.edit().putBoolean(KEEP_SETTINGS_VISIBLE, keepSettingsVisible).apply()
|
||||
|
@ -6,7 +6,6 @@ const val ORIENT_LANDSCAPE_RIGHT = 2
|
||||
|
||||
// shared preferences
|
||||
const val SAVE_PHOTOS = "save_photos"
|
||||
const val SHOW_PREVIEW = "show_preview"
|
||||
const val SOUND = "sound"
|
||||
const val FOCUS_BEFORE_CAPTURE = "focus_before_capture_2"
|
||||
const val VOLUME_BUTTONS_AS_SHUTTER = "volume_buttons_as_shutter"
|
||||
@ -19,7 +18,6 @@ const val BACK_PHOTO_RESOLUTION_INDEX = "back_photo_resolution_index_2"
|
||||
const val BACK_VIDEO_RESOLUTION_INDEX = "back_video_resolution_index_2"
|
||||
const val FRONT_PHOTO_RESOLUTION_INDEX = "front_photo_resolution_index_2"
|
||||
const val FRONT_VIDEO_RESOLUTION_INDEX = "front_video_resolution_index_2"
|
||||
const val PHOTO_PREVIEW_HINT_SHOWN = "photo_preview_hint_shown"
|
||||
const val KEEP_SETTINGS_VISIBLE = "keep_settings_visible"
|
||||
const val ALWAYS_OPEN_BACK_CAMERA = "always_open_back_camera"
|
||||
const val SAVE_PHOTO_METADATA = "save_photo_metadata"
|
||||
|
@ -0,0 +1,16 @@
|
||||
package com.simplemobiletools.camera.implementations
|
||||
|
||||
import android.content.Context
|
||||
import android.hardware.camera2.CameraCharacteristics
|
||||
import android.hardware.camera2.CameraManager
|
||||
|
||||
class MyCameraImpl(val context: Context) {
|
||||
fun getFrontCameraId() = CameraCharacteristics.LENS_FACING_FRONT
|
||||
|
||||
fun getBackCameraId() = CameraCharacteristics.LENS_FACING_BACK
|
||||
|
||||
fun getCountOfCameras(): Int {
|
||||
val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
|
||||
return manager.cameraIdList.size
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package com.simplemobiletools.camera.implementations
|
||||
|
||||
import android.content.Context
|
||||
import android.hardware.Camera
|
||||
import com.simplemobiletools.camera.interfaces.MyCamera
|
||||
|
||||
class MyCameraOneImpl(val context: Context) : MyCamera() {
|
||||
override fun getFrontCameraId() = Camera.CameraInfo.CAMERA_FACING_FRONT
|
||||
|
||||
override fun getBackCameraId() = Camera.CameraInfo.CAMERA_FACING_BACK
|
||||
|
||||
override fun getCountOfCameras() = Camera.getNumberOfCameras()
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
package com.simplemobiletools.camera.implementations
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.content.Context
|
||||
import android.hardware.camera2.CameraCharacteristics
|
||||
import android.hardware.camera2.CameraManager
|
||||
import android.os.Build
|
||||
import com.simplemobiletools.camera.interfaces.MyCamera
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
class MyCameraTwoImpl(val context: Context) : MyCamera() {
|
||||
override fun getFrontCameraId() = CameraCharacteristics.LENS_FACING_FRONT
|
||||
|
||||
override fun getBackCameraId() = CameraCharacteristics.LENS_FACING_BACK
|
||||
|
||||
override fun getCountOfCameras(): Int {
|
||||
val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
|
||||
return manager.cameraIdList.size
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package com.simplemobiletools.camera.interfaces
|
||||
|
||||
abstract class MyCamera {
|
||||
abstract fun getFrontCameraId(): Int
|
||||
|
||||
abstract fun getBackCameraId(): Int
|
||||
|
||||
abstract fun getCountOfCameras(): Int
|
||||
}
|
@ -32,10 +32,4 @@ interface MyPreview {
|
||||
fun initVideoMode(): Boolean
|
||||
|
||||
fun checkFlashlight()
|
||||
|
||||
fun deviceOrientationChanged()
|
||||
|
||||
fun resumeCamera(): Boolean
|
||||
|
||||
fun imageSaved()
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
package com.simplemobiletools.camera.models
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.Size
|
||||
import com.simplemobiletools.camera.R
|
||||
|
||||
@ -45,6 +43,5 @@ data class MySize(val width: Int, val height: Int) {
|
||||
else -> context.resources.getString(R.string.other)
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
fun toSize() = Size(width, height)
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.simplemobiletools.camera.views
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.annotation.TargetApi
|
||||
import android.content.Context
|
||||
import android.graphics.ImageFormat
|
||||
import android.graphics.Matrix
|
||||
@ -14,7 +13,6 @@ import android.media.ImageReader
|
||||
import android.media.MediaActionSound
|
||||
import android.media.MediaRecorder
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import android.util.DisplayMetrics
|
||||
@ -30,30 +28,22 @@ import com.simplemobiletools.camera.R
|
||||
import com.simplemobiletools.camera.activities.MainActivity
|
||||
import com.simplemobiletools.camera.dialogs.ChangeResolutionDialog
|
||||
import com.simplemobiletools.camera.extensions.config
|
||||
import com.simplemobiletools.camera.extensions.getMyCamera
|
||||
import com.simplemobiletools.camera.extensions.getOutputMediaFile
|
||||
import com.simplemobiletools.camera.helpers.*
|
||||
import com.simplemobiletools.camera.implementations.MyCameraImpl
|
||||
import com.simplemobiletools.camera.interfaces.MyPreview
|
||||
import com.simplemobiletools.camera.models.FocusArea
|
||||
import com.simplemobiletools.camera.models.MySize
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.isJellyBean1Plus
|
||||
import com.simplemobiletools.commons.models.FileDirItem
|
||||
import java.io.File
|
||||
import java.lang.IllegalArgumentException
|
||||
import java.lang.InterruptedException
|
||||
import java.lang.Math
|
||||
import java.lang.System
|
||||
import java.lang.Thread
|
||||
import java.util.*
|
||||
import java.util.concurrent.Semaphore
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.RuntimeException
|
||||
|
||||
// based on the Android Camera2 photo sample at https://github.com/googlesamples/android-Camera2Basic
|
||||
// and video sample at https://github.com/googlesamples/android-Camera2Video
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
class PreviewCameraTwo : ViewGroup, TextureView.SurfaceTextureListener, MyPreview {
|
||||
class CameraPreview : ViewGroup, TextureView.SurfaceTextureListener, MyPreview {
|
||||
private val FOCUS_TAG = "focus_tag"
|
||||
private val MAX_PREVIEW_WIDTH = 1920
|
||||
private val MAX_PREVIEW_HEIGHT = 1080
|
||||
@ -129,7 +119,7 @@ class PreviewCameraTwo : ViewGroup, TextureView.SurfaceTextureListener, MyPrevie
|
||||
null
|
||||
}
|
||||
|
||||
val isFrontCamera = cameraCharacteristics?.get(CameraCharacteristics.LENS_FACING).toString() == activity.getMyCamera().getFrontCameraId().toString()
|
||||
val isFrontCamera = cameraCharacteristics?.get(CameraCharacteristics.LENS_FACING).toString() == MyCameraImpl(activity).getFrontCameraId().toString()
|
||||
mUseFrontCamera = !activity.config.alwaysOpenBackCamera && isFrontCamera
|
||||
mIsInVideoMode = !initPhotoMode
|
||||
loadSounds()
|
||||
@ -417,13 +407,8 @@ class PreviewCameraTwo : ViewGroup, TextureView.SurfaceTextureListener, MyPrevie
|
||||
|
||||
private fun getRealDisplaySize(): MySize {
|
||||
val metrics = DisplayMetrics()
|
||||
return if (isJellyBean1Plus()) {
|
||||
mActivity.windowManager.defaultDisplay.getRealMetrics(metrics)
|
||||
MySize(metrics.widthPixels, metrics.heightPixels)
|
||||
} else {
|
||||
mActivity.windowManager.defaultDisplay.getMetrics(metrics)
|
||||
MySize(metrics.widthPixels, metrics.heightPixels)
|
||||
}
|
||||
mActivity.windowManager.defaultDisplay.getRealMetrics(metrics)
|
||||
return MySize(metrics.widthPixels, metrics.heightPixels)
|
||||
}
|
||||
|
||||
private val cameraStateCallback = object : CameraDevice.StateCallback() {
|
||||
@ -718,53 +703,6 @@ class PreviewCameraTwo : ViewGroup, TextureView.SurfaceTextureListener, MyPrevie
|
||||
return FocusArea(rect, MeteringRectangle.METERING_WEIGHT_MAX)
|
||||
}
|
||||
|
||||
// touch-to-focus stucks after capturing a photo without "Focus before capture" so just reset the whole session until fixed properly
|
||||
private fun resetPreviewSession() {
|
||||
val stateCallback = object : CameraCaptureSession.StateCallback() {
|
||||
override fun onConfigured(cameraCaptureSession: CameraCaptureSession) {
|
||||
if (mCameraDevice == null) {
|
||||
return
|
||||
}
|
||||
|
||||
mCaptureSession = cameraCaptureSession
|
||||
try {
|
||||
mPreviewRequestBuilder!!.apply {
|
||||
set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
|
||||
setFlashAndExposure(this)
|
||||
mPreviewRequest = build()
|
||||
}
|
||||
mCaptureSession!!.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mBackgroundHandler)
|
||||
mCameraState = STATE_PREVIEW
|
||||
|
||||
Handler().postDelayed({
|
||||
if (mLastFocusX != 0f && mLastFocusY != 0f) {
|
||||
if (mCaptureSession != null) {
|
||||
focusArea(mLastFocusX, mLastFocusY, false)
|
||||
}
|
||||
}
|
||||
}, 200L)
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onConfigureFailed(cameraCaptureSession: CameraCaptureSession) {}
|
||||
}
|
||||
|
||||
try {
|
||||
closeCaptureSession()
|
||||
val texture = mTextureView.surfaceTexture!!
|
||||
texture.setDefaultBufferSize(mPreviewSize!!.width, mPreviewSize!!.height)
|
||||
|
||||
val currentResolution = getCurrentResolution()
|
||||
mImageReader = ImageReader.newInstance(currentResolution.width, currentResolution.height, ImageFormat.JPEG, 2)
|
||||
mImageReader!!.setOnImageAvailableListener(imageAvailableListener, mBackgroundHandler)
|
||||
|
||||
val surface = Surface(texture)
|
||||
mCameraDevice!!.createCaptureSession(Arrays.asList(surface, mImageReader!!.surface), stateCallback, null)
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateCameraToPreviewMatrix() {
|
||||
val yScale = if (mUseFrontCamera) -1 else 1
|
||||
mCameraToPreviewMatrix.apply {
|
||||
@ -1034,11 +972,5 @@ class PreviewCameraTwo : ViewGroup, TextureView.SurfaceTextureListener, MyPrevie
|
||||
}
|
||||
}
|
||||
|
||||
override fun deviceOrientationChanged() {}
|
||||
|
||||
override fun resumeCamera() = true
|
||||
|
||||
override fun imageSaved() {}
|
||||
|
||||
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {}
|
||||
}
|
@ -1,922 +0,0 @@
|
||||
package com.simplemobiletools.camera.views
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.annotation.TargetApi
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.graphics.Point
|
||||
import android.graphics.Rect
|
||||
import android.hardware.Camera
|
||||
import android.media.AudioManager
|
||||
import android.media.CamcorderProfile
|
||||
import android.media.MediaPlayer
|
||||
import android.media.MediaRecorder
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.os.Handler
|
||||
import android.view.*
|
||||
import com.simplemobiletools.camera.R
|
||||
import com.simplemobiletools.camera.activities.MainActivity
|
||||
import com.simplemobiletools.camera.dialogs.ChangeResolutionDialog
|
||||
import com.simplemobiletools.camera.extensions.config
|
||||
import com.simplemobiletools.camera.extensions.getMyCamera
|
||||
import com.simplemobiletools.camera.extensions.getOutputMediaFile
|
||||
import com.simplemobiletools.camera.extensions.realScreenSize
|
||||
import com.simplemobiletools.camera.helpers.*
|
||||
import com.simplemobiletools.camera.implementations.MyCameraOneImpl
|
||||
import com.simplemobiletools.camera.interfaces.MyPreview
|
||||
import com.simplemobiletools.camera.models.MySize
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.isJellyBean1Plus
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
class PreviewCameraOne : ViewGroup, SurfaceHolder.Callback, MyPreview {
|
||||
private val FOCUS_AREA_SIZE = 100
|
||||
private val PHOTO_PREVIEW_LENGTH = 500L
|
||||
private val REFOCUS_PERIOD = 3000L
|
||||
|
||||
private lateinit var mSurfaceHolder: SurfaceHolder
|
||||
private lateinit var mSurfaceView: SurfaceView
|
||||
private lateinit var mScreenSize: Point
|
||||
private lateinit var mConfig: Config
|
||||
private var mSupportedPreviewSizes: List<Camera.Size>? = null
|
||||
private var mPreviewSize: Camera.Size? = null
|
||||
private var mParameters: Camera.Parameters? = null
|
||||
private var mRecorder: MediaRecorder? = null
|
||||
private var mScaleGestureDetector: ScaleGestureDetector? = null
|
||||
private var mZoomRatios = ArrayList<Int>()
|
||||
private var mFlashlightState = FLASH_OFF
|
||||
private var mCamera: Camera? = null
|
||||
private var mCameraImpl: MyCameraOneImpl? = null
|
||||
private var mAutoFocusHandler = Handler()
|
||||
private var mActivity: MainActivity? = null
|
||||
private var mTargetUri: Uri? = null
|
||||
private var mCameraState = STATE_PREVIEW
|
||||
|
||||
private var mCurrVideoPath = ""
|
||||
private var mCanTakePicture = false
|
||||
private var mIsRecording = false
|
||||
private var mIsInVideoMode = false
|
||||
private var mIsSurfaceCreated = false
|
||||
private var mSwitchToVideoAsap = false
|
||||
private var mSetupPreviewAfterMeasure = false
|
||||
private var mIsSixteenToNine = false
|
||||
private var mWasZooming = false
|
||||
private var mIsPreviewShown = false
|
||||
private var mWasCameraPreviewSet = false
|
||||
private var mIsImageCaptureIntent = false
|
||||
private var mIsFocusingBeforeCapture = false
|
||||
private var mLastClickX = 0f
|
||||
private var mLastClickY = 0f
|
||||
private var mCurrCameraId = 0
|
||||
private var mMaxZoom = 0
|
||||
private var mRotationAtCapture = 0
|
||||
|
||||
constructor(context: Context) : super(context)
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
constructor(activity: MainActivity, surfaceView: SurfaceView) : super(activity) {
|
||||
mActivity = activity
|
||||
mSurfaceView = surfaceView
|
||||
mSurfaceHolder = mSurfaceView.holder
|
||||
mSurfaceHolder.addCallback(this)
|
||||
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS)
|
||||
mCameraImpl = MyCameraOneImpl(activity.applicationContext)
|
||||
mConfig = activity.config
|
||||
mScreenSize = getScreenSize()
|
||||
initGestureDetector()
|
||||
|
||||
mSurfaceView.setOnTouchListener { view, event ->
|
||||
mLastClickX = event.x
|
||||
mLastClickY = event.y
|
||||
|
||||
if (mMaxZoom > 0 && mParameters?.isZoomSupported == true) {
|
||||
mScaleGestureDetector!!.onTouchEvent(event)
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
mSurfaceView.setOnClickListener {
|
||||
if (mIsPreviewShown) {
|
||||
resumePreview()
|
||||
} else {
|
||||
if (!mWasZooming && !mIsPreviewShown) {
|
||||
focusArea(false)
|
||||
}
|
||||
|
||||
mWasZooming = false
|
||||
mSurfaceView.isSoundEffectsEnabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResumed() {}
|
||||
|
||||
override fun onPaused() {
|
||||
releaseCamera()
|
||||
}
|
||||
|
||||
override fun tryInitVideoMode() {
|
||||
if (mIsSurfaceCreated) {
|
||||
initVideoMode()
|
||||
} else {
|
||||
mSwitchToVideoAsap = true
|
||||
}
|
||||
}
|
||||
|
||||
override fun resumeCamera(): Boolean {
|
||||
val newCamera: Camera
|
||||
try {
|
||||
newCamera = Camera.open(mCurrCameraId)
|
||||
mActivity!!.setIsCameraAvailable(true)
|
||||
} catch (e: Exception) {
|
||||
mActivity!!.showErrorToast(e)
|
||||
mActivity!!.setIsCameraAvailable(false)
|
||||
return false
|
||||
}
|
||||
|
||||
if (mCamera === newCamera) {
|
||||
return false
|
||||
}
|
||||
|
||||
releaseCamera()
|
||||
mCamera = newCamera
|
||||
if (initCamera() && mIsInVideoMode) {
|
||||
initVideoMode()
|
||||
}
|
||||
|
||||
if (!mWasCameraPreviewSet && mIsSurfaceCreated) {
|
||||
mCamera!!.setPreviewDisplay(mSurfaceHolder)
|
||||
mWasCameraPreviewSet = true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun imageSaved() {}
|
||||
|
||||
private fun initCamera(): Boolean {
|
||||
if (mCamera == null)
|
||||
return false
|
||||
|
||||
mParameters = mCamera!!.parameters
|
||||
mMaxZoom = mParameters!!.maxZoom
|
||||
|
||||
if (mParameters!!.isZoomSupported)
|
||||
mZoomRatios = mParameters!!.zoomRatios as ArrayList<Int>
|
||||
|
||||
mSupportedPreviewSizes = mParameters!!.supportedPreviewSizes.sortedByDescending { it.width * it.height }
|
||||
refreshPreview()
|
||||
|
||||
// hackfix for slow photo preview, more info at https://github.com/SimpleMobileTools/Simple-Camera/issues/120
|
||||
if (Build.MODEL == "Nexus 4") {
|
||||
mParameters!!.setRecordingHint(true)
|
||||
}
|
||||
|
||||
val focusModes = mParameters!!.supportedFocusModes
|
||||
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
|
||||
mParameters!!.focusMode = Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE
|
||||
}
|
||||
|
||||
mCamera!!.setDisplayOrientation(getPreviewRotation(mCurrCameraId))
|
||||
mParameters!!.zoom = 0
|
||||
updateCameraParameters()
|
||||
|
||||
if (mCanTakePicture) {
|
||||
try {
|
||||
mCamera!!.setPreviewDisplay(mSurfaceHolder)
|
||||
} catch (e: IOException) {
|
||||
mActivity!!.showErrorToast(e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
mActivity!!.setFlashAvailable(hasFlash(mCamera))
|
||||
return true
|
||||
}
|
||||
|
||||
override fun toggleFrontBackCamera() {
|
||||
mCurrCameraId = if (mCurrCameraId == mCameraImpl!!.getBackCameraId()) {
|
||||
mCameraImpl!!.getFrontCameraId()
|
||||
} else {
|
||||
mCameraImpl!!.getBackCameraId()
|
||||
}
|
||||
|
||||
mConfig.lastUsedCamera = mCurrCameraId.toString()
|
||||
releaseCamera()
|
||||
if (resumeCamera()) {
|
||||
setFlashlightState(FLASH_OFF)
|
||||
mActivity?.updateCameraIcon(mCurrCameraId == mCameraImpl!!.getFrontCameraId())
|
||||
mActivity?.toggleTimer(false)
|
||||
} else {
|
||||
mActivity?.toast(R.string.camera_switch_error)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getCameraState() = mCameraState
|
||||
|
||||
private fun refreshPreview() {
|
||||
mIsSixteenToNine = getSelectedResolution().isSixteenToNine()
|
||||
mSetupPreviewAfterMeasure = true
|
||||
requestLayout()
|
||||
invalidate()
|
||||
rescheduleAutofocus()
|
||||
}
|
||||
|
||||
private fun getSelectedResolution(): MySize {
|
||||
if (mParameters == null) {
|
||||
mParameters = mCamera!!.parameters
|
||||
}
|
||||
|
||||
var index = getResolutionIndex()
|
||||
val resolutions = if (mIsInVideoMode) {
|
||||
mParameters!!.supportedVideoSizes ?: mParameters!!.supportedPreviewSizes
|
||||
} else {
|
||||
mParameters!!.supportedPictureSizes
|
||||
}.map { MySize(it.width, it.height) }.sortedByDescending { it.width * it.height }
|
||||
|
||||
if (index == -1) {
|
||||
index = getDefaultFullscreenResolution(resolutions) ?: 0
|
||||
}
|
||||
|
||||
return resolutions[index]
|
||||
}
|
||||
|
||||
private fun getResolutionIndex(): Int {
|
||||
val isBackCamera = mConfig.lastUsedCamera == Camera.CameraInfo.CAMERA_FACING_BACK.toString()
|
||||
return if (mIsInVideoMode) {
|
||||
if (isBackCamera) mConfig.backVideoResIndex else mConfig.frontVideoResIndex
|
||||
} else {
|
||||
if (isBackCamera) mConfig.backPhotoResIndex else mConfig.frontPhotoResIndex
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDefaultFullscreenResolution(resolutions: List<MySize>): Int? {
|
||||
val screenAspectRatio = mActivity!!.realScreenSize.y / mActivity!!.realScreenSize.x.toFloat()
|
||||
resolutions.forEachIndexed { index, size ->
|
||||
val diff = screenAspectRatio - (size.width / size.height.toFloat())
|
||||
if (Math.abs(diff) < 0.1f) {
|
||||
mConfig.backPhotoResIndex = index
|
||||
return index
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun initGestureDetector() {
|
||||
mScaleGestureDetector = ScaleGestureDetector(mActivity, object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
|
||||
override fun onScale(detector: ScaleGestureDetector): Boolean {
|
||||
val zoomFactor = mParameters!!.zoom
|
||||
var zoomRatio = mZoomRatios[zoomFactor] / 100f
|
||||
zoomRatio *= detector.scaleFactor
|
||||
|
||||
var newZoomFactor = zoomFactor
|
||||
if (zoomRatio <= 1f) {
|
||||
newZoomFactor = 0
|
||||
} else if (zoomRatio >= mZoomRatios[mMaxZoom] / 100f) {
|
||||
newZoomFactor = mMaxZoom
|
||||
} else {
|
||||
if (detector.scaleFactor > 1f) {
|
||||
for (i in zoomFactor until mZoomRatios.size) {
|
||||
if (mZoomRatios[i] / 100.0f >= zoomRatio) {
|
||||
newZoomFactor = i
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i in zoomFactor downTo 0) {
|
||||
if (mZoomRatios[i] / 100.0f <= zoomRatio) {
|
||||
newZoomFactor = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newZoomFactor = Math.max(newZoomFactor, 0)
|
||||
newZoomFactor = Math.min(mMaxZoom, newZoomFactor)
|
||||
|
||||
mParameters!!.zoom = newZoomFactor
|
||||
updateCameraParameters()
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onScaleEnd(detector: ScaleGestureDetector) {
|
||||
super.onScaleEnd(detector)
|
||||
mWasZooming = true
|
||||
mSurfaceView.isSoundEffectsEnabled = false
|
||||
mParameters!!.focusAreas = null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun tryTakePicture() {
|
||||
if (mConfig.focusBeforeCapture) {
|
||||
focusArea(true)
|
||||
} else {
|
||||
takePicture()
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
private fun takePicture() {
|
||||
if (mCanTakePicture) {
|
||||
val selectedResolution = getSelectedResolution()
|
||||
mParameters!!.setPictureSize(selectedResolution.width, selectedResolution.height)
|
||||
val pictureSize = mParameters!!.pictureSize
|
||||
if (selectedResolution.width != pictureSize.width || selectedResolution.height != pictureSize.height) {
|
||||
mActivity!!.toast(R.string.setting_resolution_failed)
|
||||
}
|
||||
|
||||
if (isJellyBean1Plus()) {
|
||||
mCamera!!.enableShutterSound(false)
|
||||
}
|
||||
|
||||
mRotationAtCapture = mActivity!!.mLastHandledOrientation
|
||||
updateCameraParameters()
|
||||
mCameraState = STATE_PICTURE_TAKEN
|
||||
mIsPreviewShown = true
|
||||
try {
|
||||
Thread {
|
||||
mCamera!!.takePicture(null, null, takePictureCallback)
|
||||
|
||||
if (mConfig.isSoundEnabled) {
|
||||
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
val volume = audioManager.getStreamVolume(AudioManager.STREAM_SYSTEM)
|
||||
if (volume != 0) {
|
||||
val mp = MediaPlayer.create(context, Uri.parse("file:///system/media/audio/ui/camera_click.ogg"))
|
||||
mp?.start()
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
}
|
||||
mCanTakePicture = false
|
||||
mIsFocusingBeforeCapture = false
|
||||
}
|
||||
|
||||
private val takePictureCallback = Camera.PictureCallback { data, cam ->
|
||||
if (data.isEmpty()) {
|
||||
mActivity!!.toast(R.string.unknown_error_occurred)
|
||||
return@PictureCallback
|
||||
}
|
||||
|
||||
mCameraState = STATE_PREVIEW
|
||||
if (!mIsImageCaptureIntent) {
|
||||
handlePreview()
|
||||
}
|
||||
|
||||
if (mIsImageCaptureIntent) {
|
||||
if (mTargetUri != null) {
|
||||
storePhoto(data)
|
||||
} else {
|
||||
mActivity!!.apply {
|
||||
setResult(Activity.RESULT_OK)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
storePhoto(data)
|
||||
}
|
||||
}
|
||||
|
||||
private fun storePhoto(data: ByteArray) {
|
||||
val previewRotation = getPreviewRotation(mCurrCameraId)
|
||||
PhotoProcessor(mActivity!!, mTargetUri, mRotationAtCapture, previewRotation, getIsUsingFrontCamera(), mIsImageCaptureIntent).execute(data)
|
||||
}
|
||||
|
||||
private fun getIsUsingFrontCamera() = mCurrCameraId == mActivity!!.getMyCamera().getFrontCameraId()
|
||||
|
||||
private fun handlePreview() {
|
||||
if (mConfig.isShowPreviewEnabled) {
|
||||
if (!mConfig.wasPhotoPreviewHintShown) {
|
||||
mActivity!!.toast(R.string.click_to_resume_preview)
|
||||
mConfig.wasPhotoPreviewHintShown = true
|
||||
}
|
||||
} else {
|
||||
Handler().postDelayed({
|
||||
mIsPreviewShown = false
|
||||
resumePreview()
|
||||
}, PHOTO_PREVIEW_LENGTH)
|
||||
}
|
||||
}
|
||||
|
||||
private fun resumePreview() {
|
||||
mIsPreviewShown = false
|
||||
mActivity!!.toggleBottomButtons(false)
|
||||
try {
|
||||
mCamera?.startPreview()
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
mCanTakePicture = true
|
||||
focusArea(false, false)
|
||||
}
|
||||
|
||||
private fun focusArea(takePictureAfter: Boolean, showFocusRect: Boolean = true) {
|
||||
if (mCamera == null || (mIsFocusingBeforeCapture && !takePictureAfter)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (takePictureAfter) {
|
||||
mIsFocusingBeforeCapture = true
|
||||
}
|
||||
|
||||
mCamera!!.cancelAutoFocus()
|
||||
if (mParameters!!.maxNumFocusAreas > 0) {
|
||||
if (mLastClickX == 0f && mLastClickY == 0f) {
|
||||
mLastClickX = width / 2.toFloat()
|
||||
mLastClickY = height / 2.toFloat()
|
||||
}
|
||||
|
||||
val focusRect = calculateFocusArea(mLastClickX, mLastClickY)
|
||||
val focusAreas = ArrayList<Camera.Area>(1)
|
||||
focusAreas.add(Camera.Area(focusRect, 1000))
|
||||
mParameters!!.focusAreas = focusAreas
|
||||
|
||||
if (showFocusRect) {
|
||||
mActivity!!.drawFocusCircle(mLastClickX, mLastClickY)
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
val focusModes = mParameters!!.supportedFocusModes
|
||||
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
|
||||
mParameters!!.focusMode = Camera.Parameters.FOCUS_MODE_AUTO
|
||||
}
|
||||
|
||||
updateCameraParameters()
|
||||
mCamera!!.autoFocus { success, camera ->
|
||||
if (camera == null || mCamera == null) {
|
||||
return@autoFocus
|
||||
}
|
||||
|
||||
mCamera!!.cancelAutoFocus()
|
||||
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
|
||||
mParameters!!.focusMode = Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE
|
||||
}
|
||||
|
||||
updateCameraParameters()
|
||||
|
||||
if (takePictureAfter) {
|
||||
takePicture()
|
||||
} else {
|
||||
rescheduleAutofocus()
|
||||
}
|
||||
}
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateFocusArea(x: Float, y: Float): Rect {
|
||||
var left = x / mSurfaceView.width * 2000 - 1000
|
||||
var top = y / mSurfaceView.height * 2000 - 1000
|
||||
|
||||
val tmp = left
|
||||
left = top
|
||||
top = -tmp
|
||||
|
||||
val rectLeft = Math.max(left.toInt() - FOCUS_AREA_SIZE / 2, -1000)
|
||||
val rectTop = Math.max(top.toInt() - FOCUS_AREA_SIZE / 2, -1000)
|
||||
val rectRight = Math.min(left.toInt() + FOCUS_AREA_SIZE / 2, 1000)
|
||||
val rectBottom = Math.min(top.toInt() + FOCUS_AREA_SIZE / 2, 1000)
|
||||
return Rect(rectLeft, rectTop, rectRight, rectBottom)
|
||||
}
|
||||
|
||||
private fun rescheduleAutofocus() {
|
||||
mAutoFocusHandler.removeCallbacksAndMessages(null)
|
||||
mAutoFocusHandler.postDelayed({
|
||||
if (!mIsInVideoMode || !mIsRecording) {
|
||||
focusArea(false, false)
|
||||
}
|
||||
}, REFOCUS_PERIOD)
|
||||
}
|
||||
|
||||
override fun showChangeResolutionDialog() {
|
||||
if (mCamera != null) {
|
||||
val oldResolution = getSelectedResolution()
|
||||
val photoResolutions = mCamera!!.parameters.supportedPictureSizes.map { MySize(it.width, it.height) } as ArrayList<MySize>
|
||||
val videoSizes = mCamera!!.parameters.supportedVideoSizes ?: mCamera!!.parameters.supportedPreviewSizes
|
||||
val videoResolutions = videoSizes.map { MySize(it.width, it.height) } as ArrayList<MySize>
|
||||
ChangeResolutionDialog(mActivity!!, getIsUsingFrontCamera(), photoResolutions, videoResolutions, false) {
|
||||
if (oldResolution != getSelectedResolution()) {
|
||||
refreshPreview()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun releaseCamera() {
|
||||
stopRecording()
|
||||
mCamera?.stopPreview()
|
||||
mCamera?.release()
|
||||
mCamera = null
|
||||
cleanupRecorder()
|
||||
}
|
||||
|
||||
override fun surfaceCreated(holder: SurfaceHolder) {
|
||||
mIsSurfaceCreated = true
|
||||
try {
|
||||
mWasCameraPreviewSet = mCamera != null
|
||||
mCamera?.setPreviewDisplay(mSurfaceHolder)
|
||||
|
||||
if (mSwitchToVideoAsap)
|
||||
initVideoMode()
|
||||
} catch (e: IOException) {
|
||||
mActivity!!.showErrorToast(e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
|
||||
mIsSurfaceCreated = true
|
||||
|
||||
if (mIsInVideoMode) {
|
||||
initVideoMode()
|
||||
}
|
||||
}
|
||||
|
||||
override fun surfaceDestroyed(holder: SurfaceHolder) {
|
||||
mIsSurfaceCreated = false
|
||||
mCamera?.stopPreview()
|
||||
cleanupRecorder()
|
||||
}
|
||||
|
||||
private fun setupPreview() {
|
||||
mCanTakePicture = true
|
||||
if (mCamera != null && mPreviewSize != null) {
|
||||
if (mParameters == null)
|
||||
mParameters = mCamera!!.parameters
|
||||
|
||||
mParameters!!.setPreviewSize(mPreviewSize!!.width, mPreviewSize!!.height)
|
||||
updateCameraParameters()
|
||||
try {
|
||||
mCamera!!.startPreview()
|
||||
} catch (e: RuntimeException) {
|
||||
mActivity!!.showErrorToast(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun cleanupRecorder() {
|
||||
if (mRecorder != null) {
|
||||
if (mIsRecording) {
|
||||
stopRecording()
|
||||
}
|
||||
|
||||
mRecorder!!.release()
|
||||
mRecorder = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {}
|
||||
|
||||
private fun getOptimalPreviewSize(sizes: List<Camera.Size>, width: Int, height: Int): Camera.Size {
|
||||
var result: Camera.Size? = null
|
||||
for (size in sizes) {
|
||||
if (size.width <= width && size.height <= height) {
|
||||
if (result == null) {
|
||||
result = size
|
||||
} else {
|
||||
val resultArea = result.width * result.height
|
||||
val newArea = size.width * size.height
|
||||
|
||||
if (newArea > resultArea) {
|
||||
result = size
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result!!
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
setMeasuredDimension(mScreenSize.x, mScreenSize.y)
|
||||
|
||||
if (mSupportedPreviewSizes != null) {
|
||||
// for simplicity lets assume that most displays are 16:9 and the remaining ones are 4:3
|
||||
// always set 16:9 for videos as many devices support 4:3 only in low quality
|
||||
mPreviewSize = if (mIsSixteenToNine || mIsInVideoMode) {
|
||||
getOptimalPreviewSize(mSupportedPreviewSizes!!, mScreenSize.y, mScreenSize.x)
|
||||
} else {
|
||||
val newRatioHeight = (mScreenSize.x * (4.toDouble() / 3)).toInt()
|
||||
setMeasuredDimension(mScreenSize.x, newRatioHeight)
|
||||
getOptimalPreviewSize(mSupportedPreviewSizes!!, newRatioHeight, mScreenSize.x)
|
||||
}
|
||||
val lp = mSurfaceView.layoutParams
|
||||
|
||||
// make sure to occupy whole width in every case
|
||||
if (mScreenSize.x > mPreviewSize!!.height) {
|
||||
val ratio = mScreenSize.x.toFloat() / mPreviewSize!!.height
|
||||
lp.width = (mPreviewSize!!.height * ratio).toInt()
|
||||
if (mIsSixteenToNine || mIsInVideoMode) {
|
||||
lp.height = mScreenSize.y
|
||||
} else {
|
||||
lp.height = (mPreviewSize!!.width * ratio).toInt()
|
||||
}
|
||||
} else {
|
||||
lp.width = mPreviewSize!!.height
|
||||
lp.height = mPreviewSize!!.width
|
||||
}
|
||||
|
||||
if (mSetupPreviewAfterMeasure) {
|
||||
if (mCamera != null) {
|
||||
mSetupPreviewAfterMeasure = false
|
||||
mCamera!!.stopPreview()
|
||||
setupPreview()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setFlashlightState(state: Int) {
|
||||
mFlashlightState = state
|
||||
checkFlashlight()
|
||||
}
|
||||
|
||||
override fun toggleFlashlight() {
|
||||
val newState = ++mFlashlightState % if (mIsInVideoMode) 2 else 3
|
||||
setFlashlightState(newState)
|
||||
}
|
||||
|
||||
override fun checkFlashlight() {
|
||||
when (mFlashlightState) {
|
||||
FLASH_OFF -> disableFlash()
|
||||
FLASH_ON -> enableFlash()
|
||||
FLASH_AUTO -> setAutoFlash()
|
||||
}
|
||||
mActivity?.updateFlashlightState(mFlashlightState)
|
||||
}
|
||||
|
||||
private fun disableFlash() {
|
||||
mFlashlightState = FLASH_OFF
|
||||
mParameters?.flashMode = Camera.Parameters.FLASH_MODE_OFF
|
||||
updateCameraParameters()
|
||||
}
|
||||
|
||||
private fun enableFlash() {
|
||||
mFlashlightState = FLASH_ON
|
||||
mParameters?.flashMode = Camera.Parameters.FLASH_MODE_TORCH
|
||||
updateCameraParameters()
|
||||
}
|
||||
|
||||
private fun setAutoFlash() {
|
||||
mFlashlightState = FLASH_AUTO
|
||||
mParameters?.flashMode = Camera.Parameters.FLASH_MODE_OFF
|
||||
updateCameraParameters()
|
||||
|
||||
Handler().postDelayed({
|
||||
mActivity?.runOnUiThread {
|
||||
mParameters?.flashMode = Camera.Parameters.FLASH_MODE_AUTO
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
override fun initPhotoMode() {
|
||||
stopRecording()
|
||||
cleanupRecorder()
|
||||
mIsRecording = false
|
||||
mIsInVideoMode = false
|
||||
refreshPreview()
|
||||
}
|
||||
|
||||
// VIDEO RECORDING
|
||||
override fun initVideoMode(): Boolean {
|
||||
if (mCamera == null || mRecorder != null || !mIsSurfaceCreated) {
|
||||
return false
|
||||
}
|
||||
|
||||
refreshPreview()
|
||||
mSwitchToVideoAsap = false
|
||||
|
||||
mIsRecording = false
|
||||
mIsInVideoMode = true
|
||||
mRecorder = MediaRecorder().apply {
|
||||
setCamera(mCamera)
|
||||
setVideoSource(MediaRecorder.VideoSource.DEFAULT)
|
||||
setAudioSource(MediaRecorder.AudioSource.DEFAULT)
|
||||
}
|
||||
|
||||
mCurrVideoPath = mActivity!!.getOutputMediaFile(false)
|
||||
if (mCurrVideoPath.isEmpty()) {
|
||||
mActivity?.toast(R.string.video_creating_error)
|
||||
return false
|
||||
}
|
||||
|
||||
if (mRecorder == null) {
|
||||
mActivity?.toast(R.string.unknown_error_occurred)
|
||||
return false
|
||||
}
|
||||
|
||||
val resolution = getSelectedResolution()
|
||||
val profile = if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_HIGH)) {
|
||||
CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)
|
||||
} else {
|
||||
CamcorderProfile.get(CamcorderProfile.QUALITY_LOW)
|
||||
}
|
||||
|
||||
if (profile == null) {
|
||||
mActivity?.toast(R.string.unknown_error_occurred)
|
||||
return false
|
||||
}
|
||||
|
||||
profile.apply {
|
||||
videoFrameWidth = resolution.width
|
||||
videoFrameHeight = resolution.height
|
||||
mRecorder!!.setProfile(this)
|
||||
}
|
||||
|
||||
checkPermissions()
|
||||
if (mRecorder == null) {
|
||||
return false
|
||||
}
|
||||
mRecorder!!.setPreviewDisplay(mSurfaceHolder.surface)
|
||||
|
||||
val rotation = getVideoRotation()
|
||||
mRecorder!!.setOrientationHint(rotation)
|
||||
|
||||
try {
|
||||
mRecorder!!.prepare()
|
||||
} catch (e: Exception) {
|
||||
setupFailed(e)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun checkPermissions(): Boolean {
|
||||
if (mActivity!!.needsStupidWritePermissions(mCurrVideoPath)) {
|
||||
if (mConfig.treeUri.isEmpty()) {
|
||||
mActivity!!.toast(R.string.save_error_internal_storage)
|
||||
mConfig.savePhotosFolder = Environment.getExternalStorageDirectory().toString()
|
||||
releaseCamera()
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
var document = mActivity!!.getDocumentFile(mCurrVideoPath.getParentPath())
|
||||
if (document == null) {
|
||||
mActivity!!.toast(R.string.unknown_error_occurred)
|
||||
return false
|
||||
}
|
||||
|
||||
document = document.createFile("video/mp4", mCurrVideoPath.substring(mCurrVideoPath.lastIndexOf('/') + 1))
|
||||
val fileDescriptor = context.contentResolver.openFileDescriptor(document.uri, "rw")
|
||||
mRecorder!!.setOutputFile(fileDescriptor!!.fileDescriptor)
|
||||
} catch (e: Exception) {
|
||||
setupFailed(e)
|
||||
}
|
||||
} else {
|
||||
mRecorder!!.setOutputFile(mCurrVideoPath)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun setupFailed(e: Exception) {
|
||||
mActivity!!.showErrorToast(e)
|
||||
releaseCamera()
|
||||
}
|
||||
|
||||
private fun updateCameraParameters() {
|
||||
try {
|
||||
mCamera?.parameters = mParameters
|
||||
} catch (e: RuntimeException) {
|
||||
}
|
||||
}
|
||||
|
||||
override fun setTargetUri(uri: Uri) {
|
||||
mTargetUri = uri
|
||||
}
|
||||
|
||||
override fun setIsImageCaptureIntent(isImageCaptureIntent: Boolean) {
|
||||
mIsImageCaptureIntent = isImageCaptureIntent
|
||||
}
|
||||
|
||||
override fun toggleRecording() {
|
||||
if (mIsRecording) {
|
||||
stopRecording()
|
||||
initVideoMode()
|
||||
} else {
|
||||
startRecording()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getVideoRotation(): Int {
|
||||
val deviceRot = compensateDeviceRotation(mActivity!!.mLastHandledOrientation, getIsUsingFrontCamera())
|
||||
val previewRot = getPreviewRotation(mCurrCameraId)
|
||||
return (deviceRot + previewRot) % 360
|
||||
}
|
||||
|
||||
override fun deviceOrientationChanged() {
|
||||
if (mIsInVideoMode && !mIsRecording) {
|
||||
mRecorder = null
|
||||
initVideoMode()
|
||||
}
|
||||
}
|
||||
|
||||
private fun startRecording() {
|
||||
try {
|
||||
mCamera!!.unlock()
|
||||
toggleShutterSound(true)
|
||||
mRecorder!!.start()
|
||||
toggleShutterSound(false)
|
||||
mIsRecording = true
|
||||
mActivity!!.setRecordingState(true)
|
||||
} catch (e: Exception) {
|
||||
mActivity!!.showErrorToast(e)
|
||||
releaseCamera()
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopRecording() {
|
||||
if (mRecorder != null && mIsRecording) {
|
||||
try {
|
||||
toggleShutterSound(true)
|
||||
mRecorder!!.stop()
|
||||
mActivity!!.rescanPaths(arrayListOf(mCurrVideoPath)) {
|
||||
mActivity!!.videoSaved(Uri.fromFile(File(mCurrVideoPath)))
|
||||
toggleShutterSound(false)
|
||||
}
|
||||
} catch (e: RuntimeException) {
|
||||
mActivity!!.showErrorToast(e)
|
||||
toggleShutterSound(false)
|
||||
File(mCurrVideoPath).delete()
|
||||
mRecorder = null
|
||||
mIsRecording = false
|
||||
releaseCamera()
|
||||
}
|
||||
}
|
||||
|
||||
mRecorder = null
|
||||
if (mIsRecording) {
|
||||
mActivity!!.setRecordingState(false)
|
||||
}
|
||||
mIsRecording = false
|
||||
|
||||
val file = File(mCurrVideoPath)
|
||||
if (file.exists() && file.length() == 0L) {
|
||||
file.delete()
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleShutterSound(mute: Boolean?) {
|
||||
if (!mConfig.isSoundEnabled) {
|
||||
(mActivity!!.getSystemService(Context.AUDIO_SERVICE) as AudioManager).setStreamMute(AudioManager.STREAM_SYSTEM, mute!!)
|
||||
}
|
||||
}
|
||||
|
||||
private fun hasFlash(camera: Camera?): Boolean {
|
||||
if (camera == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (camera.parameters.flashMode == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
val supportedFlashModes = camera.parameters.supportedFlashModes
|
||||
if (supportedFlashModes == null || supportedFlashModes.isEmpty() ||
|
||||
supportedFlashModes.size == 1 && supportedFlashModes[0] == Camera.Parameters.FLASH_MODE_OFF) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun getScreenSize(): Point {
|
||||
val display = mActivity!!.windowManager.defaultDisplay
|
||||
val size = Point()
|
||||
display.getSize(size)
|
||||
size.y += mActivity!!.resources.getNavBarHeight()
|
||||
return size
|
||||
}
|
||||
|
||||
private fun getPreviewRotation(cameraId: Int): Int {
|
||||
val info = getCameraInfo(cameraId)
|
||||
val degrees = when (mActivity!!.windowManager.defaultDisplay.rotation) {
|
||||
Surface.ROTATION_90 -> 90
|
||||
Surface.ROTATION_180 -> 180
|
||||
Surface.ROTATION_270 -> 270
|
||||
else -> 0
|
||||
}
|
||||
|
||||
var result: Int
|
||||
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
|
||||
result = (info.orientation + degrees) % 360
|
||||
result = 360 - result
|
||||
} else {
|
||||
result = info.orientation - degrees + 360
|
||||
}
|
||||
|
||||
return result % 360
|
||||
}
|
||||
|
||||
private fun getCameraInfo(cameraId: Int): Camera.CameraInfo {
|
||||
val info = android.hardware.Camera.CameraInfo()
|
||||
Camera.getCameraInfo(cameraId, info)
|
||||
return info
|
||||
}
|
||||
}
|
@ -6,12 +6,6 @@
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black">
|
||||
|
||||
<SurfaceView
|
||||
android:id="@+id/camera_surface_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<com.simplemobiletools.camera.views.AutoFitTextureView
|
||||
android:id="@+id/camera_texture_view"
|
||||
android:layout_width="wrap_content"
|
||||
@ -29,8 +23,8 @@
|
||||
android:id="@+id/toggle_photo_video"
|
||||
android:layout_width="@dimen/icon_size"
|
||||
android:layout_height="@dimen/icon_size"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@+id/settings"
|
||||
android:layout_alignParentRight="true"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_video"/>
|
||||
|
||||
@ -38,8 +32,8 @@
|
||||
android:id="@+id/change_resolution"
|
||||
android:layout_width="@dimen/icon_size"
|
||||
android:layout_height="@dimen/icon_size"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@+id/toggle_photo_video"
|
||||
android:layout_alignParentRight="true"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_resolution"/>
|
||||
|
||||
@ -47,8 +41,8 @@
|
||||
android:id="@+id/last_photo_video_preview"
|
||||
android:layout_width="@dimen/icon_size"
|
||||
android:layout_height="@dimen/icon_size"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@+id/change_resolution"
|
||||
android:layout_alignParentRight="true"
|
||||
android:padding="@dimen/medium_margin"/>
|
||||
|
||||
<LinearLayout
|
||||
|
@ -18,18 +18,18 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
android:paddingBottom="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/settings_purchase_thank_you"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:text="@string/purchase_simple_thank_you"/>
|
||||
|
||||
</RelativeLayout>
|
||||
@ -40,18 +40,18 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
android:paddingBottom="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/settings_customize_colors"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:text="@string/customize_colors"/>
|
||||
|
||||
</RelativeLayout>
|
||||
@ -62,10 +62,10 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
android:paddingBottom="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||
android:id="@+id/settings_use_english"
|
||||
@ -73,8 +73,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:text="@string/use_english_language"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
@ -86,10 +86,10 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
android:paddingBottom="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||
android:id="@+id/settings_avoid_whats_new"
|
||||
@ -97,8 +97,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:text="@string/avoid_whats_new"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
@ -110,10 +110,10 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
android:paddingBottom="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||
android:id="@+id/settings_keep_settings_visible"
|
||||
@ -121,8 +121,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:text="@string/keep_settings_visible"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
@ -135,10 +135,10 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
android:paddingBottom="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||
android:id="@+id/settings_focus_before_capture"
|
||||
@ -146,8 +146,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:text="@string/focus_before_capture"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
@ -164,8 +164,8 @@
|
||||
android:id="@+id/shutter_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/bigger_margin"
|
||||
android:layout_marginStart="@dimen/bigger_margin"
|
||||
android:layout_marginLeft="@dimen/bigger_margin"
|
||||
android:layout_marginTop="@dimen/activity_margin"
|
||||
android:text="@string/shutter"
|
||||
android:textAllCaps="true"
|
||||
@ -177,10 +177,10 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
android:paddingBottom="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||
android:id="@+id/settings_sound"
|
||||
@ -188,8 +188,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:text="@string/shutter_sound"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
@ -201,10 +201,10 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
android:paddingBottom="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||
android:id="@+id/settings_volume_buttons_as_shutter"
|
||||
@ -212,8 +212,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:text="@string/volume_buttons_as_shutter"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
@ -230,8 +230,8 @@
|
||||
android:id="@+id/startup_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/bigger_margin"
|
||||
android:layout_marginStart="@dimen/bigger_margin"
|
||||
android:layout_marginLeft="@dimen/bigger_margin"
|
||||
android:layout_marginTop="@dimen/activity_margin"
|
||||
android:text="@string/startup"
|
||||
android:textAllCaps="true"
|
||||
@ -243,10 +243,10 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
android:paddingBottom="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||
android:id="@+id/settings_turn_flash_off_at_startup"
|
||||
@ -254,8 +254,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:text="@string/turn_flash_off_at_startup"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
@ -267,10 +267,10 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
android:paddingBottom="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||
android:id="@+id/settings_always_open_back_camera"
|
||||
@ -278,8 +278,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:text="@string/always_open_back_camera"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
@ -296,8 +296,8 @@
|
||||
android:id="@+id/saving_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/bigger_margin"
|
||||
android:layout_marginStart="@dimen/bigger_margin"
|
||||
android:layout_marginLeft="@dimen/bigger_margin"
|
||||
android:layout_marginTop="@dimen/activity_margin"
|
||||
android:text="@string/saving_label"
|
||||
android:textAllCaps="true"
|
||||
@ -309,10 +309,10 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
android:paddingBottom="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||
android:id="@+id/settings_save_photo_metadata"
|
||||
@ -320,47 +320,23 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:text="@string/save_photo_metadata"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_show_preview_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||
android:id="@+id/settings_show_preview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:text="@string/show_preview"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_flip_photos_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
android:paddingBottom="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||
android:id="@+id/settings_flip_photos"
|
||||
@ -368,8 +344,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:text="@string/flip_front_camera_photos_horizontally"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
@ -381,18 +357,18 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/bigger_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/bigger_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/bigger_margin">
|
||||
android:paddingBottom="@dimen/bigger_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/settings_save_photos_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toLeftOf="@+id/settings_save_photos"
|
||||
android:layout_toStartOf="@+id/settings_save_photos"
|
||||
android:layout_toLeftOf="@+id/settings_save_photos"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingRight="@dimen/medium_margin"
|
||||
android:text="@string/save_photos"/>
|
||||
@ -416,18 +392,18 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/bigger_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/bigger_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/bigger_margin">
|
||||
android:paddingBottom="@dimen/bigger_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/settings_photo_quality_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toLeftOf="@+id/settings_photo_quality"
|
||||
android:layout_toStartOf="@+id/settings_photo_quality"
|
||||
android:layout_toLeftOf="@+id/settings_photo_quality"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingRight="@dimen/medium_margin"
|
||||
android:text="@string/photo_compression_quality"/>
|
||||
|
@ -19,8 +19,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toLeftOf="@+id/change_resolution_photo"
|
||||
android:layout_toStartOf="@+id/change_resolution_photo"
|
||||
android:layout_toLeftOf="@+id/change_resolution_photo"
|
||||
android:text="@string/photo"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
@ -47,8 +47,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toLeftOf="@+id/change_resolution_video"
|
||||
android:layout_toStartOf="@+id/change_resolution_video"
|
||||
android:layout_toLeftOf="@+id/change_resolution_video"
|
||||
android:text="@string/video"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="FullScreenTheme" parent="AppTheme.Base">
|
||||
<item name="android:windowTranslucentNavigation">true</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
@ -3,10 +3,9 @@
|
||||
|
||||
<style name="AppTheme" parent="AppTheme.Base"/>
|
||||
|
||||
<style name="FullScreenTheme.Base" parent="AppTheme">
|
||||
<style name="FullScreenTheme" parent="AppTheme">
|
||||
<item name="android:windowContentOverlay">@null</item>
|
||||
<item name="android:windowTranslucentNavigation">true</item>
|
||||
</style>
|
||||
|
||||
<style name="FullScreenTheme" parent="FullScreenTheme.Base"/>
|
||||
|
||||
</resources>
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.2.60'
|
||||
ext.kotlin_version = '1.2.71'
|
||||
|
||||
repositories {
|
||||
google()
|
||||
|
Loading…
x
Reference in New Issue
Block a user