mirror of
				https://github.com/SimpleMobileTools/Simple-Flashlight.git
				synced 2025-06-05 21:59:19 +02:00 
			
		
		
		
	Merge pull request #174 from KryptKode/feat/brightness-control
Add torch brightness level support for Android 13+
This commit is contained in:
		| @@ -4,7 +4,6 @@ import android.annotation.SuppressLint | ||||
| import android.content.Intent | ||||
| import android.content.pm.ActivityInfo | ||||
| import android.content.pm.ShortcutInfo | ||||
| import android.content.res.ColorStateList | ||||
| import android.graphics.drawable.Icon | ||||
| import android.graphics.drawable.LayerDrawable | ||||
| import android.os.Bundle | ||||
| @@ -19,6 +18,8 @@ import com.simplemobiletools.commons.models.FAQItem | ||||
| import com.simplemobiletools.flashlight.BuildConfig | ||||
| import com.simplemobiletools.flashlight.R | ||||
| import com.simplemobiletools.flashlight.extensions.config | ||||
| import com.simplemobiletools.flashlight.helpers.CameraTorchListener | ||||
| import com.simplemobiletools.flashlight.helpers.MIN_BRIGHTNESS_LEVEL | ||||
| import com.simplemobiletools.flashlight.helpers.MyCameraImpl | ||||
| import com.simplemobiletools.flashlight.models.Events | ||||
| import kotlinx.android.synthetic.main.activity_main.* | ||||
| @@ -179,10 +180,17 @@ class MainActivity : SimpleActivity() { | ||||
|     } | ||||
|  | ||||
|     private fun setupCameraImpl() { | ||||
|         mCameraImpl = MyCameraImpl.newInstance(this) | ||||
|         mCameraImpl = MyCameraImpl.newInstance(this, object : CameraTorchListener { | ||||
|             override fun onTorchEnabled(isEnabled: Boolean) { | ||||
|                 if (mCameraImpl!!.supportsBrightnessControl()) { | ||||
|                     brightness_bar.beVisibleIf(isEnabled) | ||||
|                 } | ||||
|             } | ||||
|         }) | ||||
|         if (config.turnFlashlightOn) { | ||||
|             mCameraImpl!!.enableFlashlight() | ||||
|         } | ||||
|         setupBrightness() | ||||
|     } | ||||
|  | ||||
|     private fun setupStroboscope() { | ||||
| @@ -211,6 +219,16 @@ class MainActivity : SimpleActivity() { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun setupBrightness() { | ||||
|         brightness_bar.max = mCameraImpl?.getMaximumBrightnessLevel() ?: MIN_BRIGHTNESS_LEVEL | ||||
|         brightness_bar.progress = mCameraImpl?.getCurrentBrightnessLevel() ?: MIN_BRIGHTNESS_LEVEL | ||||
|         brightness_bar.onSeekBarChangeListener { level -> | ||||
|             val newLevel = level.coerceAtLeast(MIN_BRIGHTNESS_LEVEL) | ||||
|             mCameraImpl?.updateBrightnessLevel(newLevel) | ||||
|             config.brightnessLevel = newLevel | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun cameraPermissionGranted(isSOS: Boolean) { | ||||
|         if (isSOS) { | ||||
|             val isSOSRunning = mCameraImpl!!.toggleSOS() | ||||
|   | ||||
| @@ -0,0 +1,12 @@ | ||||
| package com.simplemobiletools.flashlight.helpers | ||||
|  | ||||
| interface CameraFlash { | ||||
|     fun initialize() | ||||
|     fun toggleFlashlight(enable: Boolean) | ||||
|     fun changeTorchBrightness(level: Int) {} | ||||
|     fun getMaximumBrightnessLevel(): Int = DEFAULT_BRIGHTNESS_LEVEL | ||||
|     fun supportsBrightnessControl(): Boolean = false | ||||
|     fun getCurrentBrightnessLevel(): Int = DEFAULT_BRIGHTNESS_LEVEL | ||||
|     fun unregisterListeners(){} | ||||
|     fun release(){} | ||||
| } | ||||
| @@ -0,0 +1,5 @@ | ||||
| package com.simplemobiletools.flashlight.helpers | ||||
|  | ||||
| interface CameraTorchListener { | ||||
|     fun onTorchEnabled(isEnabled:Boolean) | ||||
| } | ||||
| @@ -40,4 +40,8 @@ class Config(context: Context) : BaseConfig(context) { | ||||
|     var forcePortraitMode: Boolean | ||||
|         get() = prefs.getBoolean(FORCE_PORTRAIT_MODE, true) | ||||
|         set(forcePortraitMode) = prefs.edit().putBoolean(FORCE_PORTRAIT_MODE, forcePortraitMode).apply() | ||||
|  | ||||
|     var brightnessLevel: Int | ||||
|         get() = prefs.getInt(BRIGHTNESS_LEVEL, DEFAULT_BRIGHTNESS_LEVEL) | ||||
|         set(brightnessLevel) = prefs.edit().putInt(BRIGHTNESS_LEVEL, brightnessLevel).apply() | ||||
| } | ||||
|   | ||||
| @@ -11,3 +11,6 @@ const val STROBOSCOPE_FREQUENCY = "stroboscope_frequency" | ||||
| const val STROBOSCOPE_PROGRESS = "stroboscope_progress" | ||||
| const val FORCE_PORTRAIT_MODE = "force_portrait_mode" | ||||
| const val SOS = "sos" | ||||
| const val BRIGHTNESS_LEVEL = "brightness_level" | ||||
| const val MIN_BRIGHTNESS_LEVEL = 1 | ||||
| const val DEFAULT_BRIGHTNESS_LEVEL = -1 | ||||
|   | ||||
| @@ -0,0 +1,37 @@ | ||||
| @file:Suppress("DEPRECATION") | ||||
|  | ||||
| package com.simplemobiletools.flashlight.helpers | ||||
|  | ||||
| import android.graphics.SurfaceTexture | ||||
| import android.hardware.Camera | ||||
|  | ||||
| class LollipopCameraFlash : CameraFlash { | ||||
|     private var camera: Camera? = null | ||||
|     private var params: Camera.Parameters? = null | ||||
|  | ||||
|     override fun toggleFlashlight(enable: Boolean) { | ||||
|         if (camera == null || params == null || camera!!.parameters == null) { | ||||
|             return | ||||
|         } | ||||
|         val flashMode = if (enable) Camera.Parameters.FLASH_MODE_ON else Camera.Parameters.FLASH_MODE_OFF | ||||
|         params!!.flashMode = flashMode | ||||
|         camera!!.parameters = params | ||||
|         if (enable) { | ||||
|             val dummy = SurfaceTexture(1) | ||||
|             camera!!.setPreviewTexture(dummy) | ||||
|             camera!!.startPreview() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun initialize() { | ||||
|         camera = Camera.open() | ||||
|         params = camera!!.parameters | ||||
|         params!!.flashMode = Camera.Parameters.FLASH_MODE_OFF | ||||
|         camera!!.parameters = params | ||||
|     } | ||||
|  | ||||
|     override fun release() { | ||||
|         camera!!.release() | ||||
|         camera = null | ||||
|     } | ||||
| } | ||||
| @@ -1,37 +0,0 @@ | ||||
| package com.simplemobiletools.flashlight.helpers | ||||
|  | ||||
| import android.annotation.TargetApi | ||||
| import android.content.Context | ||||
| import android.hardware.camera2.CameraManager | ||||
| import android.os.Build | ||||
| import android.os.Handler | ||||
| import com.simplemobiletools.commons.extensions.showErrorToast | ||||
| import com.simplemobiletools.flashlight.models.Events | ||||
| import org.greenrobot.eventbus.EventBus | ||||
|  | ||||
| internal class MarshmallowCamera constructor(val context: Context) { | ||||
|  | ||||
|     private val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager | ||||
|     private var cameraId: String? = null | ||||
|  | ||||
|     init { | ||||
|         try { | ||||
|             cameraId = manager.cameraIdList[0] ?: "0" | ||||
|         } catch (e: Exception) { | ||||
|             context.showErrorToast(e) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @TargetApi(Build.VERSION_CODES.M) | ||||
|     fun toggleMarshmallowFlashlight(enable: Boolean) { | ||||
|         try { | ||||
|             manager.setTorchMode(cameraId!!, enable) | ||||
|         } catch (e: Exception) { | ||||
|             context.showErrorToast(e) | ||||
|             val mainRunnable = Runnable { | ||||
|                 EventBus.getDefault().post(Events.CameraUnavailable()) | ||||
|             } | ||||
|             Handler(context.mainLooper).post(mainRunnable) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,94 @@ | ||||
| package com.simplemobiletools.flashlight.helpers | ||||
|  | ||||
| import android.content.Context | ||||
| import android.hardware.camera2.CameraCharacteristics | ||||
| import android.hardware.camera2.CameraManager | ||||
| import android.os.Build | ||||
| import android.os.Handler | ||||
| import androidx.annotation.RequiresApi | ||||
| import com.simplemobiletools.commons.extensions.showErrorToast | ||||
| import com.simplemobiletools.commons.helpers.isTiramisuPlus | ||||
| import com.simplemobiletools.flashlight.extensions.config | ||||
| import com.simplemobiletools.flashlight.models.Events | ||||
| import org.greenrobot.eventbus.EventBus | ||||
|  | ||||
| @RequiresApi(Build.VERSION_CODES.M) | ||||
| internal class MarshmallowPlusCameraFlash( | ||||
|     private val context: Context, | ||||
|     private var cameraTorchListener: CameraTorchListener? = null, | ||||
| ) : CameraFlash { | ||||
|  | ||||
|     private val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager | ||||
|     private var cameraId: String? = null | ||||
|  | ||||
|     private val torchCallback = object : CameraManager.TorchCallback() { | ||||
|         override fun onTorchModeChanged(cameraId: String, enabled: Boolean) { | ||||
|             cameraTorchListener?.onTorchEnabled(enabled) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     init { | ||||
|         try { | ||||
|             cameraId = manager.cameraIdList[0] ?: "0" | ||||
|         } catch (e: Exception) { | ||||
|             context.showErrorToast(e) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun toggleFlashlight(enable: Boolean) { | ||||
|         try { | ||||
|             if (supportsBrightnessControl() && enable) { | ||||
|                 val brightnessLevel = getCurrentBrightnessLevel() | ||||
|                 changeTorchBrightness(brightnessLevel) | ||||
|             } else { | ||||
|                 manager.setTorchMode(cameraId!!, enable) | ||||
|             } | ||||
|         } catch (e: Exception) { | ||||
|             context.showErrorToast(e) | ||||
|             val mainRunnable = Runnable { | ||||
|                 EventBus.getDefault().post(Events.CameraUnavailable()) | ||||
|             } | ||||
|             Handler(context.mainLooper).post(mainRunnable) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun changeTorchBrightness(level: Int) { | ||||
|         if (isTiramisuPlus()) { | ||||
|             manager.turnOnTorchWithStrengthLevel(cameraId!!, level) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun getMaximumBrightnessLevel(): Int { | ||||
|         return if (isTiramisuPlus()) { | ||||
|             val characteristics = manager.getCameraCharacteristics(cameraId!!) | ||||
|             characteristics.get(CameraCharacteristics.FLASH_INFO_STRENGTH_MAXIMUM_LEVEL) ?: MIN_BRIGHTNESS_LEVEL | ||||
|         } else { | ||||
|             MIN_BRIGHTNESS_LEVEL | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun supportsBrightnessControl(): Boolean { | ||||
|         val maxBrightnessLevel = getMaximumBrightnessLevel() | ||||
|         return maxBrightnessLevel > MIN_BRIGHTNESS_LEVEL | ||||
|     } | ||||
|  | ||||
|     override fun getCurrentBrightnessLevel(): Int { | ||||
|         var brightnessLevel = context.config.brightnessLevel | ||||
|         if (brightnessLevel == DEFAULT_BRIGHTNESS_LEVEL) { | ||||
|             brightnessLevel = getMaximumBrightnessLevel() | ||||
|         } | ||||
|         return brightnessLevel | ||||
|     } | ||||
|  | ||||
|     override fun initialize() { | ||||
|         manager.registerTorchCallback(torchCallback, Handler(context.mainLooper)) | ||||
|     } | ||||
|  | ||||
|     override fun unregisterListeners() { | ||||
|         manager.unregisterTorchCallback(torchCallback) | ||||
|     } | ||||
|  | ||||
|     override fun release() { | ||||
|         cameraTorchListener = null | ||||
|     } | ||||
| } | ||||
| @@ -1,20 +1,17 @@ | ||||
| package com.simplemobiletools.flashlight.helpers | ||||
|  | ||||
| import android.content.Context | ||||
| import android.graphics.SurfaceTexture | ||||
| import android.hardware.Camera | ||||
| import android.os.Handler | ||||
| import com.simplemobiletools.commons.extensions.showErrorToast | ||||
| import com.simplemobiletools.commons.extensions.toast | ||||
| import com.simplemobiletools.commons.helpers.isMarshmallowPlus | ||||
| import com.simplemobiletools.commons.helpers.isNougatPlus | ||||
| import com.simplemobiletools.flashlight.R | ||||
| import com.simplemobiletools.flashlight.extensions.config | ||||
| import com.simplemobiletools.flashlight.extensions.updateWidgets | ||||
| import com.simplemobiletools.flashlight.models.Events | ||||
| import org.greenrobot.eventbus.EventBus | ||||
|  | ||||
| class MyCameraImpl(val context: Context) { | ||||
| class MyCameraImpl private constructor(val context: Context, private var cameraTorchListener: CameraTorchListener? = null) { | ||||
|     var stroboFrequency = 1000L | ||||
|  | ||||
|     companion object { | ||||
| @@ -23,15 +20,12 @@ class MyCameraImpl(val context: Context) { | ||||
|         private var u = 200L // The length of one dit (Time unit) | ||||
|         private val SOS = arrayListOf(u, u, u, u, u, u * 3, u * 3, u, u * 3, u, u * 3, u * 3, u, u, u, u, u, u * 7) | ||||
|  | ||||
|         private var camera: Camera? = null | ||||
|         private var params: Camera.Parameters? = null | ||||
|         private var isMarshmallow = false | ||||
|         private var shouldEnableFlashlight = false | ||||
|         private var shouldEnableStroboscope = false | ||||
|         private var shouldEnableSOS = false | ||||
|         private var isStroboSOS = false     // are we sending SOS, or casual stroboscope? | ||||
|  | ||||
|         private var marshmallowCamera: MarshmallowCamera? = null | ||||
|         private var cameraFlash: CameraFlash? = null | ||||
|  | ||||
|         @Volatile | ||||
|         private var shouldStroboscopeStop = false | ||||
| @@ -42,11 +36,10 @@ class MyCameraImpl(val context: Context) { | ||||
|         @Volatile | ||||
|         private var isSOSRunning = false | ||||
|  | ||||
|         fun newInstance(context: Context) = MyCameraImpl(context) | ||||
|         fun newInstance(context: Context, cameraTorchListener: CameraTorchListener? = null) = MyCameraImpl(context, cameraTorchListener) | ||||
|     } | ||||
|  | ||||
|     init { | ||||
|         isMarshmallow = isMarshmallowPlus() | ||||
|         handleCameraSetup() | ||||
|         stroboFrequency = context.config.stroboscopeFrequency | ||||
|     } | ||||
| @@ -57,6 +50,8 @@ class MyCameraImpl(val context: Context) { | ||||
|     } | ||||
|  | ||||
|     fun toggleStroboscope(): Boolean { | ||||
|         handleCameraSetup() | ||||
|  | ||||
|         if (isSOSRunning) { | ||||
|             stopSOS() | ||||
|             shouldEnableStroboscope = true | ||||
| @@ -68,6 +63,8 @@ class MyCameraImpl(val context: Context) { | ||||
|             disableFlashlight() | ||||
|         } | ||||
|  | ||||
|         cameraFlash!!.unregisterListeners() | ||||
|  | ||||
|         if (!tryInitCamera()) { | ||||
|             return false | ||||
|         } | ||||
| @@ -87,6 +84,8 @@ class MyCameraImpl(val context: Context) { | ||||
|     } | ||||
|  | ||||
|     fun toggleSOS(): Boolean { | ||||
|         handleCameraSetup() | ||||
|  | ||||
|         if (isStroboscopeRunning) { | ||||
|             stopStroboscope() | ||||
|             shouldEnableSOS = true | ||||
| @@ -106,6 +105,8 @@ class MyCameraImpl(val context: Context) { | ||||
|             disableFlashlight() | ||||
|         } | ||||
|  | ||||
|         cameraFlash!!.unregisterListeners() | ||||
|  | ||||
|         return if (isSOSRunning) { | ||||
|             stopSOS() | ||||
|             false | ||||
| @@ -121,58 +122,26 @@ class MyCameraImpl(val context: Context) { | ||||
|     } | ||||
|  | ||||
|     private fun tryInitCamera(): Boolean { | ||||
|         if (!isNougatPlus()) { | ||||
|             if (camera == null) { | ||||
|                 initCamera() | ||||
|             } | ||||
|  | ||||
|             if (camera == null) { | ||||
|         handleCameraSetup() | ||||
|         if (cameraFlash == null) { | ||||
|             context.toast(R.string.camera_error) | ||||
|             return false | ||||
|         } | ||||
|         } | ||||
|         return true | ||||
|     } | ||||
|  | ||||
|     fun handleCameraSetup() { | ||||
|         if (isMarshmallow) { | ||||
|             setupMarshmallowCamera() | ||||
|         } else { | ||||
|             setupCamera() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun setupMarshmallowCamera() { | ||||
|         if (marshmallowCamera == null) { | ||||
|             marshmallowCamera = MarshmallowCamera(context) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun setupCamera() { | ||||
|         if (isMarshmallow) { | ||||
|             return | ||||
|         } | ||||
|  | ||||
|         if (camera == null) { | ||||
|             initCamera() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun initCamera() { | ||||
|         try { | ||||
|             camera = Camera.open() | ||||
|             params = camera!!.parameters | ||||
|             params!!.flashMode = Camera.Parameters.FLASH_MODE_OFF | ||||
|             camera!!.parameters = params | ||||
|             if (cameraFlash == null) { | ||||
|                 cameraFlash = if (isMarshmallowPlus()) MarshmallowPlusCameraFlash(context, cameraTorchListener) else LollipopCameraFlash() | ||||
|             } | ||||
|         } catch (e: Exception) { | ||||
|             EventBus.getDefault().post(Events.CameraUnavailable()) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun checkFlashlight() { | ||||
|         if (camera == null) { | ||||
|         handleCameraSetup() | ||||
|         } | ||||
|  | ||||
|         if (isFlashlightOn) { | ||||
|             enableFlashlight() | ||||
| @@ -188,26 +157,13 @@ class MyCameraImpl(val context: Context) { | ||||
|             return | ||||
|         } | ||||
|  | ||||
|         if (isMarshmallow) { | ||||
|             toggleMarshmallowFlashlight(true) | ||||
|         } else { | ||||
|         try { | ||||
|                 if (camera == null || params == null || camera!!.parameters == null) { | ||||
|                     return | ||||
|                 } | ||||
|             } catch (e: Exception) { | ||||
|                 return | ||||
|             } | ||||
|  | ||||
|             params!!.flashMode = Camera.Parameters.FLASH_MODE_TORCH | ||||
|             camera!!.parameters = params | ||||
|             try { | ||||
|                 camera!!.startPreview() | ||||
|             cameraFlash!!.initialize() | ||||
|             cameraFlash!!.toggleFlashlight(true) | ||||
|         } catch (e: Exception) { | ||||
|             context.showErrorToast(e) | ||||
|             disableFlashlight() | ||||
|         } | ||||
|         } | ||||
|  | ||||
|         val mainRunnable = Runnable { stateChanged(true) } | ||||
|         Handler(context.mainLooper).post(mainRunnable) | ||||
| @@ -218,22 +174,13 @@ class MyCameraImpl(val context: Context) { | ||||
|             return | ||||
|         } | ||||
|  | ||||
|         if (isMarshmallow) { | ||||
|             toggleMarshmallowFlashlight(false) | ||||
|         } else { | ||||
|         try { | ||||
|                 if (camera == null || params == null || camera!!.parameters == null) { | ||||
|                     return | ||||
|                 } | ||||
|             cameraFlash!!.toggleFlashlight(false) | ||||
|         } catch (e: Exception) { | ||||
|                 return | ||||
|             } | ||||
|  | ||||
|             params!!.flashMode = Camera.Parameters.FLASH_MODE_OFF | ||||
|             camera!!.parameters = params | ||||
|             context.showErrorToast(e) | ||||
|             disableFlashlight() | ||||
|         } | ||||
|         stateChanged(false) | ||||
|         releaseCamera() | ||||
|     } | ||||
|  | ||||
|     private fun stateChanged(isEnabled: Boolean) { | ||||
| @@ -242,17 +189,16 @@ class MyCameraImpl(val context: Context) { | ||||
|         context.updateWidgets(isEnabled) | ||||
|     } | ||||
|  | ||||
|     private fun toggleMarshmallowFlashlight(enable: Boolean) { | ||||
|         marshmallowCamera!!.toggleMarshmallowFlashlight(enable) | ||||
|     } | ||||
|  | ||||
|     fun releaseCamera() { | ||||
|         cameraFlash?.unregisterListeners() | ||||
|  | ||||
|         if (isFlashlightOn) { | ||||
|             disableFlashlight() | ||||
|         } | ||||
|  | ||||
|         camera?.release() | ||||
|         camera = null | ||||
|         cameraFlash?.release() | ||||
|         cameraFlash = null | ||||
|         cameraTorchListener = null | ||||
|  | ||||
|         isFlashlightOn = false | ||||
|         shouldStroboscopeStop = true | ||||
| @@ -271,54 +217,26 @@ class MyCameraImpl(val context: Context) { | ||||
|         } | ||||
|  | ||||
|         var sosIndex = 0 | ||||
|         if (isNougatPlus()) { | ||||
|         handleCameraSetup() | ||||
|         while (!shouldStroboscopeStop) { | ||||
|             try { | ||||
|                     marshmallowCamera!!.toggleMarshmallowFlashlight(true) | ||||
|                 cameraFlash!!.toggleFlashlight(true) | ||||
|                 val onDuration = if (isStroboSOS) SOS[sosIndex++ % SOS.size] else stroboFrequency | ||||
|                 Thread.sleep(onDuration) | ||||
|                     marshmallowCamera!!.toggleMarshmallowFlashlight(false) | ||||
|                 cameraFlash!!.toggleFlashlight(false) | ||||
|                 val offDuration = if (isStroboSOS) SOS[sosIndex++ % SOS.size] else stroboFrequency | ||||
|                 Thread.sleep(offDuration) | ||||
|             } catch (e: Exception) { | ||||
|                 shouldStroboscopeStop = true | ||||
|             } | ||||
|         } | ||||
|         } else { | ||||
|             if (camera == null) { | ||||
|                 initCamera() | ||||
|             } | ||||
|  | ||||
|             try { | ||||
|                 val torchOn = camera!!.parameters ?: return@Runnable | ||||
|                 val torchOff = camera!!.parameters | ||||
|                 torchOn.flashMode = Camera.Parameters.FLASH_MODE_TORCH | ||||
|                 torchOff.flashMode = Camera.Parameters.FLASH_MODE_OFF | ||||
|  | ||||
|                 val dummy = SurfaceTexture(1) | ||||
|                 camera!!.setPreviewTexture(dummy) | ||||
|  | ||||
|                 camera!!.startPreview() | ||||
|  | ||||
|                 while (!shouldStroboscopeStop) { | ||||
|                     camera!!.parameters = torchOn | ||||
|                     val onDuration = if (isStroboSOS) SOS[sosIndex++ % SOS.size] else stroboFrequency | ||||
|                     Thread.sleep(onDuration) | ||||
|                     camera!!.parameters = torchOff | ||||
|                     val offDuration = if (isStroboSOS) SOS[sosIndex++ % SOS.size] else stroboFrequency | ||||
|                     Thread.sleep(offDuration) | ||||
|                 } | ||||
|  | ||||
|                 if (camera != null) { | ||||
|                     camera!!.parameters = torchOff | ||||
|                     if (!shouldEnableFlashlight || isMarshmallow) { | ||||
|                         camera!!.release() | ||||
|                         camera = null | ||||
|                     } | ||||
|                 } | ||||
|             } catch (e: RuntimeException) { | ||||
|                 shouldStroboscopeStop = true | ||||
|             } | ||||
|         // disable flash immediately if stroboscope is stopped and normal flash mode is disabled | ||||
|         if (shouldStroboscopeStop && !shouldEnableFlashlight) { | ||||
|             handleCameraSetup() | ||||
|             cameraFlash!!.toggleFlashlight(false) | ||||
|             cameraFlash!!.release() | ||||
|             cameraFlash = null | ||||
|         } | ||||
|  | ||||
|         shouldStroboscopeStop = false | ||||
| @@ -343,4 +261,20 @@ class MyCameraImpl(val context: Context) { | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fun getMaximumBrightnessLevel(): Int { | ||||
|         return cameraFlash!!.getMaximumBrightnessLevel() | ||||
|     } | ||||
|  | ||||
|     fun getCurrentBrightnessLevel(): Int { | ||||
|         return cameraFlash!!.getCurrentBrightnessLevel() | ||||
|     } | ||||
|  | ||||
|     fun supportsBrightnessControl(): Boolean { | ||||
|         return cameraFlash!!.supportsBrightnessControl() | ||||
|     } | ||||
|  | ||||
|     fun updateBrightnessLevel(level: Int) { | ||||
|         cameraFlash!!.changeTorchBrightness(level) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -105,6 +105,20 @@ | ||||
|                 app:layout_constraintStart_toStartOf="parent" | ||||
|                 app:layout_constraintTop_toBottomOf="@+id/stroboscope_btn" /> | ||||
|  | ||||
|             <com.simplemobiletools.commons.views.MySeekBar | ||||
|                 android:id="@+id/brightness_bar" | ||||
|                 android:layout_width="@dimen/seekbar_width" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_margin="@dimen/activity_margin" | ||||
|                 android:paddingTop="@dimen/medium_margin" | ||||
|                 android:paddingBottom="@dimen/medium_margin" | ||||
|                 android:visibility="invisible" | ||||
|                 app:layout_constraintBottom_toBottomOf="parent" | ||||
|                 app:layout_constraintEnd_toEndOf="parent" | ||||
|                 app:layout_constraintHorizontal_bias="0.5" | ||||
|                 app:layout_constraintStart_toStartOf="parent" | ||||
|                 app:layout_constraintTop_toBottomOf="@+id/stroboscope_btn" /> | ||||
|  | ||||
|         </androidx.constraintlayout.widget.ConstraintLayout> | ||||
|     </androidx.core.widget.NestedScrollView> | ||||
| </androidx.coordinatorlayout.widget.CoordinatorLayout> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user