0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Flutter] Google Drive を利用する

Posted at

Flutter でスマホアプリを作成する際、Google Drive にアプリデータを保存して端末間で同期できるようにしました。
その際、google_sign_in プラグインを利用しました。
そこで苦労したことを書こうと思います。

Google Drive 利用のためのスコープ

前提として、Google Drive にアプリ向けのデータ保存を行うには、以下の2つのスコープが必要になります。

  final List<String> _scopes = [
    drive.DriveApi.driveAppdataScope,
    drive.DriveApi.driveFileScope,
  ];

サインインの際に、これらを利用することの承認画面が表示され、ユーザーが同意することでアプリから Google Drive にデータを保存することができるようになります。

認可で問題発生

今回、google_sign_in は v6.x を利用していましたが、途中から最新の v7.2.0 を使うように変更しました。
v6.x から v7.x へは破壊的変更が入り、v6.x で書いたコードがそのまま使えない感じになります。

Google Drive の利用には、シングルトンである GoogleSignIn インスタンスの初期化が必要です。

GoogleSignIn.instance.initialize()

次にサインインの認証を行います。
この時、スコープを渡すことができます。

final account = await GoogleSignIn.instance.authenticate(
    scopeHint: _scopes,
);

ここまでで、サインイン(認証)とGoogle Drive を利用することの同意(認可)が行われます。




そう思っていた時期もありました。。。w


実際は、ここまでを実行した場合、iOS では Google Drive の利用の同意画面が表示されますが、Android では表示ません。
両方NGであれば、コードが悪いと思うのですが、なぜか iOS だけうまく動くので、混乱しました。
Android を利用するための Firebase や Google Cloud Platform の設定を疑い、しかし何度確認しても問題はなさそうで、さらに混乱。。。

対策

結論から言うと、google_sign_in のドキュメント(google_sign_in6.x から 7.x への移行)を読むと、認証と認可は分ける必要がありそうでした。

これらのステップを同時に実行する必要があるアプリケーションでは、scopeHint認証ステップ中に を渡すことができます。これをサポートするプラットフォームでは、これにより認証と認可のUIフローを組み合わせたフローが可能になります。ただし、すべてのプラットフォームでこれらのフローの組み合わせが許可されているわけではないため、必要に応じてアプリケーションで個別の認可プロンプトをトリガーできるように準備しておく必要があります。

iOS と Android で動きが異なったのは、Android がサポートしていないプラットフォームだったと思われます。
以下のような実装で、両方で動作するようになりました。

  // 初期化
  // Firebase 利用時は、serverId などの指定は不要.
  await GoogleSignIn.instance.initialize();

  // サインイン(認証)
  // ここでスコープを指定すると、次のスコープの確認の際に正しく確認できない.
  final account = await GoogleSignIn.instance.authenticate();

  // スコープの確認
  final auth = await account.authorizationClient.authorizationForScopes(_scopes);
  if (auth == null) {
    // スコープが存在しない、不足している場合は、スコープを要求する(認可)
    final authResult = await account.authorizationClient.authorizeScopes(_scopes);
  }

ポイントは、以下です。

  • authenticate で scopeHint を指定すると、iOS は認可画面が表示されるが、Android では表示されない。
  • authenticate で scopeHint を指定すると、Android では authorizationForScopes の結果が null にならない。
    認可の同意プロセスを経ていないのに、認可されたものとなっていると思われる。
  • authorizationForScopes の結果が null の場合、 authorizeScopes で認可の同意プロセスを実行する。

わかればその通りの手順で実装すれば良いだけなのですが、ライブラリ利用はロジックではなく、知っているか否かなので難しいですね。

さいごに

公式ドキュメントをよく読み、迷ったらサンプル通りに書いてみろ!と。

今回のアプリは、AIのバイブコーディングでどこまでできるかを試していたため、ほとんどコードを書いてませんでした。
そのため、AIに解決してもらおうとして沼にハマって、公式をよく読まなかったのも良くなかったです。
AIも使い方、使い所が重要で、沼った時の経験や知識は重要であることも再認識できました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?