إنشاء تطبيق Android لـ Matter

‫1. مرحبًا

تم تصميم معيار Matter بهدف توحيد معايير إنترنت الأشياء، وهو يربط الأجهزة المنزلية الذكية في مختلف الأنظمة المتوافقة، مثل Google Home وZigbee وBluetooth Mesh وZ-Wave وغيرها.

تُعد الأجهزة الجوّالة نقطة تفاعل مركزية مع الأجهزة المنزلية الذكية. إذا أردت إنشاء تطبيقات Android خاصة بك لتتوافق مع أجهزة Matter، يمكننا مساعدتك في البدء بسرعة.

يعرض تطبيق Google Home التجريبي لبروتوكول Matter (GHSA for Matter) واجهات برمجة التطبيقات Home Mobile SDK، ما يتيح للمستخدمين إعداد الأجهزة ومشاركتها. يمكنك أيضًا استخدام نموذج التطبيق كأداة تعليمية لفهم مفاهيم Matter الأساسية بشكل أفضل، بالإضافة إلى أداة لتصحيح الأخطاء وتحديد المشاكل وحلّها في التفاعلات مع أجهزة Matter.

الإجراءات التي ستنفذّها

في هذا الدرس التطبيقي حول الترميز، ستنزّل الرمز المصدر لنموذج التطبيق وتتعرّف على كيفية استخدام حزمة تطوير البرامج (SDK) للأجهزة الجوّالة في Home لإعداد الأجهزة ومشاركتها. يمكنك أيضًا التعرّف على كيفية استخدام مكتبات التفويض والتجميع من مستودع Matter (connectedhomeip).

بعد تنزيل التطبيق النموذجي، سنراجع رمز المصدر في "استوديو Android" وننفّذ واجهات برمجة التطبيقات التالية لحزمة Home Mobile SDK:

ستتعرّف أيضًا على المزيد من المعلومات حول مفاهيم الإعداد، وشبكات Matter، وكيفية التحكّم في أجهزة Matter.

المتطلبات

قبل البدء، تأكَّد من إكمال الخطوات التالية:

لا تحتاج إلى مركز تحكّم، مثل Google Nest Hub (الجيل الثاني)، لتشغيل الأجهزة والتحكّم فيها باستخدام نموذج التطبيق.

‫2. طريقة الإعداد

يتوفّر تطبيق البداية الخاص بدرس البرمجة العملي في الفرع codelab. لبدء العمل مع الرمز المصدري لبرنامج codelab، يمكنك تنزيل ملف ZIP.

ستستخدم codelab ملف ZIP هذا لإنشاء نموذج عملي.

إصدارات الدروس التطبيقية حول الترميز

تم وضع علامة codelab على فرع الإصدار 2.0.0 من نموذج التطبيق. ولمقارنة التعديلات أثناء تنفيذ كل خطوة، يمكنك تنزيل الرمز المصدر المكتمل لهذا الإصدار.

إذا أردت استنساخ مستودع GitHub، اتّبِع التعليمات الواردة في ملف README الخاص بنموذج التطبيق.

الاعتمادية

سنقدّم لك الإرشادات بشأن رمز المصدر المطلوب لمشاركة الأجهزة وتوفيرها، ولكن قد يكون من المفيد معرفة التبعيات التالية قبل البدء. يُرجى العِلم أنّه يتم تحديد هذه التبعيات في الملف libs.versions.toml وتحديد استخدامها في الملف build.gradle.kts.

رمز مصدر

تمّ إنشاء واجهة المستخدم ومعظم الوظائف لك مسبقًا.

في هذا الدرس التطبيقي حول الترميز، سنضيف وظائف 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()

يتيح لك ذلك تحديد موقع القسم المناسب في الدرس العملي بسرعة.

3- العمولة المدفوعة إلى Google

قبل أن تتمكّن من التحكّم في الأجهزة والسماح لها بالتواصل مع بعضها البعض ضمن النسيج نفسه، يجب أن يتم إعدادها من قِبل "المُعدّ"، وهو في هذه الحالة هذا التطبيق النموذجي، أي تطبيق Google Home النموذجي المتوافق مع Matter.

من المهم فهم المفاهيم التالية حول عملية إعداد Matter:

  • تسمح الأقمشة للأجهزة بالتواصل مع بعضها البعض.
  • تحتفظ الأقمشة بمجموعة مشتركة من بيانات الاعتماد الفريدة.
  • تكون الأنظمة المتكاملة مسؤولة عن إصدار شهادات الجذر الموثوقة وتحديد معرّفات البنية الأساسية وتحديد معرّفات العُقد الفريدة. النظام الأساسي هو خدمة الخلفية الخاصة بالجهة المسؤولة عن الإعداد، مثل "رسم بياني للمنزل" لنظام Google Home الأساسي.
  • يمكن إعداد الأجهزة لأكثر من شبكة واحدة (ميزة "المشرفون المتعدّدون").

لتفعيل جهاز، عليك استخدام CommissioningClient API. يؤدي طلب إلى .commissionDevice() إلى عرض IntentSender، ما يؤدي إلى تشغيل النشاط المناسب في "خدمات Google Play":

interface CommissioningClient {
  Task<IntentSender> commissionDevice(CommissioningRequest request);
}

في الأقسام التالية، سنتناول الحد الأدنى من الرموز المطلوبة لتفعيل الأجهزة على منصة Google.

الخطوة 1: Activity Launcher

للتعامل مع IntentSender من CommissioningClient، يمكنك استخدام 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.

  1. تبدأ عملية الإعداد باستخدام الدالة commissionDevice(). أولاً، يتم تحديد CommissioningRequest. باستخدام هذا الإعداد التلقائي، يتم إعداد الأجهزة في شبكة Android المحلية فقط.
  2. Matter هي نقطة الدخول إلى حزمة تطوير البرامج (SDK) للأجهزة الجوّالة الخاصة بتطبيق "Google Home". في المكالمة التالية، يحصل .getCommissioningClient على CommissioningClient من خلال this (Activity).
  3. يقبل .commissionDevice() CommissioningRequest.
  4. وأخيرًا، يتم استدعاء .addOnSuccessListener لمعالجة CommissioningResult وتشغيل نشاط Commission Device في "خدمات 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())
        }
}

يمكن الاستفادة من Local Android Fabric من خلال إعدادات Android لتبسيط عملية ربط أجهزتها بشبكات أخرى.

بعد ذلك، ستتعرّف على كيفية إعداد جهاز في بيئة تطوير.

للحصول على نظرة عامة على واجهة المستخدم أثناء عملية الإعداد، يُرجى الرجوع إلى دليل تطبيق Google Home التجريبي لـ Matter.

4. العمولة إلى نسيج التطوير

يمكن إعداد الأجهزة لأكثر من شبكة منزلية واحدة. لإدارة عمليات الاقتران الموثوق بها، تخزِّن الأجهزة FabricTable يحتوي على عناصر FabricInfo مختلفة، مثل:

  • تحديد نوع القماش
  • رقم تعريف العقدة الذي خصّصته البنية للجهاز
  • معرّف المورّد
  • معرّف القماش
  • بيانات اعتماد تشغيل الجهاز

يحدد مدير النطاق الإداري (ADM) بيانات اعتماد البنية الأساسية. في السيناريو السابق، تكون "خدمات Google Play" هي المنظومة المتكاملة التي تعمل كمرجع تصديق جذر (CA) موثوق به. عند إعداد الأجهزة في Local Android fabric، يتضمّن كل جهاز مجموعة بيانات اعتماد fabric نفسها، ومجموعة شهادات CA نفسها.

خدمات التشغيل المخصّصة

لإرسال طلب إلى Local Android fabric، استخدَمنا المَعلمات التلقائية لإنشاء CommissioningRequest في CommissioningClient API:

val request: CommissioningRequest = CommissioningRequest.builder().build()

إذا أردت التحكّم في الأجهزة الجديدة وإدارتها من تطبيقك، عليك إنشاء بنية تطوير محلية والحصول على بيانات الاعتماد التشغيلية لتفعيل الأجهزة. في هذه الحالة، يصبح تطبيقك نظامًا بيئيًا فريدًا ومستقلاً يمنح الأجهزة بيانات اعتماد العُقد المناسبة.

يمكنك إبلاغ حزمة تطوير البرامج (SDK) لتطبيق "Google Home" للأجهزة الجوّالة بأنّك تريد إعداد الأجهزة في شبكتك الخاصة من خلال تمرير خدمة مخصّصة إلى CommissioningRequest:

class CommissioningRequest {
  static CommissioningRequest.Builder builder();

  class Builder {
    Builder setCommissioningService(@Nullable ComponentName commissioningService);

    CommissioningRequest build();
  }
}

في الخطوات التالية، سنعدّل الدالة commissionDevice() لاستخدام خدمة مخصّصة. سنضيف أيضًا "مشغّل الأنشطة" إلى جزء "الصفحة الرئيسية"، وسنستخدم عناصر LiveData لإدارة مسار واجهة برمجة التطبيقات.

الخطوة 1: إنشاء مشغّل لنشاط نظام تحديد المواقع العالمي (GPS)

أولاً، لننشئ Activity Launcher لمعالجة IntentSender من CommissioningClient API.

  1. افتح HomeScreen في المجلد java/com/google/homesampleapp/screens/home/.
  2. استبدِل التعليق // 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: استدعاء واجهة برمجة التطبيقات

  1. لا يزال في HomeScreen.kt في المجلد java/com/google/homesampleapp/screens/home
  2. استبدِل التعليق // CODELAB: commissionDevice بالتعليق التالي commissionDeviceRequest. يربط setCommissioningService السمة AppCommissioningService بمثيل CommissioningService، ويتم عرضها في دالة رد اتصال. عند تمرير خدمة مخصّصة، ستكلّف حزمة تطوير البرامج (SDK) للأجهزة الجوّالة في المنزل الأجهزة أولاً بالانضمام إلى شبكة Android المحلية، ثم سترسل حمولة الإعداد إلى AppCommissioningService.
    val commissionDeviceRequest =
        CommissioningRequest.builder()
            .setCommissioningService(ComponentName(
                context, AppCommissioningService::class.java))
            .build()
    
  3. اتّصِل بالرقم .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()، طلبنا الحصول على CommissioningService من CommissioningClient API. في هذا المسار، تعمل واجهة برمجة التطبيقات CommissioningClient على إعداد الأجهزة في Local Android fabric أولاً، ثم تعرض دالة رد اتصال تتضمّن الكائن 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 المخصّصة. في ما يلي نظرة عامة سريعة على وظائف الخدمة. للمتابعة، افتح AppCommissioningService في java/commissioning.

أضفنا عمليات الاستيراد التالية لواجهات برمجة التطبيقات الخاصة بحزمة Home Mobile SDK:

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

لإضافة أجهزة إلى بيئة تطوير التطبيق، يُرجى إكمال الخطوات التالية:

  1. فتح AppCommissioningService في java/commissioning.
  2. ابحث عن الدالة onCommissioningRequested(). لقد قدّمنا رسالة سجلّ تطبع CommissioningRequestMetadata. استبدِل التعليق // CODELAB: onCommissioningRequested() لبدء روتين serviceScope الفرعي والحصول على deviceId.
    // Perform commissioning on custom fabric for the sample app.
    serviceScope.launch {
      val deviceId = devicesRepository.incrementAndReturnLastDeviceId()
    
  3. إجراء عملية الإعداد بالنسبة إلى هذه الخطوة، يمكننا تمرير معلومات الجهاز التي تم عرضها في كائن CommissioningRequestMetadata. تستخدم ChipClient معلومات البيانات الوصفية هذه لإنشاء قناة آمنة بين تطبيق GHSA for Matter وجهازك.
    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
    }
    
  4. استخدِم 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 بت.

6. التحكّم في الأجهزة

يتيح لك الإعداد في بيئة تطوير استخدام المكتبات من مستودع Matter (connectedhomeip) للتحكّم في الأجهزة من نموذج التطبيق.

لقد أنشأنا بعض الفئات المساعدة لتسهيل الوصول إلى مجموعات الأجهزة وإرسال الأوامر. لمزيد من المعلومات، افتح ClustersHelper في java/clusters. يستورد برنامج Singleton المساعد المكتبات التالية للوصول إلى معلومات الجهاز:

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 أوامر عبر قناة التشغيل الآمنة التي تم إنشاؤها أثناء عملية الإعداد.

على الجهاز، يتم التحقّق من صحة الحِزم وفك تشفيرها ثم إرسالها باستخدام دالة رد الاتصال. تتضمّن دوال ردّ الاتصال EndpointId وClusterId وAttributeId، ويمكن الوصول إليها من attributePath. على سبيل المثال، يمكن تنفيذ هذه التعليمات البرمجية على جهاز متوافق مع 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;
}

في الخطوات التالية، ستستخدم حزمة تطوير البرامج (SDK) الخاصة بـ Matter وClustersHelper لتبديل حالة الجهاز.

  1. انتقِل إلى DeviceViewModel في java/screens/device.
  2. ابحث عن الدالة updateDeviceStateOn.
  3. استبدِل التعليق // 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.

في الخطوات السابقة، تعرّفنا على أنّ حزمة تطوير البرامج (SDK) الخاصة بتطبيق Home Mobile تتيح إعداد الأجهزة في شبكة Local Android، وكذلك في شبكة تطوير لنموذج التطبيق. هذا مثال على عملية الإعداد المتعددة، حيث يمكن إعداد الأجهزة في أكثر من شبكة واحدة.

الآن، قد تحتاج إلى مشاركة الأجهزة مع المزيد من الأقمشة، خاصةً إذا كان هذا منزلًا يفضّل فيه كل فرد تطبيقات ومنصات مختلفة.

توفّر حزمة Home Mobile SDK هذه الوظيفة في ShareDeviceRequest API، ما يتيح لك إجراء ما يلي:

  1. افتح نافذة إعداد مؤقتة للأجهزة.
  2. غيِّر حالة أجهزتك لتتمكّن من إضافتها إلى شبكة أخرى.
  3. التحكّم في أجهزتك من تطبيقات وأنظمة بيئية أخرى

في الخطوات التالية، ستستخدم حزمة تطوير البرامج (SDK) للأجهزة الجوّالة في المنزل لمشاركة الأجهزة.

الخطوة 1: إنشاء مشغّل لنشاط نظام تحديد المواقع العالمي (GPS)

على غرار أداة تشغيل نشاط الإعداد التي أنشأناها عند الإعداد في بيئة تطوير، أنشأنا أداة تشغيل نشاط مشاركة الجهاز للتعامل مع IntentSender من CommissioningClient API.

  1. افتح DeviceScreen في المجلد java/com/google/homesampleapp/screens/device/.
  2. استبدِل التعليق // 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 إشارة إلى واجهة المستخدم لإعلامها بذلك. يتم التواصل بين ViewModel وواجهة المستخدم من خلال عناصر 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: استدعاء واجهة برمجة التطبيقات

حان الوقت الآن لبدء مهمة مشاركة الجهاز.

  1. افتح DeviceScreen.kt في مجلد java/com/google/homesampleapp/screens/device/.
  2. ابحث عن الدالة shareDevice(). استبدِل التعليق // CODELAB: shareDevice بالتعليق ShareDeviceRequest. تقدّم السمة DeviceDescriptor معلومات محدّدة عن الجهاز، مثل معرّف المورّد ومعرّف المنتج ونوع الجهاز. في هذا المثال، نُضمِّن القيم بشكل ثابت.
    val shareDeviceRequest =
      ShareDeviceRequest.builder()
        .setDeviceDescriptor(DeviceDescriptor.builder().build())
        .setDeviceName("GHSAFM temp device name")
    
  3. اضبط CommissioningWindow والمَعلمات.
        .setCommissioningWindow(
            CommissioningWindow.builder()
                .setDiscriminator(Discriminator.forLongValue(DISCRIMINATOR))
                .setPasscode(SETUP_PIN_CODE)
                .setWindowOpenMillis(SystemClock.elapsedRealtime())
                .setDurationSeconds(OPEN_COMMISSIONING_WINDOW_DURATION_SECONDS.toLong())
                .build())
        .build()
    
  4. استدعِ الدالة .getCommissioningClient()، ولكن استخدِم واجهة برمجة التطبيقات .shareDevice() هذه المرة.
    Matter.getCommissioningClient(context)
        .shareDevice(shareDeviceRequest)
    

تقدّم دالة معاودة الاتصال الناجحة لواجهة برمجة التطبيقات commissioningClient.shareDevice() السمة IntentSender التي سيتم استخدامها لتشغيل ميزة "مشاركة نشاط الجهاز" في "خدمات Google Play".

  1. لإكمال الدالة shareDevice، أضِف addOnSuccessListener وaddOnFailureListener. في حال النجاح، يتم استدعاء launch على shareDeviceLauncher لتشغيل نشاط نظام تحديد المواقع العالمي (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.

يمكن لأجهزتك الآن المشاركة في ثلاث شبكات:

  1. The Local Android fabric.
  2. نسيج التطوير (هذا التطبيق)
  3. هذه هي الشبكة الثالثة التي شاركت الجهاز معها للتو.

8. الخطوات التالية

تهانينا

تهانينا، لقد أكملت هذا الدرس التطبيقي حول الترميز بنجاح وتعرّفت على كيفية إعداد الأجهزة ومشاركتها باستخدام حزمة تطوير البرامج (SDK) لتطبيق Home على الأجهزة الجوّالة.

إذا كنت تواجه مشاكل في نموذج التطبيق، جرِّب إكمال الخطوات التالية لإثبات ملكية بيئتك:

إذا كانت لديك أسئلة حول استخدام نموذج التطبيق أو اكتشفت خطأً في الرمز البرمجي، يمكنك إرسال المشاكل إلى Issue Tracker في مستودع GitHub:

للحصول على إرشادات رسمية من Google بشأن الأسئلة الفنية، يمكنك استخدام "منتدى المطوّرين في المنزل الذكي":

للحصول على الدعم الفني من المنتدى، استخدِم العلامة google-smart-home على Stack Overflow: