ネイティブアプリで実践! mixi Graph API活用法
OAuth 2.0を使う
  ソーシャルなAndroidアプリの作り方 
株式会社ミクシィ
システム本部 技術部 たんぽぽグループ 藤崎 友樹
プラットフォームサービス開発部 鶴原 翔夢
2011/3/30
 Access Tokenを用いてPeople APIへリクエストを発行
- - PR -
 
Access Tokenの取得まで完了したら、いよいよPeople APIへリクエストを発行します。
People APIで友人一覧を取得するには、次のURLへGETリクエストを発行します。
http://api.mixi-platform.com/2/people/@me/@friends
Access Tokenは、リクエストヘッダのAuthorizationヘッダとして「OAuth a1b2c3……」という形でセットします。
ApiRequestUtils.java抜粋    if (store != null) {
        // token を取得
        token = getValidAccessToken(store);
        if (token != null) {
            // Authorization ヘッダを付与
            authorizationHeader = 
                new BasicHeader("Authorization", "OAuth " + token.accessToken);
            request.addHeader(authorizationHeader);
        }
    }
ヘッダを付与した状態でGETリクエストを行い、成功すると結果としてJSONが返されます。JSONは、次のようなコードでJSONObjectを利用してパースし、結果をArrayListへ格納します。今回のサンプルでは、返されたdisplayNameとprofileUrlのみ取り出しています。
PeopleApiClient.java抜粋private PeopleApiResponse parsePeopleFromResponse(String string) {
    PeopleApiResponse res = new PeopleApiResponse();
    ArrayList<MixiPerson> people = new ArrayList<MixiPerson>();
    try {
        // 外側
        JSONObject json = new JSONObject(string);
        res.itemsPerPage = json.getInt("itemsPerPage");
        res.startIndex = json.getInt("startIndex");
        res.totalResults = json.getInt("totalResults");
        
        // 内側(結果のリスト)
        JSONArray entries = json.getJSONArray("entry");
        int count = entries.length();
        for (int i = 0; i < count; i++) {
            JSONObject entry = entries.getJSONObject(i);
            
            MixiPerson person = new MixiPerson();
            person.displayName = entry.getString("displayName");
            person.profileUrl  = entry.getString("profileUrl");
            
            people.add(person);
        }
        res.entry = people;
 
        return res;
    } catch (JSONException e) {
        Log.w(TAG, "something went wrong while parsing json", e);
    }
    return null;
}
後は、取得できた内容をListViewへセットします。ListViewには、ArrayAdapterをセットしておきます。また、友人が多い場合はページングにて次のn件を取得するため、「ListView#addFooterView」メソッドで末尾要素として「続きを取得」という要素を追加しておきます。
MainActivity.java抜粋    // リストの末尾要素(続きを取得/読み込み中)の構成
    mFooterView = createFooterView();
    mFooterLoadingView = createFooterLoadingView();
 
    // リストの構成
    mListView = (ListView) findViewById(android.R.id.list);
    mListView.setOnItemClickListener(this);
    mListView.addFooterView(mFooterView, null, true);
 
    // リストにセットするアダプタ
    mAdapter = new ArrayAdapter<MixiPerson>(this,
        android.R.layout.simple_list_item_1, android.R.id.text1);
    mListView.setAdapter(mAdapter);
このAdapterに対して、取得した要素をaddします。Adapter#addで要素を追加すると、その結果は自動的にListViewにも反映され、以下の図のようにユーザーの友人一覧が表示されます。
その他、MainActivity上での画面やListAdapterの処理は、ASyncTaskを継承した「MainActivity.PeopleLoaderTask」クラスで、APIのリクエストやレスポンスの処理は、「PeopleApiClient」クラスに記述していますので、適宜ご参照ください。
 Access Tokenの有効期限が切れた場合の処理
Access Tokenには有効期限があります。期限が過ぎると、そのトークンは利用できなくなります。利用期限が過ぎた場合は、トークンのリフレッシュを行い、新しいAccess Tokenを取得する必要があります。
利用期限は、トークンの取得時のexpires_inから算出して求められるほか、実際にリクエストを発行した際に、レスポンスとしてHTTPステータスコード「401 Authorization Required」とともに、次のヘッダが付与されることで判別できます。
WWW-Authenticate: OAuth error='expired_token'
このレスポンスを受け取った場合、トークンをリフレッシュしてからリクエストを再試行する必要があります。トークンのリフレッシュは、前述のAuthorization CodeからAccess Tokenを取得する処理と、次の2点が異なる以外は同じ処理となります。
- grant_typeが「refresh_token」
 - 「redirect_uri」「code」の代わりに「refresh_token」を指定する
 
ただ、難しくない処理とはいえ、APIのリクエスト処理を書くたびに、毎回トークンのリフレッシュ機構を書くのは面倒です。API呼び出しのHTTPリクエストを1層ラップして、リクエストの際に自動的にAuthorizationヘッダを付与し、必要であればトークンのリフレッシュも行うように実装しておくと便利です。
今回のサンプルでは、その処理を行う「ApiRequestUtils.executeRequestWithRefresh()」メソッドを、次のように実装しています。
ApiRequestUtils.java抜粋private static <T> T executeRequestWithRefresh(HttpRequestBase request,ResponseHandler<T> responseHandler, OAuthTokenStore store, boolean isRetry)
throws ClientProtocolException, IOException {
    OAuthToken token = null;
    Header authorizationHeader = null;
    if (store != null) {
        token = getValidAccessToken(store);
        if (token != null) {
            authorizationHeader = 
                new BasicHeader("Authorization", "OAuth " + token.accessToken);
            request.addHeader(authorizationHeader);
        }
    }
    try {
        return executeRequest(request, responseHandler);
    } catch (TokenExpiredException e) {
        if (!e.isRetryable()) {
            Log.w(TAG, "Access token is invalid.");
        } else {
            if (isRetry) {
                Log.e(TAG, "An error occured while trying to refresh the access token.");
            } else {
                // try to refresh
                Log.v(TAG, "Access token has been expired. Trying to refresh.");
                if (authorizationHeader != null)
                    request.removeHeader(authorizationHeader);
                store.setToken(OAuthClient.refreshToken(token.refreshToken));
                return executeRequestWithRefresh(request, responseHandler, store, true);
            }
        }
        throw e;
    }
}
 Refresh Tokenが無効になった場合
ユーザーがサイト上から認可を取り下げた場合や、当初の認可画面で設定された期限が過ぎた場合、Refresh Tokenも無効となります。この場合は、認可フローを最初からやり直す必要があるため、その旨をユーザーに通知し、処理を行う必要があります。
MainActivity.java抜粋    PeopleApiClient client = new PeopleApiClient(MainActivity.this);
    try {
        return client.getFriends(startIndex, FETCH_COUNT_PER_REQUEST);
    } catch (TokenInvalidException e) {
        Log.w(TAG, "token is no longer valid");
        // トークンが無効になり、リフレッシュもできない場合は、再ログインが必要
        mNeedRelogin = true; 
    } catch (ClientProtocolException e) {
        Log.w(TAG, "request failed", e);
        errorMessage = e.getLocalizedMessage();
    } catch (IOException e) {
        Log.w(TAG, "request failed", e);
        errorMessage = e.getLocalizedMessage();
    }
    return null;
 アプリにソーシャルな要素を取り入れてみまソ
本稿では、Androidアプリケーションで外部サービス連携を行う際に必須の技術となるOAuth 2.0について概要を説明し、ネイティブ・アプリケーションでOAuth 2.0を用いた外部連携を行う方法を見てきましたが、いかがでしたでしょうか。
冒頭でも述べたように、外部との連携をうまく使うことでユーザーに大きなメリットをもたらすことができます。本稿のアプリケーションを基に、皆さんのアプリにもソーシャルな要素を取り入れてみてはいかがでしょうか。
■ @IT関連記事
| 今日から始める! Androidケータイアプリ作成の基礎 いまこそ知っておきたい「Androidアプリ」とは 日に日に国内でのニュースが増えているAndroidケータイ。その特徴を押さえてアプリ作成を始めるための基礎を紹介します 「Smart & Social」フォーラム 2009/11/19  | 
  ||
| Androidで動く携帯Javaアプリ作成入門 本連載で、SDKとEclipseを使ってAndroidの携帯端末で動くJavaアプリを作成し、Android Marketでの配布を目指しましょう 「Smart & Social」フォーラム  | 
  ||
| スマートフォンで「できちゃうこと」って? イチから始める! Androidセキュリティ(1) Androidに潜む危険はマルウェアだけはありません。実はアプリの作り方にも注意が必要です。クウと一緒に学びましょう 「Security&Trust」フォーラム 2011/3/3 
         | 
  ||
| Androidアプリで高速描画チューニングをするコツ インタビュー特集:Google直伝!(1) Googleのさまざまなサービスを使いこなすコツをグーグル担当者に聞くインタビュー。初回は日本で端末販売がせまるAndroidについて 「リッチクライアント & 帳票」フ ォーラム 2009/4/21  | 
  ||
| Androidのオープン性でガラパゴスから脱出しよう ものになるモノ、ならないモノ(29) ガラパゴスとやゆされる日本の高機能ケータイ。閉塞感に満ちた国内市場から世界に出るための解は、Androidのオープン性にある 「Master of IP   Network」フォーラム 2008/12/1 
         | 
  ||
 
        
      ケータイ分野以外の組み込みデバイス開発の現場でも注目を集めている「Android」。組み込みデバイスへの適用からアプリケーション開発、イベントレポート、ニュースなどAndroidに関するさまざまな技術情報・最新動向をお届けします! | 
  
| 3/3 | 
| INDEX | ||
| ネイティブアプリで実践! mixi Graph API活用法  OAuth 2.0を使うソーシャルなAndroidアプリの作り方  | 
  ||
| Page1 「OAuth」を使ってスマートでソーシャルなアプリを作ろう mixi Graph APIの利用登録  | 
  ||
| Page2 リダイレクト先のURL(独自スキーマ)の定義 Webブラウザからのリダイレクトを受け取る 認可コードからAccess Tokenを受け取る  | 
  ||
| Page3 Access Tokenを用いてPeople APIへリクエストを発行 Access Tokenの有効期限が切れた場合の処理 Refresh Tokenが無効になった場合 アプリにソーシャルな要素を取り入れてみまソ  | 
  ||
| Smart&Social フォーラム トップページへ | 
- 夏休みの自由研究にマイコンボードで「電子サイコロ」を作ったり、音楽プログラミングをしたりしてみよう (2017/7/24)
子ども向け電子工作&プログラミング用マイコンボード「chibi:bit」の基本的な使い方を紹介する企画。夏休みの自由研究に「電子サイコロ」を作ったり、音楽プログラミングをしたりしてみよう - 子ども向け電子工作&プログラミング用マイコンボード「chibi:bit」の基本的な使い方 (2017/7/20)
子ども向け電子工作&プログラミング用マイコンボード「chibi:bit」の基本的な使い方を紹介する。夏休みの子どもの自由研究などに役立てつつ、プログラミングを始めるきっかけにしてみてはいかがだろうか - 3DゲームのAIをiOSのSceneKitとGameplayKitで作る基本 (2017/7/10)
3Dゲーム用のフレームワークSceneKitを使った簡単なアプリ制作を通して、3Dゲーム用の人工知能(AI)について学ぶ - UnityアプリをWebGL、UWP、Android、iOS用としてビルドしてみた (2017/6/27)
アプリをWebで実行できるように書き出す方法やWindows上でUWP、Android、iOS用などにビルドする方法について解説する【Windows 10、Unity 5.6に対応】 
 
  | 
 |





