以下の内容はhttps://yutailang0119.hatenablog.com/entry/2025/01/19/180000より取得しました。


iOSアプリでGoogle Smart Device Management APIを使う (2025)

2回目の登場、はてなエンジニアアドベントカレンダー2024 50日目の記事です。
1回目は SwiftでAdvent of Code 2024 #AdventOfCode - がんばってなんか書く

Google Device Access

家には猫監視用にGoogle Nest Camがあります。
これはAPIが公開されているので、iOSアプリとしてアクセスしてみたい。

developers.google.com

基本は Get Started  |  Device Access  |  Google for Developers を進めていくといいのですが、iOSアプリのでOAuthは直接フォローされていないので、備考録的にまとめます。

準備

iOSアプリ作成前に、環境の準備が必要なので済ませていきます。

Device Accessの登録

https://developers.google.com/nest/device-access/get-started#register_for_device_access

Device AccessAPIを使うためには登録が必要で、US$5+taxがかかります。
¥860でした。

Google Cloud OAuth 2.0

https://developers.google.com/nest/device-access/get-started#set_up_google_cloud_platform

OAuth 2.0は、Google Cloudを使って行います。 プロジェクトを選んで、アプリケーションスコープを選択します。
iOS以外にもAndroidやDesktop Appもあります。

Configure your OAuth client

iOSでは、Bundle identifierを入力します。
作成が完了すると、Info.plistをダウンロードできます。 *1

一旦はテストモードにしておくとよいでしょう。
Google Auth Platform > Audience から、Publishing statusをTestingに変更します。
Test usersに自身のGoogleアカウントユーザーを登録すれば、自分だけが認証を通すことができます。

Device Accessプロジェクト作成

https://developers.google.com/nest/device-access/get-started#create_a_device_access_project

Device Accessコンソールに戻って、Device Access側でもプロジェクトを作成します。
Google Cloudで作った OAuth client ID が必要です。

Google Nest permissions設定

Device AccessプロジェクトをSandboxで運用する場合、デバイスを個別に許可する必要があります。
これはアプリ内OAuthのフローには組み込まれていないため、OAuth URLで選択してください。

https://nestservices.google.com/partnerconnections/{project-id}/auth
?redirect_uri={redirect_uri}
&response_type=code
&client_id={client_id}
&scope=https://www.googleapis.com/auth/sdm.service
&access_type=offline

Google Nest permissions

これでAPIにアクセスする準備完了。

iOSアプリ

Google Sign-Inのインストール

developers.google.com

Google CloudのOAuth 2.0は、Google Sign-InのSDKを使いましょう。
上記のGet Startedで概ねいいですが、微妙に情報が古かった。

Swift Package Managerでは7.0.0を使うように書いていますが、2025/01/19現在の最新は8.0.0がリリースされているので、こちらを使います。

OAuth client IDの設定

https://developers.google.com/identity/sign-in/ios/start-integrating#configure_app_project

Info.plistにGIDClientIDCFBundleURLSchemesを設定します。
例示されている com.googleusercontent.apps.1234567890-abcdefg だと、以下を入力することになります。

  • GIDClientID: 1234567890-abcdefg.apps.googleusercontent.com
  • CFBundleURLSchemes: com.googleusercontent.apps.1234567890-abcdefg

後述の認証をしてみると、アプリ内で完結するためにDeepLinkは使わなそうな気もしますが、サインインを始めるとエラーになります。

Your app is missing support for the following URL schemes: com.googleusercontent.apps.1234567890-abcdefg

OAuth

https://developers.google.com/identity/sign-in/ios/sign-in#3_add_a_google_sign-in_button

GoogleSignではSwiftUIをサポートしています。
しかし、UIViewControllerを要求するのでちょっとテクニックが必要。
UIViewControllerRepresentable > UIHostingController > SwiftUI.View で回避しました。
SwiftUIで提供されているメリットが薄いので、もっと楽な方法がありそう。

public struct SignInView: UIViewControllerRepresentable {
  public init() {}

  public func makeCoordinator() -> () {}

  public func makeUIViewController(context: Context) -> some UIViewController {
    SignInViewController(rootView: SignInViewController.ContentView())
  }

  public func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {}
}

private final class SignInViewController: UIHostingController<SignInViewController.ContentView> {
  public override func viewDidLoad() {
    super.viewDidLoad()
    self.rootView.rootViewController = self
  }
}

extension SignInViewController {
  struct ContentView: View {
    var rootViewController: UIViewController!

    public var body: some View {
      GoogleSignInButton {}
    }
  }
}

SDKはドキュメントのサンプルコードから更新されていて、Swift Concurrency対応しています。
Smart Device Management APIにアクセスするためには、アクセススコープを追加する必要もあります。
https://www.googleapis.com/auth/sdm.service

      GoogleSignInButton {
        Task {
          _ = try await GIDSignIn.sharedInstance.signIn(
            withPresenting: rootViewController,
            hint: nil,
            additionalScopes: ["https://www.googleapis.com/auth/sdm.service"]
          )
        }
    }

これでボタンを押すと、よく目にするGoogleアカウントの連携画面が表示されて、許可することでアクセストークンを取得できます。
最短ルートのはず。

API実行

https://developers.google.com/nest/device-access/authorize#4-api-call

devices.list APIを実行してみましょう。

Task {
  let url = "https://smartdevicemanagement.googleapis.com/v1/enterprises/\(projectId)/devices"
  var request = URLRequest(url: URL(string: url)!)
  request.httpMethod = "GET"
  request.setValue("Bearer \(access-token)", forHTTPHeaderField: "Authorization")
  request.setValue("application/json", forHTTPHeaderField: "Content-Type")
  let (data, response) = try await URLSession.shared.data(for: request)
  print(String(data: data, encoding: .utf8))
}

Responseを確認して、成功しているでしょう!

おわり

  • Smart Device Management APIを使うために
  • Google CloudのOAuth 2.0を用意して
  • iOSアプリでGoogle Sign-Inして
  • APIを実行

までを行いました。

次の目標はLiveストリームにアクセスして、WebRTCを表示すること。

WebRTCのライブラリがないので、情報お待ちしております!

*1:現代的には、これを直接使う感じではなさそう




以上の内容はhttps://yutailang0119.hatenablog.com/entry/2025/01/19/180000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14