2011年6月2日木曜日

Androidでtwitter実装

■Androidでtwitterを実装するには

AndroidでtwitterAPIを活用したアプリを自作したい場合どうしたらいいのかと土曜の夜当たりから調べて、昨日、タイムラインを取得してツィートを投げるまでは実装できた。

ライブラリとしてはtwitter4jにアンドロイド用のjarがあるっぽいので活用し、oAuth認証でもxAuth実装できるらしい、
自分はtwitterへ申請するのが嫌だし、アプリにIDとパスワードを扱うxAuthはどうも好きではないので、oAuthでやってみた。

自宅で少しずつ勉強中なのでよく分かっていない事も多いが、後ほど自宅PCの前にゆっくり座れる時にでも、ソースコードを交えて詳しく紹介したい、でもtwitter4j Androidでgoogle先生に聞いた方が早いのは間違いがないw

全体的な流れとしては

twitterのoAuth認証URLをブラウザのインテントに渡してブラウザで認証してもらって、ブラウザからコールバックを自作アプリのActivityが拾い、あとはaccess_tokenとaccess_token_seckretを拾い、あとはちょめちょめとtwitter4jのメソッドを叩く。

oAuth認証が通るまでは不安で仕方がないが通ってしまえばなんていうこともないので大丈夫。

では、次のエントリーでtwitter4jの実装を紹介しますノシ

■Androidでtwitter実装その2

昼に書いたアンドロイドでtwitter4jを活用した実装を記述しようと思う。
準備:
1.twitter4jのアンドロイド用jarファイルをGET
2.twitterで連携アプリを設定するoAuth認証を行う場合、WEBアプリケーションとして登録する。コールバックURLは適当なURLを記載する(使わないので適当でいいが念のため他人の鯖には迷惑をかけないように自宅鯖とかがいいだろう)
3.consumer keyとconsumer key secretをメモっておく(まーコピペが早いからブラウザは閉じないでそのままにしておけば良い)
3.適当にアンドロイドプロジェクトをeclipseに作ったらtwitter4jの[twitter4j-core-android-2.2.1-SNAPSHOT.jar]をビルドパスに通す。ビルドパスはプロジェクトのプロパティ>javaのビルド・パスがあるのでライブラリタグから外部JARの追加で追加する。


では本題ですが、oAuth認証はIntent.ACTION_VIEWでhttpとかに反応するWEBブラウザに任せ、コールバックに自分のアプリを指定しておき、認証情報をブラウザからコールバックして貰うという流れになります。

onCreateの実装
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main);
mainlayout = (LinearLayout)findViewById(R.id.mainlayout);

//ツィートを書き込むためのEditText
tweet = (EditText)findViewById(R.id.tweet);

//ツィート送信ボタン

tweetBtn = (Button)findViewById(R.id.button1);
tweetBtn.setOnClickListener(this);

//プレリファレンスにはaccessTokenを覚えさせている。これはDBでも何でも良い。
SharedPreferences pref =

getSharedPreferences("pref",MODE_WORLD_READABLE);
mAccessToken = pref.getString("access_token", "nothing");
mAccessTokenSecret = pref.getString("access_token_secret", "nothing");

//アクセストークンを保持していない場合はアクセストークンを取得に行く

if(mAccessToken == "nothing" || mAccessTokenSecret == "nothing"){
askOAuth();
}
else{
createTwitterInstance();

}
}



askOAuthでブラウザのインテントを立上げコールバックで戻るまで
※かなり他ブログのコピペで実装しました。

private void askOAuth() {

//使用クラスはtwitter4jのおまじないである。
ConfigurationBuilder cbuilder = new ConfigurationBuilder();
  //CONSUMER_KEYを入れる。
cbuilder.setOAuthConsumerKey(CONSUMER_KEY);
//CONSUMER_SECRETを入れる。

cbuilder.setOAuthConsumerSecret(CONSUMER_SECRET);
Configuration conf = cbuilder.build();
mOauth = new OAuthAuthorization(conf);
mOauth.setOAuthAccessToken(null); // これが無いとgetOAuthRequestToken()で例外が発生するらしい
String authUrl = null;
try {

/*ここで指定したコールバックURLはアプリのインテントでありTweitterに登録したものとは別物
他のアプリとかぶるとコールバック時どのアプリか選択する画面が出てしまいウザイので
自分のアプリ名などを混ぜたものを設定した方が良い*/
authUrl = mOauth.getOAuthRequestToken("twittersamp://twitteroauth").getAuthorizationURL();
} catch (Exception e) {

Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show();
//Logger.putLog(e.toString());
return;
}
//ここでauthUrl(twitterのoauth認証画面へのURL)に反応するブラウザをキックする

Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl));
startActivity(intent);
}

/**
*askOuthでキックしたブラウザからコールバックされるとここのメソッドが呼ばれる
*/

@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);

Uri uri = intent.getData();
if (uri != null && uri.toString().startsWith(CALLBACK_URL)) {

//クエリーぱらめたからAccessTokenとAccessTokenSecretを取得して保存する
String verifier = uri.getQueryParameter("oauth_verifier");
try {
AccessToken at = mOauth.getOAuthAccessToken(verifier);

mAccessToken = at.getToken();
mAccessTokenSecret = at.getTokenSecret();
//このサンプルではプレリファレンスに記憶させている。
SharedPreferences pref =

getSharedPreferences("pref",MODE_WORLD_READABLE|MODE_WORLD_WRITEABLE);
Editor edit = pref.edit();
edit.putString("access_token", mAccessToken);
edit.putString("access_token_secret", mAccessTokenSecret);

edit.commit();
//Twitterクラスのインスタンス生成と初期処理をするメソッド、参考ブログのやり方のままである
createTwitterInstance();
} catch (Exception e) {

Toast.makeText(this,e.getMessage(),Toast.LENGTH_LONG).show();
}
}
}





createTwitterInstanceの中身

private void createTwitterInstance(){
//このあたりはお約束っぽいCOUNSUMER_KEYとかは自分の登録したCONSUMER_KEY等を入れる
ConfigurationBuilder cbuilder = new ConfigurationBuilder();
cbuilder.setOAuthConsumerKey(CONSUMER_KEY);

cbuilder.setOAuthConsumerSecret(CONSUMER_SECRET);
cbuilder.setOAuthAccessToken(mAccessToken);
cbuilder.setOAuthAccessTokenSecret(mAccessTokenSecret);
mConf = cbuilder.build();
TwitterFactory twitterFactory = new TwitterFactory(mConf);
mTwitter = twitterFactory.getInstance();

ResponseList res;
try {
//とりあえずタイムラインを取得してみる
res = mTwitter.getHomeTimeline();

Iterator ite = res.iterator();
ArrayList data = new ArrayList();


while(ite.hasNext()){
data.add(ite.next().getText);
}

/*

さしあたってツィート本文をListViewに突っ込んで表示させてみる
なおプロフィール画像等もStatus.getUser().getProfileImageUrlに近しい呼び出し等で取得できる
  詳しくはtwitter4jのドキュメントを参照*/
ArrayAdapter arrayAdapter

= new ArrayAdapter(this,R.layout.row,data);

ListView list = new ListView(this);
list.setAdapter(arrayAdapter);
mainlayout.addView(list, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));


} catch (TwitterException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
Toast.makeText(this,e.getMessage(),Toast.LENGTH_LONG).show();
Log.d("E", e.getMessage());

}

}


rowdata.xml layoutの中身
一応乗せるListview Stringのレイアウトl




もう遅くなってしまったのでtweet送信ボタンのあたりは急ぎ足でボタンとEditText等を適当に用意して下記の様なコードでとりあえずツィートできました。
public void onClick(View v){
if (v == tweetBtn){

SpannableStringBuilder sb = (SpannableStringBuilder)tweet.getText();
String str = sb.toString();
try {
mTwitter.updateStatus(str);

} catch (TwitterException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
Toast.makeText(this,e.getMessage(),Toast.LENGTH_LONG).show();

}
Toast.makeText(this,"ツィートしました。",Toast.LENGTH_LONG).show();
}
}


AndroidManifest.xml

注目店としてはコールバック用にを指定することとINTERNETのパーミッションが必要だってあたりです。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="jp.hoge.TwitterSample"
    android:versionCode="1"
    android:versionName="1.0">

<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".mainActivity"
            android:label="@string/app_name"
            android:launchMode="singleTask">

<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />

<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="twittersample" android:host="twitteroauth"/>
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
</manifest>

以上で、ツィート本文の羅列を表示してツィートを書き込み送信できるのではないかと思います。
ソースをブログに載せるにあたってところどころ改変したので動かなかったら適当に直していただければと思います。
この実装で1回認証を通したあとはプレリファレンスからaccess_tokenとaccess_token_secretを取りに行くようになります。
アプリ内でユーザーのID、パスワードを所持しないので気持ち悪くないですし、twitterへ申請も不要です。
ただ一度ブラウザを起動するのは正直カッコウ悪いです。
企業とか本格的なものを配布するならxAuth使ったほうが見栄えがいいだろうと思います。

申請も出せば通るようなので。

ではこのあたりでかなり眠いノシ