2 * Copyright (c) 2020 Project CHIP Authors
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package com.google.chip.chiptool
20 import android.content.Intent
21 import android.nfc.NdefMessage
22 import android.nfc.NfcAdapter
23 import android.os.Bundle
24 import androidx.appcompat.app.AlertDialog
25 import androidx.appcompat.app.AppCompatActivity
26 import androidx.fragment.app.Fragment
27 import chip.setuppayload.SetupPayloadParser
28 import com.google.chip.chiptool.attestation.AttestationTestFragment
29 import com.google.chip.chiptool.clusterclient.OnOffClientFragment
30 import com.google.chip.chiptool.commissioner.CommissionerActivity
31 import com.google.chip.chiptool.echoclient.EchoClientFragment
32 import com.google.chip.chiptool.provisioning.DeviceProvisioningFragment
33 import com.google.chip.chiptool.provisioning.ProvisionNetworkType
34 import com.google.chip.chiptool.setuppayloadscanner.BarcodeFragment
35 import com.google.chip.chiptool.setuppayloadscanner.CHIPDeviceDetailsFragment
36 import com.google.chip.chiptool.setuppayloadscanner.CHIPDeviceInfo
37 import com.google.chip.chiptool.setuppayloadscanner.QrCodeInfo
38 import chip.devicecontroller.PersistentStorage
40 class CHIPToolActivity :
42 BarcodeFragment.Callback,
43 SelectActionFragment.Callback,
44 DeviceProvisioningFragment.Callback {
46 private var networkType: ProvisionNetworkType? = null
48 override fun onCreate(savedInstanceState: Bundle?) {
49 super.onCreate(savedInstanceState)
50 setContentView(R.layout.top_activity)
52 PersistentStorage.initialize(this);
54 if (savedInstanceState == null) {
55 val fragment = SelectActionFragment.newInstance()
56 supportFragmentManager
58 .add(R.id.fragment_container, fragment, fragment.javaClass.simpleName)
62 ProvisionNetworkType.fromName(savedInstanceState.getString(ARG_PROVISION_NETWORK_TYPE))
65 if (intent?.action == NfcAdapter.ACTION_NDEF_DISCOVERED)
69 override fun onSaveInstanceState(outState: Bundle) {
70 outState.putString(ARG_PROVISION_NETWORK_TYPE, networkType?.name)
72 super.onSaveInstanceState(outState)
75 override fun onCHIPDeviceInfoReceived(deviceInfo: CHIPDeviceInfo) {
76 if (networkType == null) {
77 showFragment(CHIPDeviceDetailsFragment.newInstance(deviceInfo))
79 showFragment(DeviceProvisioningFragment.newInstance(deviceInfo, networkType!!), false)
83 override fun onPairingComplete() {
84 showFragment(OnOffClientFragment.newInstance(), false)
87 override fun handleScanQrCodeClicked() {
88 showFragment(BarcodeFragment.newInstance())
91 override fun onProvisionWifiCredentialsClicked() {
92 networkType = ProvisionNetworkType.WIFI
93 showFragment(BarcodeFragment.newInstance(), false)
96 override fun onProvisionThreadCredentialsClicked() {
97 networkType = ProvisionNetworkType.THREAD
98 showFragment(BarcodeFragment.newInstance(), false)
101 override fun handleCommissioningClicked() {
102 var intent = Intent(this, CommissionerActivity::class.java)
103 startActivityForResult(intent, REQUEST_CODE_COMMISSIONING)
106 override fun handleEchoClientClicked() {
107 showFragment(EchoClientFragment.newInstance())
110 override fun handleOnOffClicked() {
111 showFragment(OnOffClientFragment.newInstance())
114 override fun handleAttestationTestClicked() {
115 showFragment(AttestationTestFragment.newInstance())
118 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
119 super.onActivityResult(requestCode, resultCode, data)
121 if (requestCode == REQUEST_CODE_COMMISSIONING) {
122 // Simply ignore the commissioning result.
123 // TODO: tracking commissioned devices.
127 private fun showFragment(fragment: Fragment, showOnBack: Boolean = true) {
128 val fragmentTransaction = supportFragmentManager
130 .replace(R.id.fragment_container, fragment, fragment.javaClass.simpleName)
133 fragmentTransaction.addToBackStack(null)
136 fragmentTransaction.commit()
139 private fun onNfcIntent(intent: Intent?) {
140 // Require 1 NDEF message containing 1 NDEF record
141 val messages = intent?.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
142 if (messages?.size != 1) return
144 val records = (messages[0] as NdefMessage).records
145 if (records.size != 1) return
147 // Require NDEF URI record starting with "ch:"
148 val uri = records[0].toUri()
149 if (!uri?.scheme.equals("ch", true)) return
151 // TODO: Issue #4504 - Remove replacing _ with spaces after problem described in #415 will be fixed.
152 val setupPayload = SetupPayloadParser().parseQrCode(uri.toString().toUpperCase().replace('_', ' '))
153 val deviceInfo = CHIPDeviceInfo(
154 setupPayload.version,
155 setupPayload.vendorId,
156 setupPayload.productId,
157 setupPayload.discriminator,
158 setupPayload.setupPinCode,
159 setupPayload.optionalQRCodeInfo.mapValues { (_, info) -> QrCodeInfo(info.tag, info.type, info.data, info.int32) }
162 val buttons = arrayOf(
163 getString(R.string.nfc_tag_action_show),
164 getString(R.string.nfc_tag_action_wifi),
165 getString(R.string.nfc_tag_action_thread))
167 AlertDialog.Builder(this)
168 .setTitle(R.string.nfc_tag_action_title)
169 .setItems(buttons) { _, which ->
170 this.networkType = when (which) {
171 1 -> ProvisionNetworkType.WIFI
172 2 -> ProvisionNetworkType.THREAD
175 onCHIPDeviceInfoReceived(deviceInfo)
182 private const val ARG_PROVISION_NETWORK_TYPE = "provision_network_type"
184 var REQUEST_CODE_COMMISSIONING = 0xB003