S-JIS[2010-09-08/2010-09-12] 変更履歴
Twitter4Jは、Twitterへアクセスする為のJavaのライブラリー。
Twitterへアクセスする為の公式なTwitter APIはHTTPで呼び出すので、それを理解していればHTTPクライアントを作るだけでアクセスできるようだが、その部分をTwitter4Jがライブラリー化してくれている。
したがって、Twitter4Jのクラス・メソッドを使用してTwitterにアクセスできる。
ちなみに、twitter4j-examples-2.1.3.jarはTwitter4Jのサンプルプログラム。ソースは「C:\workspace\twitter\twitter4j-2.1.3\twitter4j-examples\src\main\java」。
twitter4j-examplesのGetTimelinesクラスを参考に、タイムライン(TL)を取得して表示してみる。
import twitter4j.Status; import twitter4j.Twitter; import twitter4j.TwitterException; import twitter4j.TwitterFactory; import java.util.List;
public final class GetTimelines { public static void main(String[] args) { System.out.println("■factory."); Twitter twitter = new TwitterFactory().getInstance(); //認証なしで接続 System.out.println("■Showing public timeline."); try { List<Status> statuses = twitter.getPublicTimeline(); //パブリックタイムラインの取得 for (Status status : statuses) { System.out.println(status.getUser().getName() + ":" + status.getText()); } } catch (TwitterException e) { System.err.println(e.getMessage()); e.printStackTrace(); } } }
TwitterFactory#getInstance()を呼ぶと、コンソールにログが出力される。
Twitter#getPublicTimeline()を呼ぶと、パブリックタイムラインのツイートが取得される。
■factory. [Wed Sep 08 02:37:15 JST 2010]Will use class twitter4j.internal.logging.StdOutLoggerFactory as logging factory. [Wed Sep 08 02:37:16 JST 2010]Will use twitter4j.internal.http.HttpClientImpl as HttpClient implementation. ■Showing public timeline. 〜
Twitter#getUserTimeline()で、特定ユーザーのツイートが取得できる。
List<Status> statuses = twitter.getUserTimeline("hishidama");
Twitter#showStatus()で、特定のツイート(ステータス)が取得できる。
Status status = twitter.showStatus(81642112L);
twitter4j-examplesのGetTimelinesクラスには、ユーザーID・パスワードを指定してタイムラインを取得するサンプルも入っている。
Twitter twitter = new TwitterFactory().getInstance(userId, password);
しかしこれはBasic認証を使用する方法であり、Basic認証は現在廃止になっているので、実行するとエラーになる。
Failed to get timeline: 401:Authentication credentials were missing or incorrect.
{"errors":[{"code":53,"message":"Basic authentication is not supported"}]}
クライアントアプリケーションでOAuth認証を使ってみる。[2010-09-11]
(OAuth認証を使う為には、事前に自分のアプリケーション専用の認証情報をTwitterから発行してもらう必要がある)
参考: Twitter4JのコードサンプルのOAuth認可
import twitter4j.Twitter; import twitter4j.TwitterException; import twitter4j.TwitterFactory; import twitter4j.http.AccessToken; import twitter4j.http.RequestToken; import java.awt.Desktop; import java.io.IOException; import java.net.URI; import javax.swing.JOptionPane;
private static final String CONSUMER_KEY = "Twitter登録時に表示されたConsumer key"; private static final String CONSUMER_SECRET = "Twitter登録時に表示されたConsumer secret";
public Twitter loginOAuth() throws TwitterException { Twitter twitter = new TwitterFactory().getOAuthAuthorizedInstance(CONSUMER_KEY, CONSUMER_SECRET); getOAuthAccessToken(twitter); return twitter; }
AccessToken getOAuthAccessToken(Twitter twitter) throws TwitterException { //■リクエストトークンの作成 RequestToken requestToken = twitter.getOAuthRequestToken(); String url = requestToken.getAuthorizationURL(); // System.out.println("AuthorizationURL\t" + url); //■ブラウザーでTwitterの認証画面を表示する(ここでTwitterにログインすることにより、暗証番号が表示される) Desktop desktop = Desktop.getDesktop(); try { desktop.browse(URI.create(url)); } catch (IOException e) { throw new TwitterException(e); } //■暗証番号の入力を求めるダイアログ String pin = JOptionPane.showInputDialog("暗証番号を入力して下さい"); if (pin == null) { throw new TwitterException("暗証番号の入力がキャンセルされました"); } pin = pin.trim(); //■アクセストークンの作成(認証) try { AccessToken accessToken = twitter.getOAuthAccessToken(requestToken, pin); // System.out.println("AccessToken\t" + accessToken); return accessToken; } catch (TwitterException e) { // System.out.println(e.getStatusCode()); //拒否されると401 throw e; } }
Consumer key/secretは、自分のアプリケーション固有の値。
OAuthの登録を行った時に表示された英数字の羅列をコピペする。
https://twitter.com/oauth/authorize?oauth_token=hogehogeufufu
」といった感じ
。「oauth_token=
」以降は毎回変わる)過去に表示された暗証番号は再使用できないようだ。アクセストークン作成時にエラーになる。
一度認証されたアクセストークンは、保持しておけば何度でも使える。[2010-09-12]
(いちいち暗証番号を確認したり入力したりする必要が無くなる)
以下、シリアライズを使ってアクセストークンをファイルに保存しておく例。
public Twitter loginOAuth(String name) throws TwitterException { Twitter twitter; AccessToken accessToken = loadAccessToken(name); if (accessToken != null) { // 保存されていたアクセストークンを使う twitter = new TwitterFactory().getOAuthAuthorizedInstance(CONSUMER_KEY, CONSUMER_SECRET, accessToken); } else { // 認証して暗証番号を入力してもらい、アクセストークンを保存する twitter = new TwitterFactory().getOAuthAuthorizedInstance(CONSUMER_KEY, CONSUMER_SECRET); accessToken = getOAuthAccessToken(twitter); storeAccessToken(name, accessToken); } return twitter; }
// アクセストークンをファイルから読み込む AccessToken loadAccessToken(String name) { File f = createAccessTokenFileName(name); ObjectInputStream is = null; try { is = new ObjectInputStream(new FileInputStream(f)); AccessToken accessToken = (AccessToken) is.readObject(); return accessToken; } catch (IOException e) { return null; //ファイルが読めない(存在しない)場合はnullを返す } catch (Exception e) { e.printStackTrace(); return null; } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } }
// アクセストークンをファイルに保存する void storeAccessToken(String name, AccessToken accessToken) { File f = createAccessTokenFileName(name); File d = f.getParentFile(); if (!d.exists()) { d.mkdirs(); } ObjectOutputStream os = null; try { os = new ObjectOutputStream(new FileOutputStream(f)); os.writeObject(accessToken); } catch (IOException e) { e.printStackTrace(); } finally { if (os != null) { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } }
// アクセストークンを保存するファイル名を生成する File createAccessTokenFileName(String name) { String s = System.getProperty("user.home") + "/.twitter/client/sample/accessToken_" + name + ".dat"; return new File(s); }
OAuth認証を使ってツイート(つぶやきを投稿)する例。[2010-09-11]
void tweet() {
try {
Twitter twitter = loginOAuth(); //毎回暗証番号を入力
// Twitter twitter = loginOAuth("hishidama"); //初回だけ暗証番号を入力[2010-09-12]
twitter.updateStatus("Twitter4Jで投稿する実験");
// twitter.updateStatus("リツィートする実験 RT @hishidama 実験", ステータスID);
} catch (TwitterException e) {
System.err.println(e.getMessage());
e.printStackTrace();
}
}
参考: 18.updateStatus() - 陽昇れども地の底に光届かず
ちなみに、アプリをOAuthに登録した際に「Read-only(読取専用)」にしていると、例外が発生して投稿できない。
401:Authentication credentials were missing or incorrect. {"request":"/1/statuses/update.json","error":"Read-only application cannot POST"} TwitterException{exceptionCode=[15bb6564-00e304a2], statusCode=401, retryAfter=0, rateLimitStatus=null, version=2.1.3} at twitter4j.internal.http.HttpClientImpl.request(HttpClientImpl.java:307) at twitter4j.internal.http.HttpClientWrapper.request(HttpClientWrapper.java:72) at twitter4j.internal.http.HttpClientWrapper.post(HttpClientWrapper.java:103) at twitter4j.Twitter.updateStatus(Twitter.java:496) at jp.hishidama.twitter.sample.GetTimelines.tweet(Sample.java:201) at jp.hishidama.twitter.sample.GetTimelines.main(Sample.java:60)