From d158f6b6ded3a7735173f2772b037de274a9a027 Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Thu, 27 Feb 2020 22:37:31 -0600 Subject: [PATCH 01/27] Enable camera resolution switching for legacy devices, dynamically load list --- .../controller/fragments/SettingsCamera.kt | 82 ++++++++++++++++--- .../android/controller/utils/CameraUtil.kt | 55 +++++++++++++ .../controller/utils/v16/Camera1Util.kt | 24 ++++++ .../controller/{ => utils/v21}/Camera2Util.kt | 45 ++++------ app/src/main/res/values/strings.xml | 4 +- app/src/main/res/xml/settings_camera.xml | 1 - .../controller/sdk/RemoSettingsUtil.kt | 6 +- 7 files changed, 169 insertions(+), 48 deletions(-) create mode 100644 app/src/main/java/tv/remo/android/controller/utils/CameraUtil.kt create mode 100644 app/src/main/java/tv/remo/android/controller/utils/v16/Camera1Util.kt rename app/src/main/java/tv/remo/android/controller/{ => utils/v21}/Camera2Util.kt (50%) diff --git a/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt b/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt index abb8610..3d113eb 100644 --- a/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt +++ b/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt @@ -1,31 +1,85 @@ package tv.remo.android.controller.fragments import android.content.Context +import android.content.pm.PackageManager import android.hardware.camera2.CameraCharacteristics import android.hardware.camera2.CameraManager import android.os.Build import android.os.Bundle +import android.view.View +import android.widget.Toast import androidx.preference.EditTextPreference import androidx.preference.ListPreference import androidx.preference.Preference import androidx.preference.SwitchPreferenceCompat -import tv.remo.android.controller.Camera2Util import tv.remo.android.controller.R import tv.remo.android.controller.sdk.RemoSettingsUtil import tv.remo.android.controller.sdk.utils.ValueUtil +import tv.remo.android.controller.utils.CameraUtil import tv.remo.android.settingsutil.fragments.BasePreferenceFragmentCompat +import tv.remo.android.settingsutil.interfaces.SwitchBarCapableActivity import java.util.* class SettingsCamera : BasePreferenceFragmentCompat( R.xml.settings_camera, R.string.cameraSettingsEnableKey ) { - override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - super.onCreatePreferences(savedInstanceState, rootKey) + + private val cameraId: Int + get() { + return RemoSettingsUtil.with(context!!).cameraDeviceId.getPref() + } + + private val cameraAllowed : Boolean + get() { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + context!!.checkSelfPermission(android.Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED + } else { + true + } + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + (activity as SwitchBarCapableActivity).getSwitchBar().apply { + addOnSwitchChangeListener{ _, isChecked -> + if(isChecked) + checkPermissions() + } + } + RemoSettingsUtil.with(context!!) { val currCameraId = it.cameraDeviceId.getPref() checkForCamera2SupportAndReact(it.cameraDeviceId.getPref()) updateUIFromCameraSelection(currCameraId) addListeners() + if(it.cameraEnabled.getPref()) + checkPermissions() + } + } + + private fun checkPermissions() { + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !cameraAllowed){ + preferenceManager.preferenceScreen.isEnabled = false + requestPermissions(arrayOf(android.Manifest.permission.CAMERA), 111) + } + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + if(requestCode == 111){ + if(cameraAllowed){ + preferenceManager.preferenceScreen.isEnabled = true + updateUIFromCameraSelection(cameraId) + } + else{ + Toast.makeText(context!!, + "Camera permissions required to modify camera settings!", + Toast.LENGTH_SHORT).show() + } } } @@ -52,18 +106,15 @@ class SettingsCamera : BasePreferenceFragmentCompat( } } - private fun updateUIFromCameraSelection(newValue: Int) { - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - val sizes = try { - Camera2Util.GetCameraSizes(requireContext(), newValue) - } catch (e: IndexOutOfBoundsException) { - ArrayList>().also { - it.add(Pair(640, 480)) - } + private fun updateUIFromCameraSelection(cameraIndex: Int) { + val sizes = try { + CameraUtil.getCameraSizes(requireContext(), cameraIndex) + } catch (e: IndexOutOfBoundsException) { + ArrayList>().also { + it.add(Pair(640, 480)) } - setNewResolutionList(sizes) } + setNewResolutionList(sizes) } private fun setNewResolutionList(sizes: ArrayList>) { @@ -76,6 +127,11 @@ class SettingsCamera : BasePreferenceFragmentCompat( sizes.removeAll { pair -> blacklist.contains(pair) } + if(sizes.isEmpty()) { + //this one always will work. + // We also need a fallback in case permissions have not been accepted + sizes.add(Pair(640, 480)) + } //init values for listPreference val values = initResolutionArray(sizes.size) diff --git a/app/src/main/java/tv/remo/android/controller/utils/CameraUtil.kt b/app/src/main/java/tv/remo/android/controller/utils/CameraUtil.kt new file mode 100644 index 0000000..19611db --- /dev/null +++ b/app/src/main/java/tv/remo/android/controller/utils/CameraUtil.kt @@ -0,0 +1,55 @@ +package tv.remo.android.controller.utils + +import android.content.Context +import android.os.Build +import android.util.Log +import androidx.annotation.RequiresApi +import tv.remo.android.controller.sdk.utils.ValueUtil +import tv.remo.android.controller.utils.v16.Camera1Util +import tv.remo.android.controller.utils.v21.Camera2Util +import java.util.* + +/** + * Created by Brendon on 2/27/2020. + */ +object CameraUtil{ + fun getCameraSizes(requireContext: Context, cameraIndex: Int): ArrayList> { + val sizes = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP + && isFullyCamera2Compatible(requireContext, cameraIndex)) { + Camera2Util.getCameraSizes(requireContext, cameraIndex) + } else{ + Camera1Util.getCameraSizes(requireContext, cameraIndex) + } + + val finalList = ArrayList>() + val ratio16by9 = 16f / 9f + val ratio4by3 = 4f / 3f + val ratio3by2 = 3f / 2f + sizes.forEach { + val height = it.first + val width = it.second + val ratio = (width * 1f / height * 1f) + val outsideOfAllowedSizes = width < 640 || height < 480 + || width > 1920 || height > 1080 + val isAllowedRatio = ratio == ratio16by9 + || ratio == ratio4by3 + || ratio == ratio3by2 + if (isAllowedRatio && !outsideOfAllowedSizes) { + finalList.add(Pair(width, height)) + } + + //logging only + val gcm = ValueUtil.gcm(width, height) + Log.d( + "RemoApplication", + "PictureSize: ${width}x${height} : ${width / gcm}:${height / gcm}" + ) + } + return finalList + } + + @RequiresApi(Build.VERSION_CODES.LOLLIPOP) + private fun isFullyCamera2Compatible(context: Context, cameraIndex: Int): Boolean { + return Camera2Util.checkFullyCompatible(context, cameraIndex); + } +} \ No newline at end of file diff --git a/app/src/main/java/tv/remo/android/controller/utils/v16/Camera1Util.kt b/app/src/main/java/tv/remo/android/controller/utils/v16/Camera1Util.kt new file mode 100644 index 0000000..9e4654a --- /dev/null +++ b/app/src/main/java/tv/remo/android/controller/utils/v16/Camera1Util.kt @@ -0,0 +1,24 @@ +package tv.remo.android.controller.utils.v16 + +import android.content.Context +import android.hardware.Camera +import java.util.* + +/** + * Created by Brendon on 2/27/2020. + */ +object Camera1Util { + fun getCameraSizes(requireContext: Context, cameraIndex: Int): ArrayList> { + val list = ArrayList>() + kotlin.runCatching { + val camera = Camera.open(cameraIndex) + camera.runCatching { + parameters.supportedPreviewSizes.forEach{ + list.add(Pair(it.height, it.width)) + } + } + camera.release() + } + return list + } +} \ No newline at end of file diff --git a/app/src/main/java/tv/remo/android/controller/Camera2Util.kt b/app/src/main/java/tv/remo/android/controller/utils/v21/Camera2Util.kt similarity index 50% rename from app/src/main/java/tv/remo/android/controller/Camera2Util.kt rename to app/src/main/java/tv/remo/android/controller/utils/v21/Camera2Util.kt index abc9cc4..20a3818 100644 --- a/app/src/main/java/tv/remo/android/controller/Camera2Util.kt +++ b/app/src/main/java/tv/remo/android/controller/utils/v21/Camera2Util.kt @@ -1,4 +1,4 @@ -package tv.remo.android.controller +package tv.remo.android.controller.utils.v21 import android.content.Context import android.graphics.ImageFormat @@ -8,12 +8,11 @@ import android.hardware.camera2.CameraManager import android.os.Build import android.util.Log import androidx.annotation.RequiresApi -import tv.remo.android.controller.sdk.utils.ValueUtil @RequiresApi(Build.VERSION_CODES.LOLLIPOP) object Camera2Util { @Throws(ArrayIndexOutOfBoundsException::class) - fun GetCameraSizes(context : Context, cameraIndex : Int = 0) : ArrayList> { + fun getCameraSizes(context : Context, cameraIndex : Int = 0) : ArrayList> { val list = ArrayList>() val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager try { @@ -25,35 +24,9 @@ object Camera2Util { // Images supported size by device val pictureSizes = map!!.getOutputSizes(ImageFormat.YUV_420_888) - - val ratio16by9 = 16f / 9f - val ratio4by3 = 4f / 3f - val ratio3by2 = 3f / 2f pictureSizes.forEach { - val height = it.height - val width = it.width - val ratio = (width * 1f / height * 1f) - val outsideOfAllowedSizes = width < 640 || height < 480 - || width > 1920 || height > 1080 - val isAllowedRatio = ratio == ratio16by9 - || ratio == ratio4by3 - || ratio == ratio3by2 - if (isAllowedRatio && !outsideOfAllowedSizes) { - list.add(Pair(width, height)) - } - - //logging only - val gcm = ValueUtil.gcm(width, height) - Log.d( - "RemoApplication", - "PictureSize: ${width}x${height} : ${width / gcm}:${height / gcm}" - ) + list.add(Pair(it.height, it.width)) } - /*TODO switch to video recording // Video supported size by device - val videoSizes = map.getOutputSizes(MediaRecorder::class.java) - videoSizes.forEach { - Log.d("RemoApplication", "VideoSize: ${it.width}x${it.height}") - }*/ } catch (e: CameraAccessException) { e.printStackTrace() Log.e("RemoApplication", "setUpCameraOutputs: catch: " + e.message) @@ -62,4 +35,16 @@ object Camera2Util { } return list } + + fun checkFullyCompatible(context: Context, cameraIndex: Int): Boolean { + kotlin.runCatching { + val cm = (context.getSystemService(Context.CAMERA_SERVICE) as CameraManager) + val hardwareLevel = cm.getCameraCharacteristics( + cm.cameraIdList[cameraIndex] + )[CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL] + return hardwareLevel != CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY + && hardwareLevel != CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED + } + return false + } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9839634..db3fa6d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -53,9 +53,7 @@ Auto Focus Orientation Camera2 Disabled - Device is using legacy camera API. - Resolution is locked at 640x480. Disabled since device OS is below 5.0 - or selected camera id does not support new camera api + Device is using legacy camera API. Some features may be locked Microphone Volume, Bitrate diff --git a/app/src/main/res/xml/settings_camera.xml b/app/src/main/res/xml/settings_camera.xml index 5966ed0..f5ad506 100644 --- a/app/src/main/res/xml/settings_camera.xml +++ b/app/src/main/res/xml/settings_camera.xml @@ -16,7 +16,6 @@ app:isPreferenceVisible="false"/> with(context: Context, func : (RemoSettingsUtil)->T) : T{ - val settingsUtil = INSTANCE ?: create(context) + val settingsUtil = with(context) return func(settingsUtil) } + + fun with(context: Context) : RemoSettingsUtil{ + return INSTANCE ?: create(context) + } } } From a4097a121977f3122caac198b30b62189731e54c Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Thu, 27 Feb 2020 22:56:45 -0600 Subject: [PATCH 02/27] Camera Device ID now only shows camera indexes that are available instead of just 10 device ids --- .../controller/fragments/SettingsCamera.kt | 22 +++++++++++++++++++ .../android/controller/utils/CameraUtil.kt | 8 +++++++ .../controller/utils/v16/Camera1Util.kt | 4 ++++ .../controller/utils/v21/Camera2Util.kt | 5 +++++ 4 files changed, 39 insertions(+) diff --git a/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt b/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt index 3d113eb..60487a9 100644 --- a/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt +++ b/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt @@ -49,6 +49,7 @@ class SettingsCamera : BasePreferenceFragmentCompat( RemoSettingsUtil.with(context!!) { val currCameraId = it.cameraDeviceId.getPref() + setupCameraIdList(currCameraId) checkForCamera2SupportAndReact(it.cameraDeviceId.getPref()) updateUIFromCameraSelection(currCameraId) addListeners() @@ -57,6 +58,27 @@ class SettingsCamera : BasePreferenceFragmentCompat( } } + private fun setupCameraIdList(currCameraId: Int) { + val cameras = CameraUtil.getCameraCount(context!!) + findPreference(getString(R.string.cameraDeviceIdKey))?.apply { + createEntries(cameras).also { + entries = it + entryValues = it + } + if(currCameraId >= cameras){ + Toast.makeText(context!!, "Last selected camera is no longer available...", + Toast.LENGTH_LONG).show() + value = entries[0] as String + } + } + } + + private fun createEntries(size: Int): Array { + return Array(size){ + it.toString() + } + } + private fun checkPermissions() { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !cameraAllowed){ preferenceManager.preferenceScreen.isEnabled = false diff --git a/app/src/main/java/tv/remo/android/controller/utils/CameraUtil.kt b/app/src/main/java/tv/remo/android/controller/utils/CameraUtil.kt index 19611db..bb124e8 100644 --- a/app/src/main/java/tv/remo/android/controller/utils/CameraUtil.kt +++ b/app/src/main/java/tv/remo/android/controller/utils/CameraUtil.kt @@ -48,6 +48,14 @@ object CameraUtil{ return finalList } + fun getCameraCount(context: Context) : Int{ + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Camera2Util.getCameras(context) + }else{ + Camera1Util.getCameras() + } + } + @RequiresApi(Build.VERSION_CODES.LOLLIPOP) private fun isFullyCamera2Compatible(context: Context, cameraIndex: Int): Boolean { return Camera2Util.checkFullyCompatible(context, cameraIndex); diff --git a/app/src/main/java/tv/remo/android/controller/utils/v16/Camera1Util.kt b/app/src/main/java/tv/remo/android/controller/utils/v16/Camera1Util.kt index 9e4654a..b7c2b2d 100644 --- a/app/src/main/java/tv/remo/android/controller/utils/v16/Camera1Util.kt +++ b/app/src/main/java/tv/remo/android/controller/utils/v16/Camera1Util.kt @@ -21,4 +21,8 @@ object Camera1Util { } return list } + + fun getCameras(): Int { + return Camera.getNumberOfCameras() + } } \ No newline at end of file diff --git a/app/src/main/java/tv/remo/android/controller/utils/v21/Camera2Util.kt b/app/src/main/java/tv/remo/android/controller/utils/v21/Camera2Util.kt index 20a3818..b0c6ac0 100644 --- a/app/src/main/java/tv/remo/android/controller/utils/v21/Camera2Util.kt +++ b/app/src/main/java/tv/remo/android/controller/utils/v21/Camera2Util.kt @@ -47,4 +47,9 @@ object Camera2Util { } return false } + + fun getCameras(context: Context) : Int{ + val cm = (context.getSystemService(Context.CAMERA_SERVICE) as CameraManager) + return cm.cameraIdList.size + } } From 93f3a8c9d58da7bf41c979e4852e9cc5d682bec5 Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Thu, 27 Feb 2020 23:07:22 -0600 Subject: [PATCH 03/27] break up a method --- .../main/java/tv/remo/android/controller/utils/CameraUtil.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/tv/remo/android/controller/utils/CameraUtil.kt b/app/src/main/java/tv/remo/android/controller/utils/CameraUtil.kt index bb124e8..95f53bb 100644 --- a/app/src/main/java/tv/remo/android/controller/utils/CameraUtil.kt +++ b/app/src/main/java/tv/remo/android/controller/utils/CameraUtil.kt @@ -20,7 +20,10 @@ object CameraUtil{ } else{ Camera1Util.getCameraSizes(requireContext, cameraIndex) } + return filterSizes(sizes) + } + private fun filterSizes(sizes: ArrayList>): ArrayList> { val finalList = ArrayList>() val ratio16by9 = 16f / 9f val ratio4by3 = 4f / 3f @@ -45,7 +48,7 @@ object CameraUtil{ "PictureSize: ${width}x${height} : ${width / gcm}:${height / gcm}" ) } - return finalList + return sizes } fun getCameraCount(context: Context) : Int{ From 0e97b258065c8f8093641fd3d3e6dc2415ede3d2 Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Fri, 28 Feb 2020 19:43:06 -0600 Subject: [PATCH 04/27] minor reformatting --- .../controller/sdk/utils/ComponentBuilderUtil.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sdk/src/main/java/tv/remo/android/controller/sdk/utils/ComponentBuilderUtil.kt b/sdk/src/main/java/tv/remo/android/controller/sdk/utils/ComponentBuilderUtil.kt index 35d3e22..7c2f12e 100644 --- a/sdk/src/main/java/tv/remo/android/controller/sdk/utils/ComponentBuilderUtil.kt +++ b/sdk/src/main/java/tv/remo/android/controller/sdk/utils/ComponentBuilderUtil.kt @@ -76,13 +76,13 @@ object ComponentBuilderUtil { return Bundle().apply { val resolution = settings.cameraResolution.getPref().split("x") val streamInfo = StreamInfo( - settings.videoUrl - ,settings.audioUrl - ,deviceInfo = CameraDeviceInfo.fromCamera(settings.cameraDeviceId.getPref()) - ,orientation = Orientation.valueOf(settings.cameraOrientation.getPref()) - ,bitrate = settings.cameraBitrate.getPref().toIntOrNull() ?: 512 - ,width = resolution[0].toInt() - ,height = resolution[1].toInt() + settings.videoUrl, + settings.audioUrl, + deviceInfo = CameraDeviceInfo.fromCamera(settings.cameraDeviceId.getPref()), + orientation = Orientation.valueOf(settings.cameraOrientation.getPref()), + bitrate = settings.cameraBitrate.getPref().toIntOrNull() ?: 512, + width = resolution[0].toInt(), + height = resolution[1].toInt() ) //use our customized remo classes VideoRetrieverFactory.putClassInBundle(CameraCompatOverride::class.java, this) From 53c3956c0506cc12cf5fd808135c471e7e8943e2 Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Fri, 28 Feb 2020 20:25:14 -0600 Subject: [PATCH 05/27] Fix wrong list being returned... --- .../main/java/tv/remo/android/controller/utils/CameraUtil.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/tv/remo/android/controller/utils/CameraUtil.kt b/app/src/main/java/tv/remo/android/controller/utils/CameraUtil.kt index 95f53bb..5b9fb93 100644 --- a/app/src/main/java/tv/remo/android/controller/utils/CameraUtil.kt +++ b/app/src/main/java/tv/remo/android/controller/utils/CameraUtil.kt @@ -48,7 +48,7 @@ object CameraUtil{ "PictureSize: ${width}x${height} : ${width / gcm}:${height / gcm}" ) } - return sizes + return finalList } fun getCameraCount(context: Context) : Int{ From 609cd597a00b0762a9ba43d6f4e78a97e4214284 Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Fri, 28 Feb 2020 20:27:50 -0600 Subject: [PATCH 06/27] Add 960x720 to known working resolutions --- .../java/tv/remo/android/controller/fragments/SettingsCamera.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt b/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt index 60487a9..a132c26 100644 --- a/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt +++ b/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt @@ -161,7 +161,7 @@ class SettingsCamera : BasePreferenceFragmentCompat( //create a list of known resolutions that are okay. Unknown ones are marked with (not tested) val knownWorkingResolutions = - listOf(Pair(640, 480), Pair(1280, 720), Pair(1280, 960), Pair(1920, 1080)) + listOf(Pair(640, 480), Pair(1280, 720), Pair(960, 720), Pair(1280, 960), Pair(1920, 1080)) //iterate through the array to add sizes to values and userFacingValues arrays sizes.forEachIndexed { i, pair -> From a011168aa96b4ba0f7abc81089f5710b44a05857 Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Fri, 28 Feb 2020 21:34:34 -0600 Subject: [PATCH 07/27] remove setting of camera back to 640x480 when camera2 support changes since camera1 can now change resolutions --- .../tv/remo/android/controller/fragments/SettingsCamera.kt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt b/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt index a132c26..7c01b4f 100644 --- a/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt +++ b/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt @@ -205,12 +205,6 @@ class SettingsCamera : BasePreferenceFragmentCompat( val featureSwitch = findPreference(getString(R.string.useCamera2)) featureSwitch?.isEnabled = supportsCamera2 featureSwitch?.isChecked = supportsCamera2 - if (!supportsCamera2) - findPreference( - getString(R.string.cameraResolutionKey) - )?.let { - it.value = "640x480" - } return supportsCamera2 } From 96d015bb4449274535236bf00a82688a1d81b3ca Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Fri, 28 Feb 2020 22:46:58 -0600 Subject: [PATCH 08/27] demo statuses --- .../controller/activities/MainActivity.kt | 21 ++++ .../android/controller/ui/CustomImageView.kt | 16 +++ .../android/controller/ui/RemoStatusView.kt | 108 ++++++++++++++++++ app/src/main/res/layout/activity_main.xml | 53 +++++++++ app/src/main/res/values/colors.xml | 7 ++ app/src/main/res/values/dimens.xml | 4 + 6 files changed, 209 insertions(+) create mode 100644 app/src/main/java/tv/remo/android/controller/ui/CustomImageView.kt create mode 100644 app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt create mode 100644 app/src/main/res/values/dimens.xml diff --git a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt index 8c3b4d3..d2bd092 100644 --- a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt +++ b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt @@ -33,6 +33,9 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { setContentView(R.layout.activity_main) setupControlSDK() setupUI() + window.decorView.post { + buildStatusList() + } } override fun onClick(v: View?) { @@ -69,6 +72,24 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { } settingsButton.setOnClickListener(this) powerButton?.setOnClickListener(this) + + } + + private fun buildStatusList() { + val prev = websiteConnectionStatusView.x + websiteConnectionStatusView.x = 500f + websiteConnectionStatusView.animate().also { + it.startDelay = 1000 + it.duration = 1000 + it.x(prev) + }.start() + + handler.postDelayed({ + websiteConnectionStatusView.animate().also { + it.duration = 1000 + it.x(500f) + }.start() + }, 5000) } val operationObserver : (Operation) -> Unit = { serviceStatus -> diff --git a/app/src/main/java/tv/remo/android/controller/ui/CustomImageView.kt b/app/src/main/java/tv/remo/android/controller/ui/CustomImageView.kt new file mode 100644 index 0000000..3fb9e36 --- /dev/null +++ b/app/src/main/java/tv/remo/android/controller/ui/CustomImageView.kt @@ -0,0 +1,16 @@ +package tv.remo.android.controller.ui + +import android.content.Context +import android.util.AttributeSet + +/** + * Image View that follows other UI behavior if disabled + */ +open class CustomImageView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 +) : androidx.appcompat.widget.AppCompatImageView(context, attrs, defStyleAttr) { + override fun setEnabled(enabled: Boolean) { + super.setEnabled(enabled) + imageAlpha = if(enabled) 0xFF else 0x3F + } +} \ No newline at end of file diff --git a/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt b/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt new file mode 100644 index 0000000..de5e8aa --- /dev/null +++ b/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt @@ -0,0 +1,108 @@ +package tv.remo.android.controller.ui + +import android.content.Context +import android.graphics.Color +import android.graphics.PorterDuff +import android.graphics.drawable.Drawable +import android.os.Build +import android.os.Handler +import android.os.Looper +import android.util.AttributeSet +import android.util.SparseIntArray +import org.btelman.controlsdk.enums.ComponentStatus +import tv.remo.android.controller.R + +/** + * Status view that will communicate directly with a chosen component + * + * TODO replace with ViewModel + */ +class RemoStatusView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 +) : CustomImageView(context, attrs, defStyleAttr), Runnable { + private var colorLookup = SparseIntArray().also{ + appendColor(context, it, R.color.colorIndicatorDisabledFromSettings) + appendColor(context, it, R.color.colorIndicatorDisabled) + appendColor(context, it, R.color.colorIndicatorConnecting) + appendColor(context, it, R.color.colorIndicatorStable) + appendColor(context, it, R.color.colorIndicatorUnstable) + appendColor(context, it, R.color.colorIndicatorError) + } + + @Suppress("DEPRECATION") + private fun appendColor(context: Context, it: SparseIntArray, resId: Int) { + val color : Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + context.getColor(resId) + } + else{ + context.resources.getColor(resId) + } + it.append(resId, color) + } + + private var uiHandler : Handler = Handler(Looper.getMainLooper()) + private var component: String? = null + private var status : ComponentStatus? = null + val values = ComponentStatus.values() + init{ + uiHandler.post(this) + } + + fun setDrawableColor(drawable: Drawable, id : Int) : Drawable{ + val color : Int = colorLookup.get(id, Color.BLACK) + drawable.setColorFilter(color, PorterDuff.Mode.MULTIPLY) + return drawable + } + + fun setStatus(componentStatus: ComponentStatus){ + background = when(componentStatus){ + ComponentStatus.DISABLED_FROM_SETTINGS -> setDrawableColor(background, R.color.colorIndicatorDisabledFromSettings) + ComponentStatus.DISABLED -> setDrawableColor(background, R.color.colorIndicatorDisabled) + ComponentStatus.CONNECTING -> setDrawableColor(background, R.color.colorIndicatorConnecting) + ComponentStatus.STABLE -> setDrawableColor(background, R.color.colorIndicatorStable) + ComponentStatus.INTERMITTENT -> setDrawableColor(background, R.color.colorIndicatorUnstable) + ComponentStatus.ERROR -> setDrawableColor(background, R.color.colorIndicatorError) + } + } + + override fun run() { + status?.let { + setStatus(it) + uiHandler.postDelayed(this, 100) + } ?: run{ + setStatus(loopStatus()) + uiHandler.postDelayed(this, 1000) + } + } + + var i = 0 + private fun loopStatus(): ComponentStatus { + var status : ComponentStatus = ComponentStatus.DISABLED_FROM_SETTINGS + values.forEachIndexed { index, componentStatus -> + if (index == i) { + status = componentStatus + } + } + i++ + if(i > values.size) + i = 0 + return status + } + + private val onStatus: (Any?) -> Unit = { + it?.takeIf { it is ComponentStatus }?.let{ + status = it as ComponentStatus + } + } + + fun setComponentInterface(component: String) { +// this.component?.let { EventManager.unsubscribe(it, onStatus) } +// this.component = component +// EventManager.subscribe(component, onStatus) + } + + fun onDestroy(){ +// this.component?.let { EventManager.unsubscribe(it, onStatus) } + uiHandler.removeCallbacksAndMessages(null) + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 479b085..b1c5244 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -8,6 +8,59 @@ android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context=".activities.MainActivity"> + + + + + + + + #3255fb #8c12cb #ececec + + #263238 + #000000 + #1B5E20 + #FFD600 + #E65100 + #B71C1C diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..f05672d --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,4 @@ + + + 38dp + \ No newline at end of file From a897ce7987f0a9858442b61f84a362faead33fab Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Fri, 28 Feb 2020 23:15:10 -0600 Subject: [PATCH 09/27] Change statuses to top of buttons. Slight color changes --- .../controller/activities/MainActivity.kt | 38 +++++++------------ .../android/controller/ui/RemoStatusView.kt | 20 +++++----- .../drawable/ic_phone_android_black_24dp.xml | 2 +- app/src/main/res/layout/activity_main.xml | 13 ++----- app/src/main/res/values/colors.xml | 21 ++++++---- app/src/main/res/values/dimens.xml | 2 +- settingsutil/src/main/res/drawable/circle.xml | 2 +- 7 files changed, 42 insertions(+), 56 deletions(-) diff --git a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt index d2bd092..5b2ad9c 100644 --- a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt +++ b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt @@ -76,20 +76,7 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { } private fun buildStatusList() { - val prev = websiteConnectionStatusView.x - websiteConnectionStatusView.x = 500f - websiteConnectionStatusView.animate().also { - it.startDelay = 1000 - it.duration = 1000 - it.x(prev) - }.start() - - handler.postDelayed({ - websiteConnectionStatusView.animate().also { - it.duration = 1000 - it.x(500f) - }.start() - }, 5000) + } val operationObserver : (Operation) -> Unit = { serviceStatus -> @@ -193,6 +180,18 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { or View.SYSTEM_UI_FLAG_FULLSCREEN) } + + @Suppress("DEPRECATION") + fun parseColorForOperation(state : Operation?) : Int{ + return when(state){ + Operation.OK -> resources.getColor(R.color.powerIndicatorOn) + Operation.NOT_OK -> resources.getColor(R.color.powerIndicatorOff) + Operation.LOADING -> resources.getColor(R.color.powerIndicatorInProgress) + null -> resources.getColor(R.color.powerIndicatorError) + else -> Color.BLACK + } + } + // Shows the system bars by removing all the flags // except for the ones that make the content appear under the system bars. private fun showSystemUI() { @@ -203,17 +202,6 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { fun getIntent(context: Context) : Intent { return Intent(context, MainActivity::class.java) } - - fun parseColorForOperation(state : Operation?) : Int{ - val color : Int = when(state){ - Operation.OK -> Color.GREEN - Operation.NOT_OK -> Color.RED - Operation.LOADING -> Color.YELLOW - null -> Color.CYAN - else -> Color.BLACK - } - return color - } } } diff --git a/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt b/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt index de5e8aa..09fd9a2 100644 --- a/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt +++ b/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt @@ -3,7 +3,6 @@ package tv.remo.android.controller.ui import android.content.Context import android.graphics.Color import android.graphics.PorterDuff -import android.graphics.drawable.Drawable import android.os.Build import android.os.Handler import android.os.Looper @@ -48,20 +47,19 @@ class RemoStatusView @JvmOverloads constructor( uiHandler.post(this) } - fun setDrawableColor(drawable: Drawable, id : Int) : Drawable{ + fun setDrawableColor(id : Int){ val color : Int = colorLookup.get(id, Color.BLACK) - drawable.setColorFilter(color, PorterDuff.Mode.MULTIPLY) - return drawable + setColorFilter(color, PorterDuff.Mode.MULTIPLY) } fun setStatus(componentStatus: ComponentStatus){ - background = when(componentStatus){ - ComponentStatus.DISABLED_FROM_SETTINGS -> setDrawableColor(background, R.color.colorIndicatorDisabledFromSettings) - ComponentStatus.DISABLED -> setDrawableColor(background, R.color.colorIndicatorDisabled) - ComponentStatus.CONNECTING -> setDrawableColor(background, R.color.colorIndicatorConnecting) - ComponentStatus.STABLE -> setDrawableColor(background, R.color.colorIndicatorStable) - ComponentStatus.INTERMITTENT -> setDrawableColor(background, R.color.colorIndicatorUnstable) - ComponentStatus.ERROR -> setDrawableColor(background, R.color.colorIndicatorError) + when(componentStatus){ + ComponentStatus.DISABLED_FROM_SETTINGS -> setDrawableColor(R.color.colorIndicatorDisabledFromSettings) + ComponentStatus.DISABLED -> setDrawableColor(R.color.colorIndicatorDisabled) + ComponentStatus.CONNECTING -> setDrawableColor(R.color.colorIndicatorConnecting) + ComponentStatus.STABLE -> setDrawableColor(R.color.colorIndicatorStable) + ComponentStatus.INTERMITTENT -> setDrawableColor(R.color.colorIndicatorUnstable) + ComponentStatus.ERROR -> setDrawableColor(R.color.colorIndicatorError) } } diff --git a/app/src/main/res/drawable/ic_phone_android_black_24dp.xml b/app/src/main/res/drawable/ic_phone_android_black_24dp.xml index b32b05e..2bf760c 100644 --- a/app/src/main/res/drawable/ic_phone_android_black_24dp.xml +++ b/app/src/main/res/drawable/ic_phone_android_black_24dp.xml @@ -1,4 +1,4 @@ - + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index b1c5244..a41ec3e 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -10,19 +10,18 @@ tools:context=".activities.MainActivity"> diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index d79f620..3a29ad3 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,14 +1,19 @@ - #3255fb - #3255fb - #8c12cb + #6200EA + #4A148C + #304FFE #ececec - #263238 - #000000 - #1B5E20 + #000000 + #00B8D4 + #00C853 #FFD600 - #E65100 - #B71C1C + #FF6D00 + #D50000 + + #D50000 + #FFD600 + #00C853 + #AA00FF diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index f05672d..bab3d65 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -1,4 +1,4 @@ - 38dp + 24dp \ No newline at end of file diff --git a/settingsutil/src/main/res/drawable/circle.xml b/settingsutil/src/main/res/drawable/circle.xml index 475d442..7c5f085 100644 --- a/settingsutil/src/main/res/drawable/circle.xml +++ b/settingsutil/src/main/res/drawable/circle.xml @@ -4,7 +4,7 @@ android:shape="oval"> + android:color="#000"/> Date: Sat, 29 Feb 2020 21:03:24 -0600 Subject: [PATCH 10/27] Hook up component statuses to each component we want. --- .../controller/activities/MainActivity.kt | 11 ++- .../android/controller/ui/RemoStatusView.kt | 71 ++++++++++++++----- .../drawable/ic_phone_android_black_24dp.xml | 2 +- app/src/main/res/layout/activity_main.xml | 7 -- .../sdk/components/RemoSocketComponent.kt | 5 ++ .../components/StatusBroadcasterComponent.kt | 64 +++++++++++++++++ 6 files changed, 132 insertions(+), 28 deletions(-) create mode 100644 sdk/src/main/java/tv/remo/android/controller/sdk/components/StatusBroadcasterComponent.kt diff --git a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt index 5b2ad9c..26e6edb 100644 --- a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt +++ b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt @@ -11,12 +11,17 @@ import androidx.appcompat.app.AppCompatActivity import com.google.gson.Gson import kotlinx.android.synthetic.main.activity_main.* import org.btelman.controlsdk.enums.Operation +import org.btelman.controlsdk.hardware.components.CommunicationDriverComponent import org.btelman.controlsdk.interfaces.ControlSdkApi import org.btelman.controlsdk.models.ComponentHolder import org.btelman.controlsdk.services.ControlSDKServiceConnection import org.btelman.controlsdk.services.observeAutoCreate +import org.btelman.controlsdk.streaming.components.AudioComponent +import org.btelman.controlsdk.streaming.components.VideoComponent import tv.remo.android.controller.R import tv.remo.android.controller.sdk.RemoSettingsUtil +import tv.remo.android.controller.sdk.components.RemoSocketComponent +import tv.remo.android.controller.sdk.components.StatusBroadcasterComponent import tv.remo.android.controller.sdk.models.api.Message import tv.remo.android.controller.sdk.utils.ChatUtil import tv.remo.android.controller.sdk.utils.ComponentBuilderUtil @@ -76,7 +81,10 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { } private fun buildStatusList() { - + websiteConnectionStatusView.registerStatusEvents(RemoSocketComponent::class.java) + hardwareConnectionStatusView.registerStatusEvents(CommunicationDriverComponent::class.java) + audioConnectionStatusView.registerStatusEvents(AudioComponent::class.java) + videoConnectionStatusView.registerStatusEvents(VideoComponent::class.java) } val operationObserver : (Operation) -> Unit = { serviceStatus -> @@ -158,6 +166,7 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { private fun createComponentHolders() { RemoSettingsUtil.with(this){ settings -> + arrayList.add(ComponentHolder(StatusBroadcasterComponent::class.java, null)) arrayList.add(ComponentBuilderUtil.createSocketComponent(settings)) arrayList.addAll(ComponentBuilderUtil.createTTSComponents(settings)) arrayList.addAll(ComponentBuilderUtil.createStreamingComponents(settings)) diff --git a/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt b/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt index 09fd9a2..79fee9e 100644 --- a/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt +++ b/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt @@ -1,6 +1,9 @@ package tv.remo.android.controller.ui +import android.content.BroadcastReceiver import android.content.Context +import android.content.Intent +import android.content.IntentFilter import android.graphics.Color import android.graphics.PorterDuff import android.os.Build @@ -8,8 +11,11 @@ import android.os.Handler import android.os.Looper import android.util.AttributeSet import android.util.SparseIntArray +import androidx.localbroadcastmanager.content.LocalBroadcastManager import org.btelman.controlsdk.enums.ComponentStatus +import org.btelman.controlsdk.models.Component import tv.remo.android.controller.R +import tv.remo.android.controller.sdk.components.StatusBroadcasterComponent /** * Status view that will communicate directly with a chosen component @@ -18,7 +24,7 @@ import tv.remo.android.controller.R */ class RemoStatusView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : CustomImageView(context, attrs, defStyleAttr), Runnable { +) : CustomImageView(context, attrs, defStyleAttr), Runnable{ private var colorLookup = SparseIntArray().also{ appendColor(context, it, R.color.colorIndicatorDisabledFromSettings) appendColor(context, it, R.color.colorIndicatorDisabled) @@ -28,6 +34,16 @@ class RemoStatusView @JvmOverloads constructor( appendColor(context, it, R.color.colorIndicatorError) } + private val receiver = object : BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + intent?.let { + onBroadcastDataReceived(it) + } + } + } + + private val broadcastManager = LocalBroadcastManager.getInstance(context) + @Suppress("DEPRECATION") private fun appendColor(context: Context, it: SparseIntArray, resId: Int) { val color : Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { @@ -45,6 +61,33 @@ class RemoStatusView @JvmOverloads constructor( val values = ComponentStatus.values() init{ uiHandler.post(this) + post { + onCreated() + } + } + + private fun onCreated() { + + } + + fun onDestroy(){ + uiHandler.removeCallbacksAndMessages(null) + } + + fun registerStatusEvents(statusClassName : Class){ + broadcastManager.unregisterReceiver(receiver) + val filter = IntentFilter(StatusBroadcasterComponent.ACTION_SERVICE_STATUS) + filter.addAction(StatusBroadcasterComponent.generateComponentStatusAction(statusClassName)) + broadcastManager.registerReceiver(receiver, filter) + } + + fun unregisterStatusEvents(){ + broadcastManager.unregisterReceiver(receiver) + } + + private fun onBroadcastDataReceived(intent: Intent) { + val componentStatus = intent.getSerializableExtra(StatusBroadcasterComponent.STATUS_NAME) + status = componentStatus as? ComponentStatus } fun setDrawableColor(id : Int){ @@ -52,7 +95,14 @@ class RemoStatusView @JvmOverloads constructor( setColorFilter(color, PorterDuff.Mode.MULTIPLY) } - fun setStatus(componentStatus: ComponentStatus){ + fun postStatus(status: ComponentStatus){ + post { + this.status = status + setStatus(status) + } + } + + private fun setStatus(componentStatus: ComponentStatus){ when(componentStatus){ ComponentStatus.DISABLED_FROM_SETTINGS -> setDrawableColor(R.color.colorIndicatorDisabledFromSettings) ComponentStatus.DISABLED -> setDrawableColor(R.color.colorIndicatorDisabled) @@ -86,21 +136,4 @@ class RemoStatusView @JvmOverloads constructor( i = 0 return status } - - private val onStatus: (Any?) -> Unit = { - it?.takeIf { it is ComponentStatus }?.let{ - status = it as ComponentStatus - } - } - - fun setComponentInterface(component: String) { -// this.component?.let { EventManager.unsubscribe(it, onStatus) } -// this.component = component -// EventManager.subscribe(component, onStatus) - } - - fun onDestroy(){ -// this.component?.let { EventManager.unsubscribe(it, onStatus) } - uiHandler.removeCallbacksAndMessages(null) - } } diff --git a/app/src/main/res/drawable/ic_phone_android_black_24dp.xml b/app/src/main/res/drawable/ic_phone_android_black_24dp.xml index 2bf760c..9130560 100644 --- a/app/src/main/res/drawable/ic_phone_android_black_24dp.xml +++ b/app/src/main/res/drawable/ic_phone_android_black_24dp.xml @@ -1,4 +1,4 @@ - + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index a41ec3e..a0f3259 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -33,13 +33,6 @@ android:scaleType="centerInside" android:layout_height="@dimen/status_view_size" android:layout_width="@dimen/status_view_size"/> - generateComponentStatusAction(clazz : Class) : String{ +// if(clazz.getAnnotation(DriverComponent::class.java) != null){ +// return generateComponentStatusAction(CommunicationDriverComponent::class.java) +// } + return "${clazz.name}.${ACTION_COMPONENT_STATUS}" + } + const val ACTION_SERVICE_STATUS = "control.sdk.ACTION_SERVICE_STATUS" + const val ACTION_COMPONENT_STATUS = "ACTION_COMPONENT_STATUS" + const val CLASS_NAME = "component.class" + const val STATUS_NAME = "component.status.name" + } +} \ No newline at end of file From c2908f419ea7791c21036fbb96fbfe125fe24e2c Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Sat, 29 Feb 2020 21:28:20 -0600 Subject: [PATCH 11/27] Hook up debug view. Fix status being replaced by service status --- .../controller/activities/MainActivity.kt | 22 ++++++++++++ .../android/controller/ui/RemoStatusView.kt | 1 + app/src/main/res/values/colors.xml | 2 +- .../components/StatusBroadcasterComponent.kt | 10 +++++- .../controller/sdk/models/api/Message.kt | 35 +++++++++++++------ 5 files changed, 57 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt index 26e6edb..b09eadd 100644 --- a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt +++ b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt @@ -1,15 +1,19 @@ package tv.remo.android.controller.activities +import android.content.BroadcastReceiver import android.content.Context import android.content.Intent +import android.content.IntentFilter import android.graphics.Color import android.os.Bundle import android.os.Handler import android.os.Looper import android.view.View import androidx.appcompat.app.AppCompatActivity +import androidx.localbroadcastmanager.content.LocalBroadcastManager import com.google.gson.Gson import kotlinx.android.synthetic.main.activity_main.* +import org.btelman.controlsdk.enums.ComponentStatus import org.btelman.controlsdk.enums.Operation import org.btelman.controlsdk.hardware.components.CommunicationDriverComponent import org.btelman.controlsdk.interfaces.ControlSdkApi @@ -31,6 +35,7 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { private val arrayList = ArrayList>() private var controlSDKServiceApi: ControlSdkApi? = null private lateinit var handler : Handler + private val telemetryEnabled = true override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -41,6 +46,23 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { window.decorView.post { buildStatusList() } + if(telemetryEnabled) + setupChatViewAsLogger(); + } + + private fun setupChatViewAsLogger() { + val receiver = object : BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + intent?.let { + val name = it.getStringExtra(StatusBroadcasterComponent.CLASS_NAME) + val status = it.getSerializableExtra(StatusBroadcasterComponent.STATUS_NAME) as? ComponentStatus + ChatUtil.broadcastChatMessage(context!!, + Message.createDummyMessage(name.split(".").last(), status.toString())) + } + } + } + val broadcastManager = LocalBroadcastManager.getInstance(this) + broadcastManager.registerReceiver(receiver, IntentFilter(StatusBroadcasterComponent.ACTION_COMPONENT_STATUS)) } override fun onClick(v: View?) { diff --git a/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt b/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt index 79fee9e..34d56db 100644 --- a/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt +++ b/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt @@ -86,6 +86,7 @@ class RemoStatusView @JvmOverloads constructor( } private fun onBroadcastDataReceived(intent: Intent) { + if(intent.action == StatusBroadcasterComponent.ACTION_SERVICE_STATUS) return val componentStatus = intent.getSerializableExtra(StatusBroadcasterComponent.STATUS_NAME) status = componentStatus as? ComponentStatus } diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 3a29ad3..bf163e0 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -6,7 +6,7 @@ #ececec #000000 - #00B8D4 + #FFFFFF #00C853 #FFD600 #FF6D00 diff --git a/sdk/src/main/java/tv/remo/android/controller/sdk/components/StatusBroadcasterComponent.kt b/sdk/src/main/java/tv/remo/android/controller/sdk/components/StatusBroadcasterComponent.kt index 9da07b1..ef11836 100644 --- a/sdk/src/main/java/tv/remo/android/controller/sdk/components/StatusBroadcasterComponent.kt +++ b/sdk/src/main/java/tv/remo/android/controller/sdk/components/StatusBroadcasterComponent.kt @@ -36,11 +36,19 @@ class StatusBroadcasterComponent : Component() { override fun handleExternalMessage(message: ComponentEventObject): Boolean { if(message.what == STATUS_EVENT){ - val intent = Intent(generateComponentStatusAction(message.source.javaClass)).apply { + + //create an intent that will send all classes in the same action + val intent = Intent(ACTION_COMPONENT_STATUS).apply { putExtra(CLASS_NAME, message.source.javaClass.name) putExtra(STATUS_NAME, message.data as ComponentStatus) } + //create an intent that will only contain a single class of statuses + val intentClassLevel = Intent(generateComponentStatusAction(message.source.javaClass)).apply { + putExtra(STATUS_NAME, message.data as ComponentStatus) + } + //now send both of them localBroadcastManager?.sendBroadcast(intent) + localBroadcastManager?.sendBroadcast(intentClassLevel) } return super.handleExternalMessage(message) } diff --git a/sdk/src/main/java/tv/remo/android/controller/sdk/models/api/Message.kt b/sdk/src/main/java/tv/remo/android/controller/sdk/models/api/Message.kt index 9a85c94..189cdb6 100644 --- a/sdk/src/main/java/tv/remo/android/controller/sdk/models/api/Message.kt +++ b/sdk/src/main/java/tv/remo/android/controller/sdk/models/api/Message.kt @@ -1,36 +1,49 @@ package tv.remo.android.controller.sdk.models.api +import com.google.gson.Gson import com.google.gson.annotations.SerializedName import java.io.Serializable +import java.util.* data class Message( @SerializedName("badges") - val badges: List, + var badges: List, @SerializedName("broadcast") - val broadcast: String, + var broadcast: String, @SerializedName("chat_id") - val chatId: String, + var chatId: String, @SerializedName("display_message") - val displayMessage: Boolean, + var displayMessage: Boolean, @SerializedName("id") - val id: String, + var id: String, @SerializedName("message") var message: String, @SerializedName("sender") - val sender: String, + var sender: String, @SerializedName("sender_id") - val senderId: String, + var senderId: String, @SerializedName("server_id") - val serverId: String, + var serverId: String, @SerializedName("channel_id") - val channelId: String, + var channelId: String, @SerializedName("time_stamp") - val timeStamp: Long, + var timeStamp: Long, @SerializedName("type") - val type: String + var type: String ) : Serializable{ companion object{ const val serialversionUID = 3124135231234895L + fun createDummyMessage(username : String, message: String) : Message{ + val json = "{\"message\":\"test\",\"sender\":\"ReconDelta090\",\"sender_id\":\"user-6a9591cc-f3d3-4e47-a208-e749679a899a\",\"chat_id\":\"chat-8a05f730-c663-434d-9f24-6d8c24453c5f\",\"server_id\":\"serv-46437781-4a9b-4531-9db1-74bc2f818b58\",\"id\":\"mesg-ec54bf9a-23d4-4fa6-b6f1-9a5c8e3e2440\",\"time_stamp\":1574296097994,\"broadcast\":\"\",\"channel_id\":\"chan-7a304995-cba0-463c-81a6-ffeffc059058\",\"display_message\":true,\"badges\":[\"owner\"],\"type\":\"\"}" + return Gson().fromJson(json, Message::class.java).also { + it.sender = username + it.displayMessage = true + it.message = message + it.timeStamp = System.currentTimeMillis() + val id = UUID.randomUUID().toString() + it.id = id + } + } } } \ No newline at end of file From 82b18f340331ae8b9fe2dbf931c006a779328d74 Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Sun, 1 Mar 2020 03:10:12 -0600 Subject: [PATCH 12/27] Update ControlSDK to v0.11.0 with updated status control. Fix errors --- sdk/build.gradle | 2 +- .../sdk/components/StreamCommandHandler.kt | 12 +- .../components/audio/RemoAudioComponent.kt | 10 +- .../sdk/components/video/Camera1Override.kt | 11 + .../sdk/components/video/Camera2Override.kt | 263 +----------------- .../components/video/CameraCompatOverride.kt | 70 +---- .../components/video/RemoVideoProcessor.kt | 8 - 7 files changed, 45 insertions(+), 331 deletions(-) create mode 100644 sdk/src/main/java/tv/remo/android/controller/sdk/components/video/Camera1Override.kt diff --git a/sdk/build.gradle b/sdk/build.gradle index e5f19cc..bbdfd2d 100644 --- a/sdk/build.gradle +++ b/sdk/build.gradle @@ -32,7 +32,7 @@ dependencies { androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - def controlsdk_version = "0.10.1" + def controlsdk_version = "0.11.1" api "org.btelman.controlsdk:core:$controlsdk_version" api("org.btelman.controlsdk:streaming:$controlsdk_version") api "org.btelman.controlsdk:hardware:$controlsdk_version" diff --git a/sdk/src/main/java/tv/remo/android/controller/sdk/components/StreamCommandHandler.kt b/sdk/src/main/java/tv/remo/android/controller/sdk/components/StreamCommandHandler.kt index 6e22bd8..8612133 100644 --- a/sdk/src/main/java/tv/remo/android/controller/sdk/components/StreamCommandHandler.kt +++ b/sdk/src/main/java/tv/remo/android/controller/sdk/components/StreamCommandHandler.kt @@ -2,6 +2,7 @@ package tv.remo.android.controller.sdk.components import android.content.Context import android.os.Bundle +import kotlinx.coroutines.runBlocking import org.btelman.controlsdk.models.ComponentEventObject import org.btelman.controlsdk.streaming.models.StreamInfo import tv.remo.android.controller.sdk.interfaces.CommandStreamHandler @@ -45,13 +46,20 @@ class StreamCommandHandler(val context: Context?, val streamHandler : CommandStr ".stream sleep" -> { if(!sleepMode){ sleepMode = true - streamHandler.acquireRetriever().disable() + runBlocking { + streamHandler.acquireRetriever().disable().await() + } } } ".stream wakeup" -> { if(sleepMode) { sleepMode = false - streamHandler.acquireRetriever().enable(context, streamHandler.pullStreamInfo()) + runBlocking { + streamHandler.acquireRetriever().also { + it.updateStreamInfo(streamHandler.pullStreamInfo()) + it.enable().await() + } + } } } ".stream reset" -> { diff --git a/sdk/src/main/java/tv/remo/android/controller/sdk/components/audio/RemoAudioComponent.kt b/sdk/src/main/java/tv/remo/android/controller/sdk/components/audio/RemoAudioComponent.kt index 57718e7..d5d0045 100644 --- a/sdk/src/main/java/tv/remo/android/controller/sdk/components/audio/RemoAudioComponent.kt +++ b/sdk/src/main/java/tv/remo/android/controller/sdk/components/audio/RemoAudioComponent.kt @@ -2,6 +2,7 @@ package tv.remo.android.controller.sdk.components.audio import android.content.Context import android.os.Bundle +import kotlinx.coroutines.runBlocking import org.btelman.controlsdk.enums.ComponentType import org.btelman.controlsdk.models.ComponentEventObject import org.btelman.controlsdk.streaming.components.AudioComponent @@ -10,8 +11,6 @@ import org.btelman.controlsdk.streaming.models.StreamInfo import org.btelman.controlsdk.tts.TTSBaseComponent import tv.remo.android.controller.sdk.R import tv.remo.android.controller.sdk.RemoSettingsUtil -import tv.remo.android.controller.sdk.components.RemoCommandHandler -import tv.remo.android.controller.sdk.components.RemoSocketComponent import tv.remo.android.controller.sdk.components.StreamCommandHandler import tv.remo.android.controller.sdk.interfaces.CommandStreamHandler import tv.remo.android.controller.sdk.interfaces.RemoCommandSender @@ -107,8 +106,11 @@ class RemoAudioComponent : AudioComponent() , CommandStreamHandler { } //we only care about rebooting ffmpeg - processor.disable() - processor.enable(context!!, streamInfo) + runBlocking { + processor.disable().await() + processor.updateStreamInfo(streamInfo) + processor.enable().await() + } } } } diff --git a/sdk/src/main/java/tv/remo/android/controller/sdk/components/video/Camera1Override.kt b/sdk/src/main/java/tv/remo/android/controller/sdk/components/video/Camera1Override.kt new file mode 100644 index 0000000..7b0f444 --- /dev/null +++ b/sdk/src/main/java/tv/remo/android/controller/sdk/components/video/Camera1Override.kt @@ -0,0 +1,11 @@ +package tv.remo.android.controller.sdk.components.video + +import android.hardware.Camera +import org.btelman.controlsdk.streaming.video.retrievers.api16.Camera1SurfaceTextureComponent + +@Suppress("DEPRECATION") +class Camera1Override : Camera1SurfaceTextureComponent() { + override fun updateCameraParams(parameters: Camera.Parameters): Camera.Parameters { + return super.updateCameraParams(parameters) + } +} \ No newline at end of file diff --git a/sdk/src/main/java/tv/remo/android/controller/sdk/components/video/Camera2Override.kt b/sdk/src/main/java/tv/remo/android/controller/sdk/components/video/Camera2Override.kt index f9b0c32..d5d5707 100644 --- a/sdk/src/main/java/tv/remo/android/controller/sdk/components/video/Camera2Override.kt +++ b/sdk/src/main/java/tv/remo/android/controller/sdk/components/video/Camera2Override.kt @@ -1,237 +1,27 @@ package tv.remo.android.controller.sdk.components.video -import android.annotation.SuppressLint -import android.content.Context -import android.graphics.ImageFormat -import android.hardware.camera2.* -import android.media.Image +import android.hardware.camera2.CameraMetadata +import android.hardware.camera2.CaptureRequest import android.media.ImageReader -import android.os.Build -import android.os.Handler -import android.os.HandlerThread import android.util.Range -import androidx.annotation.NonNull import androidx.annotation.RequiresApi -import org.btelman.controlsdk.streaming.models.ImageDataPacket -import org.btelman.controlsdk.streaming.models.StreamInfo -import org.btelman.controlsdk.streaming.video.retrievers.BaseVideoRetriever +import org.btelman.controlsdk.streaming.video.retrievers.api21.Camera2Component import tv.remo.android.controller.sdk.RemoSettingsUtil /** * Copied from org.btelman.controlsdk.streaming.video.retrievers.api21.Camera2SurfaceTextureComponent */ @RequiresApi(21) -class Camera2Override : BaseVideoRetriever(), ImageReader.OnImageAvailableListener { - - private var data: ByteArray? = null - private var width = 0 - private var height = 0 +class Camera2Override : Camera2Component(), ImageReader.OnImageAvailableListener { private var focusMode = "video" - var reader : ImageReader? = null - - private var mPreviewBuilder: CaptureRequest.Builder? = null - /** - * An additional thread for running tasks that shouldn't block the UI. - */ - private var mBackgroundThread: HandlerThread? = null - - /** - * A [Handler] for running tasks in the background. - */ - private var mBackgroundHandler: Handler? = null - - /** - * [CameraDevice.StateCallback] is called when [CameraDevice] changes its status. - */ - private val mStateCallback = object : CameraDevice.StateCallback() { - - override fun onOpened(@NonNull cameraDevice: CameraDevice) { - mCameraDevice = cameraDevice - startPreview() - } - - override fun onDisconnected(@NonNull cameraDevice: CameraDevice) { - closePreviewSession() - cameraDevice.close() - mCameraDevice = null - } - - override fun onError(@NonNull cameraDevice: CameraDevice, error: Int) { - closePreviewSession() - cameraDevice.close() - mCameraDevice = null - } - - } - - override fun enable(context: Context, streamInfo: StreamInfo) { - super.enable(context, streamInfo) - setupCamera(streamInfo) - RemoSettingsUtil.with(context){ - focusMode = it.cameraFocus.getPref() - } - } - - override fun disable() { - super.disable() - releaseCamera() - } - - @SuppressLint("MissingPermission") //Already handled. No way to call this - fun setupCamera(streamInfo : StreamInfo?) { - startBackgroundThread() - width = streamInfo?.width ?: 640 - height = streamInfo?.height ?: 640 - reader = ImageReader.newInstance(width, height, ImageFormat.YUV_420_888, 2) - reader?.setOnImageAvailableListener(this, mBackgroundHandler) - val manager = context!!.getSystemService(Context.CAMERA_SERVICE) as CameraManager - try { - val list = manager.cameraIdList - val requestedId = streamInfo?.deviceInfo?.getCameraId()?:0 - if(requestedId+1 > list.size){ - throw java.lang.Exception("Attempted to open camera $requestedId. Only ${list.size} cameras exist! 0 is first camera") - } - manager.openCamera(list[requestedId], mStateCallback, null) - } catch (e: CameraAccessException) { - e.printStackTrace() - //TODO throw error and kill service? - } catch (e: NullPointerException) { - e.printStackTrace() - //TODO throw error and kill service? - } catch (e: InterruptedException) { - e.printStackTrace() - //TODO throw error and kill service? - throw RuntimeException("Interrupted while trying to lock camera opening.") - } - } - - private fun releaseCamera() { - stopBackgroundThread() - reader?.close() - closePreviewSession() - mCameraDevice?.close() - } - - private var latestPackage : ImageDataPacket? = null - - override fun grabImageData(): ImageDataPacket? { - return latestPackage - } - - /** - * A reference to the opened [android.hardware.camera2.CameraDevice]. - */ - private var mCameraDevice: CameraDevice? = null - - /** - * A reference to the current [android.hardware.camera2.CameraCaptureSession] for - * preview. - */ - private var mPreviewSession: CameraCaptureSession? = null - - override fun onImageAvailable(reader: ImageReader?) { - var image: Image? = null - try { - image = reader?.acquireLatestImage() - image?.let { - latestPackage = ImageDataPacket(convertYuv420888ToYuv(image), ImageFormat.YUV_420_888) - notifyFrameUpdated() - } - } finally { - image?.close() - } - } - - fun convertYuv420888ToYuv(image: Image): ByteArray { - val yPlane = image.planes[0] - val ySize = yPlane.buffer.remaining() - - val uPlane = image.planes[1] - val vPlane = image.planes[2] - - // be aware that this size does not include the padding at the end, if there is any - // (e.g. if pixel stride is 2 the size is ySize / 2 - 1) - val uSize = uPlane.buffer.remaining() - val vSize = vPlane.buffer.remaining() - - if(data?.size != ySize + ySize / 2) - data = ByteArray(ySize + ySize / 2) - - yPlane.buffer.get(data, 0, ySize) - - val ub = uPlane.buffer - val vb = vPlane.buffer - - val uvPixelStride = uPlane.pixelStride //stride guaranteed to be the same for u and v planes - if (uvPixelStride == 1) { - uPlane.buffer.get(data, ySize, uSize) - vPlane.buffer.get(data, ySize + uSize, vSize) - } - else{ - // if pixel stride is 2 there is padding between each pixel - // converting it to NV21 by filling the gaps of the v plane with the u values - vb.get(data, ySize, vSize) - var i = 0 - while (i < uSize) { - data!![ySize + i + 1] = ub.get(i) - i += 2 - } - } - return data!! + override fun enableInternal() { + super.enableInternal() + focusMode = RemoSettingsUtil.with(context!!).cameraFocus.getPref() } - /** - * Start the camera preview. - */ - private fun startPreview() { - if (null == mCameraDevice) { - return - } - try { - closePreviewSession() - mPreviewBuilder = mCameraDevice!!.createCaptureRequest(CameraDevice.TEMPLATE_RECORD) - mPreviewBuilder!!.addTarget(reader?.surface!!) - - mCameraDevice!!.createCaptureSession(listOf(/*previewSurface, */reader?.surface), - object : CameraCaptureSession.StateCallback() { - - override fun onConfigured(@NonNull session: CameraCaptureSession) { - mPreviewSession = session - updatePreview() - } - - override fun onConfigureFailed(@NonNull session: CameraCaptureSession) { - - } - }, mBackgroundHandler) - } catch (e: Exception) { - e.printStackTrace() - } - - } - - /** - * Update the camera preview. [.startPreview] needs to be called in advance. - */ - private fun updatePreview() { - if (null == mCameraDevice) { - return - } - try { - mPreviewBuilder?.let { setUpCaptureRequestBuilder(it) } - val thread = HandlerThread("CameraPreview") - thread.start() - mPreviewSession!!.setRepeatingRequest(mPreviewBuilder!!.build() - ,null - , mBackgroundHandler) - } catch (e: Exception) { - e.printStackTrace() - } - } - - private fun setUpCaptureRequestBuilder(builder: CaptureRequest.Builder) { + override fun setUpCaptureRequestBuilder(builder: CaptureRequest.Builder) { builder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, Range(15, 30)) val focusMode = when(focusMode){ "video" -> { @@ -258,41 +48,4 @@ class Camera2Override : BaseVideoRetriever(), ImageReader.OnImageAvailableListen builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO) } } - - private fun closePreviewSession() { - if (mPreviewSession != null) { - mPreviewSession?.close() - mPreviewSession = null - } - } - - /** - * Starts a background thread and its [Handler]. - */ - private fun startBackgroundThread() { - mBackgroundThread = HandlerThread("CameraBackground") - mBackgroundThread?.start() - mBackgroundHandler = Handler(mBackgroundThread?.looper) - } - - /** - * Stops the background thread and its [Handler]. - */ - private fun stopBackgroundThread() { - mBackgroundThread?.quitSafely() - try { - mBackgroundThread?.join() - mBackgroundThread = null - mBackgroundHandler = null - } catch (e: InterruptedException) { - e.printStackTrace() - } - } - - companion object{ - //checks for if this class can be run on this device - fun isSupported() : Boolean{ - return Build.VERSION.SDK_INT >= 21 - } - } } \ No newline at end of file diff --git a/sdk/src/main/java/tv/remo/android/controller/sdk/components/video/CameraCompatOverride.kt b/sdk/src/main/java/tv/remo/android/controller/sdk/components/video/CameraCompatOverride.kt index 0309420..94c6ae4 100644 --- a/sdk/src/main/java/tv/remo/android/controller/sdk/components/video/CameraCompatOverride.kt +++ b/sdk/src/main/java/tv/remo/android/controller/sdk/components/video/CameraCompatOverride.kt @@ -1,71 +1,19 @@ package tv.remo.android.controller.sdk.components.video -import android.annotation.TargetApi -import android.content.Context -import android.hardware.camera2.CameraCharacteristics -import android.hardware.camera2.CameraManager -import android.os.Build -import android.util.Log -import org.btelman.controlsdk.streaming.models.ImageDataPacket -import org.btelman.controlsdk.streaming.models.StreamInfo +import androidx.annotation.RequiresApi import org.btelman.controlsdk.streaming.video.retrievers.BaseVideoRetriever -import org.btelman.controlsdk.streaming.video.retrievers.api16.Camera1SurfaceTextureComponent +import org.btelman.controlsdk.streaming.video.retrievers.CameraCompatRetriever /** - * Handle compatibility between camera1 and camera2 usage, since some api21 devices are - * not compatible, which makes frame grabbing really slow. Usage of Camera1 or Camera2 classes are - * still supported, but may not work on every device - * ex. Samsung Galaxy S4 + * Override to use different camera classes */ -class CameraCompatOverride : BaseVideoRetriever(){ - private var retriever : BaseVideoRetriever? = null - - override fun grabImageData(): ImageDataPacket? { - return retriever?.grabImageData() - } - - override fun enable(context: Context, streamInfo: StreamInfo) { - super.enable(context, streamInfo) - val cameraInfo = streamInfo.deviceInfo - val cameraId = cameraInfo.getCameraId() - retriever = if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP - && validateCamera2Support(context, cameraId)){ - Log.d("CameraRetriever", "Using Camera2 API") - Camera2Override() - } else{ - Log.d("CameraRetriever", - "Using Camera1 API. Device API too low or LIMITED capabilities") - Camera1SurfaceTextureComponent() - } - retriever?.enable(context, streamInfo) - } - - override fun listenForFrame(func: () -> Unit) { - retriever?.listenForFrame(func) +class CameraCompatOverride : CameraCompatRetriever(){ + @RequiresApi(21) + override fun createCamera2(): BaseVideoRetriever? { + return Camera2Override() } - override fun removeListenerForFrame() { - retriever?.removeListenerForFrame() - } - - override fun disable() { - super.disable() - retriever?.disable() - retriever = null - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - private fun validateCamera2Support(context: Context, cameraId: Int): Boolean { - try { - val cm = (context.getSystemService(Context.CAMERA_SERVICE) as CameraManager) - val hardwareLevel = cm.getCameraCharacteristics( - cm.cameraIdList[cameraId] - )[CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL] - return hardwareLevel != CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY - && hardwareLevel != CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED - } catch (_: Exception) { - - } - return false + override fun createCamera1(): BaseVideoRetriever? { + return Camera1Override() } } \ No newline at end of file diff --git a/sdk/src/main/java/tv/remo/android/controller/sdk/components/video/RemoVideoProcessor.kt b/sdk/src/main/java/tv/remo/android/controller/sdk/components/video/RemoVideoProcessor.kt index d138873..a1bb9a3 100644 --- a/sdk/src/main/java/tv/remo/android/controller/sdk/components/video/RemoVideoProcessor.kt +++ b/sdk/src/main/java/tv/remo/android/controller/sdk/components/video/RemoVideoProcessor.kt @@ -1,6 +1,5 @@ package tv.remo.android.controller.sdk.components.video -import android.content.Context import org.btelman.controlsdk.streaming.models.StreamInfo import org.btelman.controlsdk.streaming.video.processors.FFmpegVideoProcessor import tv.remo.android.controller.sdk.RemoSettingsUtil @@ -11,13 +10,6 @@ import tv.remo.android.controller.sdk.models.StringPref */ class RemoVideoProcessor : FFmpegVideoProcessor() { - private var streamProps: StreamInfo? = null - - override fun enable(context: Context, streamInfo: StreamInfo) { - super.enable(context, streamInfo) - this.streamProps = streamInfo - } - override fun getFilterOptions(props: StreamInfo): String { var filter = "" context?.let { From 86fda5991f95a968f1f757a8fded30017bbcc8c3 Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Sun, 1 Mar 2020 04:14:26 -0600 Subject: [PATCH 13/27] Update ControlSDK to v0.11.4 to fix camera issues --- .../java/tv/remo/android/controller/RemoApplication.kt | 4 ++++ .../tv/remo/android/controller/activities/MainActivity.kt | 8 ++++---- sdk/build.gradle | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/tv/remo/android/controller/RemoApplication.kt b/app/src/main/java/tv/remo/android/controller/RemoApplication.kt index d81920d..59491c6 100644 --- a/app/src/main/java/tv/remo/android/controller/RemoApplication.kt +++ b/app/src/main/java/tv/remo/android/controller/RemoApplication.kt @@ -9,6 +9,10 @@ class RemoApplication : Application() { override fun onCreate() { super.onCreate() +// LogUtilInstance(ControlSDKService.CONTROL_SERVICE, LogLevel.VERBOSE).also { +// Log.d("RemoApplication", "Setup ControlSDK logger") +// LogUtil.addCustomLogUtilInstance(ControlSDKService::class.java.name, it) +// } Instance = this } diff --git a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt index b09eadd..cb1f012 100644 --- a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt +++ b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt @@ -20,12 +20,12 @@ import org.btelman.controlsdk.interfaces.ControlSdkApi import org.btelman.controlsdk.models.ComponentHolder import org.btelman.controlsdk.services.ControlSDKServiceConnection import org.btelman.controlsdk.services.observeAutoCreate -import org.btelman.controlsdk.streaming.components.AudioComponent -import org.btelman.controlsdk.streaming.components.VideoComponent import tv.remo.android.controller.R import tv.remo.android.controller.sdk.RemoSettingsUtil import tv.remo.android.controller.sdk.components.RemoSocketComponent import tv.remo.android.controller.sdk.components.StatusBroadcasterComponent +import tv.remo.android.controller.sdk.components.audio.RemoAudioProcessor +import tv.remo.android.controller.sdk.components.video.RemoVideoProcessor import tv.remo.android.controller.sdk.models.api.Message import tv.remo.android.controller.sdk.utils.ChatUtil import tv.remo.android.controller.sdk.utils.ComponentBuilderUtil @@ -105,8 +105,8 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { private fun buildStatusList() { websiteConnectionStatusView.registerStatusEvents(RemoSocketComponent::class.java) hardwareConnectionStatusView.registerStatusEvents(CommunicationDriverComponent::class.java) - audioConnectionStatusView.registerStatusEvents(AudioComponent::class.java) - videoConnectionStatusView.registerStatusEvents(VideoComponent::class.java) + audioConnectionStatusView.registerStatusEvents(RemoAudioProcessor::class.java) + videoConnectionStatusView.registerStatusEvents(RemoVideoProcessor::class.java) } val operationObserver : (Operation) -> Unit = { serviceStatus -> diff --git a/sdk/build.gradle b/sdk/build.gradle index bbdfd2d..9505bc8 100644 --- a/sdk/build.gradle +++ b/sdk/build.gradle @@ -32,7 +32,7 @@ dependencies { androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - def controlsdk_version = "0.11.1" + def controlsdk_version = "0.11.4" api "org.btelman.controlsdk:core:$controlsdk_version" api("org.btelman.controlsdk:streaming:$controlsdk_version") api "org.btelman.controlsdk:hardware:$controlsdk_version" From 6a88aa601a43385bf47f34ec606665b07191d94f Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Sun, 1 Mar 2020 21:53:37 -0600 Subject: [PATCH 14/27] Logging --- .../android/controller/RemoApplication.kt | 37 +++++++++++++++++-- .../controller/activities/MainActivity.kt | 2 +- .../android/controller/ui/RemoStatusView.kt | 12 +++++- .../components/StatusBroadcasterComponent.kt | 4 +- 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/tv/remo/android/controller/RemoApplication.kt b/app/src/main/java/tv/remo/android/controller/RemoApplication.kt index 59491c6..fc6480a 100644 --- a/app/src/main/java/tv/remo/android/controller/RemoApplication.kt +++ b/app/src/main/java/tv/remo/android/controller/RemoApplication.kt @@ -1,22 +1,51 @@ package tv.remo.android.controller import android.app.Application +import android.util.Log +import org.btelman.controlsdk.services.ControlSDKService +import org.btelman.logutil.kotlin.LogLevel +import org.btelman.logutil.kotlin.LogUtil +import org.btelman.logutil.kotlin.LogUtilInstance /** * Created by Brendon on 7/28/2019. */ class RemoApplication : Application() { + private val log = LogUtil("RemoApplication", logID) override fun onCreate() { super.onCreate() -// LogUtilInstance(ControlSDKService.CONTROL_SERVICE, LogLevel.VERBOSE).also { -// Log.d("RemoApplication", "Setup ControlSDK logger") -// LogUtil.addCustomLogUtilInstance(ControlSDKService::class.java.name, it) -// } + LogUtilInstance(ControlSDKService.CONTROL_SERVICE, LogLevel.VERBOSE).also { + Log.d("RemoApplication", "Setup ControlSDK logger") + LogUtil.addCustomLogUtilInstance(ControlSDKService::class.java.name, it) + } + + log.d{ + "Remo.TV ${BuildConfig.VERSION_NAME} onCreate..." + } + Instance = this } companion object{ var Instance : RemoApplication? = null + val logID = "Remo.TV".also {name-> + LogUtilInstance(ControlSDKService.CONTROL_SERVICE, LogLevel.VERBOSE).also { + Log.d("RemoApplication", "Setup Remo.TV logger") + LogUtil.addCustomLogUtilInstance(name, it) + } + } + + fun getLogger(tag : String) : LogUtil{ + return LogUtil(tag, logID) + } + + fun getLogger(obj : Any, extra : String? = null) : LogUtil{ + var log = obj.javaClass.simpleName + extra?.let{ + log += " : $extra" + } + return getLogger(log) + } } } \ No newline at end of file diff --git a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt index cb1f012..9d41dbd 100644 --- a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt +++ b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt @@ -188,11 +188,11 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { private fun createComponentHolders() { RemoSettingsUtil.with(this){ settings -> - arrayList.add(ComponentHolder(StatusBroadcasterComponent::class.java, null)) arrayList.add(ComponentBuilderUtil.createSocketComponent(settings)) arrayList.addAll(ComponentBuilderUtil.createTTSComponents(settings)) arrayList.addAll(ComponentBuilderUtil.createStreamingComponents(settings)) arrayList.addAll(ComponentBuilderUtil.createHardwareComponents(settings)) + arrayList.add(ComponentHolder(StatusBroadcasterComponent::class.java, null)) } } diff --git a/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt b/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt index 34d56db..17e13fe 100644 --- a/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt +++ b/app/src/main/java/tv/remo/android/controller/ui/RemoStatusView.kt @@ -15,6 +15,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager import org.btelman.controlsdk.enums.ComponentStatus import org.btelman.controlsdk.models.Component import tv.remo.android.controller.R +import tv.remo.android.controller.RemoApplication import tv.remo.android.controller.sdk.components.StatusBroadcasterComponent /** @@ -25,6 +26,8 @@ import tv.remo.android.controller.sdk.components.StatusBroadcasterComponent class RemoStatusView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : CustomImageView(context, attrs, defStyleAttr), Runnable{ + + private var log = RemoApplication.getLogger(this) private var colorLookup = SparseIntArray().also{ appendColor(context, it, R.color.colorIndicatorDisabledFromSettings) appendColor(context, it, R.color.colorIndicatorDisabled) @@ -77,7 +80,11 @@ class RemoStatusView @JvmOverloads constructor( fun registerStatusEvents(statusClassName : Class){ broadcastManager.unregisterReceiver(receiver) val filter = IntentFilter(StatusBroadcasterComponent.ACTION_SERVICE_STATUS) - filter.addAction(StatusBroadcasterComponent.generateComponentStatusAction(statusClassName)) + StatusBroadcasterComponent.generateComponentStatusAction(statusClassName).also { + filter.addAction(it) + log.d { "switching log to $it" } + log = RemoApplication.getLogger(this, it) + } broadcastManager.registerReceiver(receiver, filter) } @@ -86,6 +93,9 @@ class RemoStatusView @JvmOverloads constructor( } private fun onBroadcastDataReceived(intent: Intent) { + log.v{ + "onBroadcastDataReceived ${intent.action} ${intent.getSerializableExtra(StatusBroadcasterComponent.STATUS_NAME)}" + } if(intent.action == StatusBroadcasterComponent.ACTION_SERVICE_STATUS) return val componentStatus = intent.getSerializableExtra(StatusBroadcasterComponent.STATUS_NAME) status = componentStatus as? ComponentStatus diff --git a/sdk/src/main/java/tv/remo/android/controller/sdk/components/StatusBroadcasterComponent.kt b/sdk/src/main/java/tv/remo/android/controller/sdk/components/StatusBroadcasterComponent.kt index ef11836..f41d103 100644 --- a/sdk/src/main/java/tv/remo/android/controller/sdk/components/StatusBroadcasterComponent.kt +++ b/sdk/src/main/java/tv/remo/android/controller/sdk/components/StatusBroadcasterComponent.kt @@ -36,7 +36,9 @@ class StatusBroadcasterComponent : Component() { override fun handleExternalMessage(message: ComponentEventObject): Boolean { if(message.what == STATUS_EVENT){ - + log.d{ + "STATUS_EVENT ${message.data as ComponentStatus} from ${message.source.javaClass.name}" + } //create an intent that will send all classes in the same action val intent = Intent(ACTION_COMPONENT_STATUS).apply { putExtra(CLASS_NAME, message.source.javaClass.name) From 8900fc5cf9ce40c570cd187106e6293a87d79d11 Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Sun, 1 Mar 2020 22:39:19 -0600 Subject: [PATCH 15/27] Update ControlSDK to 0.12.0-beta1 --- .../tv/remo/android/controller/activities/MainActivity.kt | 4 ++-- sdk/build.gradle | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt index 9d41dbd..acc9266 100644 --- a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt +++ b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt @@ -16,7 +16,7 @@ import kotlinx.android.synthetic.main.activity_main.* import org.btelman.controlsdk.enums.ComponentStatus import org.btelman.controlsdk.enums.Operation import org.btelman.controlsdk.hardware.components.CommunicationDriverComponent -import org.btelman.controlsdk.interfaces.ControlSdkApi +import org.btelman.controlsdk.interfaces.ControlSdkServiceWrapper import org.btelman.controlsdk.models.ComponentHolder import org.btelman.controlsdk.services.ControlSDKServiceConnection import org.btelman.controlsdk.services.observeAutoCreate @@ -33,7 +33,7 @@ import tv.remo.android.controller.sdk.utils.ComponentBuilderUtil class MainActivity : AppCompatActivity(), View.OnClickListener { private var recording = false private val arrayList = ArrayList>() - private var controlSDKServiceApi: ControlSdkApi? = null + private var controlSDKServiceApi: ControlSdkServiceWrapper? = null private lateinit var handler : Handler private val telemetryEnabled = true diff --git a/sdk/build.gradle b/sdk/build.gradle index 9505bc8..450c7f0 100644 --- a/sdk/build.gradle +++ b/sdk/build.gradle @@ -32,7 +32,7 @@ dependencies { androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - def controlsdk_version = "0.11.4" + def controlsdk_version = "0.12.0-beta1" api "org.btelman.controlsdk:core:$controlsdk_version" api("org.btelman.controlsdk:streaming:$controlsdk_version") api "org.btelman.controlsdk:hardware:$controlsdk_version" From f10f16060c03e82eb6d50129e48847540997bc5b Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Sun, 1 Mar 2020 22:56:30 -0600 Subject: [PATCH 16/27] Convert StatusBroadcasterComponent.kt to a listener class --- .../controller/activities/MainActivity.kt | 18 +++++- .../components/StatusBroadcasterComponent.kt | 62 ++++++++----------- 2 files changed, 44 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt index acc9266..a531f1d 100644 --- a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt +++ b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt @@ -31,6 +31,7 @@ import tv.remo.android.controller.sdk.utils.ChatUtil import tv.remo.android.controller.sdk.utils.ComponentBuilderUtil class MainActivity : AppCompatActivity(), View.OnClickListener { + private val listenerControllerList = ArrayList>() private var recording = false private val arrayList = ArrayList>() private var controlSDKServiceApi: ControlSdkServiceWrapper? = null @@ -79,6 +80,7 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { override fun onDestroy() { super.onDestroy() + handleListenerAddOrRemove(Operation.NOT_OK) controlSDKServiceApi?.disconnectFromService() } @@ -87,11 +89,25 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { controlSDKServiceApi?.getServiceStateObserver()?.observeAutoCreate(this, operationObserver) controlSDKServiceApi?.getServiceBoundObserver()?.observeAutoCreate(this){ connected -> powerButton.isEnabled = connected == Operation.OK + handleListenerAddOrRemove(connected) } controlSDKServiceApi?.connectToService() createComponentHolders() } + private fun handleListenerAddOrRemove(connected : Operation) { + if(connected == Operation.OK){ + listenerControllerList.forEach { + controlSDKServiceApi?.addListenerOrController(it) + } + } + else if(connected == Operation.NOT_OK){ + listenerControllerList.forEach { + controlSDKServiceApi?.removeListenerOrController(it) + } + } + } + private fun setupUI() { remoChatView.setOnTouchListener { _, _ -> handleSleepLayoutTouch() @@ -192,7 +208,7 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { arrayList.addAll(ComponentBuilderUtil.createTTSComponents(settings)) arrayList.addAll(ComponentBuilderUtil.createStreamingComponents(settings)) arrayList.addAll(ComponentBuilderUtil.createHardwareComponents(settings)) - arrayList.add(ComponentHolder(StatusBroadcasterComponent::class.java, null)) + listenerControllerList.add(ComponentHolder(StatusBroadcasterComponent::class.java, null)) } } diff --git a/sdk/src/main/java/tv/remo/android/controller/sdk/components/StatusBroadcasterComponent.kt b/sdk/src/main/java/tv/remo/android/controller/sdk/components/StatusBroadcasterComponent.kt index f41d103..f69b675 100644 --- a/sdk/src/main/java/tv/remo/android/controller/sdk/components/StatusBroadcasterComponent.kt +++ b/sdk/src/main/java/tv/remo/android/controller/sdk/components/StatusBroadcasterComponent.kt @@ -5,65 +5,57 @@ import android.content.Intent import android.os.Bundle import androidx.localbroadcastmanager.content.LocalBroadcastManager import org.btelman.controlsdk.enums.ComponentStatus -import org.btelman.controlsdk.enums.ComponentType -import org.btelman.controlsdk.models.Component -import org.btelman.controlsdk.models.ComponentEventObject +import org.btelman.controlsdk.enums.ServiceStatus +import org.btelman.controlsdk.interfaces.IListener +import org.btelman.controlsdk.services.ControlSDKService +import org.btelman.logutil.kotlin.LogUtil /** * Broadcast the statuses of each component, and some service level events */ -class StatusBroadcasterComponent : Component() { +class StatusBroadcasterComponent : IListener { + private val log = LogUtil("StatusBroadcasterComponent", ControlSDKService.loggerID) var localBroadcastManager : LocalBroadcastManager? = null override fun onInitializeComponent(applicationContext: Context, bundle: Bundle?) { - super.onInitializeComponent(applicationContext, bundle) localBroadcastManager = LocalBroadcastManager.getInstance(applicationContext) } - override fun disableInternal() { - setServiceStatus(ComponentStatus.DISABLED) + override fun onRemoved() { + localBroadcastManager = null } - override fun enableInternal() { - setServiceStatus(ComponentStatus.STABLE) + override fun onServiceStateChange(status: ServiceStatus) { + super.onServiceStateChange(status) + setServiceStatus(status) } - fun setServiceStatus(status : ComponentStatus){ + fun setServiceStatus(status : ServiceStatus){ val intent = Intent(ACTION_SERVICE_STATUS).apply{ putExtra(STATUS_NAME, status) } localBroadcastManager?.sendBroadcast(intent) } - override fun handleExternalMessage(message: ComponentEventObject): Boolean { - if(message.what == STATUS_EVENT){ - log.d{ - "STATUS_EVENT ${message.data as ComponentStatus} from ${message.source.javaClass.name}" - } - //create an intent that will send all classes in the same action - val intent = Intent(ACTION_COMPONENT_STATUS).apply { - putExtra(CLASS_NAME, message.source.javaClass.name) - putExtra(STATUS_NAME, message.data as ComponentStatus) - } - //create an intent that will only contain a single class of statuses - val intentClassLevel = Intent(generateComponentStatusAction(message.source.javaClass)).apply { - putExtra(STATUS_NAME, message.data as ComponentStatus) - } - //now send both of them - localBroadcastManager?.sendBroadcast(intent) - localBroadcastManager?.sendBroadcast(intentClassLevel) + override fun onComponentStatus(clazz: Class<*>, componentStatus: ComponentStatus) { + log.d{ + "STATUS_EVENT $componentStatus from ${clazz.name}" } - return super.handleExternalMessage(message) - } - - override fun getType(): ComponentType { - return ComponentType.CUSTOM + super.onComponentStatus(clazz, componentStatus) + val intent = Intent(ACTION_COMPONENT_STATUS).apply { + putExtra(CLASS_NAME, clazz.name) + putExtra(STATUS_NAME, componentStatus) + } + //create an intent that will only contain a single class of statuses + val intentClassLevel = Intent(generateComponentStatusAction(clazz)).apply { + putExtra(STATUS_NAME, componentStatus) + } + //now send both of them + localBroadcastManager?.sendBroadcast(intent) + localBroadcastManager?.sendBroadcast(intentClassLevel) } companion object{ fun generateComponentStatusAction(clazz : Class) : String{ -// if(clazz.getAnnotation(DriverComponent::class.java) != null){ -// return generateComponentStatusAction(CommunicationDriverComponent::class.java) -// } return "${clazz.name}.${ACTION_COMPONENT_STATUS}" } const val ACTION_SERVICE_STATUS = "control.sdk.ACTION_SERVICE_STATUS" From 23a8121b61e163bd9051eaaf78470cd777be71ca Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Sun, 1 Mar 2020 23:09:48 -0600 Subject: [PATCH 17/27] Update to beta2 to fix hardware component status bug --- sdk/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/build.gradle b/sdk/build.gradle index 450c7f0..78ecd8d 100644 --- a/sdk/build.gradle +++ b/sdk/build.gradle @@ -32,7 +32,7 @@ dependencies { androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - def controlsdk_version = "0.12.0-beta1" + def controlsdk_version = "0.12.0-beta2" api "org.btelman.controlsdk:core:$controlsdk_version" api("org.btelman.controlsdk:streaming:$controlsdk_version") api "org.btelman.controlsdk:hardware:$controlsdk_version" From aaefb207be3b16724e44634b228964b33464d153 Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Sun, 8 Mar 2020 20:47:12 -0500 Subject: [PATCH 18/27] Add a TTS status component --- .../tv/remo/android/controller/activities/MainActivity.kt | 4 +++- app/src/main/res/drawable/ic_volume_up_white_24dp.xml | 4 ++++ app/src/main/res/layout/activity_main.xml | 7 +++++++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 app/src/main/res/drawable/ic_volume_up_white_24dp.xml diff --git a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt index a531f1d..4bcf883 100644 --- a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt +++ b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt @@ -20,6 +20,7 @@ import org.btelman.controlsdk.interfaces.ControlSdkServiceWrapper import org.btelman.controlsdk.models.ComponentHolder import org.btelman.controlsdk.services.ControlSDKServiceConnection import org.btelman.controlsdk.services.observeAutoCreate +import org.btelman.controlsdk.tts.SystemDefaultTTSComponent import tv.remo.android.controller.R import tv.remo.android.controller.sdk.RemoSettingsUtil import tv.remo.android.controller.sdk.components.RemoSocketComponent @@ -36,7 +37,7 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { private val arrayList = ArrayList>() private var controlSDKServiceApi: ControlSdkServiceWrapper? = null private lateinit var handler : Handler - private val telemetryEnabled = true + private val telemetryEnabled = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -123,6 +124,7 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { hardwareConnectionStatusView.registerStatusEvents(CommunicationDriverComponent::class.java) audioConnectionStatusView.registerStatusEvents(RemoAudioProcessor::class.java) videoConnectionStatusView.registerStatusEvents(RemoVideoProcessor::class.java) + ttsConnectionStatusView.registerStatusEvents(SystemDefaultTTSComponent::class.java) } val operationObserver : (Operation) -> Unit = { serviceStatus -> diff --git a/app/src/main/res/drawable/ic_volume_up_white_24dp.xml b/app/src/main/res/drawable/ic_volume_up_white_24dp.xml new file mode 100644 index 0000000..6fc27fc --- /dev/null +++ b/app/src/main/res/drawable/ic_volume_up_white_24dp.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index a0f3259..85edb7a 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -33,6 +33,13 @@ android:scaleType="centerInside" android:layout_height="@dimen/status_view_size" android:layout_width="@dimen/status_view_size"/> + Date: Sun, 8 Mar 2020 20:49:14 -0500 Subject: [PATCH 19/27] Update ControlSDK version to 0.12.0 --- sdk/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/build.gradle b/sdk/build.gradle index 78ecd8d..a4086bd 100644 --- a/sdk/build.gradle +++ b/sdk/build.gradle @@ -32,7 +32,7 @@ dependencies { androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - def controlsdk_version = "0.12.0-beta2" + def controlsdk_version = "0.12.0" api "org.btelman.controlsdk:core:$controlsdk_version" api("org.btelman.controlsdk:streaming:$controlsdk_version") api "org.btelman.controlsdk:hardware:$controlsdk_version" From 6977524105343a407ec838cbd7c63e9e82c5ed9c Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Sun, 8 Mar 2020 20:57:20 -0500 Subject: [PATCH 20/27] Fix java 8 issues. Add licence info for LogUtilKt --- app/build.gradle | 5 +++++ sdk/build.gradle | 4 ++++ .../java/tv/remo/android/controller/sdk/models/Licenses.kt | 3 ++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index fe3a5a8..8ed8153 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,6 +16,11 @@ android { } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + defaultConfig { applicationId "tv.remo.android.controller" minSdkVersion 16 diff --git a/sdk/build.gradle b/sdk/build.gradle index a4086bd..8a9c7a9 100644 --- a/sdk/build.gradle +++ b/sdk/build.gradle @@ -23,6 +23,10 @@ android { } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } } dependencies { diff --git a/sdk/src/main/java/tv/remo/android/controller/sdk/models/Licenses.kt b/sdk/src/main/java/tv/remo/android/controller/sdk/models/Licenses.kt index 4814db3..e02c567 100644 --- a/sdk/src/main/java/tv/remo/android/controller/sdk/models/Licenses.kt +++ b/sdk/src/main/java/tv/remo/android/controller/sdk/models/Licenses.kt @@ -22,6 +22,7 @@ object Licenses { License("OkHttp", LicenseType.APACHE2_0), License("FFmpeg, github.com/btelman96/ffmpeg-android", LicenseType.LGPL3), License("github.com/btelman96/AndroidUvcDemo", LicenseType.GPL3 - , "https://raw.githubusercontent.com/btelman96/AndroidUvcDemo/master/LICENCE") + , "https://raw.githubusercontent.com/btelman96/AndroidUvcDemo/master/LICENCE"), + License("LogUtilKt, https://github.com/btelman96/LogUtilKt", LicenseType.APACHE2_0, "https://github.com/btelman96/LogUtilKt/blob/master/LICENSE") ) } \ No newline at end of file From 527a2fefc54dc3f913d6bc1a48e9c1879886a431 Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Sun, 8 Mar 2020 21:24:18 -0500 Subject: [PATCH 21/27] Clean up RemoSocketComponent.kt --- .../sdk/components/RemoSocketComponent.kt | 51 +++++++++---------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/sdk/src/main/java/tv/remo/android/controller/sdk/components/RemoSocketComponent.kt b/sdk/src/main/java/tv/remo/android/controller/sdk/components/RemoSocketComponent.kt index e498a69..5637e02 100644 --- a/sdk/src/main/java/tv/remo/android/controller/sdk/components/RemoSocketComponent.kt +++ b/sdk/src/main/java/tv/remo/android/controller/sdk/components/RemoSocketComponent.kt @@ -70,35 +70,31 @@ class RemoSocketComponent : Component() , RemoCommandSender { } private fun subToSocketEvents(listener: SocketListener) { - listener.on(SocketListener.ON_OPEN){ - sendHandshakeAuth() - }.on(SocketListener.ON_CLOSE){ - status = ComponentStatus.ERROR - Log.d("TAG","onClosing $it") - }.on(SocketListener.ON_ERROR){ - status = ComponentStatus.ERROR - handler.postDelayed ({ - //attempt a reconnect every second - attemptReconnect() - }, 1000) - Log.d("TAG","onFailure $it") - }.on("ROBOT_VALIDATED"){ - status = ComponentStatus.STABLE - sendChannelsRequest(it) - }.on("SEND_ROBOT_SERVER_INFO"){ - verifyAndSubToChannel(it) - }.on(SocketListener.ON_MESSAGE){ - Log.d("SOCKET", it) - }.on("MESSAGE_RECEIVED"){ - sendChatUpwards(it) - }.on("BUTTON_COMMAND"){ - sendCommandUpwards(it) - }.on("LOCAL_MODERATION"){ - processChatModeration(it) - } + listener.on(SocketListener.ON_CLOSE) { + status = ComponentStatus.ERROR + Log.d("TAG", "onClosing $it") + }.on(SocketListener.ON_OPEN, this::sendHandshakeAuth) + .on(SocketListener.ON_ERROR, this::handleConnectionError) + .on("ROBOT_VALIDATED", this::sendChannelsRequest) + .on("SEND_ROBOT_SERVER_INFO", this::verifyAndSubToChannel) + .on("MESSAGE_RECEIVED", this::sendChatUpwards) + .on("BUTTON_COMMAND", this::sendCommandUpwards) + .on("LOCAL_MODERATION", this::processChatModeration) + .on(SocketListener.ON_MESSAGE) { + Log.d("SOCKET", it) + } //.on("SEND_CHAT") //TODO? of type Messages } + private fun handleConnectionError(value: String) { + status = ComponentStatus.ERROR + handler.postDelayed({ + //attempt a reconnect every second + attemptReconnect() + }, 1000) + Log.d("TAG", "onFailure $value") + } + private fun attemptReconnect() { status = ComponentStatus.CONNECTING url ?: return @@ -220,13 +216,14 @@ class RemoSocketComponent : Component() , RemoCommandSender { } private fun sendChannelsRequest(json : String) { + status = ComponentStatus.STABLE val jsonObject = JSONObject(json) val host = jsonObject.getString("host") val str = "{\"e\":\"GET_CHANNELS\",\"d\":{\"server_id\":\"$host\"}}" socket?.send(str) } - private fun sendHandshakeAuth() { + private fun sendHandshakeAuth(value : String) { val json = "{\"e\": \"AUTHENTICATE_ROBOT\", \"d\": {\"token\": \"$apiKey\"}}" socket?.send(json) } From c249fb6e4e64dfd367b9f8d87917ff8e6bb5439a Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Sun, 8 Mar 2020 21:29:31 -0500 Subject: [PATCH 22/27] Clean up MainActivity.kt and SettingsCamera.kt --- .../controller/activities/MainActivity.kt | 32 ------------------- .../controller/fragments/SettingsCamera.kt | 15 ++------- 2 files changed, 2 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt index 4bcf883..7fe6a51 100644 --- a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt +++ b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt @@ -1,19 +1,14 @@ package tv.remo.android.controller.activities -import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import android.content.IntentFilter import android.graphics.Color import android.os.Bundle import android.os.Handler import android.os.Looper import android.view.View import androidx.appcompat.app.AppCompatActivity -import androidx.localbroadcastmanager.content.LocalBroadcastManager -import com.google.gson.Gson import kotlinx.android.synthetic.main.activity_main.* -import org.btelman.controlsdk.enums.ComponentStatus import org.btelman.controlsdk.enums.Operation import org.btelman.controlsdk.hardware.components.CommunicationDriverComponent import org.btelman.controlsdk.interfaces.ControlSdkServiceWrapper @@ -27,8 +22,6 @@ import tv.remo.android.controller.sdk.components.RemoSocketComponent import tv.remo.android.controller.sdk.components.StatusBroadcasterComponent import tv.remo.android.controller.sdk.components.audio.RemoAudioProcessor import tv.remo.android.controller.sdk.components.video.RemoVideoProcessor -import tv.remo.android.controller.sdk.models.api.Message -import tv.remo.android.controller.sdk.utils.ChatUtil import tv.remo.android.controller.sdk.utils.ComponentBuilderUtil class MainActivity : AppCompatActivity(), View.OnClickListener { @@ -48,23 +41,6 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { window.decorView.post { buildStatusList() } - if(telemetryEnabled) - setupChatViewAsLogger(); - } - - private fun setupChatViewAsLogger() { - val receiver = object : BroadcastReceiver() { - override fun onReceive(context: Context?, intent: Intent?) { - intent?.let { - val name = it.getStringExtra(StatusBroadcasterComponent.CLASS_NAME) - val status = it.getSerializableExtra(StatusBroadcasterComponent.STATUS_NAME) as? ComponentStatus - ChatUtil.broadcastChatMessage(context!!, - Message.createDummyMessage(name.split(".").last(), status.toString())) - } - } - } - val broadcastManager = LocalBroadcastManager.getInstance(this) - broadcastManager.registerReceiver(receiver, IntentFilter(StatusBroadcasterComponent.ACTION_COMPONENT_STATUS)) } override fun onClick(v: View?) { @@ -169,14 +145,6 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { } } - private fun UnitTestRunChat(){ - val json = "{\"message\":\"test\",\"sender\":\"ReconDelta090\",\"sender_id\":\"user-6a9591cc-f3d3-4e47-a208-e749679a899a\",\"chat_id\":\"chat-8a05f730-c663-434d-9f24-6d8c24453c5f\",\"server_id\":\"serv-46437781-4a9b-4531-9db1-74bc2f818b58\",\"id\":\"mesg-ec54bf9a-23d4-4fa6-b6f1-9a5c8e3e2440\",\"time_stamp\":1574296097994,\"broadcast\":\"\",\"channel_id\":\"chan-7a304995-cba0-463c-81a6-ffeffc059058\",\"display_message\":true,\"badges\":[\"owner\"],\"type\":\"\"}" - Gson().fromJson(json, Message::class.java).also { rawMessage -> - ChatUtil.broadcastChatMessage(this, rawMessage) - ChatUtil.broadcastChatMessage(this, rawMessage) //should just be ignored - } - } - private fun launchSettings() { if(controlSDKServiceApi?.getServiceStateObserver()?.value == Operation.OK){ powerCycle() diff --git a/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt b/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt index 7c01b4f..bd3df82 100644 --- a/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt +++ b/app/src/main/java/tv/remo/android/controller/fragments/SettingsCamera.kt @@ -1,8 +1,6 @@ package tv.remo.android.controller.fragments import android.content.Context import android.content.pm.PackageManager -import android.hardware.camera2.CameraCharacteristics -import android.hardware.camera2.CameraManager import android.os.Build import android.os.Bundle import android.view.View @@ -15,6 +13,7 @@ import tv.remo.android.controller.R import tv.remo.android.controller.sdk.RemoSettingsUtil import tv.remo.android.controller.sdk.utils.ValueUtil import tv.remo.android.controller.utils.CameraUtil +import tv.remo.android.controller.utils.v21.Camera2Util import tv.remo.android.settingsutil.fragments.BasePreferenceFragmentCompat import tv.remo.android.settingsutil.interfaces.SwitchBarCapableActivity import java.util.* @@ -237,17 +236,7 @@ class SettingsCamera : BasePreferenceFragmentCompat( private fun validateCamera2Support(context: Context, cameraId: Int): Boolean { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - try { - val cm = - (context.getSystemService(Context.CAMERA_SERVICE) as CameraManager) - val hardwareLevel = cm.getCameraCharacteristics( - cm.cameraIdList[cameraId] - )[CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL] - return hardwareLevel != CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY - && hardwareLevel != CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED - } catch (_: Exception) { - - } + return Camera2Util.checkFullyCompatible(context, cameraId) } return false } From d9ef385c6801fcfc6ee7a6922dd4fea4e3ab4f0d Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Sun, 8 Mar 2020 21:36:41 -0500 Subject: [PATCH 23/27] Move a function to util class --- .../controller/sdk/components/RemoSocketComponent.kt | 12 +----------- .../remo/android/controller/sdk/utils/StringUtil.kt | 7 +++++++ 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/sdk/src/main/java/tv/remo/android/controller/sdk/components/RemoSocketComponent.kt b/sdk/src/main/java/tv/remo/android/controller/sdk/components/RemoSocketComponent.kt index 5637e02..d28e063 100644 --- a/sdk/src/main/java/tv/remo/android/controller/sdk/components/RemoSocketComponent.kt +++ b/sdk/src/main/java/tv/remo/android/controller/sdk/components/RemoSocketComponent.kt @@ -16,10 +16,7 @@ import org.json.JSONObject import tv.remo.android.controller.sdk.RemoSettingsUtil import tv.remo.android.controller.sdk.interfaces.RemoCommandSender import tv.remo.android.controller.sdk.models.api.* -import tv.remo.android.controller.sdk.utils.ChatUtil -import tv.remo.android.controller.sdk.utils.EndpointBuilder -import tv.remo.android.controller.sdk.utils.SocketListener -import tv.remo.android.controller.sdk.utils.isUrl +import tv.remo.android.controller.sdk.utils.* /** * Remo Socket component @@ -152,13 +149,6 @@ class RemoSocketComponent : Component() , RemoCommandSender { } } - private fun String.startsWith(vararg prefix : String) : Boolean{ - prefix.forEach { - if(this.startsWith(it, false)) return true - } - return false - } - private fun searchAndSendCommand(message: Message) : Boolean{ //TODO get list of mods or users that have access to commands if(message.message.startsWith(".", "/")){ diff --git a/sdk/src/main/java/tv/remo/android/controller/sdk/utils/StringUtil.kt b/sdk/src/main/java/tv/remo/android/controller/sdk/utils/StringUtil.kt index 4f010d7..b876bcc 100644 --- a/sdk/src/main/java/tv/remo/android/controller/sdk/utils/StringUtil.kt +++ b/sdk/src/main/java/tv/remo/android/controller/sdk/utils/StringUtil.kt @@ -28,4 +28,11 @@ fun String.isUrl() : Boolean{ return true } return false +} + +fun String.startsWith(vararg prefix : String) : Boolean{ + prefix.forEach { + if(this.startsWith(it, false)) return true + } + return false } \ No newline at end of file From bdd3ed51618fedde19d98767a0aa302d2117d5b2 Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Sun, 8 Mar 2020 21:39:09 -0500 Subject: [PATCH 24/27] Clean up StreamCommandHandler.kt --- .../sdk/components/StreamCommandHandler.kt | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/sdk/src/main/java/tv/remo/android/controller/sdk/components/StreamCommandHandler.kt b/sdk/src/main/java/tv/remo/android/controller/sdk/components/StreamCommandHandler.kt index 8612133..ebc87f8 100644 --- a/sdk/src/main/java/tv/remo/android/controller/sdk/components/StreamCommandHandler.kt +++ b/sdk/src/main/java/tv/remo/android/controller/sdk/components/StreamCommandHandler.kt @@ -44,32 +44,39 @@ class StreamCommandHandler(val context: Context?, val streamHandler : CommandStr context?:return when (data) { ".stream sleep" -> { - if(!sleepMode){ - sleepMode = true - runBlocking { - streamHandler.acquireRetriever().disable().await() - } - } + handleSleep() } ".stream wakeup" -> { - if(sleepMode) { - sleepMode = false - runBlocking { - streamHandler.acquireRetriever().also { - it.updateStreamInfo(streamHandler.pullStreamInfo()) - it.enable().await() - } - } - } + handleWakeup() } ".stream reset" -> { - sleepMode = false reload() } } processSubscribedArrayForCommand(data) } + private fun handleWakeup() { + if(sleepMode) { + sleepMode = false + runBlocking { + streamHandler.acquireRetriever().also { + it.updateStreamInfo(streamHandler.pullStreamInfo()) + it.enable().await() + } + } + } + } + + private fun handleSleep() { + if(!sleepMode){ + sleepMode = true + runBlocking { + streamHandler.acquireRetriever().disable().await() + } + } + } + /** * Iterate through the array and trigger the subscribers if conditions are met */ @@ -100,6 +107,7 @@ class StreamCommandHandler(val context: Context?, val streamHandler : CommandStr } private fun reload() { + sleepMode = false streamHandler.resetComponents() } From 176fa528f4ae2b2274d86587e6b1f8a863d6a53a Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Sat, 14 Mar 2020 01:07:23 -0500 Subject: [PATCH 25/27] Update ControlSDK to 0.12.1 to fix component issue with not being removed from lifecycle --- sdk/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/build.gradle b/sdk/build.gradle index 8a9c7a9..0df4f42 100644 --- a/sdk/build.gradle +++ b/sdk/build.gradle @@ -36,7 +36,7 @@ dependencies { androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - def controlsdk_version = "0.12.0" + def controlsdk_version = "0.12.1" api "org.btelman.controlsdk:core:$controlsdk_version" api("org.btelman.controlsdk:streaming:$controlsdk_version") api "org.btelman.controlsdk:hardware:$controlsdk_version" From a2fdac7649845755e1cdaf53b97655d61fbcb46e Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Sat, 14 Mar 2020 01:07:57 -0500 Subject: [PATCH 26/27] Change order to disable before removing from lifecycle, since that seems to make more sense --- .../java/tv/remo/android/controller/activities/MainActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt index 7fe6a51..0fee352 100644 --- a/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt +++ b/app/src/main/java/tv/remo/android/controller/activities/MainActivity.kt @@ -163,10 +163,10 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { } Operation.LOADING -> {} //do nothing Operation.OK -> { + controlSDKServiceApi?.disable() arrayList.forEach { controlSDKServiceApi?.detachFromLifecycle(it) } - controlSDKServiceApi?.disable() } null -> powerButton.setTextColor(parseColorForOperation(null)) } From c0551278c0c9220f3f4ce6e5f02b19754a3165c9 Mon Sep 17 00:00:00 2001 From: Brendon Telman Date: Sun, 15 Mar 2020 18:14:45 -0500 Subject: [PATCH 27/27] Up build number to 0.16.0 --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 8ed8153..b5dae27 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,7 +26,7 @@ android { minSdkVersion 16 targetSdkVersion 28 versionCode 13 - versionName "0.15.0" + versionName "0.16.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes {