From cc90decf9b10b0e3f50ca68f84ef403803307481 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Wed, 15 Feb 2023 07:21:55 -0800 Subject: [PATCH] Migrate from Kotlin synthetics to Jetpack view binding (#25063) --- examples/android/CHIPTool/app/build.gradle | 8 +- .../chip/chiptool/SelectActionFragment.kt | 61 ++++---- .../attestation/AttestationTestFragment.kt | 37 +++-- .../clusterclient/AddressUpdateFragment.kt | 20 ++- .../clusterclient/BasicClientFragment.kt | 67 ++++----- .../clusterclient/MultiAdminClientFragment.kt | 47 +++--- .../clusterclient/OnOffClientFragment.kt | 73 ++++----- .../clusterclient/OpCredClientFragment.kt | 29 ++-- .../clusterclient/SensorClientFragment.kt | 73 ++++----- .../clusterclient/WildcardFragment.kt | 55 +++---- .../ClusterDetailFragment.kt | 138 ++++++++++-------- .../ClusterInteractionFragment.kt | 57 +++++--- .../ClusterInteractionHistoryFragment.kt | 23 ++- .../HistoryCommandAdapter.kt | 50 ++++--- .../AddressCommissioningFragment.kt | 62 ++++---- .../provisioning/EnterNetworkFragment.kt | 28 ++-- .../provisioning/UnpairDeviceFragment.kt | 21 ++- .../setuppayloadscanner/BarcodeFragment.kt | 49 +++---- .../CHIPDeviceDetailsFragment.kt | 81 +++++----- .../setuppayloadscanner/CHIPDeviceInfo.kt | 2 +- .../CHIPLedgerDetailsFragment.kt | 114 ++++++++------- .../src/main/res/layout/barcode_fragment.xml | 6 +- 22 files changed, 601 insertions(+), 500 deletions(-) diff --git a/examples/android/CHIPTool/app/build.gradle b/examples/android/CHIPTool/app/build.gradle index 1ad83dc8788344..fc57fc86e67aee 100644 --- a/examples/android/CHIPTool/app/build.gradle +++ b/examples/android/CHIPTool/app/build.gradle @@ -1,6 +1,6 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-parcelize' android { compileSdkVersion 31 @@ -34,11 +34,16 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + buildFeatures { + viewBinding = true + } + configurations.all { resolutionStrategy.eachDependency { DependencyResolveDetails details -> def requested = details.requested @@ -103,6 +108,7 @@ dependencies { implementation "androidx.camera:camera-lifecycle:${camerax_version}" implementation "androidx.camera:camera-view:${camerax_version}" } + repositories { mavenCentral() } diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt index f21b650ac6dc8b..9f1bbdaed7aa9c 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt @@ -28,40 +28,42 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AlertDialog import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment +import com.google.chip.chiptool.databinding.SelectActionFragmentBinding import com.google.chip.chiptool.util.FragmentUtil -import kotlinx.android.synthetic.main.select_action_fragment.provisionThreadCredentialsBtn -import kotlinx.android.synthetic.main.select_action_fragment.provisionWiFiCredentialsBtn -import kotlinx.android.synthetic.main.select_action_fragment.view.* /** Fragment to select from various options to interact with a CHIP device. */ class SelectActionFragment : Fragment() { + private var _binding: SelectActionFragmentBinding? = null + private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - return inflater.inflate(R.layout.select_action_fragment, container, false).apply { - scanQrBtn.setOnClickListener { getCallback()?.handleScanQrCodeClicked() } - provisionWiFiCredentialsBtn.apply { - isEnabled = hasLocationPermission() - setOnClickListener { getCallback()?.handleProvisionWiFiCredentialsClicked() } - } - provisionThreadCredentialsBtn.apply { - isEnabled = hasLocationPermission() - setOnClickListener { getCallback()?.handleProvisionThreadCredentialsClicked() } - } - onOffClusterBtn.setOnClickListener { getCallback()?.handleOnOffClicked() } - sensorClustersBtn.setOnClickListener { getCallback()?.handleSensorClicked() } - multiAdminClusterBtn.setOnClickListener { getCallback()?.handleMultiAdminClicked() } - opCredClustersBtn.setOnClickListener { getCallback()?.handleOpCredClicked() } - basicClusterBtn.setOnClickListener { getCallback()?.handleBasicClicked() } - attestationTestBtn.setOnClickListener { getCallback()?.handleAttestationTestClicked() } - clusterInteractionBtn.setOnClickListener { getCallback()?.handleClusterInteractionClicked() } - provisionCustomFlowBtn.setOnClickListener{ getCallback()?.handleProvisionCustomFlowClicked() } - wildcardBtn.setOnClickListener { getCallback()?.handleWildcardClicked() } - unpairDeviceBtn.setOnClickListener{ getCallback()?.handleUnpairDeviceClicked() } + _binding = SelectActionFragmentBinding.inflate(inflater, container, false) + + binding.scanQrBtn.setOnClickListener { getCallback()?.handleScanQrCodeClicked() } + binding.provisionWiFiCredentialsBtn.apply { + isEnabled = hasLocationPermission() + setOnClickListener { getCallback()?.handleProvisionWiFiCredentialsClicked() } } + binding.provisionThreadCredentialsBtn.apply { + isEnabled = hasLocationPermission() + setOnClickListener { getCallback()?.handleProvisionThreadCredentialsClicked() } + } + binding.onOffClusterBtn.setOnClickListener { getCallback()?.handleOnOffClicked() } + binding.sensorClustersBtn.setOnClickListener { getCallback()?.handleSensorClicked() } + binding.multiAdminClusterBtn.setOnClickListener { getCallback()?.handleMultiAdminClicked() } + binding.opCredClustersBtn.setOnClickListener { getCallback()?.handleOpCredClicked() } + binding.basicClusterBtn.setOnClickListener { getCallback()?.handleBasicClicked() } + binding.attestationTestBtn.setOnClickListener { getCallback()?.handleAttestationTestClicked() } + binding.clusterInteractionBtn.setOnClickListener { getCallback()?.handleClusterInteractionClicked() } + binding.provisionCustomFlowBtn.setOnClickListener{ getCallback()?.handleProvisionCustomFlowClicked() } + binding.wildcardBtn.setOnClickListener { getCallback()?.handleWildcardClicked() } + binding.unpairDeviceBtn.setOnClickListener{ getCallback()?.handleUnpairDeviceClicked() } + + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -80,11 +82,11 @@ class SelectActionFragment : Fragment() { } } if (granted) { - provisionWiFiCredentialsBtn.isEnabled = true - provisionThreadCredentialsBtn.isEnabled = true + binding.provisionWiFiCredentialsBtn.isEnabled = true + binding.provisionThreadCredentialsBtn.isEnabled = true } else { - provisionWiFiCredentialsBtn.isEnabled = false - provisionThreadCredentialsBtn.isEnabled = false + binding.provisionWiFiCredentialsBtn.isEnabled = false + binding.provisionThreadCredentialsBtn.isEnabled = false AlertDialog.Builder(requireContext()) .setTitle(R.string.location_permission_denied_title) @@ -109,6 +111,11 @@ class SelectActionFragment : Fragment() { permissionRequest.launch(permissions) } + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + private fun hasLocationPermission(): Boolean { val locationPermissionGranted = ContextCompat.checkSelfPermission( diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/attestation/AttestationTestFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/attestation/AttestationTestFragment.kt index b12bfe08451583..d4ff86d3719293 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/attestation/AttestationTestFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/attestation/AttestationTestFragment.kt @@ -6,29 +6,38 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import com.google.chip.chiptool.R -import kotlinx.android.synthetic.main.attestation_test_fragment.view.* +import com.google.chip.chiptool.databinding.AttestationTestFragmentBinding /** Fragment for launching external attestation apps */ class AttestationTestFragment : Fragment() { + private var _binding: AttestationTestFragmentBinding? = null + private val binding get() = _binding!! + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - return inflater.inflate(R.layout.attestation_test_fragment, container, false).apply { - attestationText.text = context.getString(R.string.attestation_fetching_status) - val appIntent = AttestationAppLauncher.getAttestationIntent(requireContext()) + ): View { + _binding = AttestationTestFragmentBinding.inflate(inflater, container, false) - if (appIntent != null) { - AttestationAppLauncher - .getLauncher(this@AttestationTestFragment) { result -> - attestationText.text = result - } - .launch(appIntent) - } else { - attestationText.text = context.getString(R.string.attestation_app_not_found) - } + binding.attestationText.text = context!!.getString(R.string.attestation_fetching_status) + val appIntent = AttestationAppLauncher.getAttestationIntent(requireContext()) + if (appIntent != null) { + AttestationAppLauncher + .getLauncher(this@AttestationTestFragment) { result -> + binding.attestationText.text = result + } + .launch(appIntent) + } else { + binding.attestationText.text = context!!.getString(R.string.attestation_app_not_found) } + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null } companion object { diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/AddressUpdateFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/AddressUpdateFragment.kt index 217cbc00737721..9e7c021aad039a 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/AddressUpdateFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/AddressUpdateFragment.kt @@ -10,9 +10,8 @@ import chip.devicecontroller.ChipDeviceController import chip.devicecontroller.ChipIdLookup import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.R +import com.google.chip.chiptool.databinding.AddressUpdateFragmentBinding import com.google.chip.chiptool.util.DeviceIdUtil -import kotlinx.android.synthetic.main.address_update_fragment.deviceIdEd -import kotlinx.android.synthetic.main.address_update_fragment.fabricIdEd /** Fragment for updating the address of a device given its fabric and node ID. */ class AddressUpdateFragment: Fragment() { @@ -20,21 +19,30 @@ class AddressUpdateFragment: Fragment() { get() = ChipClient.getDeviceController(requireContext()) val deviceId: Long - get() = deviceIdEd.text.toString().toULong().toLong() + get() = binding.deviceIdEd.text.toString().toULong().toLong() + + private var _binding: AddressUpdateFragmentBinding? = null + private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - return inflater.inflate(R.layout.address_update_fragment, container, false).apply { } + _binding = AddressUpdateFragmentBinding.inflate(inflater, container, false) + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val compressedFabricId = deviceController.compressedFabricId - fabricIdEd.setText(compressedFabricId.toULong().toString(16).padStart(16, '0')) - deviceIdEd.setText(DeviceIdUtil.getLastDeviceId(requireContext()).toString()) + binding.fabricIdEd.setText(compressedFabricId.toULong().toString(16).padStart(16, '0')) + binding.deviceIdEd.setText(DeviceIdUtil.getLastDeviceId(requireContext()).toString()) + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null } } \ No newline at end of file diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/BasicClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/BasicClientFragment.kt index 37c7fa7ab1cdd1..d98147eb97dbf7 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/BasicClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/BasicClientFragment.kt @@ -15,15 +15,7 @@ import chip.devicecontroller.ChipDeviceController import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.GenericChipDeviceListener import com.google.chip.chiptool.R -import kotlinx.android.synthetic.main.basic_client_fragment.attributeNameSpinner -import kotlinx.android.synthetic.main.basic_client_fragment.basicClusterCommandStatus -import kotlinx.android.synthetic.main.basic_client_fragment.locationEd -import kotlinx.android.synthetic.main.basic_client_fragment.nodeLabelEd -import kotlinx.android.synthetic.main.basic_client_fragment.view.attributeNameSpinner -import kotlinx.android.synthetic.main.basic_client_fragment.view.readAttributeBtn -import kotlinx.android.synthetic.main.basic_client_fragment.view.writeLocalConfigDisabledSwitch -import kotlinx.android.synthetic.main.basic_client_fragment.view.writeLocationBtn -import kotlinx.android.synthetic.main.basic_client_fragment.view.writeNodeLabelBtn +import com.google.chip.chiptool.databinding.BasicClientFragmentBinding import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -35,34 +27,43 @@ class BasicClientFragment : Fragment() { private lateinit var addressUpdateFragment: AddressUpdateFragment + private var _binding: BasicClientFragmentBinding? = null + private val binding get() = _binding!! + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { + _binding = BasicClientFragmentBinding.inflate(inflater, container, false) scope = viewLifecycleOwner.lifecycleScope - return inflater.inflate(R.layout.basic_client_fragment, container, false).apply { - deviceController.setCompletionListener(ChipControllerCallback()) - - addressUpdateFragment = - childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment - - writeNodeLabelBtn.setOnClickListener { scope.launch { - sendWriteNodeLabelAttribute() - nodeLabelEd.onEditorAction(EditorInfo.IME_ACTION_DONE) - }} - writeLocationBtn.setOnClickListener { scope.launch { - sendWriteLocationAttribute() - locationEd.onEditorAction(EditorInfo.IME_ACTION_DONE) - }} - writeLocalConfigDisabledSwitch.setOnCheckedChangeListener { _, isChecked -> - scope.launch { sendWriteLocalConfigDisabledAttribute(isChecked) } - } - makeAttributeList() - attributeNameSpinner.adapter = makeAttributeNamesAdapter() - readAttributeBtn.setOnClickListener { scope.launch { readAttributeButtonClick() }} + deviceController.setCompletionListener(ChipControllerCallback()) + + addressUpdateFragment = + childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment + + binding.writeNodeLabelBtn.setOnClickListener { scope.launch { + sendWriteNodeLabelAttribute() + binding.nodeLabelEd.onEditorAction(EditorInfo.IME_ACTION_DONE) + }} + binding.writeLocationBtn.setOnClickListener { scope.launch { + sendWriteLocationAttribute() + binding.locationEd.onEditorAction(EditorInfo.IME_ACTION_DONE) + }} + binding.writeLocalConfigDisabledSwitch.setOnCheckedChangeListener { _, isChecked -> + scope.launch { sendWriteLocalConfigDisabledAttribute(isChecked) } } + makeAttributeList() + binding.attributeNameSpinner.adapter = makeAttributeNamesAdapter() + binding.readAttributeBtn.setOnClickListener { scope.launch { readAttributeButtonClick() }} + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null } inner class ChipControllerCallback : GenericChipDeviceListener() { @@ -98,7 +99,7 @@ class BasicClientFragment : Fragment() { private suspend fun readAttributeButtonClick() { try { - readBasicClusters(attributeNameSpinner.selectedItemPosition) + readBasicClusters(binding.attributeNameSpinner.selectedItemPosition) } catch (ex: Exception) { showMessage("readBasicCluster failed: $ex") } @@ -244,7 +245,7 @@ class BasicClientFragment : Fragment() { showMessage("Write NodeLabel failure $ex") Log.e(TAG, "Write NodeLabel failure", ex) } - }, nodeLabelEd.text.toString()) + }, binding.nodeLabelEd.text.toString()) } private suspend fun sendReadLocationAttribute() { @@ -271,7 +272,7 @@ class BasicClientFragment : Fragment() { showMessage("Write Location failure $ex") Log.e(TAG, "Write Location failure", ex) } - }, locationEd.text.toString()) + }, binding.locationEd.text.toString()) } private suspend fun sendReadHardwareVersionAttribute() { @@ -457,7 +458,7 @@ class BasicClientFragment : Fragment() { private fun showMessage(msg: String) { requireActivity().runOnUiThread { - basicClusterCommandStatus.text = msg + binding.basicClusterCommandStatus.text = msg } } diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/MultiAdminClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/MultiAdminClientFragment.kt index ff61638b9bac0b..6f0a7a72b26b0f 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/MultiAdminClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/MultiAdminClientFragment.kt @@ -13,13 +13,7 @@ import chip.devicecontroller.OpenCommissioningCallback import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.GenericChipDeviceListener import com.google.chip.chiptool.R -import kotlinx.android.synthetic.main.multi_admin_client_fragment.discriminatorEd -import kotlinx.android.synthetic.main.multi_admin_client_fragment.timeoutEd -import kotlinx.android.synthetic.main.multi_admin_client_fragment.multiAdminClusterCommandStatus -import kotlinx.android.synthetic.main.multi_admin_client_fragment.setupPinCodeEd -import kotlinx.android.synthetic.main.multi_admin_client_fragment.view.basicCommissioningMethodBtn -import kotlinx.android.synthetic.main.multi_admin_client_fragment.view.enhancedCommissioningMethodBtn -import kotlinx.android.synthetic.main.multi_admin_client_fragment.view.revokeBtn +import com.google.chip.chiptool.databinding.MultiAdminClientFragmentBinding import kotlinx.coroutines.* class MultiAdminClientFragment : Fragment() { @@ -30,23 +24,27 @@ class MultiAdminClientFragment : Fragment() { private lateinit var addressUpdateFragment: AddressUpdateFragment + private var _binding: MultiAdminClientFragmentBinding? = null + private val binding get() = _binding!! + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { + _binding = MultiAdminClientFragmentBinding.inflate(inflater, container, false) scope = viewLifecycleOwner.lifecycleScope - return inflater.inflate(R.layout.multi_admin_client_fragment, container, false).apply { - deviceController.setCompletionListener(ChipControllerCallback()) + deviceController.setCompletionListener(ChipControllerCallback()) - addressUpdateFragment = - childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment + addressUpdateFragment = + childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment - basicCommissioningMethodBtn.setOnClickListener { scope.launch { sendBasicCommissioningCommandClick() } } - enhancedCommissioningMethodBtn.setOnClickListener { scope.launch { sendEnhancedCommissioningCommandClick() } } - revokeBtn.setOnClickListener { scope.launch { sendRevokeCommandClick() } } - } + binding.basicCommissioningMethodBtn.setOnClickListener { scope.launch { sendBasicCommissioningCommandClick() } } + binding.enhancedCommissioningMethodBtn.setOnClickListener { scope.launch { sendEnhancedCommissioningCommandClick() } } + binding.revokeBtn.setOnClickListener { scope.launch { sendRevokeCommandClick() } } + + return binding.root } override fun onStart() { @@ -55,9 +53,14 @@ class MultiAdminClientFragment : Fragment() { val testDiscriminator = "3840" val testSetupPinCode = 20202021L val testDuration = 180 - discriminatorEd.setText(testDiscriminator) - setupPinCodeEd.setText(testSetupPinCode.toString()) - timeoutEd.setText(testDuration.toString()) + binding.discriminatorEd.setText(testDiscriminator) + binding.setupPinCodeEd.setText(testSetupPinCode.toString()) + binding.timeoutEd.setText(testDuration.toString()) + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null } inner class ChipControllerCallback : GenericChipDeviceListener() { @@ -81,7 +84,7 @@ class MultiAdminClientFragment : Fragment() { } private suspend fun sendBasicCommissioningCommandClick() { - val testDuration = timeoutEd.text.toString().toInt() + val testDuration = binding.timeoutEd.text.toString().toInt() deviceController.openPairingWindowCallback( ChipClient.getConnectedDevicePointer( requireContext(), @@ -100,13 +103,13 @@ class MultiAdminClientFragment : Fragment() { } private suspend fun sendEnhancedCommissioningCommandClick() { - val testDuration = timeoutEd.text.toString().toInt() + val testDuration = binding.timeoutEd.text.toString().toInt() val testIteration = 1000 val devicePointer = ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) deviceController.openPairingWindowWithPINCallback( devicePointer, testDuration, testIteration.toLong(), - discriminatorEd.text.toString().toInt(), setupPinCodeEd.text.toString().toULong().toLong(), + binding.discriminatorEd.text.toString().toInt(), binding.setupPinCodeEd.text.toString().toULong().toLong(), object:OpenCommissioningCallback { override fun onError(status: Int, deviceId: Long) { showMessage("OpenCommissioning Fail! \nDevice ID : $deviceId\nErrorCode : $status") @@ -141,7 +144,7 @@ class MultiAdminClientFragment : Fragment() { private fun showMessage(msg: String) { requireActivity().runOnUiThread { - multiAdminClusterCommandStatus.text = msg + binding.multiAdminClusterCommandStatus.text = msg } } diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OnOffClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OnOffClientFragment.kt index 7918915787c02f..7f31b7485ce141 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OnOffClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OnOffClientFragment.kt @@ -18,18 +18,10 @@ import chip.devicecontroller.ChipDeviceController import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.GenericChipDeviceListener import com.google.chip.chiptool.R +import com.google.chip.chiptool.databinding.OnOffClientFragmentBinding import java.text.SimpleDateFormat import java.util.Calendar import java.util.Locale -import kotlinx.android.synthetic.main.on_off_client_fragment.commandStatusTv -import kotlinx.android.synthetic.main.on_off_client_fragment.levelBar -import kotlinx.android.synthetic.main.on_off_client_fragment.reportStatusTv -import kotlinx.android.synthetic.main.on_off_client_fragment.view.levelBar -import kotlinx.android.synthetic.main.on_off_client_fragment.view.offBtn -import kotlinx.android.synthetic.main.on_off_client_fragment.view.onBtn -import kotlinx.android.synthetic.main.on_off_client_fragment.view.readBtn -import kotlinx.android.synthetic.main.on_off_client_fragment.view.showSubscribeDialogBtn -import kotlinx.android.synthetic.main.on_off_client_fragment.view.toggleBtn import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -41,43 +33,52 @@ class OnOffClientFragment : Fragment() { private lateinit var addressUpdateFragment: AddressUpdateFragment + private var _binding: OnOffClientFragmentBinding? = null + private val binding get() = _binding!! + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { + _binding = OnOffClientFragmentBinding.inflate(inflater, container, false) scope = viewLifecycleOwner.lifecycleScope - return inflater.inflate(R.layout.on_off_client_fragment, container, false).apply { - deviceController.setCompletionListener(ChipControllerCallback()) + deviceController.setCompletionListener(ChipControllerCallback()) - addressUpdateFragment = - childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment + addressUpdateFragment = + childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment - onBtn.setOnClickListener { scope.launch { sendOnCommandClick() } } - offBtn.setOnClickListener { scope.launch { sendOffCommandClick() } } - toggleBtn.setOnClickListener { scope.launch { sendToggleCommandClick() } } - readBtn.setOnClickListener { scope.launch { sendReadOnOffClick() } } - showSubscribeDialogBtn.setOnClickListener { showSubscribeDialog() } + binding.onBtn.setOnClickListener { scope.launch { sendOnCommandClick() } } + binding.offBtn.setOnClickListener { scope.launch { sendOffCommandClick() } } + binding.toggleBtn.setOnClickListener { scope.launch { sendToggleCommandClick() } } + binding.readBtn.setOnClickListener { scope.launch { sendReadOnOffClick() } } + binding.showSubscribeDialogBtn.setOnClickListener { showSubscribeDialog() } - levelBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { - override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) { + binding.levelBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { + override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) { - } + } - override fun onStartTrackingTouch(seekBar: SeekBar?) { - } + override fun onStartTrackingTouch(seekBar: SeekBar?) { + } - override fun onStopTrackingTouch(seekBar: SeekBar?) { - Toast.makeText( - requireContext(), - "Level is: " + levelBar.progress, - Toast.LENGTH_SHORT - ).show() - scope.launch { sendLevelCommandClick() } - } - }) - } + override fun onStopTrackingTouch(seekBar: SeekBar?) { + Toast.makeText( + requireContext(), + "Level is: " + binding.levelBar.progress, + Toast.LENGTH_SHORT + ).show() + scope.launch { sendLevelCommandClick() } + } + }) + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null } private suspend fun sendReadOnOffClick() { @@ -177,7 +178,7 @@ class OnOffClientFragment : Fragment() { Log.e(TAG, "MoveToLevel command failure", ex) } - }, levelBar.progress, 0, 0, 0) + }, binding.levelBar.progress, 0, 0, 0) } private suspend fun sendOnCommandClick() { @@ -229,13 +230,13 @@ class OnOffClientFragment : Fragment() { private fun showMessage(msg: String) { requireActivity().runOnUiThread { - commandStatusTv.text = msg + binding.commandStatusTv.text = msg } } private fun showReportMessage(msg: String) { requireActivity().runOnUiThread { - reportStatusTv.text = msg + binding.reportStatusTv.text = msg } } diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OpCredClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OpCredClientFragment.kt index a56173fedab29a..fdc9720cd3a7e5 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OpCredClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OpCredClientFragment.kt @@ -12,9 +12,7 @@ import chip.devicecontroller.ChipDeviceController import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.GenericChipDeviceListener import com.google.chip.chiptool.R -import kotlinx.android.synthetic.main.op_cred_client_fragment.opCredClusterCommandStatus -import kotlinx.android.synthetic.main.op_cred_client_fragment.view.readCommissionedFabricBtn -import kotlinx.android.synthetic.main.op_cred_client_fragment.view.readSupportedFabricBtn +import com.google.chip.chiptool.databinding.OpCredClientFragmentBinding import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -26,22 +24,31 @@ class OpCredClientFragment : Fragment() { private lateinit var addressUpdateFragment: AddressUpdateFragment + private var _binding: OpCredClientFragmentBinding? = null + private val binding get() = _binding!! + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { + _binding = OpCredClientFragmentBinding.inflate(inflater, container, false) scope = viewLifecycleOwner.lifecycleScope - return inflater.inflate(R.layout.op_cred_client_fragment, container, false).apply { - deviceController.setCompletionListener(ChipControllerCallback()) + deviceController.setCompletionListener(ChipControllerCallback()) - addressUpdateFragment = - childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment + addressUpdateFragment = + childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment - readSupportedFabricBtn.setOnClickListener { scope.launch { sendReadOpCredSupportedFabricAttrClick() } } - readCommissionedFabricBtn.setOnClickListener { scope.launch { sendReadOpCredCommissionedFabricAttrClick() } } - } + binding.readSupportedFabricBtn.setOnClickListener { scope.launch { sendReadOpCredSupportedFabricAttrClick() } } + binding.readCommissionedFabricBtn.setOnClickListener { scope.launch { sendReadOpCredCommissionedFabricAttrClick() } } + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null } inner class ChipControllerCallback : GenericChipDeviceListener() { @@ -92,7 +99,7 @@ class OpCredClientFragment : Fragment() { private fun showMessage(msg: String) { requireActivity().runOnUiThread { - opCredClusterCommandStatus.text = msg + binding.opCredClusterCommandStatus.text = msg } } diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/SensorClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/SensorClientFragment.kt index 587eb85020651c..a7ac8728f814ca 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/SensorClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/SensorClientFragment.kt @@ -14,6 +14,8 @@ import androidx.lifecycle.lifecycleScope import chip.devicecontroller.ChipClusters import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.R +import com.google.chip.chiptool.databinding.AttestationTestFragmentBinding +import com.google.chip.chiptool.databinding.SensorClientFragmentBinding import com.google.chip.chiptool.util.DeviceIdUtil import com.jjoe64.graphview.LabelFormatter import com.jjoe64.graphview.Viewport @@ -22,13 +24,6 @@ import com.jjoe64.graphview.series.LineGraphSeries import java.text.SimpleDateFormat import java.util.Calendar import java.util.Date -import kotlinx.android.synthetic.main.sensor_client_fragment.clusterNameSpinner -import kotlinx.android.synthetic.main.sensor_client_fragment.deviceIdEd -import kotlinx.android.synthetic.main.sensor_client_fragment.endpointIdEd -import kotlinx.android.synthetic.main.sensor_client_fragment.lastValueTv -import kotlinx.android.synthetic.main.sensor_client_fragment.readSensorBtn -import kotlinx.android.synthetic.main.sensor_client_fragment.sensorGraph -import kotlinx.android.synthetic.main.sensor_client_fragment.watchSensorBtn import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -51,40 +46,47 @@ class SensorClientFragment : Fragment() { // Device whose attribute is subscribed private var subscribedDevicePtr = 0L + private var _binding: SensorClientFragmentBinding? = null + private val binding get() = _binding!! + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { + _binding = SensorClientFragmentBinding.inflate(inflater, container, false) scope = viewLifecycleOwner.lifecycleScope - return inflater.inflate(R.layout.sensor_client_fragment, container, false) + + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) ChipClient.getDeviceController(requireContext()).setCompletionListener(null) - deviceIdEd.setOnEditorActionListener { textView, actionId, _ -> + binding.deviceIdEd.setOnEditorActionListener { textView, actionId, _ -> if (actionId == EditorInfo.IME_ACTION_DONE) { resetSensorGraph() // reset the graph on device change } actionId == EditorInfo.IME_ACTION_DONE } - endpointIdEd.setOnEditorActionListener { textView, actionId, _ -> + + binding.endpointIdEd.setOnEditorActionListener { textView, actionId, _ -> if (actionId == EditorInfo.IME_ACTION_DONE) resetSensorGraph() // reset the graph on endpoint change actionId == EditorInfo.IME_ACTION_DONE } - clusterNameSpinner.adapter = makeClusterNamesAdapter() - clusterNameSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + + binding.clusterNameSpinner.adapter = makeClusterNamesAdapter() + binding.clusterNameSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onNothingSelected(parent: AdapterView<*>?) = Unit override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { resetSensorGraph() // reset the graph on cluster change } } - readSensorBtn.setOnClickListener { scope.launch { readSensorCluster() } } - watchSensorBtn.setOnCheckedChangeListener { _, isChecked -> + binding.readSensorBtn.setOnClickListener { scope.launch { readSensorCluster() } } + binding.watchSensorBtn.setOnCheckedChangeListener { _, isChecked -> if (isChecked) { scope.launch { subscribeSensorCluster() } } else { @@ -93,14 +95,14 @@ class SensorClientFragment : Fragment() { } val currentTime = Calendar.getInstance().time.time - sensorGraph.addSeries(sensorData) - sensorGraph.viewport.isXAxisBoundsManual = true - sensorGraph.viewport.setMinX(currentTime.toDouble()) - sensorGraph.viewport.setMaxX(currentTime.toDouble() + MIN_REFRESH_PERIOD_S * 1000 * MAX_DATA_POINTS) - sensorGraph.gridLabelRenderer.padding = 30 - sensorGraph.gridLabelRenderer.numHorizontalLabels = 4 - sensorGraph.gridLabelRenderer.setHorizontalLabelsAngle(150) - sensorGraph.gridLabelRenderer.labelFormatter = object : LabelFormatter { + binding.sensorGraph.addSeries(sensorData) + binding.sensorGraph.viewport.isXAxisBoundsManual = true + binding.sensorGraph.viewport.setMinX(currentTime.toDouble()) + binding.sensorGraph.viewport.setMaxX(currentTime.toDouble() + MIN_REFRESH_PERIOD_S * 1000 * MAX_DATA_POINTS) + binding.sensorGraph.gridLabelRenderer.padding = 30 + binding.sensorGraph.gridLabelRenderer.numHorizontalLabels = 4 + binding.sensorGraph.gridLabelRenderer.setHorizontalLabelsAngle(150) + binding.sensorGraph.gridLabelRenderer.labelFormatter = object : LabelFormatter { override fun setViewport(viewport: Viewport?) = Unit override fun formatLabel(value: Double, isValueX: Boolean): String { if (isValueX) @@ -114,7 +116,7 @@ class SensorClientFragment : Fragment() { override fun onStart() { super.onStart() - deviceIdEd.setText(DeviceIdUtil.getLastDeviceId(requireContext()).toString()) + binding.deviceIdEd.setText(DeviceIdUtil.getLastDeviceId(requireContext()).toString()) } override fun onStop() { @@ -122,9 +124,14 @@ class SensorClientFragment : Fragment() { super.onStop() } + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + private fun resetSensorGraph() { - watchSensorBtn.isChecked = false - sensorGraph.visibility = View.INVISIBLE + binding.watchSensorBtn.isChecked = false + binding.sensorGraph.visibility = View.INVISIBLE sensorData.resetData(emptyArray()) } @@ -140,9 +147,9 @@ class SensorClientFragment : Fragment() { private suspend fun readSensorCluster() { try { - val deviceId = deviceIdEd.text.toString().toULong().toLong() - val endpointId = endpointIdEd.text.toString().toInt() - val clusterName = clusterNameSpinner.selectedItem.toString() + val deviceId = binding.deviceIdEd.text.toString().toULong().toLong() + val endpointId = binding.endpointIdEd.text.toString().toInt() + val clusterName = binding.clusterNameSpinner.selectedItem.toString() val clusterRead = CLUSTERS[clusterName]!!["read"] as (Long, Int, ReadCallback) -> Unit val device = ChipClient.getConnectedDevicePointer(requireContext(), deviceId) val callback = makeReadCallback(clusterName, false) @@ -155,9 +162,9 @@ class SensorClientFragment : Fragment() { private suspend fun subscribeSensorCluster() { try { - val deviceId = deviceIdEd.text.toString().toULong().toLong() - val endpointId = endpointIdEd.text.toString().toInt() - val clusterName = clusterNameSpinner.selectedItem.toString() + val deviceId = binding.deviceIdEd.text.toString().toULong().toLong() + val endpointId = binding.endpointIdEd.text.toString().toInt() + val clusterName = binding.clusterNameSpinner.selectedItem.toString() val clusterSubscribe = CLUSTERS[clusterName]!!["subscribe"] as (Long, Int, ReadCallback) -> Unit val device = ChipClient.getConnectedDevicePointer(requireContext(), deviceId) val callback = makeReadCallback(clusterName, true) @@ -199,7 +206,7 @@ class SensorClientFragment : Fragment() { private fun consumeSensorValue(value: Double, unitSymbol: String, addToGraph: Boolean) { requireActivity().runOnUiThread { - lastValueTv.text = requireContext().getString( + binding.lastValueTv.text = requireContext().getString( R.string.sensor_client_last_value_text, value, unitSymbol ) @@ -212,7 +219,7 @@ class SensorClientFragment : Fragment() { // related to calculating the viewport when there is only one data point by // duplicating the first sample. sensorData.appendData(dataPoint, true, MAX_DATA_POINTS) - sensorGraph.visibility = View.VISIBLE + binding.sensorGraph.visibility = View.VISIBLE } } } diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt index 78af22e76fe742..9cc81d0db8bc63 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt @@ -22,20 +22,15 @@ import chip.devicecontroller.model.ChipPathId import chip.devicecontroller.model.NodeState import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.R +import com.google.chip.chiptool.databinding.WildcardFragmentBinding import java.lang.StringBuilder -import kotlinx.android.synthetic.main.wildcard_fragment.attributeIdEd -import kotlinx.android.synthetic.main.wildcard_fragment.clusterIdEd -import kotlinx.android.synthetic.main.wildcard_fragment.endpointIdEd -import kotlinx.android.synthetic.main.wildcard_fragment.eventIdEd -import kotlinx.android.synthetic.main.wildcard_fragment.outputTv -import kotlinx.android.synthetic.main.wildcard_fragment.view.readBtn -import kotlinx.android.synthetic.main.wildcard_fragment.view.readEventBtn -import kotlinx.android.synthetic.main.wildcard_fragment.view.subscribeBtn -import kotlinx.android.synthetic.main.wildcard_fragment.view.subscribeEventBtn import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch class WildcardFragment : Fragment() { + private var _binding: WildcardFragmentBinding? = null + private val binding get() = _binding!! + private val deviceController: ChipDeviceController get() = ChipClient.getDeviceController(requireContext()) @@ -60,7 +55,7 @@ class WildcardFragment : Fragment() { val debugString = nodeStateToDebugString(nodeState) Log.i(TAG, debugString) - requireActivity().runOnUiThread { outputTv.text = debugString } + requireActivity().runOnUiThread { binding.outputTv.text = debugString } } override fun onDone() { @@ -73,16 +68,22 @@ class WildcardFragment : Fragment() { container: ViewGroup?, savedInstanceState: Bundle?, ): View { + _binding = WildcardFragmentBinding.inflate(inflater, container, false) scope = viewLifecycleOwner.lifecycleScope - return inflater.inflate(R.layout.wildcard_fragment, container, false).apply { - subscribeBtn.setOnClickListener { scope.launch { showSubscribeDialog(ATTRIBUTE) } } - readBtn.setOnClickListener { scope.launch { showReadDialog(ATTRIBUTE) } } - subscribeEventBtn.setOnClickListener { scope.launch { showSubscribeDialog(EVENT) } } - readEventBtn.setOnClickListener { scope.launch { showReadDialog(EVENT) } } - - addressUpdateFragment = - childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment - } + binding.subscribeBtn.setOnClickListener { scope.launch { showSubscribeDialog(ATTRIBUTE) } } + binding.readBtn.setOnClickListener { scope.launch { showReadDialog(ATTRIBUTE) } } + binding.subscribeEventBtn.setOnClickListener { scope.launch { showSubscribeDialog(EVENT) } } + binding.readEventBtn.setOnClickListener { scope.launch { showReadDialog(EVENT) } } + + addressUpdateFragment = + childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null } private fun nodeStateToDebugString(nodeState: NodeState): String { @@ -121,10 +122,10 @@ class WildcardFragment : Fragment() { ResubscriptionAttemptCallback { terminationCause, nextResubscribeIntervalMsec -> Log.i(TAG, "ResubscriptionAttempt terminationCause:$terminationCause, nextResubscribeIntervalMsec:$nextResubscribeIntervalMsec") } - val endpointId = getChipPathIdForText(endpointIdEd.text.toString()) - val clusterId = getChipPathIdForText(clusterIdEd.text.toString()) - val attributeId = getChipPathIdForText(attributeIdEd.text.toString()) - val eventId = getChipPathIdForText(eventIdEd.text.toString()) + val endpointId = getChipPathIdForText(binding.endpointIdEd.text.toString()) + val clusterId = getChipPathIdForText(binding.clusterIdEd.text.toString()) + val attributeId = getChipPathIdForText(binding.attributeIdEd.text.toString()) + val eventId = getChipPathIdForText(binding.eventIdEd.text.toString()) if (type == ATTRIBUTE) { val attributePath = ChipAttributePath.newInstance(endpointId, clusterId, attributeId) @@ -156,10 +157,10 @@ class WildcardFragment : Fragment() { } private suspend fun read(type: Int, isFabricFiltered: Boolean) { - val endpointId = getChipPathIdForText(endpointIdEd.text.toString()) - val clusterId = getChipPathIdForText(clusterIdEd.text.toString()) - val attributeId = getChipPathIdForText(attributeIdEd.text.toString()) - val eventId = getChipPathIdForText(eventIdEd.text.toString()) + val endpointId = getChipPathIdForText(binding.endpointIdEd.text.toString()) + val clusterId = getChipPathIdForText(binding.clusterIdEd.text.toString()) + val attributeId = getChipPathIdForText(binding.attributeIdEd.text.toString()) + val eventId = getChipPathIdForText(binding.eventIdEd.text.toString()) if (type == ATTRIBUTE) { val attributePath = ChipAttributePath.newInstance(endpointId, clusterId, attributeId) diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterDetailFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterDetailFragment.kt index 5e9769764a5cdc..3cc7716d4ea530 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterDetailFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterDetailFragment.kt @@ -5,11 +5,7 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.ArrayAdapter -import android.widget.AutoCompleteTextView -import android.widget.Button -import android.widget.LinearLayout -import android.widget.Toast +import android.widget.* import androidx.appcompat.app.AlertDialog import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.forEach @@ -28,21 +24,9 @@ import com.google.chip.chiptool.ChipClient.getConnectedDevicePointer import com.google.chip.chiptool.GenericChipDeviceListener import com.google.chip.chiptool.R import com.google.chip.chiptool.clusterclient.clusterinteraction.ClusterInteractionHistoryFragment.Companion.clusterInteractionHistoryList +import com.google.chip.chiptool.databinding.ClusterDetailFragmentBinding import kotlin.properties.Delegates -import kotlinx.android.synthetic.main.cluster_callback_item.view.clusterCallbackDataTv -import kotlinx.android.synthetic.main.cluster_callback_item.view.clusterCallbackNameTv -import kotlinx.android.synthetic.main.cluster_callback_item.view.clusterCallbackTypeTv -import kotlinx.android.synthetic.main.cluster_detail_fragment.view.callbackList -import kotlinx.android.synthetic.main.cluster_detail_fragment.view.clusterAutoCompleteTv -import kotlinx.android.synthetic.main.cluster_detail_fragment.view.commandAutoCompleteTv -import kotlinx.android.synthetic.main.cluster_detail_fragment.view.invokeCommand -import kotlinx.android.synthetic.main.cluster_detail_fragment.view.parameterList -import kotlinx.android.synthetic.main.cluster_parameter_item.view.clusterParameterData -import kotlinx.android.synthetic.main.cluster_parameter_item.view.clusterParameterNameTv -import kotlinx.android.synthetic.main.cluster_parameter_item.view.clusterParameterTypeTv import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job import kotlinx.coroutines.cancel import kotlinx.coroutines.launch import java.util.* @@ -70,12 +54,15 @@ class ClusterDetailFragment : Fragment() { // null, and nothing will be autocompleted. If the detail page is opened from history page, // cluster name, command name and potential parameter list will be filled out based on historyCommand private var historyCommand: HistoryCommand? = null + private var _binding: ClusterDetailFragmentBinding? = null + private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { + _binding = ClusterDetailFragmentBinding.inflate(inflater, container, false) scope = viewLifecycleOwner.lifecycleScope deviceId = checkNotNull(requireArguments().getLong(DEVICE_ID)) scope.launch { @@ -83,35 +70,41 @@ class ClusterDetailFragment : Fragment() { } endpointId = checkNotNull(requireArguments().getInt(ENDPOINT_ID_KEY)) historyCommand = requireArguments().getSerializable(HISTORY_COMMAND) as HistoryCommand? - return inflater.inflate(R.layout.cluster_detail_fragment, container, false).apply { - deviceController.setCompletionListener(GenericChipDeviceListener()) - if (historyCommand != null) { - autoCompleteBasedOnHistoryCommand( - historyCommand!!, - clusterAutoCompleteTv, - commandAutoCompleteTv, - parameterList, - inflater, - callbackList - ) - } else { - commandAutoCompleteTv.visibility = View.GONE - clusterAutoCompleteSetup( - clusterAutoCompleteTv, - commandAutoCompleteTv, - parameterList, - callbackList - ) - commandAutoCompleteSetup(commandAutoCompleteTv, inflater, parameterList, callbackList) - } - setInvokeCommandOnClickListener( - invokeCommand, - callbackList, - clusterAutoCompleteTv, - commandAutoCompleteTv, - parameterList + deviceController.setCompletionListener(GenericChipDeviceListener()) + if (historyCommand != null) { + autoCompleteBasedOnHistoryCommand( + historyCommand!!, + binding.clusterAutoCompleteTv, + binding.commandAutoCompleteTv, + binding.parameterList, + inflater, + binding.callbackList + ) + } else { + binding.commandAutoCompleteTv.visibility = View.GONE + clusterAutoCompleteSetup( + binding.clusterAutoCompleteTv, + binding.commandAutoCompleteTv, + binding.parameterList, + binding.callbackList ) + commandAutoCompleteSetup(binding.commandAutoCompleteTv, inflater, binding.parameterList, binding.callbackList) } + + setInvokeCommandOnClickListener( + binding.invokeCommand, + binding.callbackList, + binding.clusterAutoCompleteTv, + binding.commandAutoCompleteTv, + binding.parameterList + ) + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null } private fun setInvokeCommandOnClickListener( @@ -136,11 +129,14 @@ class ClusterDetailFragment : Fragment() { ) ) parameterList.forEach { - val parameterName = it.clusterParameterNameTv.text.toString() + val clusterParameterNameTv: TextView = it.findViewById(R.id.clusterParameterNameTv) + val clusterParameterData: EditText = it.findViewById(R.id.clusterParameterData) + + val parameterName = clusterParameterNameTv.text.toString() val parameterType = selectedInteractionInfo.commandParameters[parameterName]!!.type val parameterUnderlyingType = selectedInteractionInfo.commandParameters[parameterName]!!.underlyingType - val data = castStringToType(it.clusterParameterData.text.toString(), parameterType, parameterUnderlyingType)!! - commandArguments[it.clusterParameterNameTv.text.toString()] = data + val data = castStringToType(clusterParameterData.text.toString(), parameterType, parameterUnderlyingType)!! + commandArguments[clusterParameterNameTv.text.toString()] = data clusterInteractionHistoryList[0].parameterList.add( HistoryParameterInfo( parameterName, @@ -172,9 +168,13 @@ class ClusterDetailFragment : Fragment() { setCallbackDelegate(inflater, callbackList) historyCommand.parameterList.forEach { val param = inflater.inflate(R.layout.cluster_parameter_item, null, false) as ConstraintLayout - param.clusterParameterNameTv.text = "${it.parameterName}" - param.clusterParameterTypeTv.text = formatParameterType(it.parameterType) - param.clusterParameterData.setText(it.parameterData) + val clusterParameterNameTv: TextView = param.findViewById(R.id.clusterParameterNameTv) + val clusterParameterTypeTv: TextView = param.findViewById(R.id.clusterParameterTypeTv) + val clusterParameterData: EditText = param.findViewById(R.id.clusterParameterData) + + clusterParameterNameTv.text = "${it.parameterName}" + clusterParameterTypeTv.text = formatParameterType(it.parameterType) + clusterParameterData.setText(it.parameterData) parameterList.addView(param) } } @@ -276,11 +276,14 @@ class ClusterDetailFragment : Fragment() { private fun populateCommandParameter(inflater: LayoutInflater, parameterList: LinearLayout) { selectedInteractionInfo.commandParameters.forEach { (paramName, paramInfo) -> val param = inflater.inflate(R.layout.cluster_parameter_item, null, false) as ConstraintLayout - param.clusterParameterNameTv.text = "${paramName}" + val clusterParameterNameTv: TextView = param.findViewById(R.id.clusterParameterNameTv) + val clusterParameterTypeTv: TextView = param.findViewById(R.id.clusterParameterTypeTv) + + clusterParameterNameTv.text = "${paramName}" // byte[].class will be output as class [B, which is not readable, so dynamically change it // to Byte[]. If more custom logic is required, should add a className field in // commandParameterInfo - param.clusterParameterTypeTv.text = formatParameterType(paramInfo.type) + clusterParameterTypeTv.text = formatParameterType(paramInfo.type) parameterList.addView(param) } } @@ -307,13 +310,17 @@ class ClusterDetailFragment : Fragment() { ) { val callbackItem = inflater.inflate(R.layout.cluster_callback_item, null, false) as ConstraintLayout - callbackItem.clusterCallbackNameTv.text = variableNameType.name - callbackItem.clusterCallbackDataTv.text = if (response.javaClass == ByteArray::class.java) { + val clusterCallbackNameTv: TextView = callbackItem.findViewById(R.id.clusterCallbackNameTv) + val clusterCallbackDataTv: TextView = callbackItem.findViewById(R.id.clusterCallbackDataTv) + val clusterCallbackTypeTv: TextView = callbackItem.findViewById(R.id.clusterCallbackTypeTv) + + clusterCallbackNameTv.text = variableNameType.name + clusterCallbackDataTv.text = if (response.javaClass == ByteArray::class.java) { (response as ByteArray).decodeToString() } else { response.toString() } - callbackItem.clusterCallbackTypeTv.text = variableNameType.type + clusterCallbackTypeTv.text = variableNameType.type callbackList.addView(callbackItem) } @@ -326,32 +333,41 @@ class ClusterDetailFragment : Fragment() { if (response.isEmpty()) { val emptyCallback = inflater.inflate(R.layout.cluster_callback_item, null, false) as ConstraintLayout - emptyCallback.clusterCallbackNameTv.text = "Result is empty" + val clusterCallbackNameTv: TextView = emptyCallback.findViewById(R.id.clusterCallbackNameTv) + + clusterCallbackNameTv.text = "Result is empty" callbackList.addView(emptyCallback) } else { response.forEachIndexed { index, it -> val attributeCallbackItem = inflater.inflate(R.layout.cluster_callback_item, null, false) as ConstraintLayout - attributeCallbackItem.clusterCallbackNameTv.text = variableNameType.name + "[$index]" + val clusterCallbackNameTv: TextView = attributeCallbackItem.findViewById(R.id.clusterCallbackNameTv) + val clusterCallbackDataTv: TextView = attributeCallbackItem.findViewById(R.id.clusterCallbackDataTv) + val clusterCallbackTypeTv: TextView = attributeCallbackItem.findViewById(R.id.clusterCallbackTypeTv) + + clusterCallbackNameTv.text = variableNameType.name + "[$index]" val objectString = if (it!!.javaClass == ByteArray::class.java) { (it as ByteArray).contentToString() } else { it.toString() } + var callbackClassName = if (it!!.javaClass == ByteArray::class.java) { "Byte[]" } else { it!!.javaClass.toString().split('$').last() } - attributeCallbackItem.clusterCallbackDataTv.text = callbackClassName - attributeCallbackItem.clusterCallbackDataTv.setOnClickListener { + + clusterCallbackDataTv.text = callbackClassName + clusterCallbackDataTv.setOnClickListener { AlertDialog.Builder(requireContext()) .setTitle(callbackClassName) .setMessage(objectString) .create() .show() } - attributeCallbackItem.clusterCallbackTypeTv.text = "List<$callbackClassName>" + + clusterCallbackTypeTv.text = "List<$callbackClassName>" callbackList.addView(attributeCallbackItem) } } diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterInteractionFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterInteractionFragment.kt index 950c270b4d43fa..c502f51d939ff9 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterInteractionFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterInteractionFragment.kt @@ -16,10 +16,8 @@ import com.google.chip.chiptool.R import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.cancel import com.google.chip.chiptool.clusterclient.AddressUpdateFragment +import com.google.chip.chiptool.databinding.ClusterInteractionFragmentBinding import kotlin.properties.Delegates -import kotlinx.android.synthetic.main.cluster_interaction_fragment.view.bottomNavigationBar -import kotlinx.android.synthetic.main.cluster_interaction_fragment.view.endpointList -import kotlinx.android.synthetic.main.cluster_interaction_fragment.view.getEndpointListBtn import kotlinx.coroutines.launch class ClusterInteractionFragment : Fragment() { @@ -30,36 +28,47 @@ class ClusterInteractionFragment : Fragment() { private lateinit var addressUpdateFragment: AddressUpdateFragment private var devicePtr by Delegates.notNull() + private var _binding: ClusterInteractionFragmentBinding? = null + private val binding get() = _binding!! + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { + _binding = ClusterInteractionFragmentBinding.inflate(inflater, container, false) scope = viewLifecycleOwner.lifecycleScope - return inflater.inflate(R.layout.cluster_interaction_fragment, container, false).apply { - deviceController.setCompletionListener(GenericChipDeviceListener()) - endpointList.visibility = View.GONE - getEndpointListBtn.setOnClickListener { - scope.launch { - devicePtr = - ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) - showMessage("Retrieving endpoints") - endpointList.visibility = View.VISIBLE - } - } - addressUpdateFragment = - childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment - var dataList: List = ArrayList() - // TODO: Dynamically retrieve endpoint information using descriptor cluster - // hardcode the endpoint for now - for (i in 0 until 2) { - dataList += EndpointItem(i) + deviceController.setCompletionListener(GenericChipDeviceListener()) + binding.endpointList.visibility = View.GONE + binding.getEndpointListBtn.setOnClickListener { + scope.launch { + devicePtr = + ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId) + showMessage("Retrieving endpoints") + binding.endpointList.visibility = View.VISIBLE } - endpointList.adapter = EndpointAdapter(dataList, EndpointListener()) - endpointList.layoutManager = LinearLayoutManager(requireContext()) - bottomNavigationBar.setOnNavigationItemSelectedListener(bottomNavigationListener) } + + addressUpdateFragment = + childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment + var dataList: List = ArrayList() + // TODO: Dynamically retrieve endpoint information using descriptor cluster + // hardcode the endpoint for now + for (i in 0 until 2) { + dataList += EndpointItem(i) + } + + binding.endpointList.adapter = EndpointAdapter(dataList, EndpointListener()) + binding.endpointList.layoutManager = LinearLayoutManager(requireContext()) + binding.bottomNavigationBar.setOnNavigationItemSelectedListener(bottomNavigationListener) + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null } private fun showMessage(msg: String) { diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterInteractionHistoryFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterInteractionHistoryFragment.kt index 3eaa874e2c6013..54a9edb18b8886 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterInteractionHistoryFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/ClusterInteractionHistoryFragment.kt @@ -8,7 +8,7 @@ import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.LinearLayoutManager import com.google.chip.chiptool.R -import kotlinx.android.synthetic.main.cluster_interaction_history_fragment.view.historyCommandList +import com.google.chip.chiptool.databinding.ClusterInteractionHistoryFragmentBinding /** * A simple [Fragment] subclass for the cluster interaction history component @@ -16,18 +16,25 @@ import kotlinx.android.synthetic.main.cluster_interaction_history_fragment.view. * create an instance of this fragment. */ class ClusterInteractionHistoryFragment : Fragment() { + private var _binding: ClusterInteractionHistoryFragmentBinding? = null + private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - // Inflate the layout for this fragment + ): View { + _binding = ClusterInteractionHistoryFragmentBinding.inflate(inflater, container, false) Log.d(TAG, clusterInteractionHistoryList.toString()) - return inflater.inflate(R.layout.cluster_interaction_history_fragment, container, false).apply { - historyCommandList.adapter = - HistoryCommandAdapter(clusterInteractionHistoryList, HistoryCommandListener(), inflater) - historyCommandList.layoutManager = LinearLayoutManager(requireContext()) - } + binding.historyCommandList.adapter = + HistoryCommandAdapter(clusterInteractionHistoryList, HistoryCommandListener(), inflater) + binding.historyCommandList.layoutManager = LinearLayoutManager(requireContext()) + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null } private fun showFragment(fragment: Fragment, showOnBack: Boolean = true) { diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/HistoryCommandAdapter.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/HistoryCommandAdapter.kt index bf817b76c9dac6..4a0dc0dff41ccc 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/HistoryCommandAdapter.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/clusterinteraction/HistoryCommandAdapter.kt @@ -4,20 +4,13 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.EditText import android.widget.LinearLayout import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout import androidx.recyclerview.widget.RecyclerView import chip.clusterinfo.CommandResponseInfo import com.google.chip.chiptool.R -import kotlinx.android.synthetic.main.cluster_callback_item.view.clusterCallbackDataTv -import kotlinx.android.synthetic.main.cluster_callback_item.view.clusterCallbackNameTv -import kotlinx.android.synthetic.main.cluster_callback_item.view.clusterCallbackTypeTv -import kotlinx.android.synthetic.main.cluster_interaction_history_item_info.view.historyClusterNameTv -import kotlinx.android.synthetic.main.cluster_interaction_history_item_info.view.historyCommandNameTv -import kotlinx.android.synthetic.main.cluster_parameter_item.view.clusterParameterData -import kotlinx.android.synthetic.main.cluster_parameter_item.view.clusterParameterNameTv -import kotlinx.android.synthetic.main.cluster_parameter_item.view.clusterParameterTypeTv /** * HistoryCommandAdapter implements the historyCommandList(RecycleView) Adapter and associates different @@ -83,8 +76,11 @@ class HistoryCommandAdapter( null, false ) as ConstraintLayout - info.historyClusterNameTv.text = HistoryCommandList[position].clusterName - info.historyCommandNameTv.text = HistoryCommandList[position].commandName + val historyClusterNameTv: TextView = info.findViewById(R.id.historyClusterNameTv) + val historyCommandNameTv: TextView = info.findViewById(R.id.historyCommandNameTv) + + historyClusterNameTv.text = HistoryCommandList[position].clusterName + historyCommandNameTv.text = HistoryCommandList[position].commandName holder.historyInfo.addView(info) // fill out parameterList if (HistoryCommandList[position].parameterList.isEmpty()) { @@ -96,9 +92,13 @@ class HistoryCommandAdapter( HistoryCommandList[position].parameterList.forEach { val param = inflater.inflate(R.layout.cluster_parameter_item, null, false) as ConstraintLayout - param.clusterParameterData.setText(it.parameterData) - param.clusterParameterNameTv.text = it.parameterName - param.clusterParameterTypeTv.text = formatParameterType(it.parameterType) + val clusterParameterNameTv: TextView = info.findViewById(R.id.clusterParameterNameTv) + val clusterParameterTypeTv: TextView = info.findViewById(R.id.clusterParameterTypeTv) + val clusterParameterData: EditText = info.findViewById(R.id.clusterParameterData) + + clusterParameterData.setText(it.parameterData) + clusterParameterNameTv.text = it.parameterName + clusterParameterTypeTv.text = formatParameterType(it.parameterType) holder.parameterList.addView(param) } } @@ -143,13 +143,17 @@ class HistoryCommandAdapter( ) { val callbackItem = inflater.inflate(R.layout.cluster_callback_item, null, false) as ConstraintLayout - callbackItem.clusterCallbackNameTv.text = variableNameType.name - callbackItem.clusterCallbackDataTv.text = if (response.javaClass == ByteArray::class.java) { + val clusterCallbackNameTv: TextView = callbackItem.findViewById(R.id.clusterCallbackNameTv) + val clusterCallbackDataTv: TextView = callbackItem.findViewById(R.id.clusterCallbackDataTv) + val clusterCallbackTypeTv: TextView = callbackItem.findViewById(R.id.clusterCallbackTypeTv) + + clusterCallbackNameTv.text = variableNameType.name + clusterCallbackDataTv.text = if (response.javaClass == ByteArray::class.java) { (response as ByteArray).decodeToString() } else { response.toString() } - callbackItem.clusterCallbackTypeTv.text = variableNameType.type + clusterCallbackTypeTv.text = variableNameType.type callbackList.addView(callbackItem) } @@ -162,13 +166,19 @@ class HistoryCommandAdapter( if (response.isEmpty()) { val emptyCallback = inflater.inflate(R.layout.cluster_callback_item, null, false) as ConstraintLayout - emptyCallback.clusterCallbackNameTv.text = "Result is empty" + val clusterCallbackNameTv: TextView = emptyCallback.findViewById(R.id.clusterCallbackNameTv) + + clusterCallbackNameTv.text = "Result is empty" callbackList.addView(emptyCallback) } else { response.forEachIndexed { index, it -> val attributeCallbackItem = inflater.inflate(R.layout.cluster_callback_item, null, false) as ConstraintLayout - attributeCallbackItem.clusterCallbackNameTv.text = variableNameType.name + "[$index]" + val clusterCallbackNameTv: TextView = attributeCallbackItem.findViewById(R.id.clusterCallbackNameTv) + val clusterCallbackDataTv: TextView = attributeCallbackItem.findViewById(R.id.clusterCallbackDataTv) + val clusterCallbackTypeTv: TextView = attributeCallbackItem.findViewById(R.id.clusterCallbackTypeTv) + + clusterCallbackNameTv.text = variableNameType.name + "[$index]" val objectString = if (it!!.javaClass == ByteArray::class.java) { (it as ByteArray).contentToString() } else { @@ -179,8 +189,8 @@ class HistoryCommandAdapter( } else { it!!.javaClass.toString().split('$').last() } - attributeCallbackItem.clusterCallbackDataTv.text = objectString - attributeCallbackItem.clusterCallbackTypeTv.text = "List<$callbackClassName>" + clusterCallbackDataTv.text = objectString + clusterCallbackTypeTv.text = "List<$callbackClassName>" callbackList.addView(attributeCallbackItem) } } diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/AddressCommissioningFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/AddressCommissioningFragment.kt index 25abcc04db4182..67e65cf4697dec 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/AddressCommissioningFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/AddressCommissioningFragment.kt @@ -16,19 +16,10 @@ import android.widget.AdapterView import android.widget.ArrayAdapter import androidx.fragment.app.Fragment import com.google.chip.chiptool.ChipClient -import com.google.chip.chiptool.R +import com.google.chip.chiptool.databinding.AddressCommissioningFragmentBinding import com.google.chip.chiptool.setuppayloadscanner.BarcodeFragment import com.google.chip.chiptool.setuppayloadscanner.CHIPDeviceInfo import com.google.chip.chiptool.util.FragmentUtil -import kotlinx.android.synthetic.main.address_commissioning_fragment.addressEditText -import kotlinx.android.synthetic.main.address_commissioning_fragment.commissionBtn -import kotlinx.android.synthetic.main.address_commissioning_fragment.discoverBtn -import kotlinx.android.synthetic.main.address_commissioning_fragment.discoverListSpinner -import kotlinx.android.synthetic.main.address_commissioning_fragment.discriminatorEditText -import kotlinx.android.synthetic.main.address_commissioning_fragment.pincodeEditText -import kotlinx.android.synthetic.main.address_commissioning_fragment.wifiConnectBtn -import kotlinx.android.synthetic.main.address_commissioning_fragment.wifiScanBtn -import kotlinx.android.synthetic.main.address_commissioning_fragment.wifiScanListSpinner import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -40,22 +31,25 @@ class AddressCommissioningFragment : Fragment() { private val wifiApList = ArrayList() private var wifiApSsid = String() private val scope = CoroutineScope(Dispatchers.Main + Job()) + private var _binding: AddressCommissioningFragmentBinding? = null + private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - return inflater.inflate(R.layout.address_commissioning_fragment, container, false) + ): View { + _binding = AddressCommissioningFragmentBinding.inflate(inflater, container, false) + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - commissionBtn.setOnClickListener { - val address = addressEditText.text.toString() - val discriminator = discriminatorEditText.text.toString() - val pincode = pincodeEditText.text.toString() + binding.commissionBtn.setOnClickListener { + val address = binding.addressEditText.text.toString() + val discriminator = binding.discriminatorEditText.text.toString() + val pincode = binding.pincodeEditText.text.toString() if (address.isEmpty() || discriminator.isEmpty() || pincode.isEmpty()) { Log.e(TAG, "Address, discriminator, or pincode was empty: $address $discriminator $pincode") @@ -71,19 +65,19 @@ class AddressCommissioningFragment : Fragment() { ) } - discoverBtn.setOnClickListener { _ -> - discoverBtn.isEnabled = false + binding.discoverBtn.setOnClickListener { _ -> + binding.discoverBtn.isEnabled = false val deviceController = ChipClient.getDeviceController(requireContext()) deviceController.discoverCommissionableNodes() scope.launch { delay(7000) updateSpinner() - discoverBtn.isEnabled = true + binding.discoverBtn.isEnabled = true } } - wifiConnectBtn.setOnClickListener { _ -> - wifiConnectBtn.isEnabled = false + binding.wifiConnectBtn.setOnClickListener { _ -> + binding.wifiConnectBtn.isEnabled = false val context = getActivity() val wifiManager = context?.getSystemService(Context.WIFI_SERVICE) as WifiManager @@ -104,13 +98,13 @@ class AddressCommissioningFragment : Fragment() { Log.d(TAG, "Enable network ${config.SSID} succeeded") } else { Log.d(TAG, "Enable network ${config.SSID} failed") - wifiConnectBtn.isEnabled = true + binding.wifiConnectBtn.isEnabled = true } } } - wifiScanBtn.setOnClickListener { _ -> - wifiScanBtn.isEnabled = false + binding.wifiScanBtn.setOnClickListener { _ -> + binding.wifiScanBtn.isEnabled = false val context = getActivity() val wifiManager = context?.getSystemService(Context.WIFI_SERVICE) as WifiManager val wifiScanReceiver = object : BroadcastReceiver() { @@ -124,7 +118,7 @@ class AddressCommissioningFragment : Fragment() { } else { Log.d(TAG, "Scan failed") } - wifiScanBtn.isEnabled = true + binding.wifiScanBtn.isEnabled = true } } @@ -142,6 +136,11 @@ class AddressCommissioningFragment : Fragment() { } } + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + private fun updateWifiScanListSpinner(scanResults : MutableList) { wifiApList.clear() for (result in scanResults) { @@ -149,9 +148,9 @@ class AddressCommissioningFragment : Fragment() { wifiApList.add("${result.SSID}, ${result.BSSID}, ${result.level}") } requireActivity().runOnUiThread { - wifiScanListSpinner.adapter = + binding.wifiScanListSpinner.adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, wifiApList) - wifiScanListSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + binding.wifiScanListSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) { wifiApSsid = wifiApList[position].split(",")[0].trim() Log.d(TAG, "ready to connect to $wifiApSsid") @@ -168,14 +167,15 @@ class AddressCommissioningFragment : Fragment() { ipAddressList.add("${device.ipAddress}, ${device.discriminator}") } requireActivity().runOnUiThread { - discoverListSpinner.adapter = + binding.discoverListSpinner.adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, ipAddressList) - discoverListSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + binding.discoverListSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) { val address = ipAddressList[position].split(",")[0].trim() val discriminator = ipAddressList[position].split(",")[1].trim() - addressEditText.setText(address) - discriminatorEditText.setText(discriminator) + + binding.addressEditText.setText(address) + binding.discriminatorEditText.setText(discriminator) } override fun onNothingSelected(parent: AdapterView<*>) {} diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/EnterNetworkFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/EnterNetworkFragment.kt index 5f0d024ee694a4..a6af4ba27883f2 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/EnterNetworkFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/EnterNetworkFragment.kt @@ -21,18 +21,13 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Button +import android.widget.EditText import android.widget.Toast import androidx.fragment.app.Fragment import com.google.chip.chiptool.R import com.google.chip.chiptool.util.FragmentUtil import com.google.chip.chiptool.NetworkCredentialsParcelable -import kotlinx.android.synthetic.main.enter_thread_network_fragment.channelEd -import kotlinx.android.synthetic.main.enter_thread_network_fragment.masterKeyEd -import kotlinx.android.synthetic.main.enter_thread_network_fragment.panIdEd -import kotlinx.android.synthetic.main.enter_thread_network_fragment.xpanIdEd -import kotlinx.android.synthetic.main.enter_wifi_network_fragment.pwdEd -import kotlinx.android.synthetic.main.enter_wifi_network_fragment.ssidEd -import kotlinx.android.synthetic.main.enter_wifi_network_fragment.view.saveNetworkBtn /** * Fragment to collect Wi-Fi network information from user and send it to device being provisioned. @@ -58,19 +53,22 @@ class EnterNetworkFragment : Fragment() { } return inflater.inflate(layoutRes, container, false).apply { - saveNetworkBtn.setOnClickListener { onSaveNetworkClicked() } + val saveNetworkBtn: Button = findViewById(R.id.saveNetworkBtn) + saveNetworkBtn.setOnClickListener { onSaveNetworkClicked(this) } } } - private fun onSaveNetworkClicked() { + private fun onSaveNetworkClicked(view: View) { if (networkType == ProvisionNetworkType.WIFI) { - saveWiFiNetwork() + saveWiFiNetwork(view) } else { - saveThreadNetwork() + saveThreadNetwork(view) } } - private fun saveWiFiNetwork() { + private fun saveWiFiNetwork(view: View) { + val ssidEd: EditText = view.findViewById(R.id.ssidEd) + val pwdEd: EditText = view.findViewById(R.id.pwdEd) val ssid = ssidEd?.text val pwd = pwdEd?.text @@ -86,7 +84,11 @@ class EnterNetworkFragment : Fragment() { ?.onNetworkCredentialsEntered(networkCredentials) } - private fun saveThreadNetwork() { + private fun saveThreadNetwork(view: View) { + val channelEd: EditText = view.findViewById(R.id.channelEd) + val panIdEd: EditText = view.findViewById(R.id.panIdEd) + val xpanIdEd: EditText = view.findViewById(R.id.xpanIdEd) + val masterKeyEd: EditText = view.findViewById(R.id.masterKeyEd) val channelStr = channelEd.text val panIdStr = panIdEd.text diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/UnpairDeviceFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/UnpairDeviceFragment.kt index 801d4fc1272836..a0569b540b45c4 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/UnpairDeviceFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/UnpairDeviceFragment.kt @@ -12,7 +12,7 @@ import chip.devicecontroller.UnpairDeviceCallback import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.R import com.google.chip.chiptool.clusterclient.AddressUpdateFragment -import kotlinx.android.synthetic.main.unpair_device_fragment.view.unpairDeviceBtn +import com.google.chip.chiptool.databinding.UnpairDeviceFragmentBinding import kotlinx.coroutines.* class UnpairDeviceFragment : Fragment() { @@ -23,19 +23,28 @@ class UnpairDeviceFragment : Fragment() { private lateinit var addressUpdateFragment: AddressUpdateFragment + private var _binding: UnpairDeviceFragmentBinding? = null + private val binding get() = _binding!! + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { + _binding = UnpairDeviceFragmentBinding.inflate(inflater, container, false) scope = viewLifecycleOwner.lifecycleScope - return inflater.inflate(R.layout.unpair_device_fragment, container, false).apply { - addressUpdateFragment = - childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment + addressUpdateFragment = + childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment - unpairDeviceBtn.setOnClickListener { scope.launch { unpairDeviceClick() } } - } + binding.unpairDeviceBtn.setOnClickListener { scope.launch { unpairDeviceClick() } } + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null } inner class ChipUnpairDeviceCallback : UnpairDeviceCallback { diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/BarcodeFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/BarcodeFragment.kt index f701d2ca105117..8c5faed88e3601 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/BarcodeFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/BarcodeFragment.kt @@ -29,13 +29,10 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.Button -import android.widget.EditText import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.camera.core.* import androidx.camera.lifecycle.ProcessCameraProvider -import androidx.camera.view.PreviewView import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat.checkSelfPermission import androidx.fragment.app.Fragment @@ -44,12 +41,12 @@ import chip.setuppayload.SetupPayloadParser import chip.setuppayload.SetupPayloadParser.UnrecognizedQrCodeException import com.google.chip.chiptool.R import com.google.chip.chiptool.SelectActionFragment +import com.google.chip.chiptool.databinding.BarcodeFragmentBinding import com.google.chip.chiptool.util.FragmentUtil import com.google.mlkit.vision.barcode.BarcodeScanner import com.google.mlkit.vision.barcode.BarcodeScanning import com.google.mlkit.vision.barcode.common.Barcode import com.google.mlkit.vision.common.InputImage -import kotlinx.android.synthetic.main.barcode_fragment.view.inputAddressBtn import java.util.concurrent.Executors import kotlin.math.abs import kotlin.math.max @@ -57,10 +54,8 @@ import kotlin.math.min /** Launches the camera to scan for QR code. */ class BarcodeFragment : Fragment() { - - private lateinit var previewView: PreviewView - private var manualCodeEditText: EditText? = null - private var manualCodeBtn: Button? = null + private var _binding: BarcodeFragmentBinding? = null + private val binding get() = _binding!! private fun aspectRatio(width: Int, height: Int): Int { val previewRatio = max(width, height).toDouble() / min(width, height) @@ -82,18 +77,22 @@ class BarcodeFragment : Fragment() { container: ViewGroup?, savedInstanceState: Bundle? ): View { - return inflater.inflate(R.layout.barcode_fragment, container, false).apply { - previewView = findViewById(R.id.camera_view) - manualCodeEditText = findViewById(R.id.manualCodeEditText) - manualCodeBtn = findViewById(R.id.manualCodeBtn) - startCamera() - inputAddressBtn.setOnClickListener { - FragmentUtil.getHost( - this@BarcodeFragment, - SelectActionFragment.Callback::class.java - )?.onShowDeviceAddressInput() - } + _binding = BarcodeFragmentBinding.inflate(inflater, container, false) + + startCamera() + binding.inputAddressBtn.setOnClickListener { + FragmentUtil.getHost( + this@BarcodeFragment, + SelectActionFragment.Callback::class.java + )?.onShowDeviceAddressInput() } + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null } @SuppressLint("UnsafeOptInUsageError") @@ -101,19 +100,19 @@ class BarcodeFragment : Fragment() { val cameraProviderFuture = ProcessCameraProvider.getInstance(requireActivity()) cameraProviderFuture.addListener({ val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get() - val metrics = DisplayMetrics().also { previewView.display?.getRealMetrics(it) } + val metrics = DisplayMetrics().also { binding.cameraView.display?.getRealMetrics(it) } val screenAspectRatio = aspectRatio(metrics.widthPixels, metrics.heightPixels) // Preview val preview: Preview = Preview.Builder() .setTargetAspectRatio(screenAspectRatio) - .setTargetRotation(previewView.display.rotation) + .setTargetRotation(binding.cameraView.display.rotation) .build() - preview.setSurfaceProvider(previewView.surfaceProvider) + preview.setSurfaceProvider(binding.cameraView.surfaceProvider) // Setup barcode scanner val imageAnalysis = ImageAnalysis.Builder() .setTargetAspectRatio(screenAspectRatio) - .setTargetRotation(previewView.display.rotation) + .setTargetRotation(binding.cameraView.display.rotation) .build() val cameraExecutor = Executors.newSingleThreadExecutor() val barcodeScanner: BarcodeScanner = BarcodeScanning.getClient() @@ -135,8 +134,8 @@ class BarcodeFragment : Fragment() { }, ContextCompat.getMainExecutor(requireActivity())) //workaround: can not use gms to scan the code in China, added a EditText to debug - manualCodeBtn?.setOnClickListener { - val qrCode = manualCodeEditText?.text.toString() + binding.manualCodeBtn.setOnClickListener { + val qrCode = binding.manualCodeEditText.text.toString() Log.d(TAG, "Submit Code:$qrCode") handleInputQrCode(qrCode) } diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceDetailsFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceDetailsFragment.kt index a36238db4ea939..8d14e2ca410343 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceDetailsFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceDetailsFragment.kt @@ -25,68 +25,65 @@ import android.view.ViewGroup import android.widget.TextView import androidx.fragment.app.Fragment import com.google.chip.chiptool.R +import com.google.chip.chiptool.databinding.ChipDeviceInfoFragmentBinding import com.google.chip.chiptool.util.FragmentUtil -import kotlinx.android.synthetic.main.chip_device_info_fragment.view.discoveryCapabilitiesTv -import kotlinx.android.synthetic.main.chip_device_info_fragment.view.discriminatorTv -import kotlinx.android.synthetic.main.chip_device_info_fragment.view.productIdTv -import kotlinx.android.synthetic.main.chip_device_info_fragment.view.setupCodeTv -import kotlinx.android.synthetic.main.chip_device_info_fragment.view.vendorIdTv -import kotlinx.android.synthetic.main.chip_device_info_fragment.view.vendorTagsContainer -import kotlinx.android.synthetic.main.chip_device_info_fragment.view.vendorTagsLabelTv -import kotlinx.android.synthetic.main.chip_device_info_fragment.view.versionTv -import kotlinx.android.synthetic.main.chip_device_info_fragment.view.commissioningFlowTv -import kotlinx.android.synthetic.main.chip_device_info_fragment.view.customFlowBtn /** Show the [CHIPDeviceInfo]. */ class CHIPDeviceDetailsFragment : Fragment() { - private lateinit var deviceInfo: CHIPDeviceInfo + private var _binding: ChipDeviceInfoFragmentBinding? = null + private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { + _binding = ChipDeviceInfoFragmentBinding.inflate(inflater, container, false) deviceInfo = checkNotNull(requireArguments().getParcelable(ARG_DEVICE_INFO)) - return inflater.inflate(R.layout.chip_device_info_fragment, container, false).apply { - - versionTv.text = "${deviceInfo.version}" - vendorIdTv.text = "${deviceInfo.vendorId}" - productIdTv.text = "${deviceInfo.productId}" - setupCodeTv.text = "${deviceInfo.setupPinCode}" - discriminatorTv.text = "${deviceInfo.discriminator}" - discoveryCapabilitiesTv.text = requireContext().getString( - R.string.chip_device_info_discovery_capabilities_text, - deviceInfo.discoveryCapabilities - ) + binding.versionTv.text = "${deviceInfo.version}" + binding.vendorIdTv.text = "${deviceInfo.vendorId}" + binding.productIdTv.text = "${deviceInfo.productId}" + binding.setupCodeTv.text = "${deviceInfo.setupPinCode}" + binding.discriminatorTv.text = "${deviceInfo.discriminator}" + binding.discoveryCapabilitiesTv.text = requireContext().getString( + R.string.chip_device_info_discovery_capabilities_text, + deviceInfo.discoveryCapabilities + ) - if (deviceInfo.optionalQrCodeInfoMap.isEmpty()) { - vendorTagsLabelTv.visibility = View.GONE - vendorTagsContainer.visibility = View.GONE - } else { - vendorTagsLabelTv.visibility = View.VISIBLE - vendorTagsContainer.visibility = View.VISIBLE + if (deviceInfo.optionalQrCodeInfoMap.isEmpty()) { + binding.vendorTagsLabelTv.visibility = View.GONE + binding.vendorTagsContainer.visibility = View.GONE + } else { + binding.vendorTagsLabelTv.visibility = View.VISIBLE + binding.vendorTagsContainer.visibility = View.VISIBLE - deviceInfo.optionalQrCodeInfoMap.forEach { (_, qrCodeInfo) -> - val tv = inflater.inflate(R.layout.barcode_vendor_tag, null, false) as TextView - val info = "${qrCodeInfo.tag}. ${qrCodeInfo.data}, ${qrCodeInfo.intDataValue}" - tv.text = info - vendorTagsContainer.addView(tv) - } + deviceInfo.optionalQrCodeInfoMap.forEach { (_, qrCodeInfo) -> + val tv = inflater.inflate(R.layout.barcode_vendor_tag, null, false) as TextView + val info = "${qrCodeInfo.tag}. ${qrCodeInfo.data}, ${qrCodeInfo.intDataValue}" + tv.text = info + binding.vendorTagsContainer.addView(tv) } + } - commissioningFlowTv.text = "${deviceInfo.commissioningFlow}" + binding.commissioningFlowTv.text = "${deviceInfo.commissioningFlow}" - // commissioningFlow = 2 (Custom), read device info from Ledger - if (deviceInfo.commissioningFlow == 2) { - customFlowBtn.visibility = View.VISIBLE - customFlowBtn.setOnClickListener { - FragmentUtil.getHost(this@CHIPDeviceDetailsFragment, Callback::class.java) - ?.handleReadFromLedgerClicked(deviceInfo) - } + // commissioningFlow = 2 (Custom), read device info from Ledger + if (deviceInfo.commissioningFlow == 2) { + binding.customFlowBtn.visibility = View.VISIBLE + binding.customFlowBtn.setOnClickListener { + FragmentUtil.getHost(this@CHIPDeviceDetailsFragment, Callback::class.java) + ?.handleReadFromLedgerClicked(deviceInfo) } } + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null } /** Interface for notifying the host. */ diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceInfo.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceInfo.kt index 67603917aabef5..6e011110aa5903 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceInfo.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceInfo.kt @@ -21,7 +21,7 @@ package com.google.chip.chiptool.setuppayloadscanner import android.os.Parcelable import chip.setuppayload.DiscoveryCapability import chip.setuppayload.SetupPayload -import kotlinx.android.parcel.Parcelize +import kotlinx.parcelize.Parcelize /** Class to hold the CHIP device information. */ @Parcelize diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPLedgerDetailsFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPLedgerDetailsFragment.kt index ed8edcbc31b0ad..496017bb15218c 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPLedgerDetailsFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPLedgerDetailsFragment.kt @@ -30,79 +30,81 @@ import com.android.volley.Request import com.android.volley.toolbox.JsonObjectRequest import com.android.volley.toolbox.Volley import com.google.chip.chiptool.R +import com.google.chip.chiptool.databinding.ChipLedgerInfoFragmentBinding import com.google.chip.chiptool.util.FragmentUtil import com.google.gson.Gson -import kotlinx.android.synthetic.main.chip_ledger_info_fragment.view.vendorIdTv -import kotlinx.android.synthetic.main.chip_ledger_info_fragment.view.productIdTv -import kotlinx.android.synthetic.main.chip_ledger_info_fragment.view.commissioningFlowUrlTv -import kotlinx.android.synthetic.main.chip_ledger_info_fragment.view.redirectBtn /** Show the [CHIPDeviceInfo] from Ledger */ class CHIPLedgerDetailsFragment : Fragment() { - private lateinit var deviceInfo: CHIPDeviceInfo + private var _binding: ChipLedgerInfoFragmentBinding? = null + private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - + _binding = ChipLedgerInfoFragmentBinding.inflate(inflater, container, false) deviceInfo = checkNotNull(requireArguments().getParcelable(ARG_DEVICE_INFO)) val queue = Volley.newRequestQueue(context) - return inflater.inflate(R.layout.chip_ledger_info_fragment, container, false).apply { - - // VID / PID - vendorIdTv.text = "${deviceInfo.vendorId}" - productIdTv.text = "${deviceInfo.productId}" - - // Ledger api url - val url = Uri.parse(context.getString(R.string.dcl_api_root_url)) - .buildUpon() - .appendPath("${deviceInfo.vendorId}") - .appendPath("${deviceInfo.productId}") - .build().toString() - Log.d(TAG, "Dcl request Url: $url") - - // Ledger API call - val jsonObjectRequest = JsonObjectRequest( - Request.Method.GET, url, null, - { response -> - Log.d(TAG, "Response from dcl $response") - - // parse redirect Url - val responseJson = response.getJSONObject(context.getString(R.string.dcl_response_key)) - val redirectUrl = responseJson.getString(context.getString(R.string.dcl_custom_flow_url_key)) - Log.d(TAG, "Redirect Url from Ledger: $redirectUrl") - commissioningFlowUrlTv.text = redirectUrl + // VID / PID + binding.vendorIdTv.text = "${deviceInfo.vendorId}" + binding.productIdTv.text = "${deviceInfo.productId}" + + // Ledger api url + val url = Uri.parse(context!!.getString(R.string.dcl_api_root_url)) + .buildUpon() + .appendPath("${deviceInfo.vendorId}") + .appendPath("${deviceInfo.productId}") + .build().toString() + Log.d(TAG, "Dcl request Url: $url") + + // Ledger API call + val jsonObjectRequest = JsonObjectRequest( + Request.Method.GET, url, null, + { response -> + Log.d(TAG, "Response from dcl $response") + + // parse redirect Url + val responseJson = response.getJSONObject(context!!.getString(R.string.dcl_response_key)) + val redirectUrl = responseJson.getString(context!!.getString(R.string.dcl_custom_flow_url_key)) + Log.d(TAG, "Redirect Url from Ledger: $redirectUrl") + binding.commissioningFlowUrlTv.text = redirectUrl + + // generate redirect payload + val gson = Gson() + val payloadJson = gson.toJson(deviceInfo) + val payloadBase64 = Base64.encodeToString(payloadJson.toByteArray(), Base64.DEFAULT) + val redirectUrlWithPayload= Uri.parse(redirectUrl) + .buildUpon() + .appendQueryParameter("payload", payloadBase64) + .appendQueryParameter("returnUrl", context!!.getString(R.string.custom_flow_return_url)) + .build() + .toString() + + Log.d(TAG, "Redirect Url with Payload: $redirectUrlWithPayload") + binding.redirectBtn.setOnClickListener { + FragmentUtil.getHost(this@CHIPLedgerDetailsFragment, Callback::class.java) + ?.handleCustomFlowRedirectClicked(redirectUrlWithPayload) + } - // generate redirect payload - val gson = Gson() - val payloadJson = gson.toJson(deviceInfo) - val payloadBase64 = Base64.encodeToString(payloadJson.toByteArray(), Base64.DEFAULT) - val redirectUrlWithPayload= Uri.parse(redirectUrl) - .buildUpon() - .appendQueryParameter("payload", payloadBase64) - .appendQueryParameter("returnUrl", context.getString(R.string.custom_flow_return_url)) - .build() - .toString() + // enable redirect button + binding.redirectBtn.visibility = View.VISIBLE + }, + { error -> + Log.e(TAG, "Dcl request failed: $error") + binding.commissioningFlowUrlTv.text = context!!.getString(R.string.chip_ledger_info_commissioning_flow_url_not_available) + } + ) + queue.add(jsonObjectRequest) - Log.d(TAG, "Redirect Url with Payload: $redirectUrlWithPayload") - redirectBtn.setOnClickListener { - FragmentUtil.getHost(this@CHIPLedgerDetailsFragment, Callback::class.java) - ?.handleCustomFlowRedirectClicked(redirectUrlWithPayload) - } + return binding.root + } - // enable redirect button - redirectBtn.visibility = View.VISIBLE - }, - { error -> - Log.e(TAG, "Dcl request failed: $error") - commissioningFlowUrlTv.text = context.getString(R.string.chip_ledger_info_commissioning_flow_url_not_available) - } - ) - queue.add(jsonObjectRequest) - } + override fun onDestroyView() { + super.onDestroyView() + _binding = null } /** Interface for notifying the host. */ diff --git a/examples/android/CHIPTool/app/src/main/res/layout/barcode_fragment.xml b/examples/android/CHIPTool/app/src/main/res/layout/barcode_fragment.xml index b8a23d960c75f3..531a7477a4c705 100644 --- a/examples/android/CHIPTool/app/src/main/res/layout/barcode_fragment.xml +++ b/examples/android/CHIPTool/app/src/main/res/layout/barcode_fragment.xml @@ -5,7 +5,7 @@ android:orientation="vertical"> @@ -43,7 +43,7 @@ android:inputType="text" android:padding="8dp" android:text="MT:YNJV7VSC00KA0648G00" - app:layout_constraintTop_toBottomOf="@id/camera_view" + app:layout_constraintTop_toBottomOf="@id/cameraView" app:layout_constraintEnd_toStartOf="@id/manualCodeBtn" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" />