Android での Google アカウント統合に関するアドバイス
Posted:
2014年12月2日火曜日
こんにちは。最近、Android の Google アカウントに関する質問がいくつか寄せられています。そこで、Google が勧めるベスト プラクティスのいくつかを記事にまとめて紹介いたします。今回は、Google Play 開発者サービスの統合によって簡単に実現できる Android ベースの認証に焦点を当てます。では、始めましょう。
固有の識別子
混乱がよく生じるのが、デベロッパーがアカウント名(E メール アドレス)を Google アカウントのプライマリー キーに使用しているケースです。たとえば、ユーザーのログインに GoogleApiClient を使用しているとき、デベロッパーは、登録されている GoogleApiClient.ConnectedCallbacks リスナーに対する onConnected コールバックの中で、下に示すようなコードを使っている場合があります。
[エラーが生じやすい擬似コード]
String accountName = Plus.AccountApi.getAccountName(mGoogleApiClient); // createLocalAccount() はアプリのローカル ストレージ ストラテジーに固有 createLocalAccount(accountName);
表示やキャッシュのために E メールアドレスを保存することに問題はありませんが、ユーザーは、Google アカウントで自身のプライマリー E メール アドレスを変更する可能性があります。そういったことは様々なタイプのアカウントで起きますが、最も頻繁に発生するのが Google Apps For Work アカウントです。
では、デベロッパーはどうしたらよいのでしょうか。Google アカウントに関連付けられているアプリのデータをキーにするときは、アカウント名ではなく、Google アカウント ID を使用します。つまり、たいていのアプリでは、アカウント ID を保存して、onConnected コールバックが呼び出されるたびに、その値を比較するだけでよく、これによって、そのデータが現在ログインしているユーザーとローカルに合致しているかを確認します。API では、アカウント ID をアカウント名から取得できるメソッドを提供しています。参考用に、スニペット例を示します。
[Google Play 開発者サービス 6.1+]
String accountName = Plus.AccountApi.getAccountName(mGoogleApiClient); String accountID = GoogleAuthUtil.getAccountId(accountName); createLocalAccount(accountID);
[Google Play 開発者サービスの以前のバージョン(クライアントをアップグレードしてください)]
Person currentUser = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient); String accountID = currentUser.getID(); createLocalAccount(accountID);
こうすることで、ローカルデータは Google アカウント ID と照合されることになります。アカウント ID は ユーザーが E メールアドレスを変更した後でも変わらない固有の識別子です。
よって、上述のケースでは、データが ID をキーとしていれば、ユーザーが E メールアドレスを変更したとしても心配する必要はないのです。ユーザーが再びログインするときも、同じ ID を取得しますので、皆さんの側で何らかのデータ処理をする必要はありません。
複数アカウント
アプリが複数のアカウントによる同時接続をサポートしている場合(たとえば、下に示す Gmail ユーザー インターフェースのようなケース)、GoogleApiClients 構築時には、setAccountName を GoogleApiClient.Builder に対して呼び出します。このとき、アプリ内にそのアカウント名と Google アカウント ID を保存する必要があります。しかし、保存したアカウント名は、ユーザーがプライマリー E メール アドレスを変更すると、違ってしまうことになります。これに対処する最も簡単な方法は、ユーザーに再ログインを促すことです。そしてログイン後に、onConnected がコールされたときにアカウント名を更新します。ログインのたびに、こういったコードを使ってアカウント ID を比較し、そのアカウント ID に対してローカルに保存されている E メールアドレスを更新します。
[Google Play 開発者サービス 6.1+]
String accountName = Plus.AccountApi.getAccountName(mGoogleApiClient); String accountID = GoogleAuthUtil.getAccountId(accountName); // isExistingLocalAccount(), createLocalAccount(), // getLocalDataAccountName()、および updateLocalAccountName() は、 // すべて、アプリのローカル ストレージ ストラテジーに固有のもの boolean existingLocalAccountData = isExistingLocalAccount(accountID); if (!existingLocalAccountData) { // 新たなログイン createLocalAccount(accountID, accountName); } else { // この Google アカウントに関する既存のローカルデータ String cachedAccountName = getLocalDataAccountName(accountID); if (!cachedAccountName.equals(accountName)) { updateLocalAccountName(accountID, accountName); } }
このシナリオからは、すべてのデータをアプリに保存するのにアカウント ID を使用することの重要性が分かります。
オンライン データ
上記のベスト プラクティスは、アプリのウェブサーバーに Google アカウントのデータを保存する際にも当てはまります。データをこの方法でサーバーに保存し、E メール アドレスをプライマリー キーとして扱っている場合、
ID [プライマリー キー]
フィールド 1
フィールド 2
フィールド 3
user1@gmail.com
値 1
値 2
値 3
プライマリー キーを Google アカウント ID とする下記のモデルに移行する必要があります。
ID [プライマリー キー]
Email
フィールド 1
フィールド 2
フィールド 3
108759069548186989918
user1@gmail.com
値 1
値 2
値 3
ウェブ サーバーから Google API コールを行わない場合は、上述の複数アカウントのサンプルコードで参照している updateLocalAccountName メソッドを実装する場合、プライマリー E メールアドレス変更をウェブ サーバーに通知するのは、Android 向けアプリケーションに任せることができるかもしれません。ウェブ サーバーから Google API のコールを行う場合は、おそらくそれはクロス クライアント認証を使って実装したものなので、ウェブ サーバー上の OAuth2 クライアント ライブラリまたは REST エンドポイントを介して変更を検出することもできます。
まとめ
アプリで Google アカウント認証を使用するとき、ユーザーのデータを識別するには、アカウント名ではなくアカウント IDを使うのがベストな方法です。この記事では、アプリを強化するために変更作業が必要となる 3 つのケースを紹介しました。Google for Work の利用が増加しているなか、ユーザーが E メール アドレスを変更しても、アカウント ID は同じまま維持するケースが増えてくると予想されます。よって、デベロッパーの皆さんには、できるだけ早急にコードの更新計画を立てることをお勧めいたします。Posted by Yuichi Araki