[Qiita] Androidの新しいGoogleサインインAPIについて
※この記事は以前Qiitaに投稿されていた古い記事です
GoogleサインインをAndroidで実装するためには、以前は実装がとても面倒かつ分かりづらいものでしたが、これが簡単に実装できるようになったのが、新しいGoogleサインインAPIです。これにより、ユーザーエクスペリエンスも向上します。
この内容については以前、勉強会で発表したのですが、今回はQiita記事として書こうと思います。
基本的に以下のGoogle Play Developersの記事を参考に書いているので、より正確な情報を見たい場合にはそちらを参照してください。
プロジェクトが既にある場合は、以下のページから必要な項目を入力し、「google-services.json」をダウンロードします。
Enable Google services for your app
ダウンロードしたら、「google-services.json」をアプリケーションのプロジェクトのappディレクトリ配下にコピーします。
たとえば、ユーザーのIDと基本的なプロフィール情報を要求するためにGoogleサインインを設定するには、DEFAULT_SIGN_INパラメータでGoogleSignInOptionsオブジェクトを作成します。
同様に、ユーザーのメールアドレスを要求するには、GoogleSignInOptionsがrequestEmailオプションを指定してオブジェクトを作成します。
例えば、Google Url Shortener APIへのリクエストを要求するには以下のようになります。
また、addScopeについてですが、GoogleSignInOptionsでrequestScopeせずにaddScopeするとIllegalStateExceptionで落ちますが、requestScopeが設定されていてaddScopeしなくてもrequestScopeしたAPIに問題無くアクセス許可できたので、今のところいつ設定すべきなのかがまだ分かっていません。
サインインボタンにクリックイベントをセットします。
結果の取得はgetSignInResultFromIntentメソッドで行い、返ってきたGoogleSignInResultから各情報を取得します。
これは、プロジェクトのクライアントが次の要件を満たすように構成されている場合、ユーザーはすぐにアプリケーションにサインインすることができます。
そして、ユーザーの情報を取得し、Google APIへのアクセスに進むことができ、ユーザーが再びアプリにサインインする必要性を回避できます。
しかし、GoogleSignInAccountクラスにはそのようなメソッドは用意されていないので、GoogleAuthUtilクラスのgetTokenメソッドを使ってAuthTokenを取得します。具体的には以下のように取得します。
AuthTokenが取得できたら、あとは以前と同じようにAPIにリクエストを投げるときにこのAuthTokenをaccess_tokenパラメータとして渡してあげることで、APIを使うことができます。
以上、お疲れさまでした。
はじめに
GoogleがGoogle Play services 8.3をリリースした際に、その新機能の1つとして新しいGoogleサインインAPIを公開しました。GoogleサインインをAndroidで実装するためには、以前は実装がとても面倒かつ分かりづらいものでしたが、これが簡単に実装できるようになったのが、新しいGoogleサインインAPIです。これにより、ユーザーエクスペリエンスも向上します。
この内容については以前、勉強会で発表したのですが、今回はQiita記事として書こうと思います。
基本的に以下のGoogle Play Developersの記事を参考に書いているので、より正確な情報を見たい場合にはそちらを参照してください。
Integrating Google Sign-In into Your Android App
https://developers.google.com/identity/sign-in/android/sign-in
Googleサインインとはどういうものか
だいたいこんな感じのやつです。-
ログインボタンを押す
-
Android端末にログインしているアカウントを選択する
-
許可する
-
許可されたAPIが使えたりアカウント情報が取得できる(∩´∀`)∩
-
許可すると、ユーザーのGoogleアカウントの「アカウントに接続されてるアプリ」から確認できるようになる
Googleサインインを使うための前提条件
- Google Play Storeを含むAndroid 2.3以上
- Google APIプラットフォームベースのAndroid 4.2.2以上を実行するAVD
設定ファイルを取得する
設定ファイルには、サービス固有の情報が記述されています。それを取得するためには、Google Developers Consoleから既存のプロジェクトを選択するか、新しいプロジェクトを作成する必要があります。また、アプリのパッケージ名と署名証明書のSHA-1ハッシュも必要となります。プロジェクトが既にある場合は、以下のページから必要な項目を入力し、「google-services.json」をダウンロードします。
Enable Google services for your app
ダウンロードしたら、「google-services.json」をアプリケーションのプロジェクトのappディレクトリ配下にコピーします。
Google Services pluginを追加する
-
プロジェクトのbuild.gradleのdependenciesに以下を追記します。
classpath 'com.google.gms:google-services:1.5.0-beta2'
-
appのbuild.gradleに以下を追加します。
apply plugin: 'com.google.gms.google-services'
Google Play Servicesを追加する
appのbuild.gradleのdependenciesにGoogle Play Servicesを宣言します。compile 'com.google.android.gms:play-services-auth:8.3.0'
OAuth 2.0 client ID を作成する
アプリがバックエンドサーバで認証したり、バックエンドサーバからGoogleのAPIにアクセスする場合は、サーバー用のOAuth 2.0 client IDを作成する必要があります。- 資格情報ページを開きます
- 資格情報を追加 > OAuth 2.0 クライアント ID
- ウェブアプリケーションを選択
- 作成
Googleサインインの実装
GoogleSignInOptionsオブジェクトを作成する
Googleサインインを実装するActivityのonCreateメソッドの中で、アプリで必要とされるユーザデータを要求するように設定します。たとえば、ユーザーのIDと基本的なプロフィール情報を要求するためにGoogleサインインを設定するには、DEFAULT_SIGN_INパラメータでGoogleSignInOptionsオブジェクトを作成します。
同様に、ユーザーのメールアドレスを要求するには、GoogleSignInOptionsがrequestEmailオプションを指定してオブジェクトを作成します。
GoogleSignInOptions gso = new GoogleSignInOptions
.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
GoogleのAPIにアクセスするための追加のスコープを要求する必要がある場合には、requestScopeでそれらを設定します。例えば、Google Url Shortener APIへのリクエストを要求するには以下のようになります。
mScope = new Scope("https://www.googleapis.com/auth/urlshortener");
GoogleSignInOptions gso = new GoogleSignInOptions
.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(mScope)
.requestEmail()
.build();
GoogleApiClientオブジェクトを作成する
GoogleSignInOptionsオブジェクトを作成した後、またGoogleサインインを実装するActivityのonCreateメソッドの中で、GoogleサインインAPIへのアクセスとオプションを使用してGoogleApiClientオブジェクトを作成します。mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addScope(mScope)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
ここで使用しているenableAutoManageメソッドの第一引数にはFragmentActivityを、第二引数にはGoogleApiClient#OnConnectionFailedListenerをActivityに実装しておく必要があります。また、addScopeについてですが、GoogleSignInOptionsでrequestScopeせずにaddScopeするとIllegalStateExceptionで落ちますが、requestScopeが設定されていてaddScopeしなくてもrequestScopeしたAPIに問題無くアクセス許可できたので、今のところいつ設定すべきなのかがまだ分かっていません。
Googleサインインボタンを追加する
Googleサインインボタンを追加したいレイアウトにSignInButtonを追加します。<com.google.android.gms.common.SignInButton
android:id="@+id/sign_in_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
ActivityにView#OnClickListenerを実装し、サインインボタンにクリックイベントをセットします。
SignInButton signInButton = (SignInButton) findViewById(R.id.sign_in_button);
signInButton.setOnClickListener(this);
このサインインボタンを使用している場合、setSizeやsetScopesメソッドによってボタンのサイズやカラースキームを変更することができます。signInButton.setSize(SignInButton.SIZE_WIDE);
signInButton.setScopes(gso.getScopeArray());
例えば、Google+のスコープを設定している場合には、サインインボタンが赤のGoogle+ブランディングでレンダリングされます。サインイン処理の実装
サインイン処理を開始するには、getSignInIntentで取得したIntentをそのままstartActivityForResultに渡してActivityを起動するだけです。@Override
public void onClick(View v) {
if(v.getId() == R.id.sign_in_button) {
signIn();
}
}
private void signIn() {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
サインイン処理の開始ができたら、ActivityのonActivityResultメソッドで結果を受け取る処理を書いていきます。結果の取得はgetSignInResultFromIntentメソッドで行い、返ってきたGoogleSignInResultから各情報を取得します。
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
}
}
サインインが成功したかどうかを取得するにはisSuccessメソッドを使用します。また、サインインが成功していた場合にはgetSignInAccountメソッドでGoogleSignInAccountオブジェクトを取得し、そこからサインインしたユーザーの電子メールアドレスやユーザー名などを取得することができます。private void handleSignInResult(GoogleSignInResult result) {
Log.d(TAG, "handleSignInResult:" + result.isSuccess());
if (result.isSuccess()) {
// サインインが成功したら、サインインボタンを消して、ユーザー名を表示する
mGoogleSignInAccount = result.getSignInAccount();
mStatusTextView.setText("DisplayName: " + mGoogleSignInAccount.getDisplayName());
updateUI(true);
} else {
// Signed out, show unauthenticated UI.
updateUI(false);
}
}
クロスプラットフォームシングルサインオン
ユーザーが以前に別のプラットフォーム上のアプリに許可を付与している場合、silentSignInを使用することができます。これは、プロジェクトのクライアントが次の要件を満たすように構成されている場合、ユーザーはすぐにアプリケーションにサインインすることができます。
- OAuth 2.0クライアントIDは、同じGoogle Developer Consoleプロジェクトでなければならない
- OAuthのスコープは、両方のクライアントで同じでなければならない
そして、ユーザーの情報を取得し、Google APIへのアクセスに進むことができ、ユーザーが再びアプリにサインインする必要性を回避できます。
多言語対応
com.google.android.gms.common.SignInButtonは、ローカライズされた文字列を提供しており、これらは自動的に使用可能となります。どの言語に対応しているかなどを確認するためにはSDKの以下のディレクトリから確認することができます。<android-sdk-folder>/extras/google/google_play_services/libproject/google-play-services_lib/res/. In that location, you will find directories named values-<langcode>
AuthTokenはどうやって取得するのか
AccountManagerでOAuth2認証していたときにはAccountManagerのgetAuthTokenメソッドを使用してAuthTokenを取得していました。しかし、GoogleSignInAccountクラスにはそのようなメソッドは用意されていないので、GoogleAuthUtilクラスのgetTokenメソッドを使ってAuthTokenを取得します。具体的には以下のように取得します。
String accessToken;
try {
accessToken = GoogleAuthUtil.getToken(
MainActivity.this,
new Account(mGoogleSignInAccount.getEmail(), ACCOUNT_TYPE),
"oauth2:" + API_SCOPE
);
Log.d(TAG, "accessToken: " + accessToken);
} catch (IOException | GoogleAuthException e) {
e.printStackTrace();
}
GoogleAuthUtilにはgetToken (Context context, String accountName, String scope)
というメソッドも存在するのですが、リファレンスを見ると[このメソッドは非推奨となっていた](https://developers.google.com/android/reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context, java.lang.String, java.lang.String))ので、getToken (Context context, Account account, String scope)
を使うようにしましょう。AuthTokenが取得できたら、あとは以前と同じようにAPIにリクエストを投げるときにこのAuthTokenをaccess_tokenパラメータとして渡してあげることで、APIを使うことができます。
おわりに
僕が以前にGoogle+ログインを使ってGoogle Url Shortenerを使おうとした時にどうやるのか調べたら、認証方法がいくつかあって、複雑すぎてとても苦労したのでOAuthHelperなんていうものを作って簡単に実装できるようにしたのですが、このGoogleサインインAPIを使えばサインインが簡単に実装できるようになるので開発者としては実装の手間が省けて幸せになれるのかなと思いました。以上、お疲れさまでした。
参考
- Integrating Google Sign-In into Your Android App
https://developers.google.com/identity/sign-in/android/sign-in - Google Sign-In Quickstart
https://github.com/googlesamples/google-services/tree/master/android/signin
コメント
コメントを投稿