SQLの窓

2013年10月12日


Twitter API の自分のアプリのトークンを使って投稿するだけの class Android_Twitter

更新履歴
2013-07-11 : 初回投稿
2013-08-24 : Twitter がエラーを返す場合は、getErrorStream を使う必要があったので修正
2013-10-12 : rfc3986 内部メソッドを追加( やはりきっちりしないとエラーになりました )

Twitter がエラーを返す場合( 例えば投稿データか空の場合 )は、getInputStream では無く getErrorStream を使わないと、エラー内容が取得できなかったので修正しました
Android なので、非同期処理は AsyncTask です。クラスのメソッド内で匿名のインナー型を使用して実装しています。終了時のイベントは、専用のインターフェイスを作成して、onPostExecute から呼び出しています。 Android_Twitter.java
package com.example.posttest;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import android.os.AsyncTask;
import android.util.Base64;
import android.widget.EditText;

public class Android_Twitter {

	// AsyncTask のインラインで参照する為の final
	private final String _consumer_key;
	private final String _consumer_secret;
	private final String _token;
	private final String _secret;

	// API
	private final String _tweet_api = "https://api.twitter.com/1.1/statuses/update.json";
	
	// **************************************************************
	// コンストラクタ
	// **************************************************************
	public Android_Twitter(String _consumer_key, String _consumer_secret,
			String _token, String _secret) {
		this._consumer_key = _consumer_key;
		this._consumer_secret = _consumer_secret;
		this._token = _token;
		this._secret = _secret;
	}

	// **************************************************************
	// AsyncTask の onPostExecute から外部イベントとして呼び出す為のインターフェイス
	// **************************************************************
	public interface Tweeted {
		public void onTweetResult(String result);
   	}
	
	// **************************************************************
	// Twitter 投稿
	// **************************************************************
	public void Tweet(String text, final Tweeted OnTweetResult) {
		
		new AsyncTask<String, Void, String>() {

			// **************************************************************
			// 非同期処理
			// **************************************************************
			@Override
			protected String doInBackground(String... params) {

				ArrayList<String> lst = new ArrayList<String>();
				String nonce = getNonce();
				String timeStamp = getTimeStamp();
				String result_string = "";
				try {
				
					// *********************************
					// 投稿に必要なデータ (1)
					// *********************************
					lst.add("oauth_consumer_key=" + _consumer_key);
					lst.add("oauth_nonce=" + nonce);
					lst.add("oauth_signature_method=" + "HMAC-SHA1");
					lst.add("oauth_timestamp=" + timeStamp);
					lst.add("oauth_token=" + _token);
					lst.add("oauth_version=1.0");				
					lst.add("status=" + rfc3986(URLEncoder.encode(params[0], "utf-8")));	

					Collections.sort(lst);
					
					String work = "";
					for(int i = 0; i < lst.size() ; i++ ){
						if ( i != 0 ) {
							work += "&";
						}
						work += lst.get(i);
					}
					
					// *********************************
					// 投稿に必要なデータ (2)
					// *********************************
					String work2 = "POST" + "&";
					// API のエントリポイント
					work2 += rfc3986(URLEncoder.encode(_tweet_api,"utf-8")) + "&";
					// 投稿に必要なデータ (1)
					work2 += rfc3986(URLEncoder.encode(work,"utf-8"));
					
					// *********************************
					// 投稿に必要なデータ (3)
					// *********************************
					String oauth_signature = getSignature(work2);
					
					// *********************************
					// 投稿に必要なデータ (4) / ヘッダ
					// *********************************
					String data = "oauth_consumer_key=" + dD(_consumer_key) +
						",oauth_nonce=" + dD(nonce) +
						",oauth_signature=" + dD(rfc3986(URLEncoder.encode(oauth_signature, "utf-8"))) +
						",oauth_signature_method=" + dD("HMAC-SHA1") +
						",oauth_timestamp=" + dD(timeStamp) +
						",oauth_token=" + dD(_token) +
						",oauth_version=" + dD("1.0");

					// 投稿先
					URL url = new URL(_tweet_api);

					// 接続準備
					HttpURLConnection http = (HttpURLConnection)url.openConnection();
					http.setConnectTimeout(30000);
					http.setReadTimeout(30000);
					http.setDoInput(true);
					// ヘッダ
					http.setRequestProperty("Authorization", "OAuth " + data);
					http.setRequestMethod("POST");					

					// 送信用ストリーム
					OutputStreamWriter osw = new OutputStreamWriter(http.getOutputStream());
					BufferedWriter bw = new BufferedWriter(osw);
					
					// 送信データの書き込み
					bw.write("status=" + rfc3986(URLEncoder.encode(params[0], "utf-8")));
					bw.close();
					osw.close();
					
					InputStreamReader isr = null;
					try {
					// 受信用ストリーム
						isr = new InputStreamReader(http.getInputStream(), "UTF-8");
					}
					catch( Exception e ) {
						isr = new InputStreamReader(http.getErrorStream(), "UTF-8");
					}
					
					// 受信
					BufferedReader br = new BufferedReader(isr);   
					String line_buffer;   
					while ( null != (line_buffer = br.readLine() ) ) {   
						// コマンドプロンプトに表示   
						result_string += line_buffer;
					}

					// 終了処理
					br.close();
					isr.close();
					http.disconnect();
				}
				catch( Exception e ) {
					result_string = "{\"errors\":\"unknown\"}"; 
				}
				
				return result_string;
			}

			// **************************************************************
			// 非同期処理終了後の処理( 画面へのアクセスが可能 )
			// **************************************************************
			@Override
			protected void onPostExecute(String result) {
				// Tweet メソッドの引数のインターフェイス内のメソッドを呼び出す
				OnTweetResult.onTweetResult(result);
			}
			
		}.execute(text);
	
	}
	
	private String rfc3986( String param ) {
		param = param.replace("+", "%20");
		param = param.replace("*", "%2A");
		param = param.replace("%7E","~");
		return param;
	}
	
	private String dD(String param){
		return "\""+param+"\"";
	}

	private String getNonce(){
		Random random = new Random(); 
		return String.valueOf(random.nextInt(1000000000));
	}
	
	private String getTimeStamp(){
		return String.valueOf(System.currentTimeMillis() / 1000L);
	}		
	
	private String getSignature(String baseString){
		
		String work = "";
		work += _consumer_secret;
		work += "&";
		work += _secret;
		   
		String signature = "";
		SecretKeySpec key = new SecretKeySpec(work.getBytes(), "HmacSHA1");
		
		try {
			
			Mac mac = Mac.getInstance(key.getAlgorithm());
			try{
				mac.init(key);
			} catch(InvalidKeyException ike){
			}
			
			byte[] rawHmac = mac.doFinal(baseString.getBytes());
			signature = new String (Base64.encodeToString(rawHmac, Base64.NO_WRAP));
			
		} catch(NoSuchAlgorithmException e){
		}
		
		return signature;
	}

}

処理が完了すると、onTweetResult が実行されます。

MainActivity.java
package com.example.posttest;

import com.example.posttest.Android_Twitter.Tweeted;

import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.widget.EditText;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

	public void postAction(View view) {
		
		EditText et = (EditText)this.findViewById(R.id.editText1);
		
		new Android_Twitter(
                    "Consumer key",
                    "Consumer secret",
                    "Access token",
                    "Access token secret").Tweet(et.getText().toString(), new Tweeted() {
			
			@Override
			public void onTweetResult(String result) {
				System.out.println(result);
			}
		});

	}
   
}

関連する記事

Twitter API の自分のアプリのトークンを使って投稿するだけの class VS2010_Twitter

Twitter API の自分のアプリのトークンを使って投稿するだけの class VS2012_Twitter

WSH : VBScript と JavaScript で Twitter に投稿する

PHP : Twitter 投稿関数( twitter_update ) / cURL 関数

Twitter アプリの登録方法と、API キーの利用



タグ:twitter API
【Androidの最新記事】
posted by lightbox at 2013-10-12 17:39 | Android | このブログの読者になる | 更新情報をチェックする
バッチ処理

Microsoft Office
container 終わり

フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

Android SDK ポケットリファレンス
改訂版 Webデザイナーのための jQuery入門
今すぐ使えるかんたん ホームページ HTML&CSS入門
CSS ドロップシャドウの参考デモ
Google Hosted Libraries
cdnjs
BUTTONS (CSS でボタン)
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり