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

1. Başlamadan önce

Google Home API'leri, Android geliştiricilerin Google Home ekosistemine erişebilmesi için bir dizi kitaplık sağlar. Geliştiriciler bu yeni API'leri kullanarak akıllı ev cihazlarını sorunsuz bir şekilde devreye alan ve 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ı sağlar. Bu codelab, izinler, devreye alma, cihaz ve yapı API'lerinin nasıl kullanılacağı konusunda size yol gösteren örnek uygulamanın bir dalını temel alır.

Ön koşullar

Neler öğreneceksiniz?

  • Google Home API'lerini en iyi uygulamalarla kullanarak Android uygulaması oluşturma.
  • Akıllı evi temsil etmek ve kontrol etmek için Device ve Structure API'lerini kullanma.
  • Google Home ekosistemine cihaz eklemek için Commissioning 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'ı kullanarak 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 taklit cihazların görünüp görünmediğini kontrol edin:

  • outlet1: Açma/kapatma priz
  • light2: Kısılabilir ışık
  • light3: Işığı açma/kapatma
  • ac3: Klima
  • blinds4: Pencere Örtüsü
  • 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çin ve Devam'a dokunun.

e9ec257b0d9b1ed2.png29fd7416e274d216.pngd974573af0611fd8.png

Google Home Playground'ta 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çin ve kurulum işlemini tamamlayın. Ana sayfaya döndüğünüzde mevcut tüm cihazları görürsünüz.

2b021202e6fd1750.png

Listede 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'lerin mimarisi

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

Home SDK'sını ayarlama

En son SDK'yı almak için SDK'yı ayarlama bölümünde açıklanan adımları uygulayın.

Örnek uygulamayı edinme

Örnek uygulamanın kaynak kodunu GitHub'da bulabilirsiniz. Bu kod laboratuvarında, örnek uygulamanın codelab-branch-1 şubesinden alınan örnekler kullanılmaktadır.

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

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

Örnek uygulamayı derleme

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

32f2b3c0cd80fcf1.png

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

3. Kimlik doğrulamayı ayarlama

Home API'leri, yapıdaki cihazlara erişim izni vermek için OAuth 2.0'ı kullanır. OAuth, kullanıcıların giriş kimlik bilgilerini göstermek zorunda kalmadan bir uygulamaya veya hizmete izin vermesine olanak tanır.

İzin ekranını yapılandırmak için OAuth iznini ayarlama başlıklı makaledeki talimatları uygulayın. En az bir test hesabı oluşturduğunuzdan emin olun.

Ardından, uygulamanın kimlik bilgilerini oluşturmak için OAuth kimlik bilgilerini ayarlama başlıklı makaledeki talimatları uygulayın.

4. İlk Kullanıma Hazırlama ve İşleme İzinleri

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 yöneteceğ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 Uygulama'da bunu, HomeApp.kt'teki tamamlayıcı nesnede statik listeler tanımlayarak yapıyoruz. Bu listelere daha sonra uygulama genelinde gerektiğinde 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 özelliklerini görmek için Desteklenen cihaz türleri ve Android'de özellik dizini başlıklı makalelere göz atın.

İzin isteyen kaynak kodunu etkinleştirmek için HomeApp.kt kaynak dosyasında 4.1.1 ve 4.1.2 adımlarının yorumunu 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 kurmanın 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ırlarız.

// 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 almak 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ı, kullanıcı kimlik doğrulaması için kod içerir. Örnek Uygulama'nın izinlerini etkinleştirmek için checkPermissions(...) ve requestPermissions(...) işlevlerinin içeriklerinin yorumunu kaldırın.

Kaydetme:

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 etme:

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

İzin isteyen kodu etkinleştirmek için PermissionsManager.kt dosyasında 4.3.1. adımındaki yorum işaretini kaldırı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()) }
    }
}

Ardından, adımları uygulayarak ve izinleri vererek uygulamayı telefonunuzda çalıştırın. Aşağıdaki akışı göreceksiniz:

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

"Yükleniyor" mesajı hiçbir zaman kaybolmaz. 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 aşağıdakilerden oluşur:

  • Structure, oda ve cihaz 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 örneğinden oluşur.
  • Trait, Attribute örnekleri (okuma/yazma için), Command örnekleri (özellikleri kontrol etmek için) ve Event örnekleri (geçmiş değişikliklerin kayıtlarını okumak veya bunlara abone olmak için) içerir.
  • Automation örnekleri bir yapının parçasıdır ve evdeki görevleri otomatikleştirmek için ev meta verilerini ve cihazları kullanır.

76d35b44d5a8035e.png

Bu bölümde, ev yapılarınızı, odalarınızı, cihazlarınızı vb. ayrıştırmak ve oluşturmak için yapı API'sinin nasıl kullanılacağını gösteren kaynak kodu nasıl geliştireceğinizi öğreneceksiniz.

Yapıları okuma

Home API'lerinin tasarımı, veri modeli nesnelerini (ör. Structure, HomeDevice vb.) aktarmak için Kotlin Flow'larını temel alır. Geliştiriciler, nesneye ait tüm nesneleri (örneğin, Structure, Room vb.) almak için bir Flow'e abone olur.

Tüm yapıları almak için bir 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ıştaki list 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 reaktif programlama yaklaşımı benimsemenizi önemle tavsiye eder.

Örnek uygulama, reaktif kodlama stiline nasıl uyar?

  • Görüntüleme modelleri (durum tutucusu 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 (StructureView ve DeviceView gibi), durumları almak ve kullanıcı arayüzünü bu değişiklikleri yansıtacak şekilde oluşturmak için görüntüleme modellerine abone olur.
  • Kullanıcı bir görünümdeki bir düğmeyi (ör. ışık cihazının "Açık" düğmesi) tıkladığında etkinlikler, yanıt veren Home API'leri işlevlerini (ör. OnOff özelliğinin On komutu) çağıran görünüm modelinin işlevlerini tetikler.

HomeAppViewModel.kt'teki 5.1.1. adımda, collect() işlevini çağırarak yapı değişikliği etkinliklerine abone oluruz. Structures API yanıtı tarafından döndürülen ve StructureViewModel's StateFlow içinde yayınlanan structureSet öğesini gezen bölümün yorumunu kaldırın. Bu, uygulamanın yapı durumu değişikliklerini 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'te uygulama, yapı verileri değiştiğinde kullanıcı arayüzünün yeniden oluşturulmasını tetikleyen StructureViewModel'sStateFlow,'e abone olur. Yapı listesini açılır menü olarak oluşturmak için 5.1.2. adımdaki kaynak kodunun yorumunu 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 taramaktır. Odaları yapıdan alma:

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

Ardından, cihazları almak için odalarda gezinebilirsiniz:

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

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

val devicesWithoutRooms: MutableSet<HomeDevice> = mutableSetOf()

for (device in structure.devices().list())
if (!device.isInRoom)
  devicesWithoutRooms.add(device)

Mevcut örnek kodda da en son Oda ve Cihaz listesini almak için bir akışa abone oluyoruz. StructureViewModel.kt kaynak dosyasında 5.2.1 ve 5.2.2 adımlarındaki kodu kontrol edin ve oda verisi aboneliğini etkinleştirmek için koddaki yorumları kaldırı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.isInRoom)
//               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ının yorumunu 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 elinize ulaştı. Şimdi bunlarla nasıl çalışacağınızı öğreneceğiz.

e715ddda50e04839.png

6. Cihazlarla çalışma

Home API'leri, cihazı ve özelliklerini yakalamak için bir HomeDevice nesnesi 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ı API'lerden aldıktan kısa bir süre sonra aşağıdakileri alabilirsiniz:

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

Cihaz özelliklerini almak için HomeDevice öğesinden türleri ve özellikleri almanız gerekir. Bunu yapmak için cihaz türü akışına aşağıdaki gibi abone olabilir ve cihaz türlerinden özellikleri 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, device.types() kullanarak alabileceğiniz bir dizi desteklenen DeviceType (paketlenmiş özellikler) içerir. Bu cihaz türleri, type.traits() kullanılarak alınabilecek özellikler içerir. Her cihaz, türlerinden birini birincil tür olarak işaretler (type.metadata.isPrimaryType kullanılarak kontrol edilebilir). Bu tür, uygulamanızda temsil etmeniz gereken türdür. 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 özelliği aldıktan sonra, değerleri yorumlamak için aşağıdaki gibi bir işlev kullanarak özelliği 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 temsil ettiği şeyde, özelliğin yer aldığı cihaz türüne bağlı olarak farklılıklar olabileceğini unutmayın (Önceki örnekteki BooleanState özelliğine bakın). Bu nedenle, özelliklerin gerçekten 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ındaki 6.1.1 ve 6.1.2 adımlarının yorumunu 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 dahil olmak üzere bir Açma/Kapatma özelliğini String olarak oluşturmak için DeviceView.kt'teki 6.1.3. adımdaki yorumu 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ı desteklenen cihaz türleriyle (ör. Light cihaz) çalıştırırsanız tüm cihazların güncel durumlarını gösterir.

1bd8b3b2796c4c7a.png

Cihaz komutları verme

Home API'ler, cihazlara komut vermek için trait.on() veya trait.moveToLevel(...) gibi özellik nesnelerinde kolaylık işlevleri sağlar:

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 ne tür işlemler yapabileceğinizi görebilirsiniz.

Uygulamaya işlevsel kontroller eklemek için DeviceView.kt dosyasında 6.2.1. adımındaki yorumu kaldırı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 fiziksel cihazları kontrol edebilirsiniz.

Ampulünüzdeki Açma/Kapatma düğmesine dokunduğunuzda 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ı etkinleştirme

Commissioning API, geliştiricilerin Google Home ekosistemine cihaz eklemesine ve bu cihazları Home API'leri kullanarak kontrol edilebilir hale getirmesine olanak tanır. Yalnızca Matter cihazlar desteklenir. Bu bölümde, uygulamalarınızda cihaz devreye alma özelliğini nasıl etkinleştirebileceğinizi inceleyeceğiz.

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

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

İsteğe bağlı: Matter ile çalıştırılabilen bir cihaz hazırlayın

Matter cihazını komisyona hazır hale getirmenin en kolay yolu, Matter Virtual Device uygulaması (MVD) tarafından sağlanan taklit edilmiş bir cihaz kullanmaktır.

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

b20283893073ac1b.png

Açma/kapatma cihazı oluşturun. Henüz etkinleştirilmediğini unutmayın. Bu codelab'in ilerleyen bölümlerinde etkinleştireceksiniz.

5f4855b808312898.png

Commissioning API'yi etkinleştirme

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

Bu değişkenlerden biri, devreye alma niyetini göndermek ve sonuç geri çağırma işlevini yönetmek için kullanılan ActivityResultLauncher değişkenidir. Diğer değişken ise CommissioningResult'tür. Bu, devreye alma sonucunu depolamak için kullanılan nesnedir. Devreye alma işlemini nasıl ayarlayacağınız hakkında 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
 }
}

Devreye alma akışınız oluşturulduktan sonra, devreye alma amacınızı oluşturur ve önceki örnekte oluşturduğumuz başlatıcıyı kullanarak başlatırsınız. Intent'i ve başlatıcıyı aşağıdaki gibi özel bir işleve yerleştirmenizi öneririz. Özel bir işlev, bir kullanıcı arayüzü öğesine (ör. +Cihaz Ekle düğmesi) bağlanabilir ve kullanıcı isteğine göre ç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())
  }
}

Devreye alma özelliğini etkinleştirmek ve Sana Özel uygulamasında +Cihaz Ekle düğmesinin çalışmasını sağlamak için CommissioningManager.kt dosyasında 7.1.1. adımındaki yorumu kaldırı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ırdığınızda, aşağıdaki ekran görüntüsüne benzeyen bir ekran görüntüleyen devreye alma akışı başlatılır:

baae45588f460664.png

Devreye alma akışını anlama

Devreye alma akışı, kullanıcıya Google Hesabı'na cihaz ekleme konusunda yol gösteren bir dizi ekran içerir:

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

Kullanıcılar, Matter cihazlardaki QR kodlarını taramak için kullanabilecekleri bir QR kodu tarayıcısıyla karşılanır. Ardından kullanıcı sözleşmesi, cihaz bulma ve devreye alma ve cihazın adlandırılması gösterilir. Akış tamamlandığında, akış odağını tekrar uygulamaya değiştirir ve önceki bölümde hazırladığımız geri çağırma işlevine devre alma sonucunu iletir.

Kullanıma Alma API'lerinin avantajlarından biri, kullanıcı deneyimi akışının SDK tarafından yönetilmesidir. Bu sayede geliştiriciler çok hızlı bir şekilde çalışmaya başlayabilir. Bu, kullanıcılara farklı uygulamalarda cihaz eklerken tutarlı bir deneyim de sunar.

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

8. Tebrikler!

Tebrikler! Google Home API'lerini kullanarak başarıyla bir Android uygulaması oluşturdunuz. Bu codelab'de izinleri, cihazları, yapıları ve devreye alma API'lerini incelediniz. Bir sonraki codelab'de (Android'de Home API'lerini kullanarak gelişmiş otomasyonlar oluşturma) Automation ve Discovery API'lerini keşfedecek ve uygulamayı tamamlayacağız.

Google Home ekosistemindeki cihazları yaratıcı bir şekilde kontrol eden uygulamalar geliştirmenin keyfini çıkaracağınızı umuyoruz.

Sonraki adımlar