Android'de Home API'lerini kullanarak mobil uygulama oluşturma

1. Başlamadan önce

Google Home API'leri, Android geliştiricilerin Google Home ekosisteminden yararlanabileceği bir dizi kitaplık sağlar. Bu yeni API'ler sayesinde geliştiriciler, akıllı ev cihazlarını sorunsuz bir şekilde devreye alıp kontrol eden uygulamalar oluşturabilir.

Google, Google Home API'lerini kullanarak çalışan bir örneğe erişmek isteyen geliştiriciler için bir Android örnek uygulaması sunar. Bu codelab, İzinler, Kullanıma Alma, Cihaz ve Yapı API'lerinin nasıl kullanılacağını adım adım açıklayan örnek uygulamanın bir dalına dayanmaktadır.

Ön koşullar

Neler öğreneceksiniz?

  • En iyi uygulamaları kullanarak Google Home API'lerini kullanan bir Android uygulaması oluşturma.
  • Akıllı bir evi temsil etmek ve kontrol etmek için Cihaz ve Yapı API'lerini kullanma
  • Cihazları Google Home ekosistemine eklemek için devreye alma API'lerini kullanma

İsteğe bağlı: Evinizi ayarlama

Google Home API'lerini kullanmadan önce Google Home uygulamasını kullanarak Google Hesabınızda bir ev oluşturmanız ve birkaç cihaz eklemeniz gerekir. Bu bölümde, sanal akıllı ev cihazları sağlayan Google Home Playground kullanılarak bu işlemin nasıl yapılacağı açıklanmaktadır.

Web tarayıcınızda home-playground.withgoogle.com adresini açın, Google Hesabınızla oturum açın ve aşağıdaki emüle edilmiş cihazların görünüp görünmediğine bakın:

  • outlet1: Açma/kapatma fişi
  • light2: Kısılabilir ışık
  • light3: Işığı açma/kapatma
  • ac3: Klima
  • blinds4: Window Covering
  • washer5: Akıllı çamaşır makinesi

914d23a42b72df8f.png

Mobil cihazınızda Google Home uygulamasını açın, Ekle düğmesine dokunun ve Google Home ile çalışır'ı seçin. Listede "playground"u arayın, ardından "Google Home Playground" projesini seçip Devam'a dokunun.

e9ec257b0d9b1ed2.png29fd7416e274d216.pngd974573af0611fd8.png

Google Home Playground'da bir hesap yetkilendirme sayfası gösterilir. Yetkilendir veya Google ile oturum aç'a dokunun. Web uygulamasından yapılandırdığınız tüm cihazları mobil uygulamada görürsünüz.

13108a3a15440151.png8791a6d33748f7c8.png

Tüm cihazları seçip kurulum sürecini tamamlayın. Ana sayfaya döndüğünüzde, kullanılabilir tüm cihazları görürsünüz.

2b021202e6fd1750.png

Listede yer alan desteklenen cihazlar artık Google Home API'leriyle kullanılabilir.

2. Projenizi oluşturma

Aşağıdaki şemada, Home APIs uygulamasının mimarisi gösterilmektedir:

Android uygulaması için Home API'lerinin mimarisi

  • Uygulama Kodu: Geliştiricilerin, uygulamanın kullanıcı arayüzünü oluşturmak ve Home API'leri SDK'sı ile etkileşim kurma mantığını geliştirmek için üzerinde çalıştığı temel kod.
  • Home APIs SDK: Google tarafından sağlanan Home APIs SDK, akıllı ev cihazlarını kontrol etmek için GMSCore'daki Home APIs Service ile birlikte çalışır. Geliştiriciler, Home API'leri SDK'sı ile paketleyerek Home API'leriyle çalışan uygulamalar oluşturur.
  • Android'de GMSCore: Google Play Hizmetleri olarak da bilinen GMSCore, temel sistem hizmetleri sağlayan ve tüm sertifikalı Android cihazlarda temel işlevleri etkinleştiren bir Google platformudur. Google Play Hizmetleri'nin ana sayfa modülü, Home API'leriyle etkileşimde bulunan hizmetleri içerir.

Home SDK'yı ayarlama

En yeni SDK'yı edinmek için SDK'yı ayarlama başlıklı makalede belirtilen adımları uygulayın.

Örnek Uygulamayı Edinme

Örnek uygulamanın kaynak kodu GitHub'da mevcuttur. Bu codelab'de, Örnek Uygulama'nın codelab-branch-1 dalındaki örnekler kullanılır.

Projeyi kaydetmek istediğiniz yere gidin ve codelab-branch-1 şubesini klonlayın:

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

Örnek Uygulamayı Oluşturma

Uygulamayı oluşturma bölümündeki 1-5 arası adımları uygulayın.

32f2b3c0cd80fcf1.png

Uygulama telefonunuzda başarıyla çalıştırıldığında örnek uygulamanın ana sayfasını görürsünüz. Ancak OAuth kimlik doğrulamasını ayarlayıp eksik parçaları Permission API'yi kullanarak uygulayana kadar oturum açamazsınız.

3. Kimlik doğrulama ayarlama

Home API'leri, yapıdaki cihazlara erişim izni vermek için OAuth 2.0'ı kullanır. OAuth, kullanıcının giriş kimlik bilgilerini ifşa etmeden bir uygulamaya veya hizmete izin vermesine olanak tanır.

İzin ekranını yapılandırmak için OAuth kullanıcı rızası ekranını ayarlama bölümündeki talimatları uygulayın. En az bir test hesabı oluşturduğunuzdan emin olun.

Ardından, uygulama için kimlik bilgileri oluşturmak üzere OAuth kimlik bilgilerini ayarlama bölümündeki talimatları uygulayın.

4. Başlatma ve İzinleri İşleme

Bu bölümde, Permissions API'yi kullanarak eksik parçaları tamamlayarak SDK'yı nasıl başlatacağınızı ve kullanıcı izinlerini nasıl işleyeceğinizi öğreneceksiniz.

Desteklenen Türleri ve Özellikleri Tanımlama

Uygulama geliştirirken uygulamanın hangi cihaz türlerini ve özelliklerini destekleyeceğini açıkça belirtmeniz gerekir. Örnek uygulamada bunu, HomeApp.kt içindeki eşlik eden nesnede statik listeler tanımlayarak yaparız. Bu listelere daha sonra gerektiğinde uygulama genelinde referans verilebilir:

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,
  // ...
  )
}

Desteklenen tüm cihaz türlerini ve özellikleri görmek için Desteklenen cihaz türleri ve Android'de Özellik Dizini başlıklı makaleyi inceleyin.

İzni isteyen kaynak kodu etkinleştirmek için HomeApp.kt kaynak dosyasında 4.1.1 ve 4.1.2 adımlarındaki yorum işaretini kaldırın.

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,
        )
}

HomeClient nesnesini başlatma

Home API'lerini kullanan tüm uygulamalar, API'lerle etkileşim kurmak için kullanılan ana arayüz olan bir HomeClient nesnesi başlatır. Bu nesneyi HomeApp (HomeApp.kt) sınıfının başlatıcısında hazırlıyoruz.

// 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)

Öncelikle, daha önce tanımladığımız desteklenen türleri ve özellikleri kullanarak bir FactoryRegistry oluştururuz. Ardından, bu kayıt defterini kullanarak API'leri çalıştırmak için gereken yapılandırmayı içeren bir HomeConfig başlatırız. Ardından, HomeClient örneğini edinmek için Home.getClient(...) çağrısını kullanırız.

Home API'lerle olan tüm etkileşimlerimiz bu HomeClient nesnesi üzerinden gerçekleşir.

Permissions API'yi kullanma

Home API'leri için kullanıcı kimlik doğrulaması, Permissions API aracılığıyla yapılır. Örnek uygulamanın PermissionsManager.kt kaynak dosyasında kullanıcı kimlik doğrulaması için kod bulunur. Örnek Uygulama için izinleri etkinleştirmek üzere checkPermissions(...) ve requestPermissions(...) işlevlerinin içeriğindeki yorum işaretini kaldırın.

Kaydolma:

homeClient.registerActivityResultCallerForPermissions(activity)

Lansman:

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) { ... }

Kontrol ediliyor:

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) { ... }

Abone olma:

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

İzinleri isteyen kodu etkinleştirmek için PermissionsManager.kt bölümünde 4.3.1. adımı yorumdan çıkarın:

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()) }
    }
}

Şimdi adımları uygulayarak uygulamayı telefonunuzda çalıştırın ve izinleri verin. Aşağıdaki akışı görmeniz gerekir:

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

"Yükleniyor" mesajı hiçbir zaman kaybolmuyor ancak bunun nedeni, yapıyı ve cihazları okuyan kodu uygulamamış olmamızdır. Bunu bir sonraki bölümde yapacağız.

5. Veri modelini anlama

Home API'lerinde Veri Modeli şu öğelerden oluşur:

  • Structure, odalar ve cihazlar içeren bir evi temsil eder.
  • Room, bir yapının parçasıdır ve cihazları içerir.
  • Cihazlar (HomeDevice olarak tanımlanır) bir yapıya (veya eve) ya da yapıdaki bir odaya atanabilir.
  • Cihazlar bir veya daha fazla DeviceType örneğinden oluşur.
  • DeviceType, Trait örnekten oluşur.
  • Trait, Attribute örneklerinden (okuma/yazma için), Command örneklerinden (özellikleri kontrol etmek için) ve Event örneklerinden (geçmiş değişikliklerin kayıtlarını okumak veya kaydetmek için) oluşur.
  • Automation örnekleri bir yapının parçasıdır ve evdeki görevleri otomatikleştirmek için ev meta verilerini ve cihazlarını kullanır.

76d35b44d5a8035e.png

Bu bölümde, ev yapılarınızı, odalarınızı, cihazlarınızı vb. ayrıştırıp oluşturmak için Structure API'nin nasıl kullanılacağını gösteren kaynak kodu geliştirmeyi öğreneceksiniz.

Yapıları okuma

Home API'lerinin tasarımı, veri modeli nesnelerini (ör. Structure, HomeDevice vb.) yayınlamak için Kotlin Flow'larına dayanır. Geliştiriciler, nesnede bulunan tüm nesneleri (örneğin, Structure, Room vb.) almak için Flow öğesine abone olur.

Tüm yapıları almak için yapı akışı döndüren structures() işlevini çağırın. Ardından, kullanıcının sahip olduğu tüm yapıları almak için akışta liste işlevini çağırın.

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

Uygulama mimarisi kılavuzu, uygulama veri akışını ve durum yönetimini iyileştirmek için modern bir Reactive programlama yaklaşımının benimsenmesini önemle tavsiye eder.

Örnek Uygulama'nın Reactive kodlama stiline nasıl uyduğu aşağıda açıklanmıştır:

  • Görünüm modelleri (durum tutucu olarak StructureViewModel ve DeviceViewModel gibi), değer değişikliklerini almak ve en son durumları korumak için Home APIs SDK'sındaki akışlara abone olur.
  • Görünümler (ör. StructureView ve DeviceView), durumları almak ve kullanıcı arayüzünü bu değişiklikleri yansıtacak şekilde oluşturmak için görünüm modellerine abone olur.
  • Bir kullanıcı, görünümdeki bir düğmeyi (örneğin, ışık cihazının "Açık" düğmesi) tıkladığında, etkinlikler görünüm modelinin işlevlerini tetikler. Bu işlevler, yanıt veren Home API işlevlerini (örneğin, OnOff özelliğinin On komutu) çağırır.

HomeAppViewModel.kt bölümündeki 5.1.1. adımda, collect() işlevini çağırarak yapı değişikliği etkinliklerine abone oluyoruz. Yapılar API yanıtı tarafından döndürülen ve StructureViewModel's StateFlow içinde sunulan structureSet bölümündeki yorum işaretini kaldırın. Bu, uygulamanın yapı durumundaki değişiklikleri izlemesine olanak tanır:

   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())
//
// }
}

DevicesView.kt içinde uygulama, yapı verileri değiştiğinde kullanıcı arayüzünün yeniden oluşturulmasını tetikleyen StructureViewModel'sStateFlow, öğesine abone olur. Yapı listesini açılır menü olarak oluşturmak için 5.1.2. adımındaki kaynak kodunun yorum işaretini kaldırın:

   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
//          }
//      )
//  }
}
...

Uygulamayı tekrar çalıştırın. Ok simgesine dokunduğunuzda menüyü görürsünüz:

f1fc2be1cb6436b6.png

Yapıyı ayrıştırma

Bir sonraki adım, bir yapıdaki ev nesnelerini geçmektir. Odaları yapıdan alma:

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

Ardından, cihazları almak için odalar arasında gezinebilirsiniz:

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

Önemli: Home APIs veri modelinde, bir yapı odaya atanmamış cihazlar içerebilir. Bu nedenle, uygulamanızda odası olmayan cihazları da yakaladığınızdan emin olun:

val devicesWithoutRooms: MutableSet<HomeDevice> = mutableSetOf()

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

Mevcut örnek kodda, en son oda ve cihaz listesini almak için bir akışa abone oluyoruz. StructureViewModel.kt kaynak dosyasındaki 5.2.1 ve 5.2.2 adımlarındaki kodu kontrol edin ve oda verileri aboneliğini etkinleştirmek için yorum satırı yapmayın:

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)
//   }
    }

Oda listesini menü olarak oluşturmak için DevicesView.kt kaynak dosyasında 5.2.3 ve 5.2.4 adımlarındaki yorum işaretini kaldırın:

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)
//   }
}

Cihazlarınızı edindiğinize göre, şimdi de bu cihazlarla nasıl çalışacağımızı öğreneceğiz.

e715ddda50e04839.png

6. Cihazlarla çalışma

Home API'leri, cihazı ve özelliklerini yakalamak için HomeDevice nesnesini kullanır. Geliştiriciler, cihaz özelliklerine abone olabilir ve bunları uygulamalarında akıllı ev cihazlarını temsil etmek için kullanabilir.

Cihaz durumlarını okuma

HomeDevice nesnesi, cihaz adı veya bağlantı durumu gibi bir dizi statik değer sunar. Geliştirici olarak, cihazı aldıktan kısa süre sonra API'lerden şunları alabilirsiniz:

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

Cihaz özelliklerini almak için HomeDevice'dan türleri ve özellikleri almanız gerekir. Bunu yapmak için cihaz türü akışına aşağıdaki şekilde abone olabilir ve özellikleri cihaz türlerinden alabilirsiniz:

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)
        }

Her cihaz, desteklenen bir dizi DeviceType (paketlenmiş özellikler) içerir. Bu özellikleri device.types() kullanarak alabilirsiniz. Bu cihaz türleri, type.traits() kullanılarak alınabilen özellikler içerir. Her cihaz, türlerinden birini birincil tür olarak işaretler (type.metadata.isPrimaryType kullanılarak kontrol edilebilir). Uygulamanızda bu türü temsil etmeniz gerekir. Kullanıcılara eksiksiz bir deneyim sunmak için döndürülen tüm türleri incelemenizi ve kullanabileceğiniz tüm özellikleri entegre etmenizi öneririz.

Bir özellik aldığınızda, değerleri yorumlamak için aşağıdaki gibi bir işlev kullanarak ayrıştırabilirsiniz:

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 -> ...
    }
}

Bir özelliğin neyi temsil ettiğinin, özelliği içeren cihaz türüne bağlı olarak değişebileceğini unutmayın (önceki örnekteki BooleanState simgesine bakın). Bu nedenle, özelliklerin neyi temsil ettiğini anlamak için her cihaz türünün bağlamını bilmeniz gerekir.

Durumları almak için DeviceViewModel.kt kaynak dosyasında 6.1.1 ve 6.1.2 adımlarındaki yorum işaretini kaldırın:

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
}

Adı ve durumu da dahil olmak üzere bir OnOff özelliğini String olarak oluşturmak için DeviceView.kt bölümünde 6.1.3. adımdaki yorum işaretini kaldırın:

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 -> {
      ...
  }
  ...
}

Uygulamayı şimdi desteklenen cihaz türleriyle (ör. ışık cihazı) çalıştırırsanız tüm cihazların güncel durumları gösterilir.

1bd8b3b2796c4c7a.png

Cihaz komutları verme

Ev API'leri, cihazlara komut göndermek için Özellik nesnelerinde (ör. trait.on() veya trait.moveToLevel(...)) kolaylık sağlayan işlevler sunar:

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

İpucu: Özelliğin türünü belirledikten sonra Android Studio'nun otomatik tamamlama özelliğini kullanarak özellikle etkileşimde bulunmak için hangi işlemlerin kullanılabildiğini görebilirsiniz.

Uygulamaya işlevsel kontroller eklemek için DeviceView.kt içinde 6.2.1. adımı yorumdan çıkarın:

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
//   )
}

Uygulamayı şimdi çalıştırırsanız gerçek hayattaki fiziksel cihazları kontrol etmenize izin vermesi gerekir.

Ampulünüzdeki Açma/Kapama kontrolüne dokunursanız cihaz açılır.

c8ed3ecf5031546e.png

Cihazları kontrol etme hakkında daha fazla bilgi için Android'de cihazları kontrol etme başlıklı makaleyi inceleyin.

7. Cihazları devreye alma

Commissioning API, geliştiricilerin Google Home ekosistemine cihaz eklemesine ve bu cihazların Home API'leri kullanılarak kontrol edilmesini sağlamasına olanak tanır. Yalnızca Matter cihazlar desteklenir. Bu bölümde, uygulamalarınızda cihaz devreye almayı nasıl etkinleştirebileceğinizi ele alacağız.

Bu bölüme başlamadan önce aşağıdaki ön koşulların karşılandığından emin olun:

Devreye alma için QR kodu içeren fiziksel bir Matter cihazınız varsa Devreye alma API'sini etkinleştirme bölümüne geçebilirsiniz. Aksi takdirde, komisyon kazandıran sanal cihazlar oluşturmak için Matter Virtual Device uygulamasını (MVD) nasıl kullanabileceğinizi ele aldığımız bir sonraki bölüme geçin.

İsteğe bağlı: Matter ile kullanıma hazır bir cihaz hazırlayın

Matter'da komisyon alınabilir bir cihaz hazırlamanın en basit yolu, Matter Virtual Device (MVD) uygulaması tarafından sağlanan bir emüle edilmiş cihazı kullanmaktır.

MVD'yi yükleyip güvenlik duvarını ayarladıktan sonra MVD'yi çalıştırın:

b20283893073ac1b.png

OnOff cihazı oluşturun. Henüz görevlendirilmediğini fark edin. Bu codelab'in ilerleyen bölümlerinde görevlendireceksiniz.

5f4855b808312898.png

Commissioning API'yi etkinleştirme

Commissioning API, uygulamanın Etkinliği dışında çalıştığı için devreye alma işleminin diğer Home API'lerinden farklı şekilde yapılması gerekir. Uygulamanızı kullanıma hazırlamak için iki değişkene ihtiyacınız vardır.

Bir değişken, hizmete alma amacını göndermek ve sonuç geri çağırmasını yönetmek için kullanılan ActivityResultLauncher'dır. Diğer değişken ise CommissioningResult'dır. Bu değişken, görevlendirme sonucunu depolamak için kullanılan nesnedir. Komisyonu nasıl ayarlayacağınızla ilgili aşağıdaki örneğe bakın:

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
 }
}

Komisyon alma akışınız ayarlandıktan sonra komisyon alma amacınızı oluşturup önceki örnekte oluşturduğumuz başlatıcıyı kullanarak başlatırsınız. Amacı ve başlatıcıyı aşağıdaki gibi özel bir işleve yerleştirmenizi öneririz. Özel bir işlev, kullanıcı isteğine bağlı olarak bir kullanıcı arayüzü öğesine (ör. +Cihaz Ekle düğmesi) bağlanabilir ve çağrılabilir:

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())
  }
}

CommissioningManager.kt bölümünde 7.1.1 adımındaki yorum işaretini kaldırarak devreye alma özelliğini etkinleştirin ve örnek uygulamada +Cihaz Ekle düğmesinin çalışmasını sağlayın.

// 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())
// }
}

Bu işlevi çalıştırmak, aşağıdaki ekran görüntüsüne benzeyen bir ekranı göstermesi gereken devreye alma akışını başlatır:

baae45588f460664.png

Devreye alma akışını anlama

Hazır hale getirme akışı, kullanıcıya cihazı Google Hesabı'na ekleme konusunda yol gösteren bir dizi ekrandan oluşur:

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

Kullanıcılar, Matter cihazlarındaki QR kodlarını taramak için kullanabilecekleri bir QR kodu tarayıcıyla karşılanır. Ardından, kullanıcı sözleşmesinin gösterilmesi, cihaz keşfi ve devreye alma ile cihaza ad verme işlemleri gerçekleştirilir. Akış tamamlandıktan sonra odak tekrar uygulamaya döner ve önceki bölümde oluşturduğumuz geri çağırma işlevinde komisyon sonucu iletilir.

Commissioning API'lerinin bir avantajı, kullanıcı deneyimi akışının SDK tarafından yönetilmesi sayesinde geliştiricilerin çok hızlı bir şekilde çalışmaya başlayabilmesidir. Bu sayede kullanıcılar, farklı uygulamalarda cihaz eklerken tutarlı bir deneyim yaşar.

Devreye alma API'si hakkında daha fazla bilgi edinmek için Android'de devreye alma API'si başlıklı makaleyi inceleyin.

8. Tebrikler!

Tebrikler! Google Home API'lerini kullanarak Android uygulamasını başarıyla oluşturdunuz. Bu codelab boyunca İzinler, Cihazlar, Yapılar ve Kullanıma Alma API'lerini incelediniz. Bir sonraki codelab'de, Android'de Home API'lerini kullanarak gelişmiş otomasyonlar oluşturma codelab'i, Otomasyon ve Keşif API'lerini inceleyip uygulamayı tamamlayacağız.

Google Home ekosistemindeki cihazları yaratıcı bir şekilde kontrol eden uygulamalar geliştirmekten keyif alacağınızı umuyoruz.

Sonraki adımlar