へんてこのブログ

日々気づいたことや、最近やっていることを書いています

AndroidでのTwitter4jを使ったOAuth認証とツイートの例

今回はTwitter4jを使ったOAuth認証とツイートのソースコードを紹介します
自分的にかなりハマってしまい、まいりました
まだ仕様が変わった後の日本語のレビューが少ないのが原因か?

まぁソースを公開します
説明はめんどうなので、ソースを舐めてください

twitter4j-core-2.2.1.jarをプロジェクトに追加してくださいね

mainActivity.java

package com.henteko.test;


import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;
import twitter4j.conf.ConfigurationBuilder;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class mainActivity extends Activity {
	
	private Twitter twitter = null;
	private RequestToken requestToken = null;
	
	private String CONSUMER_KEY = "自分専用のいれてね";
	private String CONSUMER_SECRET = "自分専用のいれてね";
	
	private String nechatterStatus;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        
        //まぁ一応書いときます
	    SharedPreferences pref = getSharedPreferences("Twitter_seting",MODE_PRIVATE);
	    //これは必要だから消さないでね
		nechatterStatus  = pref.getString("status", "");
        
		
		Button loginbutton = (Button) findViewById(R.id.tweetLogin);
        loginbutton.setOnClickListener(new View.OnClickListener() {
        	public void onClick(View view) { 
        		
        		//もう設定されているか?
        		if(isConnected(nechatterStatus)){
        			
        			//disconnectTwitter();
					
					Intent intent2=new Intent();
					intent2.setClassName("com.henteko.test","com.henteko.test.Tweet");
					intent2.setAction(Intent.ACTION_VIEW);
					startActivityForResult(intent2,0);
					
        		}else{
        			
        			try {
						connectTwitter();
					} catch (TwitterException e) {
						//showToast(R.string.nechatter_connect_error);
					}
        		}
        		
        		
        	}
        });
        
        
        
        Button logoutbutton = (Button) findViewById(R.id.logout);
        logoutbutton.setOnClickListener(new View.OnClickListener() {
        	public void onClick(View view) { 
        		
        		disconnectTwitter();
				try {
					connectTwitter();
				} catch (TwitterException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
        	
        });
        
        
    }
    
    
    
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {

		if(resultCode == RESULT_OK){
			super.onActivityResult(requestCode, resultCode, intent);

			AccessToken accessToken = null;

			try {
				accessToken = twitter.getOAuthAccessToken(
						requestToken,
						intent.getExtras().getString("oauth_verifier"));

				
		        SharedPreferences pref=getSharedPreferences("Twitter_seting",MODE_PRIVATE);

		        SharedPreferences.Editor editor=pref.edit();
		        editor.putString("oauth_token",accessToken.getToken());
		        editor.putString("oauth_token_secret",accessToken.getTokenSecret());
		        editor.putString("status","available");

		        editor.commit();
		        
		       
		        //つぶやくページへGO
		        Intent intent2 = new Intent(this, Tweet.class);
				this.startActivityForResult(intent2, 0);
		        
		        //finish();
			} catch (TwitterException e) {
				//showToast(R.string.nechatter_connect_error);
			}
		}
	}
    
    
    
    
    private void connectTwitter() throws TwitterException{
		

		//参考:http://groups.google.com/group/twitter4j/browse_thread/thread/d18c179ba0d85351
		//英語だけど読んでね!
		ConfigurationBuilder confbuilder  = new ConfigurationBuilder(); 

		confbuilder.setOAuthConsumerKey(CONSUMER_KEY).setOAuthConsumerSecret(CONSUMER_SECRET); 

		twitter = new TwitterFactory(confbuilder.build()).getInstance();
		
		
		String CALLBACK_URL = "myapp://oauth";
		// requestTokenもクラス変数。
		try {
			requestToken = twitter.getOAuthRequestToken(CALLBACK_URL);
		} catch (TwitterException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		  // 認証用URLをインテントにセット。
		  // TwitterLoginはActivityのクラス名。
		  Intent intent = new Intent(this, TwitterLogin.class);
		  intent.putExtra("auth_url", requestToken.getAuthorizationURL());

		  // アクティビティを起動
		  this.startActivityForResult(intent, 0);
		
	}
    
    
    
    final private boolean isConnected(String nechatterStatus){
		if(nechatterStatus != null && nechatterStatus.equals("available")){
			return true;
		}else{
			return false;
		}
	}
    
    
    public void disconnectTwitter(){
		
        SharedPreferences pref=getSharedPreferences("Twitter_seting",MODE_PRIVATE);

        SharedPreferences.Editor editor=pref.edit();
        editor.remove("oauth_token");
        editor.remove("oauth_token_secret");
        editor.remove("status");

        editor.commit();
        
        
        
        //finish();
	}



}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
<Button android:text="Twitterにログインしつぶやく" android:id="@+id/tweetLogin" android:layout_height="wrap_content" android:layout_width="fill_parent"></Button>
<Button android:id="@+id/logout" android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="別のアカウントでログインしつぶやく"></Button>
</LinearLayout>

TwitterLogin.java

package com.henteko.test;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class TwitterLogin extends Activity {

	protected void onCreate(Bundle bundle) {

		super.onCreate(bundle);
        setContentView(R.layout.twitterlogin);
        
		WebView webView = (WebView)findViewById(R.id.twitterlogin);
		WebSettings webSettings = webView.getSettings();
		//これで別のユーザーとしてサインインする。が実行できる
		webSettings.setJavaScriptEnabled(true);
		webView.setWebViewClient(new WebViewClient(){

			public void onPageFinished(WebView view, String url) {
				super.onPageFinished(view, url);

				String CALLBACK_URL = "myapp://oauth";
				if(url != null && url.startsWith(CALLBACK_URL )){
					String[] urlParameters = url.split("\\?")[1].split("&");

					String oauthToken = "";
					String oauthVerifier = "";

					if(urlParameters[0].startsWith("oauth_token")){
						oauthToken = urlParameters[0].split("=")[1];
					}else if(urlParameters[1].startsWith("oauth_token")){
						oauthToken = urlParameters[1].split("=")[1];
					}

					if(urlParameters[0].startsWith("oauth_verifier")){
						oauthVerifier = urlParameters[0].split("=")[1];
					}else if(urlParameters[1].startsWith("oauth_verifier")){
						oauthVerifier = urlParameters[1].split("=")[1];
					}

					Intent intent = getIntent();
					intent.putExtra("oauth_token", oauthToken);
					intent.putExtra("oauth_verifier", oauthVerifier);

					setResult(Activity.RESULT_OK, intent);
					finish();
				}
			}
		});


		webView.loadUrl(this.getIntent().getExtras().getString("auth_url"));
		
		
	}
}

twitterlogin.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
    <android.webkit.WebView android:id="@+id/twitterlogin" android:layout_width="fill_parent" android:layout_height="fill_parent"></android.webkit.WebView>
</LinearLayout>

Tweet.java

package com.henteko.test;

import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.conf.ConfigurationBuilder;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;


public class Tweet extends Activity{
	
	private String CONSUMER_KEY = "自分専用のいれてね";
	private String CONSUMER_SECRET = "自分専用のいれてね";
	private String defoTEXT = null;
	private String mainTEXT = null;
	
	
	protected void onCreate(Bundle bundle) {

		super.onCreate(bundle);
        setContentView(R.layout.tweet);
        
	    
        
        //ハッシュタグ追加!
        defoTEXT = " #testTwitter ";
        
        final EditText edit = (EditText) findViewById(R.id.editText1);
        edit.setText(defoTEXT);
        edit.setMaxLines(3); 
        edit.setSelection(0);
        
        Button tweetbutton = (Button) findViewById(R.id.tweet);
        tweetbutton.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                // クリック時の処理
            	SpannableStringBuilder sb = (SpannableStringBuilder)edit.getText();
                mainTEXT = sb.toString();
                
                
                try {
					tweet();
				} catch (TwitterException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				finish();
				
				
            }
        });
        
	}
	
	
	public void tweet() throws TwitterException {
		// 記録していた設定ファイルを読み込む。
		SharedPreferences pref = getSharedPreferences("Twitter_seting",MODE_PRIVATE);

		// 設定ファイルからoauth_tokenとoauth_token_secretを取得。
		String oauthToken  = pref.getString("oauth_token", "");
		String oauthTokenSecret = pref.getString("oauth_token_secret", "");

		ConfigurationBuilder confbuilder  = new ConfigurationBuilder(); 

		confbuilder.setOAuthAccessToken(oauthToken) 
		.setOAuthAccessTokenSecret(oauthTokenSecret) 
		.setOAuthConsumerKey(CONSUMER_KEY) 
		.setOAuthConsumerSecret(CONSUMER_SECRET); 

		Twitter twitter = new TwitterFactory(confbuilder.build()).getInstance(); 

		// 任意の文字列を引数にして、ツイート。
		twitter.updateStatus(mainTEXT);
		
		Toast.makeText(this, "つぶやきました", Toast.LENGTH_SHORT).show();
	}
	
}

tweet.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent" android:orientation="vertical">
    <EditText android:text="" android:id="@+id/editText1" android:layout_height="wrap_content" android:layout_width="fill_parent"></EditText>
    <Button android:text="つぶやく" android:id="@+id/tweet" android:layout_height="wrap_content" android:layout_width="fill_parent"></Button>
</LinearLayout>

今回一番大事なAndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.henteko.test"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="4" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".mainActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
            	<action android:name="android.intent.action.VIEW" />
            	<category android:name="android.intent.category.DEFAULT" />
            	<category android:name="android.intent.category.BROWSABLE" />
            	<data android:scheme="myapp" android:host="oauth"/>
        	</intent-filter>
        </activity>
        <activity android:name="TwitterLogin"></activity>
        <activity android:name="Tweet"></activity>

    </application>
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>


アプリの登録とかしっかりとできていて、自分専用のコードを取得できていればコピペで動くはずです
別のアカウントでログインする場合は、別のアカウントでログインしつぶやくというボタンを押し、表示されたページの別のユーザーとしてサインインするというところを押すと変更ができます
もっとうまいやり方があると思うのですが、わかりません
教えてください


今回はこんな感じです
説明がなくてすみませんでした

4/5 Tweet.javaの内容を訂正しました