連載
» 2011年07月29日 00時00分 公開

UnityでAndroidのBluetooth制御&Twitter4J連携Unityで楽々スマホ用3Dアプリ開発入門(3)(2/3 ページ)

[佐藤大介,グリー株式会社 メディア開発本部]

Unityと既存Javaライブラリとの連携

 スマートフォンでは、やはりネットワークを使って、いろいろなWebサービスと連携したアプリを開発したくなるものです。その際、例えばそのWebサービスと通信するために便利な通信ライブラリがオープンソースで出回っていたりしますが、残念ながら多くの場合、Unity用のライブラリは提供されていません。

Twitter4JとUnityの連携

 そこで、ここではJava言語で提供されているライブラリをUnityから利用する例を紹介します。ここではゲームからTwitterに、ひと言を投稿するのに便利な「Twitter4J」というライブラリを用いて実装してみます。

事前準備

 Twitter4Jのライブラリをダウンロードし、Twitterアプリ開発用の認証情報(CONSUMER_KEYとCONSUMER_SECRET)をTwitterの開発者サイトで発行しておいてください。詳細は、下記記事を参照してください。

Java側コード実装

 Java側のクラス構成として、メインActivityである「TwitterSampleActivity」クラスと、Twitter側認証画面を表示するための「TwitterAuthActivity」クラスの2つを作成します。

TwitterSampleActivity
package com.example.twittersample;
 
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;
import com.unity3d.player.UnityPlayerActivity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
 
public class TwitterSampleActivity extends UnityPlayerActivity { // [1]
    private static TwitterSampleActivity twitterSampleActivity_ = null; // [2]
    private String accessTokenString_ = null;
    private String accessSecretString_ = null;
    private Twitter twitterInstance_ = null;
    private RequestToken requestToken_ = null;
    private static String CONSUMER_KEY = "XXXXXXXXXXXXXXXXXXXX"; // [3]
    private static String CONSUMER_SECRET = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX"; // [4]
    private final static int REQUEST_CODE_AUTH = 1;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) { // [5]
        super.onCreate(savedInstanceState);
        twitterSampleActivity_ = this; // [6]
    }
    @Override
    protected void onActivityResult (int requestCode, int resultCode, Intent data){ // [7]
        String oauthVerifier = data.getExtras().getString("oauth_verifier");
        try {
            AccessToken accessToken = twitterInstance_.getOAuthAccessToken(requestToken_, oauthVerifier);
            storeAccessToken(accessToken.getToken(),accessToken.getTokenSecret());
        } catch (TwitterException e) {
            e.printStackTrace();
        }
    }
    public void auth(){ // [8]
        TwitterFactory factory = new TwitterFactory();
        twitterInstance_ = factory.getInstance();
        twitterInstance_.setOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
        if(restoreAccessToken()){
            twitterInstance_.setOAuthAccessToken(new AccessToken(accessTokenString_, accessSecretString_));
            //verify
            return;
        }
        try {
            requestToken_ = twitterInstance_.getOAuthRequestToken();
            Intent intent = new Intent(this, TwitterAuthActivity.class);
            intent.putExtra("auth_url", requestToken_.getAuthorizationURL());
            startActivityForResult(intent, REQUEST_CODE_AUTH);
        } catch (TwitterException e) {
            e.printStackTrace();
        }
    }
    private boolean restoreAccessToken(){ // [9]
        SharedPreferences pref = getSharedPreferences("oauth",MODE_PRIVATE);
        accessTokenString_ = pref.getString("token", null);
        accessSecretString_ = pref.getString("secret",null);
        if(accessTokenString_ != null && accessSecretString_ != null) return true;
        else return false;
    }
    private void storeAccessToken(String token, String secret){ // [10]
        SharedPreferences pref = getSharedPreferences("oauth",MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();
        editor.putString("token", token);
        editor.putString("secret", secret);
        editor.commit();
    }
    public void updateStatus(String message){ // [11]
        if(twitterInstance_ != null){
            try {
                twitterInstance_.updateStatus(message);
            } catch (TwitterException e) {
                e.printStackTrace();
            }
        }
    }
    public String getScreenName(){ // [12]
        if(twitterInstance_ != null){
            try {
                return twitterInstance_.getScreenName();
            } catch (IllegalStateException e) {
                e.printStackTrace();
                return null;
            } catch (TwitterException e) {
                e.printStackTrace();
                return null;
            }
        }else{
            return null;
        }
    }
}

 [1]で、UnityPlayerActivityを継承します。[2]では、staticなメンバ変数として本クラス自身を参照するための変数を定義しておきます。Unityからアクセスする際に、ここから本クラスにアクセスします。

 [3]では、Twitterから発行されたCONSUMER_KEY情報を設定しています。本来Javaのソースコードに書き込むのはよくないので、ちゃんと実装する場合はNDKなどを用いて秘匿化しておいた方がよいと思います。[4]では、Twitterから発行されたCONSUMER_SECRET情報を設定しています。こちらも[3]と同様、本来はNDKなどを用いた方がよいと思います。

 [5]は、本クラス用のonCreateメソッドです。[6]では、[2]の変数に自分自身を登録しています。

 [7]では、[8]でアクセストークンを新規に取得した場合、コールバックとして呼び出されます。また、[10]の処理を呼び出しアクセストークンを保存しています。

 Twitterサービスの情報を読み書きするのに、最初にTwitterに対してCONSUMER_KEYとCONSUMER_SECRET情報とログインID/パスワード情報を用いてアクセス許可をもらい、その許可証としてのアクセストークンを取得する必要があります(OAuth認証)。

 [8]では、まだアクセストークンを持っていない場合に認証画面を表示するために、TwitterAuthActivityクラスを呼び出しています。許可画面においてユーザーにログインと許可をユーザーが行うと、アクセストークンが付与され、[8]の処理が呼び出されます。すでにアクセストークンを取得済みの場合には、それを利用します。

 [9]では、SharedPreferencesに保存したアクセストークンを取得しています。[10]では、SharedPreferencesに[8]で取得したアクセストークンを保存しています。

 [11]では、Unityからつぶやくための関数を定義します。内部でTwitter4Jが提供する関数を呼び出し、Unityから渡された送信するメッセージを渡しています。[12]では、UnityからTwitter上でのスクリーン名を取得するための関数を定義します。内部でTwitter4Jが提供する取得関数を呼び出しし値をUnity側に戻しています。

TwitterAuthActivityクラス
package com.example.twittersample;
 
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log ;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.LinearLayout;
import android.graphics.Bitmap;
 
public class TwitterAuthActivity extends Activity {
    private WebView webView_ = null;
    private final static String CALLBACK_URL = "http://example.com/callbackurl"; // [1]
 
    @Override
    public void onCreate(Bundle savedInstanceState) { // [2]
        super.onCreate(savedInstanceState);
        setupLayout();
        String authUrl = getIntent().getExtras().getString("auth_url");
        webView_.loadUrl(authUrl);
    }
    void setupLayout(){ // [3]
        LinearLayout layout = new LinearLayout(this);
        layout.setOrientation(LinearLayout.VERTICAL);
        setContentView(layout,new ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.FILL_PARENT,
            ViewGroup.LayoutParams.FILL_PARENT
        ));
        webView_ = new WebView(this);
        webView_.setWebViewClient(new WebViewClient(){
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) { // [4]
                Log .d("onPageStarted", url);
                if(url!=null && url.startsWith(CALLBACK_URL)){
                    String oauthToken = "";
                    String oauthVerifier = "";
                    String[] urlParameters = url.split ("\\?")[1].split ("&");
                    if(urlParameters[0].startsWith("oauth_token")){
                        oauthToken = urlParameters[0].split ("=")[1];
                    }else if(urlParameters[1].startsWith("oauth_token")){
                        oauthToken = urlParameters[1].split ("=")[1];
                    }
                    if(urlParameters[0].startsWith("oauth_verifier")){
                        oauthVerifier = urlParameters[0].split ("=")[1];
                    }else if(urlParameters[1].startsWith("oauth_verifier")){
                        oauthVerifier = urlParameters[1].split ("=")[1];
                    }
                    Intent intent = getIntent();
                    intent.putExtra("oauth_token", oauthToken);
                    intent.putExtra("oauth_verifier", oauthVerifier);
                    setResult(Activity.RESULT_OK, intent);
                    finish();
                }
            }
        });
        layout.addView(webView_,new LinearLayout.LayoutParams(
            LinearLayout.LayoutParams.FILL_PARENT,
            LinearLayout.LayoutParams.FILL_PARENT
        ));
    }
}

 [1]では、Twitterの開発者サイトで登録したコールバックURLを指定します。実際にプログラムがそのURLを開くことはありませんが、そのURLに遷移を要求された際にOAuth認証完了としてプログラムが認識し、引数に渡されたパラメータから必要なトークン情報を取得します。

 この辺の詳細については以下の記事を参照いただければと思います。

 [2]は、本クラス用のonCreateメソッドです。Twitterの認証画面は標準ではWebでの提供なので、[3]でActivity上にWebViewを配置し表示するようにしています。[4]では、[3]で設置したWebViewにおいて、CALLBACKURLに遷移した際にキャッチできるようにWebViewClientをカスタマイズし、onPageStarted()関数でURLの遷移を監視しています。

 CALLBACKURLへの遷移をキャッチしたら、URLに含まれているパラメータから必要なトークン情報を取得し、メインActivityに渡して本Activityを終了させています。

 次ページでは引き続き、Unity側の呼び出しコードを実装し、アプリをビルドして実行します。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。