1. 환영합니다
IoT 표준 통합을 목표로 빌드된 Matter는 Google Home, Zigbee, 블루투스 메시, Z-Wave 등 다양한 생태계의 스마트 홈 기기를 연결합니다.
휴대기기는 스마트 홈 기기와의 중심 상호작용 지점입니다. Matter 기기를 지원하는 자체 Android 앱을 빌드하려는 경우 빠르게 시작할 수 있도록 Google의 도움을 받을 수 있습니다.
Matter용 Google Home 샘플 앱 (Matter용 GHSA)에서는 사용자가 기기를 커미셔닝하고 공유할 수 있는 Home Mobile SDK API를 보여줍니다. 또한 샘플 앱을 학습 도구로 사용하여 주요 Matter 개념을 더 잘 이해할 수 있을 뿐만 아니라 Matter 기기와의 상호작용을 디버그하고 문제를 해결하는 도구로도 활용할 수 있습니다.
실습할 내용
이 Codelab에서는 샘플 앱의 소스 코드를 다운로드하고 Home Mobile SDK를 사용하여 기기를 커미셔닝하고 공유하는 방법을 알아봅니다. Matter 저장소 (connectedhomeip
)에서 커미셔닝 및 클러스터 라이브러리를 사용하는 방법도 알아봅니다.
샘플 앱을 다운로드하면 Google에서 Android 스튜디오의 소스 코드를 검토하고 다음 Home Mobile SDK API를 구현합니다.
커미셔닝 개념, Matter 패브릭, Matter 기기 제어 방법도 자세히 알아봅니다.
필요한 항목
시작하기 전에 다음 단계를 완료해야 합니다.
- Matter용 Google Home 샘플 앱 가이드를 검토합니다.
- Android 스튜디오를 다운로드합니다.
- 테스트에 사용할 수 있는 Android O (8.1, API 수준 27) 이상의 기기가 있어야 합니다. 기기에 최신 Matter 지원이 있는지 확인하려면 Matter 모듈 확인 및 서비스 가이드를 참조하세요.
- 사용/사용 중지 기능이 있는 Matter 기기를 사용합니다. 환경 문제를 최소화하려면 처음부터 Matter 가상 기기 (MVD)를 사용하는 것이 좋습니다. 문제가 발생하는 경우 샘플 앱이 MVD에 사용되는지 여부를 훨씬 쉽게 조사할 수 있습니다. 다음은 몇 가지 다른 옵션입니다.
rootnode_dimmablelight_bCwGYSDpoe
앱으로 Matter 가상 기기를 빌드합니다. 홈 Play Console에서 Matter 통합을 생성할 때0xFFF1
를 공급업체 ID로,0x8000
를 제품 ID로 사용합니다.all-clusters-app
를 사용하여 Espressif 기기를 빌드합니다. 홈 Play Console에서 Matter 통합을 생성할 때0xFFF1
를 공급업체 ID로,0x8001
를 제품 ID로 사용합니다.
- Google Play 서비스를 설정하는 방법을 검토하세요.
샘플 앱으로 기기를 커미셔닝하고 제어하기 위해서는 허브(예: Google Nest Hub(2세대))가 필요하지 않습니다.
2. 설정
Codelab 시작 앱은 codelab
브랜치에 있습니다. Codelab 소스 코드로 작업을 시작하려면 ZIP 파일을 다운로드하면 됩니다.
이 codelab
ZIP 파일을 사용하여 작동하는 샘플을 빌드합니다.
Codelab 버전
codelab
브랜치는 샘플 앱의 2.0.0 버전으로 태그가 지정됩니다. 각 단계를 진행하면서 업데이트를 비교하려면 이 버전의 완성된 소스 코드를 다운로드하세요.
GitHub 저장소를 클론하려면 샘플 앱 리드미의 안내를 따르세요.
종속 항목
기기를 공유하고 커미셔닝하는 데 필요한 소스 코드를 안내해 드리겠지만 시작하기 전에 다음 종속 항목을 알아두면 도움이 될 수 있습니다. 이러한 종속 항목은 libs.versions.toml 파일에서 선언되고 용도는 build.gradle.kts 파일에 지정되어 있습니다.
- Home 모바일 SDK
- Matter SDK 라이브러리.
- Jetpack Compose. UI는 Compose를 사용하여 완전히 구현됩니다.
- 머티리얼 디자인. 자세한 내용은 MDC-103 Android: 색상, 고도, 유형을 사용한 Material Theming (Kotlin) 및 Material Theme Builder를 참고하세요.
- Proto DataStore: 앱 데이터를 유지하는 데 사용됩니다. Datastore 저장소 및 Serializer는 기기 및 사용자 환경설정의 스키마를 포함하여
java/data
에 저장됩니다. DataStore에 관한 자세한 내용은 Proto DataStore 작업을 참고하세요. - Hilt: 데이터를 유지하고 종속 항목 삽입을 지원합니다.
소스 코드
사용자 인터페이스와 대부분의 기능이 이미 마련되어 있습니다.
이 Codelab에서는 다음 파일에 Matter 기능을 추가합니다.
java/com/google/homesampleapp/commissioning/AppCommissioningService
: 개발 패브릭에 기기를 커미셔닝할 수 있습니다.java/com/google/homesampleapp/screens/home/HomeScreen
및java/com/google/homesampleapp/screens/home/HomeViewModel.kt
: Home Mobile SDK 커미셔닝 기능 포함java/com/google/homesampleapp/screens/device/DeviceScreen
및java/com/google/homesampleapp/screens/device/DeviceViewModel
: Share Device API 호출을 포함합니다.
각 파일은 수정할 코드 블록으로 주석 처리됩니다. 예를 들면 다음과 같습니다.
// CODELAB: add commissioningFunction()
이렇게 하면 Codelab에서 해당하는 섹션을 빠르게 찾을 수 있습니다.
3. Google에 수수료
기기를 제어하고 동일한 패브릭 내에서 서로 통신할 수 있도록 하려면 먼저 커미셔닝을 의뢰해야 합니다. 이 경우에는 샘플 애플리케이션인 Matter용 Google Home 샘플 앱입니다.
Matter 커미셔닝에 관한 다음 개념을 이해하는 것이 중요합니다.
- 패브릭을 사용하면 기기가 서로 통신할 수 있습니다.
- 패브릭은 고유한 사용자 인증 정보의 공유 세트를 유지합니다.
- 생태계는 신뢰할 수 있는 루트 인증서를 발급하고, 패브릭 ID를 할당하고, 고유한 노드 ID를 할당하는 일을 담당합니다. 생태계는 위탁자의 백엔드 서비스입니다(예: Google Home 생태계의 경우 Home Graph).
- 기기는 두 개 이상의 패브릭에 커미셔닝될 수 있습니다 (다중 관리자 기능).
기기를 커미셔닝하려면 CommissioningClient API를 사용해야 합니다. .commissionDevice()
를 호출하면 Google Play 서비스에서 적절한 활동을 실행하는 IntentSender가 반환됩니다.
interface CommissioningClient { Task<IntentSender> commissionDevice(CommissioningRequest request); }
다음 섹션에서는 기기를 Google 패브릭에 커미셔닝하는 데 필요한 최소한의 코드를 살펴봅니다.
1단계: 활동 런처
CommissioningClient
에서 IntentSender
를 처리하려면 ActivityResultLauncher를 사용하면 됩니다.
val commissioningLauncher = registerForActivityResult( StartIntentSenderForResult() ) { result: ActivityResult -> if (result.resultCode == RESULT_OK) { Timber.d(TAG, "Commissioning succeeded.") } else { Timber.d(TAG, "Commissioning failed. " + result.resultCode) } }
2단계: 커미셔닝 함수
다음은 CommissioningClient API를 사용하여 기기를 Google 패브릭에 커미셔닝하는 기본 예입니다.
- 커미셔닝 프로세스는
commissionDevice()
함수로 시작합니다. 먼저CommissioningRequest
를 정의합니다. 이 기본 구성을 사용하면 기기는 로컬 Android 패브릭에만 커미셔닝됩니다. Matter
는 Home Mobile SDK의 진입점입니다. 다음 호출에서.getCommissioningClient
는this
(활동)의 CommissioningClient를 가져옵니다..commissionDevice()
는CommissioningRequest
을 허용합니다.- 마지막으로
.addOnSuccessListener
는CommissioningResult
를 처리하고 Google Play 서비스 (GPS) 커미션 기기 활동을 시작하기 위해 호출됩니다.
private fun commissionDevice() { val request: CommissioningRequest = CommissioningRequest.builder().build() Matter.getCommissioningClient(this) .commissionDevice(request) .addOnSuccessListener { result -> commissioningLauncher.launch(IntentSenderRequest.Builder(result).build()) } }
Android 설정을 통해 로컬 Android Fabric을 활용하여 기기를 다른 패브릭에 커미셔닝하는 프로세스를 간소화할 수 있습니다.
이제 기기를 개발 패브릭에 커미셔닝하는 방법을 알아봅니다.
커미셔닝 프로세스 중 사용자 인터페이스에 관한 개요는 Matter용 Google Home 샘플 앱 가이드를 참고하세요.
4. 개발 패브릭에 대한 수수료
기기는 두 개 이상의 패브릭에 의뢰할 수 있습니다. 신뢰할 수 있는 페어링을 관리하기 위해 기기는 다양한 FabricInfo
멤버가 포함된 FabricTable
를 저장합니다. 예를 들면 다음과 같습니다.
- 패브릭 식별
- 패브릭에서 기기에 할당한 노드 ID
- 공급업체 ID
- Fabric ID
- 기기 작동 사용자 인증 정보
관리 도메인 관리자 (ADM)는 패브릭 크리덴셜을 정의합니다. 이전 시나리오에서 Google Play 서비스는 신뢰할 수 있는 루트 인증 기관 (CA) 역할을 하는 생태계입니다. 기기를 로컬 Android 패브릭에 커미셔닝하면 모든 기기에는 동일한 패브릭 사용자 인증 정보 세트와 동일한 CA 세트가 포함됩니다.
맞춤형 커미셔닝 서비스
로컬 Android 패브릭에 커미셔닝하기 위해 기본 매개변수를 사용하여 CommissioningClient API에서 CommissioningRequest
를 빌드했습니다.
val request: CommissioningRequest = CommissioningRequest.builder().build()
앱에서 새 기기를 제어하고 관리하려면 로컬 개발 패브릭을 만들고 기기를 커미셔닝하기 위한 작업용 사용자 인증 정보를 가져와야 합니다. 이 시나리오에서 앱은 기기에 적절한 노드 사용자 인증 정보를 할당하는 고유하고 독립적인 생태계가 됩니다.
CommissioningRequest에 맞춤 서비스를 전달하여 자체 패브릭에 기기를 커미셔닝하고 싶다고 Home Mobile SDK에 알릴 수 있습니다.
class CommissioningRequest { static CommissioningRequest.Builder builder(); class Builder { Builder setCommissioningService(@Nullable ComponentName commissioningService); CommissioningRequest build(); } }
다음 단계에서는 커스텀 서비스를 사용하도록 commissionDevice()
함수를 수정합니다. 또한 홈 프래그먼트에 활동 런처를 추가하고 LiveData 객체를 사용하여 API 흐름을 관리합니다.
1단계: GPS 활동 런처 만들기
먼저 CommissioningClient API에서 IntentSender
를 처리할 활동 런처를 만들어 보겠습니다.
java/com/google/homesampleapp/screens/home/
폴더에서HomeScreen
를 엽니다.- 커미셔닝 활동 결과를 등록하고 처리하도록
// CODELAB: commissionDeviceLauncher definition
주석을 다음 코드로 바꿉니다.val commissionDeviceLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.StartIntentSenderForResult() ) { result -> // Commission Device Step 5. // The Commission Device activity in GPS (step 4) has completed. val resultCode = result.resultCode if (resultCode == Activity.RESULT_OK) { Timber.d("CommissionDevice: Success") // We let the ViewModel know that GPS commissioning has completed successfully. // The ViewModel knows that we still need to capture the device name and will\ // update UI state to trigger the NewDeviceAlertDialog. homeViewModel.gpsCommissioningDeviceSucceeded(result) } else { homeViewModel.commissionDeviceFailed(resultCode) } }
2단계: 수수료 기기 작업 트리거
이 단계에서는 사용자가 '수수료 기기'를 트리거합니다. '+' 버튼을 클릭하여 버튼을 클릭합니다. 그런 다음 commissionDevice()
가 호출됩니다.
val onCommissionDevice = { ... commissionDevice(activity!!.applicationContext, commissionDeviceLauncher) }
3단계: API 호출
- 아직
java/com/google/homesampleapp/screens/home
폴더의HomeScreen.kt
에 있습니다. // CODELAB: commissionDevice
주석을 다음commissionDeviceRequest
로 바꿉니다.setCommissioningService
는AppCommissioningService
를 콜백 함수에 반환된CommissioningService
인스턴스에 바인딩합니다. 맞춤 서비스를 전달하면 Home Mobile SDK가 먼저 기기를 Android 로컬 패브릭에 커미셔닝한 다음 온보딩 페이로드를 다시AppCommissioningService
로 전송합니다.val commissionDeviceRequest = CommissioningRequest.builder() .setCommissioningService(ComponentName( context, AppCommissioningService::class.java)) .build()
.getCommissioningClient()
를 호출한 다음.commissionDevice()
를 호출합니다.
Matter.getCommissioningClient(context) .commissionDevice(commissionDeviceRequest)
commissionDevice
함수를 완료하려면 addOnSuccessListener
및 addOnFailureListener
를 추가합니다.
.addOnSuccessListener { result -> commissionDeviceLauncher.launch(IntentSenderRequest.Builder(result).build()) } .addOnFailureListener { error -> Timber.e(error) }
5. 커미셔닝 서비스 만들기
commissionDevice()
함수에서 CommissioningClient API로부터 CommissioningService를 가져오도록 요청했습니다. 이 흐름에서 CommissioningClient API는 먼저 기기를 로컬 Android 패브릭에 커미셔닝한 다음 CommissioningRequestMetadata 객체가 포함된 콜백을 반환합니다.
public interface CommissioningService { interface Callback { void onCommissioningRequested(CommissioningRequestMetadata metadata); } }
이제 CommissioningService.Callback을 상속하고 기기를 샘플 앱에 커미셔닝하는 데 필요한 기능을 제공해야 합니다. 다음은 기본적인 CommissioningService 구현의 예입니다.
class MatterCommissioningService : Service(), CommissioningService.Callback { private val commissioningServiceDelegate = CommissioningService.Builder(this) .setCallback(this) .build() override fun onBind(intent: Intent) = commissioningServiceDelegate.asBinder() override fun onCommissioningRequested(metadata: CommissioningRequestMetadata) { // perform commissioning commissioningServiceDelegate .sendCommissioningComplete(CommissioningCompleteMetadata.builder().build()) } }
1단계: 커스텀 AppCommissioningService 살펴보기
시작하는 데 도움이 되도록 이미 맞춤 CommissioningService의 기본 클래스 구조를 정의했습니다. 다음은 서비스 기능에 대한 간략한 개요입니다. 팔로우하려면 java/commissioning
에서 AppCommissioningService
앱을 여세요.
Home Mobile SDK API에 다음과 같은 가져오기가 추가되었습니다.
import com.google.android.gms.home.matter.commissioning.CommissioningCompleteMetadata import com.google.android.gms.home.matter.commissioning.CommissioningRequestMetadata import com.google.android.gms.home.matter.commissioning.CommissioningService
AppCommissioningService
에는 Matter 저장소 (connectedhomeip
)의 라이브러리도 포함됩니다.
import com.google.homesampleapp.chip.ChipClient
마지막으로 서비스에는 Hilt 및 Kotlin 코루틴을 지원하는 가져오기가 포함되어 있습니다.
다음으로, 생성자를 만들고 commissioningServiceDelegate
를 비롯한 몇 가지 항목을 설정합니다. 이는 커미셔닝이 완료되면 Google Play 서비스에 알리는 데 사용됩니다.
private lateinit var commissioningServiceDelegate: CommissioningService ... commissioningServiceDelegate = CommissioningService.Builder(this).setCallback(this).build()
이제 커미셔닝 함수를 추가할 차례입니다.
2단계: onCommissioningRequested 재정의
앱의 개발 패브릭에 기기를 커미셔닝하려면 다음 단계를 완료하세요.
java/commissioning
에서AppCommissioningService
열기onCommissioningRequested()
함수를 찾습니다.CommissioningRequestMetadata
를 출력하는 로그 메시지를 제공했습니다.// CODELAB: onCommissioningRequested()
주석을 대체하여serviceScope
코루틴을 시작하고deviceId
를 가져옵니다.// Perform commissioning on custom fabric for the sample app. serviceScope.launch { val deviceId = devicesRepository.incrementAndReturnLastDeviceId()
- 커미셔닝 실행 이 단계에서는 CommissioningRequestMetadata 객체에 반환된 기기 정보를 전달할 수 있습니다.
ChipClient
에서는 이 메타데이터 정보를 사용하여 Matter용 GHSA 앱과 기기 간에 보안 채널을 만듭니다.try { Timber.d( "Commissioning: App fabric -> ChipClient.establishPaseConnection(): deviceId [${deviceId}]") chipClient.awaitEstablishPaseConnection( deviceId, metadata.networkLocation.ipAddress.hostAddress!!, metadata.networkLocation.port, metadata.passcode) Timber.d( "Commissioning: App fabric -> ChipClient.commissionDevice(): deviceId [${deviceId}]") chipClient.awaitCommissionDevice(deviceId, null) } catch (e: Exception) { Timber.e(e, "onCommissioningRequested() failed") // No way to determine whether this was ATTESTATION_FAILED or DEVICE_UNREACHABLE. commissioningServiceDelegate .sendCommissioningError(CommissioningError.OTHER) .addOnSuccessListener { Timber.d( "Commissioning: commissioningServiceDelegate.sendCommissioningError() succeeded") } .addOnFailureListener { e2 -> Timber.e(e2, "Commissioning: commissioningServiceDelegate.sendCommissioningError() failed") } return@launch }
commissioningServiceDelegate
를 사용하여 Google Play 서비스에 커미셔닝이 완료되었음을 알립니다..sendCommissioningComplete()
에서 CommissioningCompleteMetadata를 전달합니다.commissioningServiceDelegate .sendCommissioningComplete( CommissioningCompleteMetadata.builder().setToken(deviceId.toString()).build()) .addOnSuccessListener { Timber.d("Commissioning: commissioningServiceDelegate.sendCommissioningComplete() succeeded") } .addOnFailureListener { e -> Timber.e(e, "Commissioning: commissioningServiceDelegate.sendCommissioningComplete() failed") } }
앱 실행
이제 필요한 모든 코드를 로컬 패브릭에 커미셔닝할 준비가 되었으므로 테스트할 차례입니다. Android 기기를 선택하고 앱을 실행합니다. 홈 화면에서 기기 추가를 탭하고 기기를 커미셔닝하는 단계를 완료합니다.
커미셔닝이 완료되면 기기가 이제 두 가지 패브릭, 즉 로컬 Android 패브릭과 로컬 개발 패브릭에 참여합니다. 각 패브릭에는 고유한 사용자 인증 정보 세트와 고유한 64비트 패브릭 ID가 있습니다.
6. 기기 제어
개발 패브릭에 커미셔닝하면 Matter 저장소 (connectedhomeip
)의 라이브러리를 사용하여 샘플 앱에서 기기를 제어할 수 있습니다.
기기 클러스터에 더 쉽게 액세스하고 명령어를 전송할 수 있도록 도우미 클래스를 만들었습니다. 자세히 알아보려면 java/clusters
에서 ClustersHelper
앱을 여세요. 이 싱글톤 도우미는 다음 라이브러리를 가져와 기기 정보에 액세스합니다.
import chip.devicecontroller.ChipClusters import chip.devicecontroller.ChipStructs
이 클래스를 사용하여 기기의 On/Off 클러스터를 가져온 다음 .toggle
를 호출할 수 있습니다.
suspend fun toggleDeviceStateOnOffCluster(deviceId: Long, endpoint: Int) { Timber.d("toggleDeviceStateOnOffCluster())") val connectedDevicePtr = try { chipClient.getConnectedDevicePointer(deviceId) } catch (e: IllegalStateException) { Timber.e("Can't get connectedDevicePointer.") return } return suspendCoroutine { continuation -> getOnOffClusterForDevice(connectedDevicePtr, endpoint) .toggle( object : ChipClusters.DefaultClusterCallback { override fun onSuccess() { continuation.resume(Unit) } override fun onError(ex: Exception) { Timber.e("readOnOffAttribute command failure: $ex") continuation.resumeWithException(ex) } }) } }
기기 전환
기기를 커미셔닝하면 CommissioningResult에서 반환된 페이로드가 DataStore에 추가됩니다. 이렇게 하면 앱이 명령어를 보내는 데 사용할 수 있는 기기 정보에 액세스할 수 있습니다.
Matter 앱은 이벤트 기반입니다. Matter 스택이 초기화되면 클러스터 서비스가 수신 메시지를 리슨합니다. 기기가 커미셔닝되면 Matter 클라이언트는 기기 커미셔닝 중에 설정된 보안 운영 채널을 통해 명령어를 전송합니다.
디바이스에서는 패킷이 검증되고 복호화된 후 콜백을 사용하여 전달됩니다. 콜백 함수에는 attributePath
에서 액세스할 수 있는 EndpointId, ClusterId, AttributeId가 포함됩니다. 예를 들어 Matter 기기에 다음 코드를 구현할 수 있습니다.
void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t mask, uint8_t type, uint16_t size, uint8_t * value) { // handle callback ClusterId clusterId = attributePath.mClusterId; AttributeId attributeId = attributePath.mAttributeId; }
다음 단계에서는 Matter SDK와 ClustersHelper
를 사용하여 기기를 전환합니다.
java/screens/device
의DeviceViewModel
페이지로 이동합니다.updateDeviceStateOn
함수를 찾습니다.// CODELAB: toggle
주석을clustersHelper
를 호출하는 코드로 바꾸고 기기 저장소를 업데이트합니다.Timber.d("Handling real device") try { clustersHelper.setOnOffDeviceStateOnOffCluster(deviceUiModel.device.deviceId, isOn, 1) devicesStateRepository.updateDeviceState(deviceUiModel.device.deviceId, true, isOn) } catch (e: Throwable) { Timber.e("Failed setting on/off state") }
이 함수는 DeviceScreen
에서 호출됩니다.
// On/Off Switch click. val onOnOffClick: (value: Boolean) -> Unit = { value -> deviceViewModel.updateDeviceStateOn(deviceUiModel!!, value) }
앱 실행
앱을 실행하여 업데이트를 새로고침합니다. 홈 화면에서 기기를 켜거나 끕니다.
7. 다른 생태계와 기기 공유
Matter 사양에서는 기기 공유를 다중 관리자 흐름이라고 합니다.
이전 단계에서는 Home Mobile SDK를 통해 로컬 Android 패브릭과 샘플 앱의 개발 패브릭에 기기를 커미셔닝할 수 있음을 확인했습니다. 이것은 기기를 둘 이상의 패브릭에 커미셔닝할 수 있는 다중 관리자 흐름의 예입니다.
이제는 더 많은 패브릭을 사용해 기기를 공유하고 싶을 수 있습니다. 특히 애플리케이션과 플랫폼과 관련해 사람들이 각자 선호하는 제품이 있는 가정이라면 더욱 그렇습니다.
Home Mobile SDK는 ShareDeviceRequest API에서 이 기능을 제공하여 다음을 할 수 있습니다.
- 기기의 임시 커미셔닝 창을 엽니다.
- 다른 패브릭에 커미셔닝할 수 있도록 기기의 상태를 변경합니다.
- 다른 앱과 생태계에서 기기를 제어하세요.
다음 단계에서는 Home Mobile SDK를 사용하여 기기를 공유합니다.
1단계: GPS 활동 런처 만들기
개발 패브릭에 커미셔닝할 때 만든 커미셔닝 활동 런처와 유사하게 커미셔닝Client API의 IntentSender
를 처리하기 위한 공유 기기 활동 런처를 만들었습니다.
java/com/google/homesampleapp/screens/device/
폴더에서DeviceScreen
를 엽니다.// CODELAB: shareDeviceLauncher definition
주석을 다음 코드로 바꿔.shareDevice()
활동 결과를 등록하고 처리합니다.val shareDeviceLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.StartIntentSenderForResult() ) { result -> // Commission Device Step 5. // The Share Device activity in GPS (step 4) has completed. val resultCode = result.resultCode if (resultCode == Activity.RESULT_OK) { deviceViewModel.shareDeviceSucceeded() } else { deviceViewModel.shareDeviceFailed(resultCode) } }
2단계: 기기 공유 작업 트리거
이 단계에서는 사용자가 '기기 공유'를 트리거합니다. '공유'를 클릭하여 버튼을 누릅니다. 그런 다음 deviceViewModel
가 호출되어 기기 공유를 위한 페어링 창이 열립니다.
// Share Device button click. val onShareDevice: () -> Unit = remember { { deviceViewModel.openPairingWindow(deviceUiModel!!.device.deviceId) } }
페어링 창을 성공적으로 열면 deviceViewModel
가 이 사실을 UI에 전달합니다. ViewModel
와 UI 간의 통신은 StateFlow
객체를 통해 이루어집니다.
// Communicate to the UI that the pairing window is open. // UI can then launch the GPS activity for device sharing. _pairingWindowOpenForDeviceSharing.value = true
StateFlow 객체의 변경사항을 확인한 DeviceScreen은 다음과 같이 호출합니다.
shareDevice(activity!!.applicationContext, shareDeviceLauncher, deviceViewModel)
3단계: API 호출
이제 기기 공유 작업을 시작해 보겠습니다.
java/com/google/homesampleapp/screens/device/
폴더에서DeviceScreen.kt
를 엽니다.shareDevice()
함수를 찾습니다.// CODELAB: shareDevice
주석을ShareDeviceRequest
로 바꿉니다.DeviceDescriptor
는 공급업체 ID, 제품 ID, deviceType과 같은 기기에 관한 구체적인 정보를 제공합니다. 이 예에서는 값을 하드 코딩합니다.val shareDeviceRequest = ShareDeviceRequest.builder() .setDeviceDescriptor(DeviceDescriptor.builder().build()) .setDeviceName("GHSAFM temp device name")
- CommissioningWindow 및 parameters를 설정합니다.
.setCommissioningWindow( CommissioningWindow.builder() .setDiscriminator(Discriminator.forLongValue(DISCRIMINATOR)) .setPasscode(SETUP_PIN_CODE) .setWindowOpenMillis(SystemClock.elapsedRealtime()) .setDurationSeconds(OPEN_COMMISSIONING_WINDOW_DURATION_SECONDS.toLong()) .build()) .build()
.getCommissioningClient()
를 호출합니다. 이번에는.shareDevice()
API를 사용합니다.Matter.getCommissioningClient(context) .shareDevice(shareDeviceRequest)
commissioningClient.shareDevice()
API의 성공 콜백은 Google Play 서비스에서 공유 기기 활동을 실행하는 데 사용할 IntentSender를 제공합니다.
shareDevice
함수를 완료하려면addOnSuccessListener
및addOnFailureListener
를 추가합니다. 성공하면shareDeviceLauncher
에서launch
가 호출되어 기기 공유를 위한 GPS 활동이 시작됩니다..addOnSuccessListener { result -> Timber.d("ShareDevice: Success getting the IntentSender: result [${result}]") shareDeviceLauncher.launch(IntentSenderRequest.Builder(result).build()) } .addOnFailureListener { error -> Timber.e(error) deviceViewModel.showMsgDialog("Share device failed", error.toString()) }
앱 실행
Matter 기기를 다른 생태계와 공유하려면 Android 기기에 다른 플랫폼이 설치되어 있어야 합니다. 타겟 위원장으로 사용할 수 있는 다른 샘플 앱 인스턴스를 만들었습니다.
Android 기기에 대상 위원이 설치되면 Matter 기기를 공유할 수 있는지 확인합니다. 대상 커미셔닝 앱에는 GHSAFM-TC 라벨이 지정됩니다.
이제 기기가 다음 세 가지 패브릭에 참여할 수 있습니다.
- 로컬 Android 패브릭
- 개발 패브릭 (이 앱)
- 방금 기기를 공유한 세 번째 패브릭입니다.
8. 다음 단계
축하합니다
축하합니다. 이 Codelab을 완료하고 Home Mobile SDK를 사용하여 기기를 커미셔닝하고 공유하는 방법을 배웠습니다.
샘플 앱에 문제가 있는 경우 환경을 확인하는 단계를 완료해 보세요.
샘플 앱 사용 또는 코드 버그 발견에 관해 궁금한 점이 있으면 GitHub 저장소의 Issue Tracker에 문제를 제출할 수 있습니다.
기술 관련 질문에 관한 Google의 공식 안내를 받으려면 스마트 홈 개발자 포럼을 사용하세요.
커뮤니티에서 기술 지원을 받으려면 Stack Overflow에서 google-smart-home
태그를 사용하세요.