2011年3月10日木曜日

ListViewをカスタマイズする

ListViewをカスタマイズする

ここが参考になりすぎて、自分で書くことがないのですが、とりあえずメモがわりとして。
実際に動かして表示したコードは、またいつか気が向いたら。

TwitterのTimelineを表示するのはほとんどこれでできちゃいました。
本当は、過去分とかはキャッシュしたりしてsqliteとかに放りこみたいのですが、
スポットでTimeline表示するだけならこれで十分かと。

Twitter Clientとかでよくある、30min agoとか何分前とか。"elapsed time"

これもライブラリがありました。
prettytimeだって。

Convert elapsed timestamps, like, “in 3 minutes!”
elapsed time = 経過時間 というらしい。(恥

ocpsoft-pretty-time-1.0.6.jarを使用しました。

Dateにフォーマットかけて
TextViewにセットするだけです。

PrettyTime p = new PrettyTime();
String prettyTime = p.format(*DateClassのインスタンス*);
TextView minutetext = (TextView)view.findViewById(R.id.minutetext);
minutetext.setText(prettyTime);

簡単簡単。

Twitter4j でプロフィールのイメージを表示

先の投稿、Twitter4jでxAuth認証 で作成した、TwitterWrapperを使用しています。

Activityの中で。

TwitterWrapper twa = new TwitterWrapper();
        // TwitterWrapperに用意してあるmethodで、SharedPreferencesに保存してあるTwitterの
        // oAuth Token と oAuth Token Secretを使って、アカウントをログイン状態にしています。
        twitter = twa.getAuthorizedTwitter(this);
        
        // SharedPreferencesに保存しておいた、設定を取得
        SharedPreferences pref = 
            getSharedPreferences(Values.TWITTER_PREFERENCE_NAME, Activity.MODE_PRIVATE);
        // SharedPreferencesに保存しておいた、ScreenNameを取得
        String screenName = pref.getString(Values.TWITTER_ID_KEY,"NONE");
        
        try {
            // ScreenNameをつかって、Userのデータを取得。
            User user = twitter.showUser(screenName);
            // ScreenNameをつかって、UserのProfile画像のURLを取得。
            URL imageURL = user.getProfileImageURL();
            Bitmap profile = null;
            // これは、適当にViewのLayoutファイルと紐付けしてください。
            ImageView imgv = (ImageView)findViewById(R.id.userIcon);
            try {
                // BitmapFactory.decodeStreamでビットマップを作成。
                profile = BitmapFactory.decodeStream(
                    imageURL.openConnection().getInputStream());
                if ( profile != null ) {
                    // ちゃんと画像が取得できた時だけ、ImageViewにせってい
                    imgv.setImageBitmap(profile);
                }
            } catch (IOException e) {
                // 取れなかったら無視、レイアウトファイルに
                // デフォルト画像のsrcを設定しておくとそれが出ます。
            }
            
        } catch (TwitterException e) {
            e.printStackTrace();
        }

2011年3月9日水曜日

Twitter4jでxAuth認証

実際にActivityに書いて認証を呼び出すコードを。

めんどくさいので、TwitterWrapperというクラスを作りました。
設定値は、Valuesというクラスに入れてあります。(手抜き

ステップは4つ
1)twitter4jのjarファイルをビルドパスに追加。
2)設定用のValuesクラスを用意。
3)TwitterWrapperを用意。
4)Activityにメソッドを記述。

1)twitter4jのjarファイルをビルドパスに追加。
これは適当にどこか見てみてください。
こことか。JavaでTwitterをOAuth認証して使えるTwitter4jとは

Versionは、twitter4j-android-2.2.1-SNAPSHOT.zip を使用しました。
他必要なライブラリは、oauth-signpost で、signpost-commonshttp4-1.2.1.1.jar とsignpost-core-1.2.1.1.jarです。

2)設定用のValuesクラスを用意。
設定用のValuesクラス
public class Values {

 public static final String TWITTER_SCREEN_NAME = "じぶんのアカウント";
 
 public static final String TWITTER_CONSUMER_KEY = "自分のConsumerKey";
 public static final String TWITTER_CONSUMER_SECRET = "自分のConsumerSecret";
 public static final String TWITTER_ACCESS_TOKEN_URL = "https://api.twitter.com/oauth/access_token";
 public static final String TWITTER_AUTHORIZE_URL = "https://api.twitter.com/oauth/authorize";
 public static final String TWITTER_CALLBACK_URL = "http://てけとうに自分のサイト/";
 public static final String TWITTER_PREFERENCE_NAME = "おすきに";
 
 public static final String TWITTER_ID_KEY = "screen_name";
 public static final String TWITTER_TOKEN_KEY = "token";
 public static final String TWITTER_TOKEN_SECRET_KEY = "tokenSecret";
 
 public static final String TWITTER_ACCESS_TOKEN_KEY = "accessToken";
 
}

3)TwitterWrapperを用意。


インポート文
import twitter4j.Query;
import twitter4j.QueryResult;
import twitter4j.Tweet;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.User;
import twitter4j.conf.Configuration;
import twitter4j.conf.ConfigurationBuilder;
import twitter4j.http.AccessToken;
import twitter4j.http.OAuthAuthorization;
import java.util.List;
import android.app.Activity;
import android.content.SharedPreferences;
import android.util.Log;
import android.widget.EditText;

// リソースファイルがわり。
import jp.mediba.android.util.Values;

クラス
public class TwitterWrapper {
    Twitter twitter;
 
    public TwitterWrapper() {
        // do nothing
    }

    public TwitterWrapper(Twitter twitter) {
        this.twitter = twitter;
    }
 
    public Twitter getTwitter() {
        return twitter;
    }

    public void setTwitter(Twitter twitter) {
        this.twitter = twitter;
    }
 
    /**
     * Usage: java twitter4j.examples.search.SearchTweets [query]
     */
    public List<tweet> searchTweet() {
        String str = Values.TWITTER_HASHTAG;
        Twitter twitter = new TwitterFactory().getInstance();
        try {
            Query query = new Query(str);
            query.setRpp(30);
            QueryResult result = twitter.search(query);
            List<tweet> tweets = result.getTweets();
            return tweets;
        } catch (TwitterException te) {
            te.printStackTrace();
            Log.w("TWT", "Failed to search tweets: " + te.getMessage());
        }
        return null;
    }
    
    public void authorization(Activity act) throws TwitterException {
     
        ConfigurationBuilder builder =
                new ConfigurationBuilder();
        builder.setOAuthConsumerKey(Values.TWITTER_CONSUMER_KEY);
        builder.setOAuthConsumerSecret(Values.TWITTER_CONSUMER_SECRET);
        TwitterFactory factory = new TwitterFactory(builder.build());
        String screen_name = 
                ((EditText)act.findViewById(R.id.txtScreenName)).getText().toString();
        String password = 
                ((EditText)act.findViewById(R.id.txtPassword)).getText().toString();
        Twitter twitter = factory.getInstance(screen_name,password);
        AccessToken accessToken = null;
        try {
            accessToken = twitter.getOAuthAccessToken();
            String token = accessToken.getToken();
            String tokenSecret = accessToken.getTokenSecret();
            SharedPreferences pref = 
                act.getSharedPreferences(
                    Values.TWITTER_PREFERENCE_NAME,
                    Activity.MODE_PRIVATE);
            SharedPreferences.Editor editor = pref.edit();
            editor.putString(Values.TWITTER_TOKEN_KEY,token);
            editor.putString(Values.TWITTER_TOKEN_SECRET_KEY,tokenSecret);
            editor.putString(Values.TWITTER_ID_KEY,screen_name);
            editor.commit();
        } catch (TwitterException e) {
            e.printStackTrace();
            throw e;
        }
  
    }

    
    public Twitter getAuthorizedTwitter(Activity act) {
        SharedPreferences settings = 
            act.getSharedPreferences(Values.TWITTER_PREFERENCE_NAME, 0);
        String token = settings.getString(Values.TWITTER_TOKEN_KEY,"NONE");
        String tokenSecret = settings.getString(Values.TWITTER_TOKEN_SECRET_KEY,"NONE");
     
        Twitter twitter = new TwitterFactory().getInstance();
        if(twitter.getAuthorization().isEnabled()){
            return twitter;
        } else {
            ConfigurationBuilder builder = new ConfigurationBuilder();
            builder.setOAuthConsumerKey(Values.TWITTER_CONSUMER_KEY);
            builder.setOAuthConsumerSecret(Values.TWITTER_CONSUMER_SECRET);
            builder.setOAuthAccessToken(token);
            builder.setOAuthAccessTokenSecret(tokenSecret);
            Configuration configuration = builder.build();

            TwitterFactory factory = new TwitterFactory();
            try {
                twitter = factory.getInstance(new OAuthAuthorization(configuration));
            } catch (java.lang.StringIndexOutOfBoundsException e) {
                return null;
            }
         
            if(twitter.getAuthorization().isEnabled()){
                return twitter;
            } else {
                return null;
            }
        }
    }
}

4)Activityにメソッドを記述。

Activityに以下のメソッドを書きます。

インポート文
import twitter4j.TwitterException;
import jp.mediba.android.util.TwitterWrapper;

Activityに以下のメソッドを書き、ボタンに結びつけます。

public void pushAuth(View v) {
        TwitterWrapper tw = new TwitterWrapper();
        AlertDialog.Builder abuilder = new AlertDialog.Builder(this);
        try {
         // ActivityそのものをTwitterWrapperに渡しています。
   tw.authorization(this);
   // 設定が完了したら、ダイアログを出す。
   abuilder.setMessage( R.string.dialog_api_twitter_setting_done_title )
          .setCancelable(false)
          .setPositiveButton( R.string.ok, new DialogInterface.OnClickListener() {
              public void onClick(DialogInterface dialog, int id) {
               dialog.cancel();
               // ダイアログのOKをおしたら、別画面に遷移。
               goTweet();
              }
          });
   
  } catch (TwitterException e) {
   e.printStackTrace();
   // なんかエラーが起きたら、ダイアログを出す。
   abuilder.setMessage( R.string.error_api_twitter_login )
         .setCancelable(false)
         .setPositiveButton( R.string.ok, new DialogInterface.OnClickListener() {
             public void onClick(DialogInterface dialog, int id) {
              dialog.cancel();
             }
         });
  
  }
  AlertDialog alert = abuilder.create();
  alert.show();
    }
    
    // 遷移したいActivityをセットして、画面遷移するロジックは外出ししておく。
    public void goTweet() {
     Intent intent = new Intent(this, ActTweet.class);
     startActivity(intent);
     finish();
    }
    

Twitter xAuth申請で疲れた…。

Androidにて、Twitter連携アプリを作成し、xAuthに対応させてみました。
その際、xAuthの申請で、非常に時間がかかったので、まとめ。

最初、アプリケーション名と、情報だけ書いて、開発中ですとメール送ったら、
これでできない?「http://dev.twitter.com/pages/oauth_single_token
とお返事が帰ってきました。
先に、oAuthのTokenとTokenSecretをとっておいて、アプリに埋め込んじゃえばoAuthで投稿できるよという意味らしいです。



しかしこれでは、アプリでユーザーがログインして、そのアカウントで投稿するってのができません。

xAuthの許諾は真面目に審査してるみたいです。
開発目的での許諾は行わないとのメールももらいました。

ということで、xAuthの許可を得るのに必要な準備事項をまとめておきます。

1)oAuthアプリケーションの登録。
Webでは下記の場所から登録できます。
「設定」>「連携アプリ」>「連携アプリの追加と設定は『こちら』から変更できます。」
2)アプリのログイン画面とTweet画面、TLの画面をキャプチャしてPDFか何かで、説明文をまとめたもの。
Twitterのチケットサーバーは添付ファイルに対応していないようなので、PDFや画像はどこか公開できるサーバーに配置しておきましょう。


この状態で、以下のメールをapi@twitter.comにおくります。
(英文が変なのは、気にしないでください。www )

---
Hello.

I'm a developer of "アプリケーション名".

"アプリケーション名" is a android application, for tweeting some messages.
I want to use this application for a multi users' twitter client.
I do not want to use android.webkit.WebView because of Userbility.
I send this application screen capture and explain the reason of using xAuth.
URL:{スクリーンキャプチャのURLとか。}
Please apply this app to use xAuth.

Application Name: {アプリケーション名}
App Source Code : (now developping)
My account : @{ツイッターのスクリーンネーム}
oAuth Clients : http://twitter.com/oauth_clients/details/{oAuth申請のページのID}

Thank you.
---


これで一発で通るはず。

あとは、Twitterにログインした状態で、
のステータスを確認していましょう。

ちなみに、なんでWebViewを使わないか、ってところの文章は、「日本人アンドロイドに慣れてないの。」としていましたが、これさすがに汎用的に使われると如何かと思うので、文章を「because of Userbility.」に変えてあります。

申請の際に仕様した、PDFも少々変えてありますが、添付しておきます。
(多分ちゃんとしたスクリーンキャプチャのほうが、いいはず。)