トップ 差分 一覧 ソース 置換 検索 ヘルプ PDF RSS ログイン

Android で OAuth2 認証をする

ネット上のサンプルをいじったバージョン

http://li4shi2.wordpress.com/2011/08/21/picasa%E3%81%AB%E7%94%BB%E5%83%8F%E3%82%92%E3%82%A2%E3%83%83%E3%83%97%E3%81%99%E3%82%8B%EF%BC%88android%EF%BC%89/
http://tomokey.blogspot.jp/2011/06/javaoauth.html

必要なパーミッション

 <uses-permission android:name="android.permission.INTERNET" />  
 <uses-permission android:name="android.permission.GET_ACCOUNTS" />  
 <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />  
 <uses-permission android:name="android.permission.USE_CREDENTIALS" /> 

必要なライブラリ

libs ディレクトリに libs.zip(226) を展開して jar ファイルを入れておく必要がある。

アカウント選択

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public void selectAccount(final OnSelectAccountListener listener){
    AlertDialog.Builder builder = new AlertDialog.Builder(activity);
    builder.setTitle("Select a Google account");
    final AccountManager manager = AccountManager.get(activity);
    final Account[] accounts = manager.getAccountsByType("com.google");
    final int size = accounts.length;
    String[] names = new String[size];
    for (int i = 0; i < size; i++) {
      names[i] = accounts[i].name;
    }
    // names[size] = "New Account";
    builder.setItems(names, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
          if (which == size) {
            // addAccount(manager);
            // listener.onSelect();
          } else {
            listener.onSelect(accounts[which]);
            // gotAccount(manager, accounts[which]);
          }
        }
    });
    builder.create().show();
  }

取得したアカウントで Authトークン取得

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public boolean authenticate(Account account, boolean clearCache, boolean retry ){
    
    AccountManager manager = AccountManager.get(activity);
    if (clearCache){
      manager.invalidateAuthToken("com.google", this.authToken);
    }
    
    try {
      Bundle bundle =
      manager.getAuthToken(account, PicasaWebAlbums.AUTH_TOKEN_TYPE, true,
        null, null).getResult();
        if (bundle.containsKey(AccountManager.KEY_INTENT)) {
          Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT);
          int flags = intent.getFlags();
          flags &= ~Intent.FLAG_ACTIVITY_NEW_TASK;
          intent.setFlags(flags);
          activity.startActivityForResult(intent, REQUEST_AUTHENTICATE);
          return false;
        } else 
        if (bundle.containsKey(AccountManager.KEY_AUTHTOKEN)) {
          this.authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
          this.account = account;
          transport.setClientLoginToken(this.authToken);
          return true;
        }
        return false;
    } catch (Exception e){
      if (retry){
        return reauthenticate(e, account);
      } else {
        return false;
      }
    }
  }

  private boolean reauthenticate(Exception e, Account account) {
    // e.printStackTrace();
    if (e instanceof HttpResponseException) {
      int statusCode = ((HttpResponseException) e).response.statusCode;
      if (statusCode == 401 || statusCode == 403) {
        return authenticate(account, true, false);
      }
    }
    return false;
  }

Authトークンは、一定時間で無効になる。その場合は

AccountManager#invalidateAuthToken()

してから、

AccountManager#getAuthToken()

する。また、Authトークンが無効な状態でアクセスすると

HttpResponseException

が発生し、

response.statusCode が 401 か 403 

になる・・・はず。

AndroidのAccountManager経由でGoogleのOAuth2認証を行う

http://kinsentansa.blogspot.jp/2012/08/androidaccountmanagergoogleoauth2.html
http://kinsentansa.blogspot.jp/2012/04/androidgoogleoauth2.html

必要なパーミッション

 <uses-permission android:name="android.permission.INTERNET" />  
 <uses-permission android:name="android.permission.GET_ACCOUNTS" />  
 <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />  
 <uses-permission android:name="android.permission.USE_CREDENTIALS" /> 

アカウント選択

1
2
3
4
5
6
7
8
9
10
11
  protected static final String ACCOUNT_TYPE = "com.google";  
  protected void chooseAccount() {  
    Log.v("chooseAccount", "AuthToken取得開始(アカウント選択)");  
    accountManager.getAuthTokenByFeatures(ACCOUNT_TYPE, authTokenType, null, AccountManagerOAuth2Activity.this, null, null,  
      new AccountManagerCallback<bundle>() {  
        public void run(AccountManagerFuture<bundle> future) {  
          onGetAuthToken(future);  
        }  
      },  
      null);  
  }  

アカウント名取得

1
2
 Bundle bundle = future.getResult();  
 accountName = bundle.getString(AccountManager.KEY_ACCOUNT_NAME);  

トークン取得

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
protected static final int REQUEST_CODE_AUTH = 0;  
protected void getAuthToken() {  
  Account account = null;  
  Account[] accounts = accountManager.getAccounts();  
  for (int i = 0; i < accounts.length; i++) {  
    account = accounts[i];  
    if (account.name.equals(accountName)) {  
      break;  
    }  
  }  
  Log.v("getAuthToken", "AuthToken取得開始");  
  accountManager.getAuthToken(account, authTokenType, true,  
    new AccountManagerCallback<Bundle>() {  
      public void run(AccountManagerFuture<Bundle> future) {  
        try {  
          Bundle bundle = future.getResult();  
          if (bundle.containsKey(AccountManager.KEY_INTENT)) {  
            //まだAPIアクセス許可が出ていない場合にgetAuthToken()すると  
            //BundleにKEY_INTENTが含まれる。この場合AuthTokenはNULLとなる。  
            Log.v("getAuthToken", "アクセス許可画面へ");  
            Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT);  
            //「FLAG_ACTIVITY_NEW_TASK」の前の「~」はビット反転演算子  
            //これをしないとアクセス許可画面でのボタンクリックを待たずにonActivityResult()が呼ばれてしまう  
            intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK);  
            startActivityForResult(intent, REQUEST_CODE_AUTH);  
          } else if (bundle.containsKey(AccountManager.KEY_AUTHTOKEN)) {  
            onGetAuthToken(future);  
          }  
        } catch (Exception e) {  
          Log.v("getAuthToken", "AuthToken取得失敗", e);  
        }  
      }  
    },  
    null);  
}  

Authトークン取得時に Activity に処理が流れた場合

1
2
3
4
5
6
7
8
9
10
11
12
13
protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
  super.onActivityResult(requestCode, resultCode, data);  
  Log.v("onActivityResult", "requestCode=" + requestCode + " resultCode=" + resultCode);  
  switch (requestCode) {  
  case REQUEST_CODE_AUTH:  
    if (resultCode == RESULT_OK) {  
      getAuthToken();  
    } else {  
      Log.v("onActivityResult", "アクセス許可画面で拒否された");  
    }  
    break;  
  }  
}  
resultCode == RESULT_OK

になれば Authトークン取得の準備が完了する。
再度、getAuthTokenを呼び

accountManager.getAuthToken

で Authトークンを取得する。

Authトークンについて

authTokenは一定期間過ぎると無効になるので再取得する必要がある。
一定時間が過ぎたauthTokenを使ってAPIにリクエストすると「"code":401」を含むjsonが返される。



[カテゴリ: プログラミング言語 > Java > Android]



  • Hatenaブックマークに追加
  • livedoorクリップに追加
  • del.icio.usに追加
  • FC2ブックマークに追加

最終更新時間:2013年02月20日 01時35分48秒