指定時間につぶやいてくれるtwitter clientが欲しい!
という思いつきから始まった開発ですが、webで情報を集めても取捨選択が必要だったのでその過程を残しておきます。
この情報を元に、より良いアプリが出てくることを期待しています。
今回の開発では、APIとしてtwitter4jを用いました。
OAuthに対応するにあたり、もっとも簡単な方法だと思います。
紹介してるページも多いですし。
【開発環境】
JDK 6
Android SDK Tools, Revision 8
twitter4j-android-2.2.2
Eclipse Version: Helios Service Release 2
単純に文字を表示するだけなら、TextViewにベタ書きで十分です。
一般的なTwitter Clientは、発言者やRTした人のアイコン画像と文章を表示しています。
他のTwitterClientのように発言者のアイコンも表示したいなどの欲がでてくると、一気に複雑化しますね。
さて、AndroidのJavaアプリ開発では画面の配置は、xmlで記述することができるという特徴があります。
これを使えば、デザインを変更するのに、プログラムの修正が少なく済むということで取り組みたいと思いました。
ということで、レイアウトの勉強です。
ちなみに、Androidの画面描写に必要なレイアウトの基本は、こちらの資料が参考になります。
あんざいさんによるレイアウト資料
http://www.slideshare.net/yanzm/head-first-xml-layout-on-android-5290462
ということで、基本となるタイムラインのレイアウトを考えてみました。
基本的には、左側につぶやいた人のアイコン(絵)を表示して、右側に本文を表示することを考えました。
これは、ImageViewを使うのが手っ取り早いと思います。
最初はTextViewだけで表示しようと考えたのですが、ものすごくハードルが高いのであきらめました。
次に、この基本のレイアウトを何回も繰り返し使う方法に、ListViewを用いるのがよいと考えて挑戦しています。
ListViewは、挿入、削除が簡単にでき、内部にxmlで作ったレイアウトを繰り返して使える(入れ子)ことが特徴です。
ただ、そのままのListViewの使い方では、入れ子にできません。
既存のList用のクラスを継承して作成したadapterを用い入れ子内のレイアウトに対応します。
その入れ子の方法= adapterの使い方でわかりやすかったHPがこちら。
らぼ☆ろぐ
http://lablog.lanche.jp/archives/220
私は、このコードを参考にして簡単に対応できました。
気を付けるところとしては、ImageCacheのクラスを独立したjavaファイルとして作成することです。
さて、継承するクラスをArrayAdapterに変更することで、リスト形式のデータそのものを引数で渡せるようになります。
Twitter4jのStatusはList型なので、取得したList型をそのまま渡してスグ表示が可能なのが、少し感動です。
私が変更したところがわかるように一部公開しておきます。
// Twitterリスト表示用adapterクラス(ArrayAdapter継承)
private class TimelinePartsEachAdapter extends ArrayAdapter<Status> {
private Context context;
private LayoutInflater inflater;
private List<Status> items;
//コンストラクタ
public TimelinePartsEachAdapter(Context context, int resource, List<Status> data) {
super(context, resource, data);
this.context = context;
this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
private void setListData(List<Status> data){
Log.d(LogTAG, "TimelinePartsEachAdapter.setListData enter.");
//データ内容を保持しておく
items = data;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.v(LogTAG, "TimelinePartsEachAdapter.getView enter.");
Status settingData = items.get(position);
View v = convertView;
// 自分のTweetと、他者のTweetで、xmlを切り替える
// userIDを比較して、自分のIDかどうかを判断する
if (twitter_UserID == settingData.getUser().getId()){
// 自分が発言したTweet
Log.v(LogTAG, "Myself tweet.");
v = inflater.inflate(R.layout.timeline_parts_mytweet, null);
}
else if(twitter_UserID == settingData.getInReplyToUserId()
&& twitter_UserID == settingData.getUser().getId()){
// 自分の返信 && 自分のTweet
Log.v(LogTAG, "Myself tweet(reply). Status.getID:" + settingData.getUser().getId() + " Status.getReplyToID:" + settingData.getInReplyToUserId());
v = inflater.inflate(R.layout.timeline_parts_mytweet, null);
}
else
{
// 他者のTweet
Log.v(LogTAG, "Otherwise tweet. Status.getID:" + settingData.getUser().getId() + " Status.getReplyToID:" + settingData.getInReplyToUserId());
v = inflater.inflate(R.layout.timeline_parts_othertweet, null);
}
更新ボタンを押した時に、新しいTweetを読み取り表示させる方法です。
最新の20件を取得するには、Pagingを使います。
AjakuPanic のチラシの裏
http://d.hatena.ne.jp/AjakuPanic/20101025/1288013167
このPagingに指定する引数の使い方はこちらのHPを参照してください。
風柳メモ
http://d.hatena.ne.jp/furyu-tei/20100124/1264342029
これらを使って、Timelineにまとめる方法は簡単です。
extends ArrayAdapter<Status>にすることで、下記のように addAllで追加することができます。
まだ作りかけのソースですが、公開しておきます。
tweet_paging_latestが、new Pagingで作ったのインスタンスです。
try {
twitter_statuses_latest = twitter.getHomeTimeline(tweet_paging_latest);
// 過去に取得済みのList<Status>に、新しく取得したリストを追加する。
twitter_statuses.addAll(0, twitter_statuses_latest);
// TimeLineをTextViewに表示する
ViewTimeline(twitter_statuses);
// Pagingを更新する
tweet_paging_latest.setSinceId((twitter_statuses.get(0)).getId());
Log.d(LogTAG, "GetLatestHomeTimeline setSinceId:" + tweet_paging_latest.getSinceId() + ".");
} catch (TwitterException e) {
// TODO 自動生成された catch ブロック
Log.e(LogTAG, "GetLatestHomeTimeline getHomeTimeline() error.");
e.printStackTrace();
}