Prerequisites
- Android 2.3 以上, あるいは最新のGoogle Play Storeを搭載していること.
- 最新のAndroid SDK Toolsをインストールしていること.
- Google Play Service SDKをインストールしていること.
- コンパイルバージョンがAndroid2.3以上であること.
Step 1: Google Sign-In APIの有効化
- Google Developers Consoleへ移動
- プロジェクトを作成する
- AndroidアプリケーションとしてクライアントIDを作成する
NOTE
デバッグ用.keystoreのSHA1ハッシュを確認するには次のコマンドを参照.
keytool -exportcert -alias androiddebugkey -keystore path-to-debug-or-production-keystore -list -v
デバッグ用.keystoreはMacだと~/.android/debug.keystore
. Windowsでは%USERPROFILE%\.android\debug.keystore
に標準で格納されている.
デバッグ用keystoreのパスワードはandroid
.
Step 2: Android Studio Project の設定
build.gradleのdependenciesセクションにGoogle Play Serviceを追加.
dependencies {
compile 'com.google.android.gms:play-services:7.0.0'
}
Step 3: Permission宣言
アプリケーションが使用するGoogle Play ServiceのバージョンをAndroidManifestのapplication
タグ配下に宣言する.
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
Google APIにアクセスするためINTERNETパーミッションを宣言する.
<uses-permission android:name="android.permission.INTERNET" />
アカウント名を取得するためGET_ACCOUNTパーミッションを宣言する.
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
OAuth 2.0 tokenを取得するためUSE_CREDENTIALSパーミッションを宣言する.
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
GoogleApiClient の初期化
GoogleApiClientはGoogle Play Serviceに接続されるServiceConnectionのラッパーとして作用する.
GoogleApiClientはGoogle Sign-In APIと通信し, 非同期通信によりサービスを有効化した後機能する. そのためには,
- Google Play Serviceがデバイス上で実行されており, あなたのActivityがService connectionに接続できていること.
- ユーザがあなたのアプリでアカウントを選択し, ユーザのアカウントがあなたのアプリに権限を与えていること.
GoogleApiClientのライフサイクルをActivityのライフサイクルの中で管理するための一般的な方法は下記.
- Activity.onCreateでGoogleApiClientを初期化
- Activity.onStartでGoogleApiClient.connectを起動
- Activity.onStopでGoogleApiClient.disconnectを起動
これを実行するとActivityにはコネクションが有効化あるいは接続失敗したことがConnectionCallbacksとOnConnectionFailedListenerに通知される.
addScopeメソッドでアプリが許容を求めるスコープを定義できる.
import android.app.Activity;
import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
import android.view.View;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.plus.Plus;
public class MainActivity extends Activity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
View.OnClickListener {
/* Request code used to invoke sign in user interactions. */
private static final int RC_SIGN_IN = 0;
/* Client used to interact with Google APIs. */
private GoogleApiClient mGoogleApiClient;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API)
.addScope(new Scope("profile"))
.build();
findViewById(R.id.sign_in_button).setOnClickListener(this);
}
@Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override
protected void onStop() {
super.onStop();
mGoogleApiClient.disconnect();
}
@Override
public void onClick(View v) {
// ...
}
// ...
}
GoogleApiClientがコネクションを有効化できなかった時, onConnectionFailedのコールバックが呼ばれる. これにはConnectionResultが渡されるためエラーの解決に使用できる. ConnectionResult.getResolution()を呼ぶとユーザにアカウントを選択する操作を促すためのPendingIntentを得ることができる.
(例えば年とワーク接続を有効かするように求めたり, アカウントの選択をユーザに求めたりする)
@Override
public void onConnectionFailed(ConnectionResult result) {
if (!mIntentInProgress && result.hasResolution()) {
try {
mIntentInProgress = true;
result.startResolutionForResult(this, RC_SIGN_IN);
} catch (SendIntentException e) {
// The intent was canceled before it was sent. Return to the default
// state and attempt to connect to get an updated ConnectionResult.
mIntentInProgress = false;
mGoogleApiClient.connect();
}
}
}
@Override
public void onConnected(Bundle connectionHint) {
// We've resolved any connection errors. mGoogleApiClient can be used to
// access Google APIs on behalf of the user.
}
@Override
protected void onActivityResult(int requestCode, int responseCode, Intent intent) {
if (requestCode == RC_SIGN_IN) {
mIntentInProgress = false;
if (!mGoogleApiClient.isConnected()) {
mGoogleApiClient.reconnect();
}
}
}
クライアントのサービス接続が確立されたらGoogleApiClient.disconnectをonStopメソッドの中で呼び出しこれを切断する必要がある.
Google Play ServiceはActivityがサービスコネクションをロストした際に呼ばれるonConnectionSuspendedコールバックを呼び出す. 一般的にこの場合はユーザが解決を試みることができるようにサービスへの再接続を試みる.
@Override
public void onConnectionSuspended(int cause) {
mGoogleApiClient.connect();
}
Google Sign-In ボタンの追加
- アプリケーションのレイアウトにSignInButtonを追加
<com.google.android.gms.common.SignInButton
android:id="@+id/sign_in_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
- OnClickListenerを登録する
findViewById(R.id.sign_in_button).setOnClickListener(this);
- Sign-Inボタンを使用するにはActivityのSign-Inフローを変更する必要がある. ActivityがOnCnnectionFaildコールバックを受け取ったらすぐに問題解決のためのユーザインタラクションを開始する. Activityはその間Sing-inボタンのクリックを抑止するべき.
/**
* True if the sign-in button was clicked. When true, we know to resolve all
* issues preventing sign-in without waiting.
*/
private boolean mSignInClicked;
/**
* True if we are in the process of resolving a ConnectionResult
*/
private boolean mIntentInProgress;
@Override
public void onConnectionFailed(ConnectionResult result) {
if (!mIntentInProgress) {
if (mSignInClicked && result.hasResolution()) {
// The user has already clicked 'sign-in' so we attempt to resolve all
// errors until the user is signed in, or they cancel.
try {
result.startResolutionForResult(this, RC_SIGN_IN);
mIntentInProgress = true;
} catch (SendIntentException e) {
// The intent was canceled before it was sent. Return to the default
// state and attempt to connect to get an updated ConnectionResult.
mIntentInProgress = false;
mGoogleApiClient.connect();
}
}
}
}
- ユーザがSign-Inボタンをクリックした後, mSignInClickedフラグをセットし, onConnectionFailedで接続エラーを解決する必要がある. 解決可能なエラーはユーザにサービスへの接続とアプリへの権限承認を促す.
public void onClick(View view) {
if (view.getId() == R.id.sign_in_button && !mGoogleApiClient.isConnecting()) {
mSignInClicked = true;
mGoogleApiClient.connect();
}
}
- 接続が確立された場合はmSignInClickedフラグをリセットする.
protected void onActivityResult(int requestCode, int responseCode, Intent intent) {
if (requestCode == RC_SIGN_IN) {
if (responseCode != RESULT_OK) {
mSignInClicked = false;
}
mIntentInProgress = false;
if (!mGoogleApiClient.isConnected()) {
mGoogleApiClient.reconnect();
}
}
}
- ユーザがSign-Inを無事終えるとonConnectedが呼ばれる. この時点でユーザの名前を取得するか認証リクエストを作成することができる.
@Override
public void onConnected(Bundle connectionHint) {
mSignInClicked = false;
Toast.makeText(this, "User is connected!", Toast.LENGTH_LONG).show();
}
以上.