重要な Android アプリを作成する

1. ようこそ

IoT 規格を統合することを目的に構築された Matter は、Google Home、Zigbee、Bluetooth メッシュ、Z-Wave などのさまざまなエコシステムにわたってスマートホーム デバイスを接続します。

モバイル デバイスは、スマートホーム デバイスの中心的なインタラクション ポイントです。Matter 対応デバイスをサポートする独自の Android アプリを作成する場合は、

Matter 用 Google Home サンプルアプリ(GHSA for Matter)では、Home Mobile SDK API が紹介され、ユーザーはデバイスの試し共有を行えます。また、Matter の主要な概念と、Matter デバイスとのやり取りのデバッグとトラブルシューティングを行うためのツールとして、サンプルアプリを使用することもできます。

演習内容

この Codelab では、サンプルアプリのソースコードをダウンロードし、Home Mobile SDK を使用してデバイスをコミッションして共有する方法を学びます。コミッショニング ライブラリとクラスタ ライブラリの使用方法は、Matter リポジトリ(connectedhomeipでも学ぶことができます。

サンプルアプリをダウンロードしたら、Android Studio でソースコードを確認し、Home Mobile SDK API を実装します。

また、コミッショニングのコンセプト、Matter ファブリック、Matter デバイスの操作方法についても学習します。

必要なもの

始める前に、次の手順を完了してください。

サンプルアプリでデバイスのコミッショニングと制御を行うのに、Google Nest Hub(第 2 世代)などのハブは必要ありません。

2. セットアップする

サンプルアプリの GitHub リポジトリには、Matter リポジトリ(connectedhomeipのサードパーティ ライブラリが含まれています。これらのネイティブ ライブラリは 50 MB を超えており、Git Large Storage(LFS)を使用する必要があります。

Codelab スターター アプリは codelab ブランチにあります。Codelab のソースコードの使用を開始するには、ZIP ファイルをダウンロードします。この ZIP には、Git LFS を必要とせずに Matter SDK ネイティブ ライブラリが含まれています。

この ZIP ファイルを使用して、作業サンプルを作成します。codelab

Codelab のバージョン

codelab ブランチは、サンプルアプリの 1.2.2 リリースでタグ付けされています。各ステップを進めている間にアップデートを比較するには、このリリースの完成したソースコードをダウンロードできます。

GitHub リポジトリのクローンを作成する場合は、サンプルアプリの README の手順を行ってください。

依存関係

デバイスの共有とコミッショニングに必要なソースコードについて説明しますが、使用開始前に次の依存関係を認識しておくと便利です。

  • Home Mobile SDK
    implementation 'com.google.android.gms:play-services-home:16.0.0'
    
  • Matter SDK ライブラリ
    // Native libs
    implementation fileTree(dir: "third_party/connectedhomeip/libs", include: ["*.jar", "*.so"])
    
  • マテリアル デザイン詳しくは、MDC-103 Android: 色、高度、タイプ(Kotlin)によるマテリアル テーマ設定マテリアル テーマビルダーをご覧ください。
    implementation 'com.google.android.material:material:1.5.0'
    
  • Proto DataStore。アプリデータを保持するために使用します。Datastore リポジトリとシリアライザーは、java/data に格納されます。これには、デバイスのスキーマやユーザー設定も含まれます。DataStore の詳細については、Proto DataStore の操作をご覧ください。
    implementation "androidx.datastore:datastore:$dataStoreVersion"
    implementation 'androidx.datastore:datastore-core:1.0.0'
    implementation 'com.google.protobuf:protobuf-javalite:3.18.0'
    
  • Hilt: データを保持し、依存関係インジェクションをサポートします。
    kapt 'com.google.dagger:hilt-compiler:2.41'
    implementation 'com.google.dagger:hilt-android:2.41'
    

ソースコード

ユーザー インターフェースとほとんどの機能はすでに作成されています。

この Codelab では、次のファイルに Matter 機能を追加します。

  • java/commissioning/AppCommissioningService: デバイスの開発ファブリックへのコミッショニングを許可します。
  • java/screens/HomeFragmentjava/screens/HomeViewModel.kt: Home Mobile SDK のコミッショニング機能が含まれます。
  • java/screens/DeviceViewModel: Share Device API 呼び出しが含まれます。

各ファイルには、変更するコードブロックがコメントされています。次に例を示します。

// CODELAB: add commissioningFunction()

これにより、Codelab の対応するセクションをすばやく見つけることができます。

3. Google へのコミッション

デバイスを管理し、同じファブリック内で相互に通信できるようにするには、コミッショナー(この場合は Matter 用の Google Home サンプルアプリ)から委託する必要があります。

Matter のコミッショニングについて、次のコンセプトを理解しておくことが重要です。

  • ファブリックを使用すると、デバイスが相互に通信できます。
  • ファブリックは、一意の認証情報の共有セットを保持します。
  • エコシステムは、信頼できるルート証明書を発行し、ファブリック ID を割り当て、一意のノード ID を割り当てます。エコシステムとは、Google Home エコシステムのホームグラフなど、コミッショナーのバックエンド サービスです。
  • デバイスは、複数のファブリックにコミッショニングできます(マルチ管理機能)。

デバイスのコミッショニングを行うには、CommissioningClient API を使用する必要があります。.commissionDevice() を呼び出すと、IntentSender が返されます。これにより、Google Play 開発者サービスで適切なアクティビティが開始されます。

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

次のセクションでは、デバイスを Google のファブリックに委託するために必要な最小限のコードについて説明します。

ステップ 1: アクティビティ ランチャー

CommissioningClient から IntentSender を処理するには、ActivityResultLauncher を使用します。

private lateinit var commissioningLauncher: ActivityResultLauncher<IntentSenderRequest>
commissioningLauncher = registerForActivityResult(
    StartIntentSenderForResult()
) { result: ActivityResult ->
    if (result.resultCode == RESULT_OK) {
        Timber.d(TAG, "Commissioning succeeded.")
    } else {
        Timber.d(TAG, "Commissioning failed. " + result.resultCode)
    }
}

ステップ 2: コミッショニング機能

基本的な例では、CommitmentClient API を使用してデバイスを Google のファブリックにコミッショニングします。

  1. コミッショニング プロセスは commissionDevice() 関数から始まります。まず、CommissioningRequest を定義します。このデフォルト構成では、デバイスはローカル Android ファブリックにのみコミッションされます。
  2. Matter は、Home Mobile SDK のエントリ ポイントです。次の呼び出しで、.getCommissioningClientthis(Activity)までに CommissioningClient を取得します。
  3. .commissionDevice()CommissioningRequest を受け入れます。
  4. 最後に、.addOnSuccessListener を呼び出して CommissioningResult を処理し、Google Play 開発者サービス(GPS)のコミッション デバイス アクティビティを起動します。
private fun commissionDevice() {
    val request: CommissioningRequest = CommissioningRequest.builder().build()
    Matter.getCommissioningClient(this)
        .commissionDevice(request)
        .addOnSuccessListener { result ->
            commissioningLauncher.launch(IntentSenderRequest.Builder(result).build())
        }
}

ローカル Android ファブリックは、Android の設定を介して、デバイスを他のファブリックにコミッショニングするプロセスを簡素化できます。

次に、開発ファブリックにデバイスをコミッショニングする方法について学びます。

コミッショニング プロセス中のユーザー インターフェースの概要については、Matter ガイドの Google Home サンプルアプリをご覧ください。

4. 開発ファブリックへのコミッション

デバイスは、複数のファブリックにコミッショニングできます。信頼できるペア設定を管理するため、デバイスは次のようなさまざまな FabricInfo メンバーを含む FabricTable を保存します。

  • ファブリックの識別
  • ファブリックによってデバイスに割り当てられたノード ID
  • ベンダー ID
  • ファブリック ID
  • デバイスの運用クルデンシャル

管理ドメイン マネージャー(ADM)は、ファブリック認証情報を定義します。上記のシナリオでは、Google Play 開発者サービスは信頼できるルート認証局(CA)として機能するエコシステムです。デバイスをローカル Android ファブリックにコミックする場合、各デバイスには、同じファブリック認証情報セットと同じ CA セットが含まれます。

カスタム コミッショニング サービス

ローカル Android ファブリックにコミッションするために、デフォルトのパラメータを使用して、CommitingClient API で CommissioningRequest を構築しました。

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

アプリから新しいデバイスを制御および管理する場合は、ローカルの開発ファブリックを作成し、デバイスをコミッショニングするための運用認証情報を取得する必要があります。このシナリオでは、アプリは適切なノード認証情報をデバイスに割り当てる一意の独立したエコシステムになります。

デバイスを自分のファブリックにコミックするように Home Mobile SDK に伝えるには、CommissioningRequest にカスタム サービスを渡します。

class CommissioningRequest {
  static CommissioningRequest.Builder builder();

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

    CommissioningRequest build();
  }
}

次のステップでは、カスタム サービスを使用するように commissionDevice() 関数を変更します。また、ホーム フラグメントにアクティビティ ランチャーを追加し、LiveData オブジェクトを使用して API フローを管理します。

ステップ 1: GPS アクティビティ ランチャーを作成する

まず、CommissioningClient API の IntentSender を処理するアクティビティ ランチャーを作成します。

  1. java/screens/home/ フォルダで HomeFragment を開きます。
  2. // CODELAB: commissionDeviceLauncher declaration コメントを次の宣言に置き換えます。
    // The ActivityResult launcher that launches the "commissionDevice" activity in Google Play
    // Services.
    private lateinit var commissionDeviceLauncher: ActivityResultLauncher<IntentSenderRequest>
    
  3. コミッション アクティビティの結果を登録して処理するには、// CODELAB: commissionDeviceLauncher definition コメントを次のコードに置き換えます。
    commissionDeviceLauncher =
        registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
          // Commission Device Step 5.
          // The Commission Device activity in GPS has completed.
          val resultCode = result.resultCode
          if (resultCode == Activity.RESULT_OK) {
            Timber.d("CommissionDevice: Success")
            // We now need to capture the device information for the app's fabric.
            // Once this completes, a call is made to the viewModel to persist the information
            // about that device in the app.
            showNewDeviceAlertDialog(result)
          } else {
            viewModel.commissionDeviceFailed(resultCode)
          }
        }    ```
    
    

ステップ 2: LiveData オブジェクトを作成する

.commissionDevice() API の成功コールバックは、Google Play 開発者サービスでコミッション デバイス アクティビティを起動するための IntentSender を提供します。HomeViewModel で、この API 呼び出しの結果をレポートする 2 つの LiveData オブジェクトを作成します。

  • commissionDeviceStatus: TaskStatus をトラッキングする
  • commissionDeviceIntentSender: .commissionDevice() 呼び出しの結果を処理します。この LiveData オブジェクトにより、作成した ActivityLauncher が起動し、GPS コミッションのデバイス アクティビティがユーザーに表示されます。
  1. private fun setupObservers() で、// CODELAB: commissionDeviceStatus コメントを次のオブザーバーに置き換えます。
    // The current status of the share device action.
    viewModel.commissionDeviceStatus.observe(viewLifecycleOwner) { status ->
      Timber.d("commissionDeviceStatus.observe: status [${status}]")
    }
    
  2. 次に、// CODELAB: commissionDeviceIntentSender コメントを次のオブザーバーに置き換えます。
    viewModel.commissionDeviceIntentSender.observe(viewLifecycleOwner) { sender ->
      Timber.d(
          "commissionDeviceIntentSender.observe is called with [${intentSenderToString(sender)}]")
      if (sender != null) {
        // Commission Device Step 4: Launch the activity described in the IntentSender that
        // was returned in Step 3 (where the viewModel calls the GPS API to commission
        // the device).
        Timber.d("CommissionDevice: Launch GPS activity to commission device")
        commissionDeviceLauncher.launch(IntentSenderRequest.Builder(sender).build())
        viewModel.consumeCommissionDeviceIntentSender()
      }
    }
    

ステップ 3: API を呼び出す

API フローを処理するコードを作成したので、次は API を呼び出し、カスタム サービス(次のステップで定義します)を渡して、LiveData オブジェクトに送信します。

  1. java/screens/home/ フォルダで HomeViewModel.kt を開きます。
  2. // CODELAB: commissionDevice コメントを次の commissionDeviceRequest に置き換えます。setCommissioningService は、コールバック関数で返される CommissioningService インスタンスに AppCommissioningService をバインドします。カスタム サービスを渡すと、Home Mobile SDK はまずデバイスを Google ファブリックにコミッショニングしてから、オンボーディング ペイロードを AppCommissioningService に送り返します。
    fun commissionDevice(context: Context) {
      _commissionDeviceStatus.postValue(TaskStatus.InProgress)
    
      val commissionDeviceRequest =
          CommissioningRequest.builder()
              .setCommissioningService(ComponentName(context, AppCommissioningService::class.java))
              .build()
    
  3. .getCommissioningClient() を呼び出してから、.commissionDevice() を呼び出します。
    Matter.getCommissioningClient(context)
        .commissionDevice(commissionDeviceRequest)
    

commissionDevice 関数を完成させるには、addOnSuccessListeneraddOnFailureListener を追加し、LiveData オブジェクトに送信します。

      .addOnSuccessListener { result ->
        // Communication with fragment is via livedata
        _commissionDeviceIntentSender.postValue(result)
      }
      .addOnFailureListener { error ->
        Timber.e(error)
        _commissionDeviceStatus.postValue(
          TaskStatus.Failed("Failed to to get the IntentSender.", error)
      }
}

構成の変更後に送信者が再度受信されないように、送信者の使用後に consumeCommissionDeviceIntentSender() を呼び出す必要があります。

  /**
   * Consumes the value in [_commissionDeviceIntentSender] and sets it back to null. Needs to be
   * called to avoid re-processing the IntentSender after a configuration change (where the LiveData
   * is re-posted).
   */
  fun consumeCommissionDeviceIntentSender() {
    _commissionDeviceIntentSender.postValue(null)
  }

5. コミッショニング サービスを作成する

commissionDevice() 関数で、CommitingClient API から CommissioningService を取得することをリクエストしました。このフローでは、CommitmentClient API はまずデバイスをローカル Android ファブリックにコミッショニングし、次に CommissioningRequestMetadata オブジェクトを含むコールバックを返します。

public interface CommissioningService {
interface Callback {
    void onCommissioningRequested(CommissioningRequestMetadata metadata);
  }
}

次は、CommitingService.Callback を継承し、サンプルアプリにデバイスをコミッションするために必要な機能を提供する必要があります。以下は、CommitingService の基本的な実装例です。

class MatterCommissioningService : Service(), CommissioningService.Callback {
   private val commissioningServiceDelegate =
     CommissioningService.Builder(this)
       .setCallback(this)
       .build()

   override fun onBind(intent: Intent) = commissioningServiceDelegate.asBinder()

   override fun onCommissioningRequested(metadata: CommissioningRequestMetadata) {
     // perform commissioning

     commissioningServiceDelegate
       .sendCommissioningComplete(CommissioningCompleteMetadata.builder().build())
   }
 }

ステップ 1: カスタムの AppCommissioningService を確認する

簡単に開始できるように、カスタムの CommissioningService の基本的なクラス構造を定義しています。ここでは、サービスの機能の概要を簡単に説明します。手順は次のとおりです。java/commissioningAppCommissioningService を開きます。

Home Mobile SDK API 用に次のインポートを追加しました。

import com.google.android.gms.home.matter.commissioning.CommissioningCompleteMetadata
import com.google.android.gms.home.matter.commissioning.CommissioningRequestMetadata
import com.google.android.gms.home.matter.commissioning.CommissioningService

AppCommissioningService には、Matter リポジトリ(connectedhomeipのライブラリも含まれています。

import com.google.home_sample_app_for_matter.chip.ChipClient

最後に、サービスには、HiltKotlin コルーチンをサポートするためのインポートが含まれています。

次に、コンストラクタを作成して、セットアップ完了時に Google Play 開発者サービスに通知するために使用する commissioningServiceDelegate などをセットアップします。

private lateinit var commissioningServiceDelegate: CommissioningService
...
commissioningServiceDelegate = CommissioningService.Builder(this).setCallback(this).build()

では、コミッショニング関数を追加しましょう。

ステップ 2: onCommissioningRequested をオーバーライドする

デバイスをアプリの開発ファブリックにコミックするには、次の手順を行います。

  1. java/commissioningAppCommissioningServiceを開きます。
  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このメタデータ情報を使用して、Matter アプリとデバイスの GHSA 間に安全なチャネルが作成されます。
    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)
    
  4. commissioningServiceDelegate を使用して、Google Play 開発者サービスにコミッショニングが完了したことを知らせます。.sendCommissioningComplete() で、CommissioningCompleteMetadata を渡します。
      Timber.d("Commissioning: Calling commissioningServiceDelegate.sendCommissioningComplete()")
      commissioningServiceDelegate
          .sendCommissioningComplete(
              CommissioningCompleteMetadata.builder().setToken(deviceId.toString()).build())
          .addOnSuccessListener {
              Timber.d("Commissioning: OnSuccess for commissioningServiceDelegate.sendCommissioningComplete()")
          }
          .addOnFailureListener { ex -> 
            Timber.e(ex, "Commissioning: Failed to send commissioning complete.", ex)
          }
    }
    

アプリを実行する

ローカル ファブリックにコミッションするために必要なすべてのコードを用意したら、次はテストします。Android デバイスを選択して、アプリを実行します。ホーム画面で [Add Device] をタップし、デバイスのコミッショニング手順を完了します。

コミッショニングが完了すると、デバイスがローカル Android ファブリックとローカル開発ファブリックという 2 つのファブリックに参加するようになります。各ファブリックには独自の認証情報セットと一意の 64 ビット ファブリック ID があります。

6. デバイスの操作

開発ファブリックでは、Matter リポジトリ(connectedhomeipのライブラリを使用してサンプルアプリからデバイスを制御できます。

デバイス クラスタへのアクセスとコマンドの送信を容易にするヘルパークラスを作成しました。詳細を確認するには、java/clustersClustersHelper を開いてください。このシングルトン ヘルパーは、デバイス情報にアクセスするための次のライブラリをインポートします。

import chip.devicecontroller.ChipClusters
import chip.devicecontroller.ChipStructs

このクラスを使用して、デバイスのオン/オフ クラスタを取得し、.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;
}

次の手順では、Matter SDK と ClustersHelper を使用してデバイスを切り替えます。

  1. java/screens/deviceDeviceViewModel に移動します。
  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")
        }
    

この関数は DeviceFragment から呼び出されます。

// Change the on/off state of the device
binding.onoffSwitch.setOnClickListener {
  val isOn = binding.onoffSwitch.isChecked
  viewModel.updateDeviceStateOn(selectedDeviceViewModel.selectedDeviceLiveData.value!!, isOn)
}

アプリを実行する

アプリを実行して、更新内容を再読み込みします。ホーム画面でデバイスのオンとオフを切り替えます。

7. デバイスを他のエコシステムと共有する

Matter 仕様では、デバイスの共有をマルチ管理フローと呼びます。

これまでのステップで、Home Mobile SDK を使用して、デバイスをローカルの Android ファブリックと、サンプルアプリ用の開発ファブリックにコミッショニングできることを学びました。これは、デバイスを複数のファブリックにコミッショニングできるマルチ管理フローの例です。

特に、アプリケーションやプラットフォームに関してユーザーが独自の好みを持つ家庭の場合は、さらに多くのファブリックでデバイスを共有することをおすすめします。

Home Mobile SDK は、ShareDeviceRequest API にこの機能を提供し、次のことが可能になります。

  1. デバイスの一時的なコミッショニング ウィンドウを開きます。
  2. デバイスの状態を変更して、別のファブリックでコミッショニングできるようにします。
  3. 他のアプリやエコシステムからデバイスを操作できます。

次のステップでは、Home Mobile SDK を使用してデバイスを共有します。

ステップ 1: GPS アクティビティ ランチャーを作成する

開発ファブリックに委託したときに作成したコミッション アクティビティ ランチャーと同様に、CommitingClient API から IntentSender を処理する共有デバイス アクティビティ ランチャーを作成しました。

  1. java/screens/device/ フォルダで DeviceFragment を開きます。
  2. // CODELAB: shareDeviceLauncher definition コメントを次のコードに置き換えて、.shareDevice() アクティビティの結果を登録して処理します。
    shareDeviceLauncher =
        registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
          // Share Device Step 5.
          // The Share Device activity in GPS (step 4) has completed.
          val resultCode = result.resultCode
          if (resultCode == RESULT_OK) {
            Timber.d("ShareDevice: Success")
            viewModel.shareDeviceSucceeded(selectedDeviceViewModel.selectedDeviceLiveData.value!!)
          } else {
            viewModel.shareDeviceFailed(
                selectedDeviceViewModel.selectedDeviceLiveData.value!!, resultCode)
          }
        }
    

ステップ 2: LiveData オブジェクトを確認する

.shareDevice() API の成功コールバックは、Google Play 開発者サービスで「デバイス共有」アクティビティを起動するための IntentSender を提供します。DeviceViewModel では、この API 呼び出しの結果をレポートする 2 つの LiveData オブジェクトを作成しました。

  • _shareDeviceStatus: TaskStatus をトラッキングする
    // The current status of the share device action.
    viewModel.shareDeviceStatus.observe(viewLifecycleOwner) { status ->
      val isButtonEnabled = status !is InProgress
      updateShareDeviceButton(isButtonEnabled)
      if (status is TaskStatus.Failed) {
        showAlertDialog(errorAlertDialog, status.message, status.cause!!.toString())
      }
    }
    
  • _shareDeviceIntentSender: .sharedevice() 呼び出しの結果を処理します。
    viewModel.shareDeviceIntentSender.observe(viewLifecycleOwner) { sender ->
      Timber.d("shareDeviceIntentSender.observe is called with [${intentSenderToString(sender)}]")
      if (sender != null) {
        // Share Device Step 4: Launch the activity described in the IntentSender that
        // was returned in Step 3 (where the viewModel calls the GPS API to commission
        // the device).
        Timber.d("ShareDevice: Launch GPS activity to share device")
        shareDeviceLauncher.launch(IntentSenderRequest.Builder(sender).build())
        viewModel.consumeShareDeviceIntentSender()
      }
    }
    

次の手順では、これらの LiveData オブジェクトを .shareDevice() API 呼び出しで使用します。

ステップ 3: API を呼び出す

デバイス共有タスクを開始します。

  1. java/screens/device/ フォルダで DeviceViewModel.kt を開きます。
  2. shareDevice() 関数を見つけます。// CODELAB: shareDevice コメントを ShareDeviceRequest に置き換えます。DeviceDescriptor には、ベンダー ID、プロダクト ID、deviceType など、デバイスに関する特定の情報が表示されます。この例では、値をハードコードしています。
      Timber.d("ShareDevice: Setting up the IntentSender")
      val shareDeviceRequest =
          ShareDeviceRequest.builder()
              .setDeviceDescriptor(DeviceDescriptor.builder().build())
              .setDeviceName("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() API を使用します。commissioningClient.shareDevice() API の成功コールバックは、Google Play 開発者サービスで「デバイス共有」アクティビティを起動する際に使用する IntentSender を提供します。
    Matter.getCommissioningClient(activity)
        .shareDevice(shareDeviceRequest)
    
  5. shareDevice 関数を完成させるには、addOnSuccessListeneraddOnFailureListener を追加し、LiveData オブジェクトに送信します。
          .addOnSuccessListener { result ->
            Timber.d("ShareDevice: Success getting the IntentSender: result [${result}]")
            // Communication with fragment is via livedata
            _backgroundWorkAlertDialogAction.postValue(BackgroundWorkAlertDialogAction.Hide)
            _shareDeviceIntentSender.postValue(result)
          }
          .addOnFailureListener { error ->
            Timber.e(error)
            _backgroundWorkAlertDialogAction.postValue(BackgroundWorkAlertDialogAction.Hide)
            _shareDeviceStatus.postValue(
                TaskStatus.Failed("Setting up the IntentSender failed", error))
          }
    

構成の変更後に送信者が再度受信されないように、送信者の使用後に consumeShareDeviceIntentSender を呼び出す必要があります。

  /**
   * Consumes the value in [_shareDeviceIntentSender] and sets it back to null. Needs to be called
   * to avoid re-processing an IntentSender after a configuration change where the LiveData is
   * re-posted.
   */
  fun consumeShareDeviceIntentSender() {
    _shareDeviceIntentSender.postValue(null)
  }

アプリを実行する

Matter デバイスを他のエコシステムと共有するには、お使いの Android デバイスに別のプラットフォームがインストールされている必要があります。ターゲット コミッショナーとして使用できる、サンプルアプリの別のインスタンスを作成しました。

ターゲット コミッショナーを Android デバイスにインストールしたら、Matter デバイスを共有できることを確認します。移行先のコミッショナー アプリには GHSAFM-TC というラベルが付きます。

デバイスが次の 3 つのファブリックに参加できるようになりました。

  1. ローカル Android ファブリック。
  2. 開発用ファブリック(このアプリ)。
  3. 先ほど共有した、3 つ目のファブリックです。

8. 次のステップ

お疲れさまでした

これで、この Codelab は終了です。Google Home モバイル SDK を使用してデバイスをコミッションして共有する方法を学習しました。

サンプルアプリで問題が発生した場合は、以下の手順で環境をご確認ください。

サンプルアプリの使用について質問がある場合や、コードのバグを発見した場合は、GitHub リポジトリの Issue Tracker に問題を報告してください。

技術的な質問に関する Google の公式ガイダンスを入手するには、スマートホーム デベロッパー フォーラムをご利用ください。

コミュニティからテクニカル サポートを受けるには、Stack Overflow の google-smart-home タグを使用します。