diff --git a/app/src/main/kotlin/com/simplemobiletools/flashlight/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/flashlight/activities/MainActivity.kt index 61b0244..c82a364 100644 --- a/app/src/main/kotlin/com/simplemobiletools/flashlight/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/flashlight/activities/MainActivity.kt @@ -52,7 +52,6 @@ class MainActivity : SimpleActivity() { override fun onResume() { super.onResume() mCameraImpl!!.handleCameraSetup() - mCameraImpl!!.checkFlashlight() bright_display_btn.beVisibleIf(config.brightDisplay) stroboscope_btn.beVisibleIf(config.stroboscope) @@ -105,7 +104,7 @@ class MainActivity : SimpleActivity() { } private fun setupCameraImpl() { - mCameraImpl = MyCameraImpl(this) + mCameraImpl = MyCameraImpl.newInstance(this) mCameraImpl!!.enableFlashlight() } diff --git a/app/src/main/kotlin/com/simplemobiletools/flashlight/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/flashlight/extensions/Context.kt index 02625eb..dd0b6f5 100644 --- a/app/src/main/kotlin/com/simplemobiletools/flashlight/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/flashlight/extensions/Context.kt @@ -1,6 +1,23 @@ package com.simplemobiletools.flashlight.extensions +import android.appwidget.AppWidgetManager +import android.content.ComponentName import android.content.Context +import android.content.Intent +import com.simplemobiletools.flashlight.R import com.simplemobiletools.flashlight.helpers.Config +import com.simplemobiletools.flashlight.helpers.MyWidgetProvider val Context.config: Config get() = Config.newInstance(this) + +fun Context.updateWidgets() { + val widgetsCnt = AppWidgetManager.getInstance(this).getAppWidgetIds(ComponentName(this, MyWidgetProvider::class.java)) + if (widgetsCnt.isNotEmpty()) { + val ids = intArrayOf(R.xml.widget_info) + Intent(this, MyWidgetProvider::class.java).apply { + action = AppWidgetManager.ACTION_APPWIDGET_UPDATE + putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids) + sendBroadcast(this) + } + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/flashlight/helpers/MarshmallowCamera.kt b/app/src/main/kotlin/com/simplemobiletools/flashlight/helpers/MarshmallowCamera.kt index 8de3bf9..a4bb352 100644 --- a/app/src/main/kotlin/com/simplemobiletools/flashlight/helpers/MarshmallowCamera.kt +++ b/app/src/main/kotlin/com/simplemobiletools/flashlight/helpers/MarshmallowCamera.kt @@ -12,7 +12,7 @@ import com.squareup.otto.Bus @TargetApi(Build.VERSION_CODES.LOLLIPOP) internal class MarshmallowCamera constructor(val context: Context) { - private val manager: CameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager + private val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager private var cameraId: String? = null init { diff --git a/app/src/main/kotlin/com/simplemobiletools/flashlight/helpers/MyCameraImpl.kt b/app/src/main/kotlin/com/simplemobiletools/flashlight/helpers/MyCameraImpl.kt index 183d59b..022bbd1 100644 --- a/app/src/main/kotlin/com/simplemobiletools/flashlight/helpers/MyCameraImpl.kt +++ b/app/src/main/kotlin/com/simplemobiletools/flashlight/helpers/MyCameraImpl.kt @@ -1,15 +1,14 @@ package com.simplemobiletools.flashlight.helpers -import android.annotation.TargetApi import android.content.Context import android.graphics.SurfaceTexture import android.hardware.Camera -import android.os.Build import android.os.Handler import com.simplemobiletools.commons.extensions.isMarshmallowPlus import com.simplemobiletools.commons.extensions.isNougatPlus import com.simplemobiletools.commons.extensions.toast import com.simplemobiletools.flashlight.R +import com.simplemobiletools.flashlight.extensions.updateWidgets import com.simplemobiletools.flashlight.models.Events import com.squareup.otto.Bus import java.io.IOException @@ -17,20 +16,173 @@ import java.io.IOException class MyCameraImpl(val context: Context) { var stroboFrequency = 1000 - companion object { - private var camera: Camera? = null - private var mParams: Camera.Parameters? = null - private var bus: Bus? = null + private var camera: Camera? = null + private var params: Camera.Parameters? = null + private var bus: Bus? = null - private var mIsFlashlightOn = false - private var mIsMarshmallow = false - private var mShouldEnableFlashlight = false - } + private var isFlashlightOn = false + private var isMarshmallow = false + private var shouldEnableFlashlight = false private var marshmallowCamera: MarshmallowCamera? = null @Volatile private var shouldStroboscopeStop = false @Volatile private var isStroboscopeRunning = false + companion object { + fun newInstance(context: Context) = MyCameraImpl(context) + } + + init { + isMarshmallow = context.isMarshmallowPlus() + + if (bus == null) { + bus = BusProvider.instance + bus!!.register(this) + } + + handleCameraSetup() + } + + fun toggleFlashlight() { + isFlashlightOn = !isFlashlightOn + checkFlashlight() + } + + fun toggleStroboscope(): Boolean { + if (!isStroboscopeRunning) { + disableFlashlight() + } + + if (!context.isNougatPlus()) { + if (camera == null) { + initCamera() + } + + if (camera == null) { + context.toast(R.string.camera_error) + return false + } + } + + if (isStroboscopeRunning) { + stopStroboscope() + } else { + Thread(stroboscope).start() + } + return true + } + + fun stopStroboscope() { + shouldStroboscopeStop = 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 + } catch (e: Exception) { + bus!!.post(Events.CameraUnavailable()) + } + + } + + private fun checkFlashlight() { + if (isFlashlightOn) { + enableFlashlight() + } else { + disableFlashlight() + } + } + + fun enableFlashlight() { + shouldStroboscopeStop = true + if (isStroboscopeRunning) { + shouldEnableFlashlight = true + return + } + + if (isMarshmallow) { + toggleMarshmallowFlashlight(true) + } else { + if (camera == null || params == null) { + return + } + + params!!.flashMode = Camera.Parameters.FLASH_MODE_TORCH + camera!!.parameters = params + camera!!.startPreview() + } + + val mainRunnable = Runnable { stateChanged(true) } + Handler(context.mainLooper).post(mainRunnable) + } + + private fun disableFlashlight() { + if (isStroboscopeRunning) { + return + } + + if (isMarshmallow) { + toggleMarshmallowFlashlight(false) + } else { + if (camera == null || params == null) { + return + } + + params!!.flashMode = Camera.Parameters.FLASH_MODE_OFF + camera!!.parameters = params + } + stateChanged(false) + } + + private fun stateChanged(isEnabled: Boolean) { + isFlashlightOn = isEnabled + bus!!.post(Events.StateChanged(isEnabled)) + context.updateWidgets() + } + + private fun toggleMarshmallowFlashlight(enable: Boolean) { + marshmallowCamera!!.toggleMarshmallowFlashlight(bus!!, enable) + } + + fun releaseCamera() { + if (isFlashlightOn) { + disableFlashlight() + } + + camera?.release() + camera = null + + bus?.unregister(this) + isFlashlightOn = false + shouldStroboscopeStop = true + } + private val stroboscope = Runnable { if (isStroboscopeRunning) { return@Runnable @@ -46,9 +198,7 @@ class MyCameraImpl(val context: Context) { Thread.sleep(stroboFrequency.toLong()) marshmallowCamera!!.toggleMarshmallowFlashlight(bus!!, false) Thread.sleep(stroboFrequency.toLong()) - } catch (ignored: InterruptedException) { - shouldStroboscopeStop = true - } catch (ignored: RuntimeException) { + } catch (e: Exception) { shouldStroboscopeStop = true } @@ -77,18 +227,14 @@ class MyCameraImpl(val context: Context) { Thread.sleep(stroboFrequency.toLong()) camera!!.parameters = torchOff Thread.sleep(stroboFrequency.toLong()) - } catch (ignored: InterruptedException) { - shouldStroboscopeStop = true - } catch (ignored: RuntimeException) { - shouldStroboscopeStop = true + } catch (e: Exception) { } - } try { if (camera != null) { camera!!.parameters = torchOff - if (!mShouldEnableFlashlight || mIsMarshmallow) { + if (!shouldEnableFlashlight || isMarshmallow) { camera!!.release() camera = null } @@ -100,157 +246,9 @@ class MyCameraImpl(val context: Context) { isStroboscopeRunning = false shouldStroboscopeStop = false - if (mShouldEnableFlashlight) { + if (shouldEnableFlashlight) { enableFlashlight() - mShouldEnableFlashlight = false + shouldEnableFlashlight = false } } - - init { - mIsMarshmallow = context.isMarshmallowPlus() - - if (bus == null) { - bus = BusProvider.instance - bus!!.register(this) - } - - handleCameraSetup() - checkFlashlight() - } - - fun toggleFlashlight() { - mIsFlashlightOn = !mIsFlashlightOn - handleCameraSetup() - } - - fun toggleStroboscope(): Boolean { - if (!isStroboscopeRunning) - disableFlashlight() - - if (!context.isNougatPlus()) { - if (camera == null) { - initCamera() - } - - if (camera == null) { - context.toast(R.string.camera_error) - return false - } - } - - if (isStroboscopeRunning) { - stopStroboscope() - } else { - Thread(stroboscope).start() - } - return true - } - - fun stopStroboscope() { - shouldStroboscopeStop = true - } - - fun handleCameraSetup() { - if (mIsMarshmallow) { - setupMarshmallowCamera() - } else { - setupCamera() - } - checkFlashlight() - } - - private fun setupMarshmallowCamera() { - if (marshmallowCamera == null) { - marshmallowCamera = MarshmallowCamera(context) - } - } - - private fun setupCamera() { - if (mIsMarshmallow) - return - - if (camera == null) { - initCamera() - } - } - - private fun initCamera() { - try { - camera = Camera.open() - mParams = camera!!.parameters - mParams!!.flashMode = Camera.Parameters.FLASH_MODE_OFF - camera!!.parameters = mParams - } catch (e: Exception) { - bus!!.post(Events.CameraUnavailable()) - } - - } - - fun checkFlashlight() { - if (mIsFlashlightOn) { - enableFlashlight() - } else { - disableFlashlight() - } - } - - fun enableFlashlight() { - shouldStroboscopeStop = true - if (isStroboscopeRunning) { - mShouldEnableFlashlight = true - return - } - - mIsFlashlightOn = true - if (mIsMarshmallow) { - toggleMarshmallowFlashlight(true) - } else { - if (camera == null || mParams == null) { - return - } - - mParams!!.flashMode = Camera.Parameters.FLASH_MODE_TORCH - camera!!.parameters = mParams - camera!!.startPreview() - } - - val mainRunnable = Runnable { bus!!.post(Events.StateChanged(true)) } - Handler(context.mainLooper).post(mainRunnable) - } - - private fun disableFlashlight() { - if (isStroboscopeRunning) { - return - } - - mIsFlashlightOn = false - if (mIsMarshmallow) { - toggleMarshmallowFlashlight(false) - } else { - if (camera == null || mParams == null) { - return - } - - mParams!!.flashMode = Camera.Parameters.FLASH_MODE_OFF - camera!!.parameters = mParams - } - bus!!.post(Events.StateChanged(false)) - } - - private fun toggleMarshmallowFlashlight(enable: Boolean) { - marshmallowCamera!!.toggleMarshmallowFlashlight(bus!!, enable) - } - - fun releaseCamera() { - if (mIsFlashlightOn) { - disableFlashlight() - } - - camera?.release() - camera = null - - bus?.unregister(this) - mIsFlashlightOn = false - shouldStroboscopeStop = true - } } diff --git a/app/src/main/kotlin/com/simplemobiletools/flashlight/helpers/MyWidgetProvider.kt b/app/src/main/kotlin/com/simplemobiletools/flashlight/helpers/MyWidgetProvider.kt index eed88b0..475c90f 100644 --- a/app/src/main/kotlin/com/simplemobiletools/flashlight/helpers/MyWidgetProvider.kt +++ b/app/src/main/kotlin/com/simplemobiletools/flashlight/helpers/MyWidgetProvider.kt @@ -9,24 +9,24 @@ import android.content.Intent import android.graphics.Bitmap import android.graphics.Color import android.graphics.PorterDuff +import android.hardware.camera2.CameraAccessException +import android.hardware.camera2.CameraManager +import android.os.Build +import android.support.annotation.RequiresApi +import android.util.Log import android.widget.RemoteViews -import com.simplemobiletools.commons.extensions.toast +import com.simplemobiletools.commons.extensions.isMarshmallowPlus import com.simplemobiletools.flashlight.R import com.simplemobiletools.flashlight.extensions.config import com.simplemobiletools.flashlight.models.Events -import com.squareup.otto.Bus import com.squareup.otto.Subscribe class MyWidgetProvider : AppWidgetProvider() { private val TOGGLE = "toggle" companion object { - private var mCameraImpl: MyCameraImpl? = null - private var mRemoteViews: RemoteViews? = null private var mColoredBmp: Bitmap? = null private var mWhiteBmp: Bitmap? = null - private var mBus: Bus? = null - private var mContext: Context? = null } override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { @@ -34,77 +34,70 @@ class MyWidgetProvider : AppWidgetProvider() { } private fun performUpdate(context: Context) { - mContext = context val appWidgetManager = AppWidgetManager.getInstance(context) appWidgetManager.getAppWidgetIds(getComponentName(context)).forEach { + val views = RemoteViews(context.packageName, R.layout.widget) + val intent = Intent(context, MyWidgetProvider::class.java) intent.action = TOGGLE val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0) - mRemoteViews = RemoteViews(context.packageName, R.layout.widget) - mRemoteViews!!.setOnClickPendingIntent(R.id.toggle_btn, pendingIntent) - mCameraImpl = MyCameraImpl(context) + views.setOnClickPendingIntent(R.id.toggle_btn, pendingIntent) val selectedColor = context.config.widgetBgColor val alpha = Color.alpha(selectedColor) - mColoredBmp = getColoredCircles(selectedColor, alpha) - mWhiteBmp = getColoredCircles(Color.WHITE, alpha) - mRemoteViews!!.setImageViewBitmap(R.id.toggle_btn, mWhiteBmp) + mColoredBmp = getColoredCircles(context, selectedColor, alpha) + mWhiteBmp = getColoredCircles(context, Color.WHITE, alpha) + views.setImageViewBitmap(R.id.toggle_btn, mWhiteBmp) - if (mBus == null) { - mBus = BusProvider.instance - } - registerBus() + appWidgetManager.updateAppWidget(it, views) } } private fun getComponentName(context: Context) = ComponentName(context, MyWidgetProvider::class.java) override fun onReceive(context: Context, intent: Intent) { + Log.e("DEBUG", "received action ${intent.action}") when (intent.action) { - TOGGLE -> toggleFlashlight(context) + //TOGGLE -> toggleFlashlight(context) else -> super.onReceive(context, intent) } } + @RequiresApi(Build.VERSION_CODES.LOLLIPOP) private fun toggleFlashlight(context: Context) { - if (mCameraImpl == null || mBus == null) { - performUpdate(context) + if (context.isMarshmallowPlus()) { + val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager + try { + val cameraId = manager.cameraIdList[0] + //manager.setTorchMode(cameraId!!, enable) + } catch (ignored: CameraAccessException) { + } } - - mCameraImpl!!.toggleFlashlight() } - private fun getColoredCircles(color: Int, alpha: Int): Bitmap { - val drawable = mContext!!.resources.getDrawable(R.drawable.circles_small) + private fun getColoredCircles(context: Context, color: Int, alpha: Int): Bitmap { + val drawable = context.resources.getDrawable(R.drawable.circles_small) drawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_ATOP) drawable.mutate().alpha = alpha return Utils.drawableToBitmap(drawable) } private fun enableFlashlight() { - mRemoteViews!!.setImageViewBitmap(R.id.toggle_btn, mColoredBmp) + //mRemoteViews!!.setImageViewBitmap(R.id.toggle_btn, mColoredBmp) /*for (widgetId in mWidgetIds!!) { mWidgetManager!!.updateAppWidget(widgetId, mRemoteViews) }*/ } private fun disableFlashlight() { - mRemoteViews!!.setImageViewBitmap(R.id.toggle_btn, mWhiteBmp) + //mRemoteViews!!.setImageViewBitmap(R.id.toggle_btn, mWhiteBmp) /*for (widgetId in mWidgetIds!!) { mWidgetManager!!.updateAppWidget(widgetId, mRemoteViews) }*/ } - @Subscribe - fun cameraUnavailable(event: Events.CameraUnavailable) { - if (mContext != null) { - mContext!!.toast(R.string.camera_error) - disableFlashlight() - } - } - @Subscribe fun stateChangedEvent(event: Events.StateChanged) { if (event.isEnabled) { @@ -113,34 +106,4 @@ class MyWidgetProvider : AppWidgetProvider() { disableFlashlight() } } - - override fun onDeleted(context: Context, appWidgetIds: IntArray) { - super.onDeleted(context, appWidgetIds) - unregisterBus() - releaseCamera(context) - } - - private fun releaseCamera(context: Context) { - if (mCameraImpl == null) { - performUpdate(context) - } - - mCameraImpl!!.releaseCamera() - } - - private fun registerBus() { - try { - mBus!!.register(this) - } catch (ignored: Exception) { - } - - } - - private fun unregisterBus() { - try { - mBus!!.unregister(this) - } catch (ignored: Exception) { - } - - } } diff --git a/app/src/main/kotlin/com/simplemobiletools/flashlight/models/Events.kt b/app/src/main/kotlin/com/simplemobiletools/flashlight/models/Events.kt index 5fd4593..36d4227 100644 --- a/app/src/main/kotlin/com/simplemobiletools/flashlight/models/Events.kt +++ b/app/src/main/kotlin/com/simplemobiletools/flashlight/models/Events.kt @@ -1,19 +1,7 @@ package com.simplemobiletools.flashlight.models class Events { - class StateChanged(isEnabled: Boolean) { - - val isEnabled: Boolean - get() = mIsEnabled - - init { - mIsEnabled = isEnabled - } - - companion object { - private var mIsEnabled: Boolean = false - } - } + class StateChanged(val isEnabled: Boolean) class CameraUnavailable } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index c632ad3..4975b24 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -22,7 +22,7 @@ android:layout_height="wrap_content" android:layout_marginBottom="@dimen/activity_margin" android:layout_marginTop="@dimen/buttons_margin" - android:background="@mipmap/ic_bright_display" + android:background="@drawable/ic_bright_display" android:padding="@dimen/activity_margin"/>