▼Androidメモ▼
Twitter通信


Twitter通信を行うプログラムを作成する。


アプリの登録
Twitter DevelopersでTwitterと連携するアプリの登録を行う。
アプリケーションの種類は「ブラウザアプリ」、コールバックURLには適当なURLを記述。
登録後に表示される「Consumer key」「Consumer secret」「Callback URL」を、
ソースコードの定数に記述。

ライブラリの追加
Twitterのライブラリ「twitter4j」を利用する。
最新版をダウンロードして解凍し、
「twitter4j-core-2.2.6.jar(数字はバージョンによって変換)」をAndroidプロジェクトのlibsに配置。

ソースコード
TwitterClient.java
package net.npaka.twitterclient;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

//Twitterクライアント
public class TwitterClient extends Activity {
//Twitterの設定
private final static String
CONSUMER_KEY ="Consumer keyを記述",
CONSUMER_SECRET="Consumer secretを記述",
CALLBACK ="Callback URLを記述";

//定数
private final static int
WC=LinearLayout.LayoutParams.WRAP_CONTENT,
MP=LinearLayout.LayoutParams.MATCH_PARENT,
MENU_SETUP =0,
MENU_UPDATE =1,
REQUEST_OAUTH=1;
private final static String
BR=System.getProperty("line.separator");

//システム
private Handler handler=new Handler();
private float dpi;

//UI
private ListView listView;
private Map<String,Bitmap> icons=new HashMap<String,Bitmap>();
private List<Status> statuses=new ArrayList<Status>();

//Twitter情報
private String token;
private String tokenSecret;

//アプリの初期化
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);

//DPIの取得
DisplayMetrics metrics=new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
dpi=metrics.density;

//リストビューの生成
listView=new ListView(this);
listView.setLayoutParams(new LinearLayout.LayoutParams(MP,WC));
listView.setAdapter(new ListAdapter());
setContentView(listView);

//トークンの読み込み
SharedPreferences pref=getSharedPreferences("token",MODE_PRIVATE);
token =pref.getString("token","");
tokenSecret=pref.getString("tokenSecret","");
}

@Override
public void onResume() {
super.onResume();
//ステータスの更新
updateStatuses();
}

  //オプションメニューの生成
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuItem item0=menu.add(0,MENU_SETUP,0,"設定");
item0.setIcon(android.R.drawable.ic_menu_preferences);
MenuItem item1=menu.add(0,MENU_UPDATE,0,"更新");
item1.setIcon(android.R.drawable.ic_menu_upload);
return true;
}

//メニューアイテム選択イベントの処理
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id=item.getItemId();

//OAuthの認証
if (id==MENU_SETUP) {
startOAuth();
}
//ステータスの更新
else if (id==MENU_UPDATE) {
updateStatuses();
}
return true;
}

//OAuthの認証
private void startOAuth() {
Intent intent=new Intent(this,OAuthActivity.class);
intent.putExtra(OAuthActivity.CALLBACK,CALLBACK);
intent.putExtra(OAuthActivity.CONSUMER_KEY,CONSUMER_KEY);
intent.putExtra(OAuthActivity.CONSUMER_SECRET,CONSUMER_SECRET);
startActivityForResult(intent,REQUEST_OAUTH);
}

//アクティビティ結果取得時に呼ばれる
@Override
protected void onActivityResult(int requestCode,int resultCode,Intent data) {
if (requestCode==REQUEST_OAUTH) {
if (resultCode==RESULT_OK) {
//OAuthの結果取得
token =data.getStringExtra(OAuthActivity.TOKEN);
tokenSecret=data.getStringExtra(OAuthActivity.TOKEN_SECRET);

//トークンの書き込み
SharedPreferences pref=getSharedPreferences("token",MODE_PRIVATE);
SharedPreferences.Editor editor=pref.edit();
editor.putString("token",token);
editor.putString("tokenSecret",tokenSecret);
editor.commit();
}
} else {
super.onActivityResult(requestCode,resultCode,data);
}
}

//ステータスの更新
private void updateStatuses() {
//OAuthの認証
if (token.length()==0) {
startOAuth();
return;
}

//ステータスの更新
Thread thread=new Thread(new Runnable(){public void run() {
try {
//ステータスの読み込み
Twitter twitter=new TwitterFactory().getInstance();
twitter.setOAuthConsumer(CONSUMER_KEY,CONSUMER_SECRET);
twitter.setOAuthAccessToken(new AccessToken(token,tokenSecret));
statuses=twitter.getHomeTimeline();
icons.clear();

//リストビューの更新
handler.post(new Runnable(){public void run(){
((BaseAdapter)listView.getAdapter()).notifyDataSetChanged();
}});
} catch (TwitterException e) {
toast(e.getMessage());
}
}});
thread.start();
}

//トーストの表示
private void toast(final String text) {
handler.post(new Runnable() {public void run(){
Toast.makeText(TwitterClient.this,text,Toast.LENGTH_LONG).show();
}});
}

//リストアダプタの生成
public class ListAdapter extends BaseAdapter {
//項目数の取得
@Override
public int getCount() {
return statuses.size();
}

//項目の取得
@Override
public Object getItem(int pos) {
return statuses.get(pos);
}

//項目IDの取得
@Override
public long getItemId(int pos) {
return pos;
}

//ビューの取得
@Override
public View getView(int pos,View view,ViewGroup parent) {
Context context=TwitterClient.this;
Status status=statuses.get(pos);

//レイアウトの生成
if (view==null) {
int padding=(int)(6*dpi);
LinearLayout layout=new LinearLayout(context);
layout.setPadding(padding,padding,padding,padding);
layout.setGravity(Gravity.TOP);
view=layout;

//アイコン
int size=(int)(48*dpi);
ImageView imageView=new ImageView(context);
imageView.setTag("icon");
imageView.setLayoutParams(new LinearLayout.LayoutParams(size,size));
layout.addView(imageView);

//テキストの指定
TextView textView=new TextView(context);
textView.setTag("text");
textView.setPadding(padding,0,padding,0);
layout.addView(textView);
}

//値の指定
ImageView imageView=(ImageView)view.findViewWithTag("icon");
readIcon(imageView,status.getUser().getProfileImageURL().toString());
TextView textView=(TextView)view.findViewWithTag("text");
textView.setText("【"+status.getUser().getName()+"】"+BR+
status.getText());
return view;
}
}

//アイコンの読み込み
private void readIcon(final ImageView imageView,final String url) {
//キャッシュ内アイコンの取得
if (icons.containsKey(url)) {
imageView.setImageBitmap(icons.get(url));
return;
}

//ネット上アイコンの取得
imageView.setImageBitmap(null);
Thread thread=new Thread(new Runnable(){public void run(){
try {
InputStream input=(new URL(url)).openStream();
final Bitmap icon=BitmapFactory.decodeStream(input);
if (icon!=null) {
icons.put(url,icon);
handler.post(new Runnable(){public void run(){
imageView.setImageBitmap(icon);
}});
}
} catch (Exception e) {
}
}});
thread.start();
}
}

OAuthActivity.java
package net.npaka.twitterclient;

import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.view.Window;
import android.webkit.CookieManager;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

//OAuth認証を行うアクティビティ
public class OAuthActivity extends Activity {
//アクティビティ起動時のインテントパラメータ
public static final String CALLBACK ="callback";
public static final String CONSUMER_KEY ="consumer_key";
public static final String CONSUMER_SECRET="consumer_secret";

//アクティビティ終了時のインテントパラメータ
public static final String USER_ID ="user_id";
public static final String SCREEN_NAME ="screen_name";
public static final String TOKEN ="token";
public static final String TOKEN_SECRET="token_secret";

//変数
private Handler handler=new Handler();
private WebView webView;
private Twitter twitter;
private String callback;
private String url;
private AccessToken accessToken;

//アクティビティ生成時に呼ばれる
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setResult(Activity.RESULT_CANCELED);

//プログレスの表示
requestWindowFeature(Window.FEATURE_PROGRESS);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

//Webビューの生成
webView=new WebView(this);
WebSettings settings=webView.getSettings();
settings.setSavePassword(false);
webView.setWebChromeClient(webChromeClient);
webView.setWebViewClient(webViewClient);
setContentView(webView);

//クッキーマネージャの設定
CookieManager cookieManager=CookieManager.getInstance();
cookieManager.setAcceptCookie(false);

//パラメータの取得
Intent intent=getIntent();
callback=intent.getStringExtra(CALLBACK);
String consumerKey =intent.getStringExtra(CONSUMER_KEY);
String consumerSecret=intent.getStringExtra(CONSUMER_SECRET);
if (callback==null || consumerKey==null || consumerSecret==null) {
finish();
}

//Twitterオブジェクトの取得
twitter=new TwitterFactory().getInstance();
twitter.setOAuthConsumer(consumerKey,consumerSecret);

//アクティビティ起動時の処理の実行
exePreTask();
}

//WebChromeクライアント
private WebChromeClient webChromeClient=new WebChromeClient() {
//プログレス変更時に呼ばれる
@Override
public void onProgressChanged(WebView view,int newProgress) {
super.onProgressChanged(view,newProgress);
setProgress(newProgress*100);
}
};

//Webビュークライアント
private WebViewClient webViewClient=new WebViewClient() {
//Webページ読み込み時に呼ばれる
@Override
public boolean shouldOverrideUrlLoading(WebView view,String url) {
if ((url!=null) && (url.startsWith(callback))) {
Uri uri=Uri.parse(url);
String oAuthVerifier=uri.getQueryParameter("oauth_verifier");

//アクティビティ終了時の処理の実行
exePostTask(oAuthVerifier);
return true;
}
return super.shouldOverrideUrlLoading(view,url);
}
};

//アクティビティ起動時の処理の実行
private void exePreTask() {
//プログレスの表示
setProgressBarIndeterminateVisibility(true);

Thread thread=new Thread(new Runnable(){public void run() {
//認証URLの取得
url=null;
try {
RequestToken requestToken=twitter.getOAuthRequestToken();
if (requestToken!=null) {
url=requestToken.getAuthorizationURL();
}
} catch (TwitterException e) {
}

handler.post(new Runnable(){public void run(){
//プログレスの非表示
setProgressBarIndeterminateVisibility(false);

//Webビューの更新
if (url!=null) {
webView.loadUrl(url);
} else {
finish();
}
}});
}});
thread.start();
}

//アクティビティ終了時の処理の実行
private void exePostTask(final String oAuthVerifier) {
//プログレスの表示
setProgressBarIndeterminateVisibility(true);

Thread thread=new Thread(new Runnable(){public void run() {
//アクセストークンの取得
accessToken=null;
if (oAuthVerifier!=null) {
try {
accessToken=twitter.getOAuthAccessToken(oAuthVerifier);
} catch (TwitterException e) {
}
}

handler.post(new Runnable(){public void run(){
//プログレスの非表示
setProgressBarIndeterminateVisibility(false);

//アクティビティの戻り値指定と終了
if (accessToken!=null) {
long userId=accessToken.getUserId();
String screenName=accessToken.getScreenName();
String token=accessToken.getToken();
String tokenSecret=accessToken.getTokenSecret();
Intent intent=new Intent();
intent.putExtra(USER_ID,userId);
intent.putExtra(SCREEN_NAME,screenName);
intent.putExtra(TOKEN,token);
intent.putExtra(TOKEN_SECRET,tokenSecret);
setResult(Activity.RESULT_OK,intent);
}
finish();
}});
}});
thread.start();
}
}

AndroidManifest
AndroidManifest.xml 
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.npaka.twitterclient"
android:versionCode="1"
android:versionName="1.0">

<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.INTERNET"/>

<application android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
android:theme="@style/AppTheme">

<activity
android:name=".TwitterClient"
android:label="@string/app_name"
android:launchMode="standard">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<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="myapp" android:host="mainactivity" />
</intent-filter>
</activity>

<activity
android:name=".OAuthActivity"
android:label="@string/app_name"
android:launchMode="standard">
</activity>

</application>

</manifest>


−戻る−