Mem-build aplikasi seluler menggunakan Home API di Android

1. Sebelum memulai

Google Home API menyediakan serangkaian library bagi developer Android untuk memanfaatkan ekosistem Google Home. Dengan API baru ini, developer dapat membuat aplikasi yang melakukan commissioning dan mengontrol perangkat smart home dengan lancar.

Google menyediakan Aplikasi Contoh Android bagi developer yang ingin mengakses contoh berfungsi menggunakan Google Home API. Codelab ini didasarkan pada cabang Aplikasi Contoh yang memandu Anda cara menggunakan Permissions, Commissioning, Device, dan Structure API.

Prasyarat

Yang akan Anda pelajari

  • Cara membangun aplikasi Android menggunakan Google Home API dengan praktik terbaik.
  • Cara menggunakan Device and Structure API untuk merepresentasikan dan mengontrol smart home.
  • Cara menggunakan API Komisioning untuk menambahkan perangkat ke ekosistem Google Home.

Opsional: Menyiapkan Rumah Anda

Sebelum menggunakan Google Home API, Anda harus menyiapkan rumah di Akun Google Anda menggunakan aplikasi Google Home, dan menambahkan beberapa perangkat. Bagian ini membahas cara melakukannya menggunakan Google Home Playground, yang menyediakan perangkat smart home virtual.

Buka home-playground.withgoogle.com di browser web Anda, login dengan Akun Google Anda, dan lihat apakah perangkat yang diemulasi berikut muncul:

  • outlet1: Colokan On/Off
  • light2: Lampu yang dapat diredupkan
  • light3: Lampu On/Off
  • ac3: Pendingin udara
  • blinds4: Penutup Jendela
  • washer5: Mesin cuci smart

914d23a42b72df8f.png

Buka aplikasi Google Home di perangkat seluler Anda, ketuk tombol Tambahkan, lalu pilih Kompatibel dengan Google Home. Telusuri "playground" dalam daftar, lalu pilih project "Google Home Playground", dan ketuk Lanjutkan.

e9ec257b0d9b1ed2.png29fd7416e274d216.pngd974573af0611fd8.png

Google Home Playground akan menampilkan halaman otorisasi akun. Ketuk Otorisasi atau Login dengan Google. Anda akan melihat semua perangkat yang Anda konfigurasi dari aplikasi web di aplikasi seluler.

13108a3a15440151.png8791a6d33748f7c8.png

Pilih semua perangkat dan selesaikan proses penyiapan. Setelah kembali ke halaman Beranda, Anda akan melihat semua perangkat yang tersedia.

2b021202e6fd1750.png

Perangkat yang didukung dalam daftar kini tersedia untuk digunakan dengan Google Home API.

2. Menyiapkan project

Diagram berikut mengilustrasikan arsitektur aplikasi Home API:

Arsitektur Home API untuk aplikasi Android

  • Kode Aplikasi: Kode inti yang dikerjakan developer untuk membangun antarmuka pengguna aplikasi dan logika untuk berinteraksi dengan Home APIs SDK.
  • Home APIs SDK: Home APIs SDK yang disediakan oleh Google berfungsi dengan Layanan Home API di GMSCore untuk mengontrol perangkat smart home. Developer membuat aplikasi yang berfungsi dengan Home API dengan memaketkannya dengan SDK Home API.
  • GMSCore di Android: GMSCore, yang juga dikenal sebagai layanan Google Play, adalah platform Google yang menyediakan layanan sistem inti, sehingga mengaktifkan fungsi utama di semua perangkat Android bersertifikasi. Modul beranda layanan Google Play berisi layanan yang berinteraksi dengan Home API.

Menyiapkan Home SDK

Ikuti langkah-langkah yang diuraikan dalam Menyiapkan SDK untuk mendapatkan SDK terbaru.

Mendapatkan Aplikasi Contoh

Kode sumber untuk Aplikasi Contoh tersedia di GitHub. Codelab ini menggunakan contoh dari cabang codelab-branch-1 Aplikasi Contoh.

Buka tempat Anda ingin menyimpan project dan clone cabang codelab-branch-1:

$ git clone -b codelab-branch-1 https://github.com/google-home/google-home-api-sample-app-android.git

Membangun Aplikasi Contoh

Lakukan langkah 1-5 di Membangun aplikasi.

32f2b3c0cd80fcf1.png

Jika aplikasi berhasil berjalan di ponsel, Anda akan melihat halaman utama Aplikasi Contoh. Namun, Anda tidak akan dapat login hingga Anda menyiapkan autentikasi OAuth dan menerapkan bagian yang belum ada menggunakan Permission API.

3. Menyiapkan Authentication

Home API menggunakan OAuth 2.0 untuk memberikan akses ke perangkat dalam struktur. OAuth memungkinkan pengguna memberikan izin ke aplikasi atau layanan tanpa harus mengungkapkan kredensial login mereka.

Ikuti petunjuk di Menyiapkan izin OAuth untuk mengonfigurasi layar izin. Pastikan untuk membuat setidaknya satu akun pengujian.

Kemudian, ikuti petunjuk di Menyiapkan kredensial OAuth untuk membuat kredensial aplikasi.

4. Inisialisasi dan Penanganan Izin

Di bagian ini, Anda akan mempelajari cara menginisialisasi SDK dan menangani izin pengguna dengan melengkapi bagian yang hilang menggunakan Permissions API.

Menentukan Jenis dan Ciri yang Didukung

Saat mengembangkan aplikasi, Anda harus mencatat secara eksplisit jenis dan karakteristik perangkat yang akan didukung aplikasi. Di Aplikasi Contoh, kami melakukannya dengan menentukan daftar statis di objek pendamping di HomeApp.kt, yang kemudian dapat dirujuk di seluruh aplikasi sesuai kebutuhan:

companion object {

  // List of supported device types by this app:
  val supportedTypes: List<DeviceTypeFactory<out DeviceType>> = listOf(
    OnOffLightDevice,
    DimmableLightDevice,

  // ...
  )
  // List of supported device traits by this app:
  val supportedTraits: List<TraitFactory<out Trait>> = listOf(
  OnOff,
  LevelControl,
  // ...
  )
}

Lihat Jenis perangkat yang didukung dan Indeks Karakteristik di Android untuk melihat semua jenis perangkat dan karakteristik yang didukung.

Batalkan komentar Langkah 4.1.1 dan 4.1.2 di file sumber HomeApp.kt untuk mengaktifkan kode sumber yang meminta izin.

companion object {
// List of supported device types by this app:
val supportedTypes: List<DeviceTypeFactory<out DeviceType>> = listOf(
// TODO: 4.1.1 - Non-registered device types will be unsupported
//             ContactSensorDevice,
//             ColorTemperatureLightDevice,
//             DimmableLightDevice,
//             ExtendedColorLightDevice,
//             GenericSwitchDevice,
//             GoogleDisplayDevice,
//             GoogleTVDevice,
//             OccupancySensorDevice,
//             OnOffLightDevice,
//             OnOffLightSwitchDevice,
//             OnOffPluginUnitDevice,
//             OnOffSensorDevice,
//             RootNodeDevice,
//             SpeakerDevice,
//             ThermostatDevice,
)
// List of supported device traits by this app:
val supportedTraits: List<TraitFactory<out Trait>> = listOf(
// TODO: 4.1.2 - Non-registered traits will be unsupported
//             AreaAttendanceState,
//             AreaPresenceState,
//             Assistant,
//             AssistantBroadcast,
//             AssistantFulfillment,
//             BasicInformation,
//             BooleanState,
//             OccupancySensing,
//             OnOff,
//             Notification,
//             LevelControl,
//             TemperatureControl,
//             TemperatureMeasurement,
//             Thermostat,
//             Time,
//             Volume,
        )
}

Melakukan Inisialisasi Objek HomeClient

Semua aplikasi yang menggunakan Home API menginisialisasi objek HomeClient, yang merupakan antarmuka utama untuk berinteraksi dengan API. Kita menyiapkan objek ini di penginisialisasi class HomeApp (HomeApp.kt).

// Registry to record device types and traits used in this app:
val registry = FactoryRegistry(
  types = supportedTypes,
  traits = supportedTraits
)
// Configuration options for the HomeClient:
val config = HomeConfig(
  coroutineContext = Dispatchers.IO,
  factoryRegistry = registry
)
// Initialize the HomeClient, which is the primary object to use all Home APIs:
homeClient = Home.getClient(context = context, homeConfig = config)

Pertama, kita membuat FactoryRegistry menggunakan jenis dan karakteristik yang didukung yang kita tentukan sebelumnya. Kemudian, menggunakan registry ini, kita menginisialisasi HomeConfig, yang berisi konfigurasi yang diperlukan untuk menjalankan API. Selanjutnya, kita menggunakan panggilan Home.getClient(...) untuk mendapatkan instance HomeClient.

Semua interaksi kita dengan Home API akan dilakukan melalui objek HomeClient ini.

Menggunakan Permissions API

Autentikasi pengguna untuk Home API dilakukan melalui Permissions API. File sumber PermissionsManager.kt Aplikasi Contoh berisi kode untuk autentikasi pengguna. Hapus komentar konten fungsi checkPermissions(...) dan requestPermissions(...) untuk mengaktifkan izin Aplikasi Contoh.

Mendaftarkan:

homeClient.registerActivityResultCallerForPermissions(activity)

Peluncuran:

try {
    val result: PermissionsResult
    result = homeClient.requestPermissions(forceLaunch = true)
    when (result.status) {
        PermissionsResultStatus.SUCCESS -> // Success Case
        PermissionsResultStatus.CANCELLED -> // User Cancelled
        PermissionsResultStatus.ERROR -> // Some Error
else -> // Unsupported Case
    }
}
catch (e: HomeException) { ... }

Memeriksa:

try {
    val state: PermissionsState
    state = homeClient.hasPermissions().first { state ->
        state != PermissionsState.PERMISSIONS_STATE_UNINITIALIZED
    }
    when (state) {
        PermissionsState.GRANTED -> // Signed In
        PermissionsState.NOT_GRANTED -> // Not Signed In
        PermissionsState.PERMISSIONS_STATE_UNAVAILABLE -> // ...
        PermissionsState.PERMISSIONS_STATE_UNINITIALIZED -> // ...
else -> // Unsupported case
    }
}
catch (e: HomeException) { ... }

Berlangganan:

       homeClient.hasPermissions().collect( { state ->
// Track the changes on state
        } )

Hapus tanda komentar Langkah 4.3.1 di PermissionsManager.kt untuk mengaktifkan kode yang meminta izin:

fun requestPermissions() {
    scope.launch {
    try {
// TODO: 4.3.1 - Request the permissions from the Permissions API
//                 // Request permissions from the Permissions API and record the result:
//                 val result: PermissionsResult = client.requestPermissions(forceLaunch = true)
//                 // Adjust the sign-in status according to permission result:
//                 if (result.status == PermissionsResultStatus.SUCCESS)
//                     isSignedIn.emit(true)
//                 // Report the permission result:
//                 reportPermissionResult(result)
    }
    catch (e: HomeException) { MainActivity.showError(this, e.message.toString()) }
    }
}

Sekarang jalankan aplikasi di ponsel Anda, ikuti langkah-langkahnya, dan izinkan izinnya. Anda akan melihat alur berikut:

c263dcee4e945bf1.png f518cfd1fdb8a9d8.png 59937372f28c472f.png 383073ae57d2ced4.png 89f774a2ba6898ae.png

Pesan "Memuat" tidak pernah hilang, tetapi ini karena kita belum menerapkan kode yang membaca struktur dan perangkat. Kita akan melakukannya di bagian berikutnya.

5. Memahami model data

Di Home API, Model Data terdiri dari:

  • Structure mewakili rumah yang berisi ruangan dan perangkat.
  • Room adalah bagian dari struktur dan berisi perangkat.
  • Perangkat (didefinisikan sebagai HomeDevice) dapat ditetapkan ke struktur (atau rumah) atau ruangan dalam struktur.
  • Perangkat terdiri dari satu atau beberapa instance DeviceType.
  • DeviceType terdiri dari instance Trait.
  • Trait terdiri dari instance Attribute (untuk membaca/menulis), instance Command (untuk mengontrol atribut), dan instance Event (untuk membaca atau berlangganan rekaman perubahan sebelumnya).
  • Instance Automation adalah bagian dari struktur dan menggunakan metadata dan perangkat rumah untuk mengotomatiskan tugas di rumah.

76d35b44d5a8035e.png

Di bagian ini, Anda akan mempelajari cara mengembangkan kode sumber untuk menunjukkan cara menggunakan Structure API guna mengurai dan merender struktur rumah, ruangan, perangkat, dan sebagainya.

Membaca struktur

Desain Home API didasarkan pada Kotlin Flow untuk mengalirkan objek model data (misalnya, Structure, HomeDevice, dan sebagainya). Developer berlangganan Flow untuk mendapatkan semua objek yang ada dalam objek (misalnya, Structure, Room, dan sebagainya).

Untuk mengambil semua struktur, panggil fungsi structures(), yang menampilkan alur struktur. Kemudian, panggil fungsi daftar pada alur untuk mendapatkan semua struktur yang dimiliki pengguna.

// Get the a snapshot of all structures from the current homeClient
val allStructures : Set<Structure> =
    homeClient.structures()   // HomeObjectsFlow<Structure>
    .list()                   // Set<Structure>

Panduan untuk arsitektur aplikasi sangat merekomendasikan penggunaan pendekatan pemrograman Reaktif modern untuk meningkatkan aliran data dan pengelolaan status aplikasi.

Berikut cara Aplikasi Contoh mematuhi gaya coding Reaktif:

  • Model tampilan (seperti StructureViewModel dan DeviceViewModel, sebagai pemegang status) berlangganan aliran dari SDK API Beranda untuk menerima perubahan nilai, dan mempertahankan status terbaru.
  • Tampilan (seperti StructureView dan DeviceView) berlangganan ke model tampilan untuk menerima status dan merender UI guna mencerminkan perubahan tersebut.
  • Saat pengguna mengklik tombol pada tampilan (misalnya, tombol "Aktif" pada perangkat lampu), peristiwa akan memicu fungsi model tampilan, yang memanggil fungsi Home API yang merespons (misalnya, perintah On pada trait OnOff).

Pada Langkah 5.1.1 di HomeAppViewModel.kt, kita berlangganan peristiwa perubahan struktur dengan memanggil fungsi collect(). Batalkan komentar pada bagian yang melintasi structureSet yang ditampilkan oleh respons Structures API dan dikirimkan di StructureViewModel's StateFlow. Hal ini memungkinkan aplikasi memantau perubahan status struktur:

   private suspend fun subscribeToStructures() {
// TODO: 5.1.1 - Subscribe the structure data changes
// // Subscribe to structures returned by the Structures API:
// homeApp.homeClient.structures().collect { structureSet ->
//     val structureVMList: MutableList<StructureViewModel> = mutableListOf()
//     // Store structures in container ViewModels:
//     for (structure in structureSet) {
//         structureVMList.add(StructureViewModel(structure))
//     }
//     // Store the ViewModels:
//     structureVMs.emit(structureVMList)
//
//     // If a structure isn't selected yet, select the first structure from the list:
//     if (selectedStructureVM.value == null && structureVMList.isNotEmpty())
//         selectedStructureVM.emit(structureVMList.first())
//
// }
}

Di DevicesView.kt, aplikasi berlangganan StructureViewModel'sStateFlow, yang memicu rekomposisi UI saat data struktur berubah. Batalkan komentar kode sumber di Langkah 5.1.2 untuk merender daftar struktur sebagai menu drop-down:

   val structureVMs: List<StructureViewModel> = homeAppVM.structureVMs.collectAsState().value
...
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
// TODO: 5.1.2 - Show list of structures in DropdownMenu
//  for (structure in structureVMs) {
//      DropdownMenuItem(
//          text = { Text(structure.name) },
//          onClick = {
//              scope.launch { homeAppVM.selectedStructureVM.emit(structure) }
//              expanded = false
//          }
//      )
//  }
}
...

Jalankan kembali aplikasi. Anda akan melihat menu saat mengetuk panah:

f1fc2be1cb6436b6.png

Mengurai Struktur

Langkah berikutnya adalah menjelajahi objek rumah dalam struktur. Ambil ruangan dari struktur:

val rooms: Set<Room>
rooms = structure.rooms().list()

Kemudian, Anda dapat menjelajahi ruangan untuk mengambil perangkat:

val devices: Set<HomeDevice>
devices = room.devices().list()

Penting: Dalam model data Home API, struktur dapat berisi perangkat yang tidak ditetapkan ke ruangan, jadi pastikan untuk mengambil perangkat tanpa ruangan di aplikasi Anda juga:

val devicesWithoutRooms: MutableSet<HomeDevice> = mutableSetOf()

for (device in structure.devices().list())
if (device.roomId == null)
  devicesWithoutRooms.add(device)

Sekali lagi, dalam contoh kode yang ada, kita berlangganan flow untuk mendapatkan daftar Ruangan dan Perangkat terbaru. Periksa kode di Langkah 5.2.1 dan 5.2.2 dalam file sumber StructureViewModel.kt dan hapus komentarnya untuk mengaktifkan langganan data room:

val roomVMs : MutableStateFlow<List<RoomViewModel>>
val deviceVMs : MutableStateFlow<List<DeviceViewModel>>
val deviceVMsWithoutRooms : MutableStateFlow<List<DeviceViewModel>>
private suspend fun subscribeToRooms() {
// TODO: 5.2.1 - Subscribe the room data changes
//   // Subscribe to changes on rooms:
//   structure.rooms().collect { roomSet ->
//       val roomVMs = mutableListOf<RoomViewModel>()
//       // Store rooms in container ViewModels:
//       for (room in roomSet) {
//           roomVMs.add(RoomViewModel(room))
//       }
//       // Store the ViewModels:
//       this.roomVMs.emit(roomVMs)
//   }
}
private suspend fun subscribeToDevices() {
// TODO: 5.2.2 - Subscribe the device data changes in a structure
//   // Subscribe to changes on devices:
//   structure.devices().collect { deviceSet ->
//       val deviceVMs = mutableListOf<DeviceViewModel>()
//       val deviceWithoutRoomVMs = mutableListOf<DeviceViewModel>()
//       // Store devices in container ViewModels:
//       for (device in deviceSet) {
//           val deviceVM = DeviceViewModel(device)
//           deviceVMs.add(deviceVM)
//           // For any device that's not in a room, additionally keep track of a separate list:
//           if (device.roomId == null)
//               deviceWithoutRoomVMs.add(deviceVM)
//       }
//       // Store the ViewModels:
//       this.deviceVMs.emit(deviceVMs)
//       deviceVMsWithoutRooms.emit(deviceWithoutRoomVMs)
//   }
    }

Batalkan komentar Langkah 5.2.3 dan 5.2.4 di file sumber DevicesView.kt untuk merender daftar ruang sebagai menu:

val selectedRoomVMs: List<RoomViewModel> =
selectedStructureVM.roomVMs.collectAsState().value
...
for (roomVM in selectedRoomVMs) {
// TODO: 5.2.3 - Render the list of rooms
//   RoomListItem(roomVM)
// TODO: 5.2.4 - Render the list of devices in a room
//   val deviceVMsInRoom: List<DeviceViewModel> = roomVM.deviceVMs.collectAsState().value
//
//   for (deviceVM in deviceVMsInRoom) {
//       DeviceListItem(deviceVM, homeAppVM)
//   }
}

Setelah Anda memiliki perangkat, kita akan mempelajari cara menggunakannya.

e715ddda50e04839.png

6. Menggunakan Perangkat

Home API menggunakan objek HomeDevice untuk merekam perangkat dan kemampuannya. Developer dapat berlangganan atribut perangkat dan menggunakannya untuk merepresentasikan perangkat smart home di aplikasi mereka.

Membaca status perangkat

Objek HomeDevice menyajikan serangkaian nilai statis, seperti nama perangkat atau status konektivitas. Sebagai developer, Anda dapat mengambilnya segera setelah Anda mendapatkan perangkat dari API:

val id: String = device.id.id
val name: String = device.name
val connectivity: ConnectivityState =
    device.sourceConnectivity.connectivityState

Untuk mendapatkan kemampuan perangkat, Anda perlu mengambil jenis dan karakteristik dari HomeDevice. Untuk melakukannya, Anda dapat berlangganan alur jenis perangkat sebagai berikut, dan mengambil trait dari jenis perangkat:

device.types().collect { typeSet ->
var primaryType : DeviceType = UnknownDeviceType()
for (typeInSet in typeSet)
if (typeInSet.metadata.isPrimaryType)
                    primaryType = typeInSet
            val traits: List<Trait> = mutableListOf()
for (trait in primaryType.traits())
if (trait.factory in myTraits)
                    traits.add(trait)
for (trait in traits)
                parseTrait(trait, primaryType)
        }

Setiap perangkat berisi serangkaian DeviceType yang didukung (kemampuan yang dipaketkan), yang dapat Anda ambil menggunakan device.types(). Jenis perangkat ini berisi karakteristik yang dapat diambil menggunakan type.traits(). Setiap perangkat menandai salah satu jenisnya sebagai jenis utama (yang dapat diperiksa menggunakan type.metadata.isPrimaryType) yang harus Anda tampilkan di aplikasi Anda. Untuk memberikan pengalaman yang lengkap kepada pengguna, sebaiknya jelajahi semua jenis yang ditampilkan dan integrasikan semua karakteristik yang tersedia untuk Anda.

Setelah mengambil trait, Anda dapat menguraikannya menggunakan fungsi seperti berikut untuk menafsirkan nilai:

fun <T : Trait?> parseTrait(trait : T, type: DeviceType) {
    val status : String = when (trait) {
        is OnOff -> { if (trait.onOff) "On" else "Off" }
        is LevelControl -> { trait.currentLevel.toString() }
        is BooleanState -> {
            when (type.factory) {
                ContactSensorDevice -> {
if (trait.stateValue) "Closed"
else "Open"
                }
else -> ...
            }
        }
else -> ...
    }
}

Perhatikan bahwa ada kemungkinan variasi dalam representasi suatu karakteristik, bergantung pada jenis perangkat yang menampilkannya (lihat BooleanState dalam contoh sebelumnya). Jadi, Anda harus memahami konteks setiap jenis perangkat untuk memahami representasi karakteristiknya yang sebenarnya.

Batalkan komentar Langkah 6.1.1 dan 6.1.2 dalam file sumber DeviceViewModel.kt untuk mengambil status:

private suspend fun subscribeToType() {
// Subscribe to changes on device type, and the traits/attributes within:
device.types().collect { typeSet ->
// Container for the primary type for this device:
var primaryType : DeviceType = UnknownDeviceType()
...
// TODO: 6.1.1 - Determine the primary type for this device
//       // Among all the types returned for this device, find the primary one:
//       for (typeInSet in typeSet)
//           if (typeInSet.metadata.isPrimaryType)
//               primaryType = typeInSet
//
//       // Optional: For devices with a single type that did not define a primary:
//       if (primaryType is UnknownDeviceType && typeSet.size == 1)
//           primaryType = typeSet.first()
// Container for list of supported traits present on the primary device type:
val supportedTraits: List<Trait> = getSupportedTraits(primaryType.traits())
...
}
fun getSupportedTraits(traits: Set<Trait>) : List<Trait> {
           val supportedTraits: MutableList<Trait> = mutableListOf()
// TODO: 6.1.2 - Get only the supported traits for this device
//   for (trait in traits)
//       if (trait.factory in HomeApp.supportedTraits)
//           supportedTraits.add(trait)
return supportedTraits
}

Batalkan komentar Langkah 6.1.3 di DeviceView.kt untuk merender trait OnOff, termasuk nama dan statusnya, sebagai String:

Box (Modifier.padding(horizontal = 24.dp, vertical = 8.dp)) {
when (trait) {
is OnOff -> {
// TODO: 6.1.3 - Render controls based on the trait type
// Column (Modifier.fillMaxWidth()) {
//     Text(trait.factory.toString(), fontSize = 20.sp)
//     Text(DeviceViewModel.getTraitStatus(trait, type), fontSize = 16.sp)
// }
...
}
is LevelControl -> {
      ...
  }
   is BooleanState -> {
      ...
  }
   is OccupancySensing -> {
      ...
  }
  ...
}

Jika Anda menjalankan aplikasi sekarang dengan jenis perangkat yang didukung (misalnya, perangkat Lampu), aplikasi akan menampilkan status terbaru untuk semua perangkat.

1bd8b3b2796c4c7a.png

Mengeluarkan perintah perangkat

Untuk mengeluarkan perintah ke perangkat, Home API menyediakan fungsi praktis pada objek Trait seperti trait.on() atau trait.moveToLevel(...):

fun <T : Trait?> issueCommand(trait : T) {
     when (trait) {
         is OnOff -> {
// trait.on()
// trait.off()
   }
   is LevelControl -> {
// trait.moveToLevel(...)
// trait.moveToLevelWithOnOff(...)
        }
    }
}

Tips: Setelah menentukan jenis trait, gunakan fitur pelengkapan otomatis Android Studio untuk melihat jenis tindakan yang tersedia untuk berinteraksi dengan trait.

Hapus komentar pada Langkah 6.2.1 di DeviceView.kt untuk menambahkan kontrol fungsional di aplikasi:

Box (Modifier.padding(horizontal = 24.dp, vertical = 8.dp)) {
when (trait) {
is OnOff -> {
                ....
// TODO: 6.2.1 - Render controls based on the trait type
//   Switch (checked = (trait.onOff == true), modifier = Modifier.align(Alignment.CenterEnd),
//       onCheckedChange = { state ->
//           scope.launch { if (state) trait.on() else trait.off() }
//       },
//       enabled = isConnected
//   )
}

Jika Anda menjalankan aplikasi sekarang, Anda akan dapat mengontrol perangkat fisik di dunia nyata.

Jika Anda mengetuk kontrol OnOff pada bohlam, perangkat akan menyala.

c8ed3ecf5031546e.png

Untuk mengetahui informasi selengkapnya tentang cara mengontrol perangkat, lihat Mengontrol perangkat di Android.

7. Memastikan perangkat

Commissioning API memungkinkan developer menambahkan perangkat ke ekosistem Google Home, dan menyediakannya untuk dikontrol menggunakan Home API. Hanya perangkat Matter yang didukung. Di bagian ini, kita akan mempelajari cara mengaktifkan penyiapan perangkat di aplikasi Anda.

Sebelum memulai bagian ini, pastikan prasyarat berikut terpenuhi:

Jika Anda memiliki perangkat Matter fisik dengan kode QR untuk penyiapan, Anda dapat langsung membuka Aktifkan API penyiapan. Jika tidak, lanjutkan ke bagian berikutnya, tempat kita membahas cara menggunakan aplikasi Matter Virtual Device (MVD) untuk membuat perangkat virtual yang dapat di-pairing.

Opsional: Menyiapkan perangkat yang dapat di-commissioning Matter

Cara paling sederhana untuk menyiapkan perangkat yang dapat di-commissioning Matter adalah dengan menggunakan perangkat yang diemulasi yang disediakan oleh aplikasi Matter Virtual Device (MVD).

Setelah menginstal MVD dan menyiapkan firewall, jalankan MVD:

b20283893073ac1b.png

Buat perangkat OnOff. Perhatikan bahwa aplikasi belum ditugaskan - Anda akan menugaskannya nanti dalam codelab ini.

5f4855b808312898.png

Aktifkan Commissioning API

Commissioning API berfungsi di luar Aktivitas aplikasi, sehingga commissioning harus ditangani secara berbeda dari Home API lainnya. Untuk menyiapkan aplikasi agar siap untuk penugasan, Anda memerlukan dua variabel.

Salah satu variabelnya adalah ActivityResultLauncher, yang digunakan untuk mengirim maksud pemberian izin dan mengelola callback hasil. Variabel lainnya adalah CommissioningResult, yang merupakan objek yang digunakan untuk menyimpan hasil aktivasi. Lihat contoh berikut tentang cara menyiapkan commissioning:

var launcher: ActivityResultLauncher<IntentSenderRequest>
lateinit var commissioningResult: CommissioningResult?
launcher = activity.registerForActivityResult(StartIntentSenderForResult()) { result ->
try {
  commissioningResult = CommissioningResult.fromIntentSenderResult(
      result.resultCode, result.data)
  } catch (exception: ApiException) {
// Catch any issues
 }
}

Setelah alur aktivasi Anda disiapkan, Anda akan membuat intent aktivasi, dan meluncurkannya menggunakan peluncur yang kita buat pada contoh sebelumnya. Sebaiknya tempatkan intent dan peluncur dalam fungsi khusus seperti berikut. Fungsi khusus dapat dikaitkan dengan elemen UI (seperti tombol +Tambahkan Perangkat) dan dipanggil berdasarkan permintaan pengguna:

fun requestCommissioning() {
// Retrieve the onboarding payload used when commissioning devices:
val payload = activity.intent?.getStringExtra(Matter.EXTRA_ONBOARDING_PAYLOAD)
  scope.launch {
    // Create a commissioning request to store the device in Google's Fabric:
    val request = CommissioningRequest.builder()
      .setStoreToGoogleFabric(true)
      .setOnboardingPayload(payload)
      .build()
    // Initialize client and sender for commissioning intent:
    val client: CommissioningClient = Matter.getCommissioningClient(context)
    val sender: IntentSender = client.commissionDevice(request).await()
    // Launch the commissioning intent on the launcher:
    launcher.launch(IntentSenderRequest.Builder(sender).build())
  }
}

Batalkan komentar Langkah 7.1.1 di CommissioningManager.kt untuk mengaktifkan kemampuan komisioning dan membuat tombol +Add Device berfungsi di Aplikasi Contoh.

// Called by +Add Device button in DeviceView.kt
fun requestCommissioning() {
// Retrieve the onboarding payload used when commissioning devices:
val payload = activity.intent?.getStringExtra(Matter.EXTRA_ONBOARDING_PAYLOAD)
// TODO: 7.1.1 - Launch the commissioning intent
// scope.launch {
//     // Create a commissioning request to store the device in Google's Fabric:
//     val request = CommissioningRequest.builder()
//         .setStoreToGoogleFabric(true)
//         .setOnboardingPayload(payload)
//         .build()
//     // Initialize client and sender for commissioning intent:
//     val client: CommissioningClient = Matter.getCommissioningClient(context)
//     val sender: IntentSender = client.commissionDevice(request).await()
//     // Launch the commissioning intent on the launcher:
//     launcher.launch(IntentSenderRequest.Builder(sender).build())
// }
}

Menjalankan fungsi ini akan memulai Alur Penyiapan, yang akan menampilkan layar yang menyerupai screenshot berikut:

baae45588f460664.png

Memahami alur Penyiapan

Alur aktivasi mencakup serangkaian layar yang memandu pengguna menambahkan perangkat ke Akun Google mereka:

2fb0404820d4a035.png 3cbfa8ff9cfd5ee4.png a177c197ee7a67bf.png 3fdef24672c77c0.png dec8e599f9aa119.png

Pengguna akan disambut dengan pemindai kode QR yang dapat mereka gunakan untuk memindai kode QR dari perangkat Matter. Alur ini kemudian akan menampilkan Perjanjian Pengguna, penemuan dan aktivasi perangkat, serta penamaan perangkat. Setelah alur selesai, fokus alur akan kembali ke aplikasi, dan meneruskan hasil aktivasi di fungsi callback yang kita buat di bagian sebelumnya.

Salah satu manfaat Commissioning API adalah alur UX ditangani oleh SDK, sehingga developer dapat mulai menggunakan API dengan sangat cepat. Hal ini juga memberikan pengalaman yang konsisten kepada pengguna saat menambahkan perangkat di berbagai aplikasi.

Untuk mengetahui lebih lanjut API aktivasi, buka Commissioning API di Android.

8. Selamat!

Selamat! Anda telah berhasil membuat aplikasi Android menggunakan Google Home API. Selama codelab ini, Anda telah mempelajari API Izin, Perangkat, Struktur, dan Pengoperasian. Dalam codelab berikutnya, Membuat otomatisasi lanjutan menggunakan Home API di Codelab Android, kita akan mempelajari Automation API dan Discovery API, serta menyelesaikan aplikasi.

Kami harap Anda menikmati pembuatan aplikasi yang secara kreatif mengontrol perangkat dalam ekosistem Google Home.

Langkah berikutnya