/* * * HTTPステータスコード(レスポンス) * 200 OK: 成功 * 304 Not Modified: 新しい情報はない * 400 Bad Request: API の実行回数制限に引っ掛かった、などの理由でリクエストを却下した * 401 Not Authorized: 認証失敗 * 403 Forbidden: 権限がないAPI を実行しようとした(following ではない protected なユーザの情報を取得しようとした、など) * 404 Not Found: 存在しない API を実行しようとしたり、存在しないユーザを引数で指定して API を実行しようとした * 500 Internal Server Error: Twitter 側で何らかの問題が発生している * 502 Bad Gateway: Twitter のサーバが止まっている、あるいはメンテ中 * 503 Service Unavailable: Twitter のサーバの負荷が高すぎて、リクエストを裁き切れない状態になっている */ package com.omokageru.ak.twitter; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.StringWriter; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.auth.AuthScope; import org.apache.http.auth.Credentials; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.webkit.WebView; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class Main extends Activity { private Button updateButton; private Button reloadButton; private EditText updateEdit; private WebView webView; private DefaultHttpClient httpClient; private String strpass; private String strid; /* (非 Javadoc) * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu) */ /** * オプションメニューの追加 */ @Override public boolean onCreateOptionsMenu(Menu menu) { // TODO 自動生成されたメソッド・スタブ super.onCreateOptionsMenu(menu); // 第二引数で設定するItemIDで // onMenuItemSelected で判定する menu.add( 0, 0, 0,R.string.Set_id_pass); return true; } /* (非 Javadoc) * @see android.app.Activity#onMenuItemSelected(int, android.view.MenuItem) */ /** * 選択されたオプションメニューの動作 */ @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { // TODO 自動生成されたメソッド・スタブ super.onMenuItemSelected(featureId, item); switch( item.getItemId()){ case 0: //R.string.Set_id_pass GoSetTwitterIDAndPassActivity(); break; } return true; } /* (非 Javadoc) * @see android.app.Activity#onActivityResult(int, int, android.content.Intent) */ /** * 子アクティビティからの結果を受け取る */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO 自動生成されたメソッド・スタブ // super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { SetTwitterIDAndPass(false); } } /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); updateButton = (Button) findViewById(R.id.UpdateButton); // ボタン押下時の処理 updateButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO 自動生成されたメソッド・スタブ if(!chkid(false)){ return; } // 通信を伴うので別スレッドで new Thread(){ @Override public void run() { // TODO 自動生成されたメソッド・スタブ updateButton.setClickable(false); reloadButton.setClickable(false); String str = updateEdit.getEditableText().toString(); UpdateTwitter(str); reloadButton.setClickable(true); updateButton.setClickable(true); } }.start(); } }); reloadButton = (Button) findViewById(R.id.ReloadButton); reloadButton.setOnClickListener(new OnClickListener() { public void onClick(View view) { // TODO 自動生成されたメソッド・スタブ if(!chkid(false)){ return; } // 通信を伴うので別スレッドで new Thread(){ @Override public void run() { updateButton.setClickable(false); reloadButton.setClickable(false); GetAndWriteHomeTimeLine(); reloadButton.setClickable(true); updateButton.setClickable(true); } }.start(); } }); updateEdit = (EditText) findViewById(R.id.UpdateEdit); webView = (WebView) findViewById(R.id.twitter_web); SetTwitterIDAndPass(true); } /** * Twitterへつぶやく * @param str * 投稿内容 */ private synchronized void UpdateTwitter( String str){ try { // パラメータstatus=hoge でhogeを発言(必須) HttpPost post = new HttpPost( "http://twitter.com/statuses/update.json?status=" + str); // 一応これで発言するはず HttpResponse response = httpClient.execute(post); // 失敗時の処理 if(response.getStatusLine().getStatusCode() != HttpStatus.SC_OK){ Toast.makeText( Main.this, "API制限か、Twitter ID/Password が間違っている可能性があります", Toast.LENGTH_LONG).show(); return; } // ここからの描画はなぜか利かない・・・ GetAndWriteHomeTimeLine(); } catch (ClientProtocolException e) { // TODO 自動生成された catch ブロック Toast.makeText( Main.this, "予期せぬエラー Main#UpdateTwitter ClientProtocolException", Toast.LENGTH_LONG).show(); } catch (IOException e) { // TODO 自動生成された catch ブロック Toast.makeText( Main.this, "予期せぬエラー Main#UpdateTwitter IOException", Toast.LENGTH_LONG).show(); } } /** * friend_timelineは将来廃止予定らしいので home_timeline を取得し表示。
* http://d.hatena.ne.jp/nowokay/20091030 を参考にしました。 */ private synchronized void GetAndWriteHomeTimeLine(){ try { // webView.clearCache(false); HttpGet get = new HttpGet( "http://twitter.com/statuses/home_timeline.json"); // これで取得するはず HttpResponse response = httpClient.execute(get); // 失敗時の処理 if(response.getStatusLine().getStatusCode() != HttpStatus.SC_OK){ Toast.makeText( Main.this, "API制限か、Twitter ID/Password が間違っている可能性があります", Toast.LENGTH_LONG).show(); return; } //解析と出力 //サーバーからのデータを取得 InputStream is = response.getEntity().getContent(); InputStreamReader isr = new InputStreamReader(is); StringWriter strin = new StringWriter(); BufferedReader buf = new BufferedReader(isr); for(String line; (line = buf.readLine()) != null;){ strin.write(line); } buf.close(); isr.close(); is.close(); //出力準備 StringWriter strout = new StringWriter(); PrintWriter out = new PrintWriter(strout); out.println("Twitter testapites"); out.println(""); //JSONデータからタイムラインを取得してHTMLを生成 JSONTokener token = new JSONTokener(strin.toString()); JSONArray arr = new JSONArray(token); for(int i = 0; i < arr.length(); i++){ JSONObject obj = arr.getJSONObject(i); JSONObject user = obj.getJSONObject("user"); out.println("
"); out.println(""); out.println("" + user.getString("screen_name") + "
" ); out.println(obj.get("text") + "
"); // ここで出力を確認しているが、発言内容が含まれているにもかかわらず、 // update側からはなぜか更新されない。 Log.i("t_test", "" + obj.get("text")); out.println("
"); } out.println(""); strin.close(); out.close(); // 二回呼び出すと反映される・・・ // invalidate() の意味は?? webView.loadData(strout.toString(), "text/html", "utf-8"); webView.loadData(strout.toString(), "text/html", "utf-8"); strout.close(); // 描画更新 // 本体スレッドからの呼び出しではない場合に備えpostInvalidateを使用。 // webView.postInvalidate(); // Log.i("t_test", "Invalidate"); } catch (ClientProtocolException e) { // TODO 自動生成された catch ブロック Toast.makeText( Main.this, "予期せぬエラー Main#GetAndWriteHomeTimeLine ClientProtocolException", Toast.LENGTH_LONG).show(); } catch (JSONException e) { // TODO 自動生成された catch ブロック Toast.makeText( Main.this, "予期せぬエラー Main#GetAndWriteHomeTimeLine JSONException", Toast.LENGTH_LONG).show(); } catch (IOException e) { // TODO 自動生成された catch ブロック Toast.makeText( Main.this, "予期せぬエラー Main#GetAndWriteHomeTimeLine IOException", Toast.LENGTH_LONG).show(); } } /** * TwitterのIDとPassを設定する * @param bCreate * 初回起動時はtrueを指定 */ private void SetTwitterIDAndPass( boolean bCreate){ updateButton.setClickable(false); reloadButton.setClickable(false); // プリファレンスからID/Passを取得 SharedPreferences preferences = getSharedPreferences( getString(R.string.preferences_name), MODE_PRIVATE); strid = preferences.getString( getString(R.string.preferences_id), ""); strpass = preferences.getString( getString(R.string.preferences_pass), ""); if(!chkid( bCreate)){ return; } httpClient = new DefaultHttpClient(); Credentials cred = new UsernamePasswordCredentials( strid, strpass); httpClient.getCredentialsProvider().setCredentials( new AuthScope("twitter.com", 80), cred); GetAndWriteHomeTimeLine(); updateButton.setClickable(true); reloadButton.setClickable(true); } /** * Twitter ID/pass が設定されているかを確認 * @param bCreate * 初回起動時はtrueを指定 * @return * boolean値 */ private boolean chkid( boolean bCreate){ if(strid.length() == 0 || strpass.length() == 0){ // 初回起動時にid/passが未設定なら、設定画面を呼び出す if(bCreate){ GoSetTwitterIDAndPassActivity(); } return false; } return true; } /** * Twitter ID/pass を設定するActivityへ移動 */ private void GoSetTwitterIDAndPassActivity(){ try{ Intent intent = new Intent(Main.this, SetID.class); startActivityForResult(intent, 0); } catch( ActivityNotFoundException e){ Toast.makeText( Main.this, "起動先のActivityが見つかりません", Toast.LENGTH_LONG).show(); } } }