以下の環境で、Tweetするプログラムです。2016年7月の情報です。
- Mac OS X 10.11.5 (あんまり関係ないかも)
- JDK 1.8
- Android Studio 2.1.2
- Fabric (これはバージョンはどうやって分かるのか?)
Fabric
twitterをいじるならtwitter4jだと思っていたのですが、ネットで少し調べるとFabricというキーワードの方が沢山出てくる。しかも、Twitterで開発されているツールらしいので、取り敢えず使ってみる。
作業の流れは、だいたい以下のページの通り。バージョンが少し違うので、多少違うところもあるけれど、困るほどではない。
Android Twitter Login and Twitter Post Example
登録
fabricのページ に行って登録する。メールアドレスに確認用のメールが来るので、そのURLで登録完了。どのプラットフォームで開発するのか尋ねられるので、Androidを選択する。(ここの選択は、その後に表示されるドキュメントが変わるだけと思われる。)
Twitterの開発者の登録
Twitter Developersで、開発者および開発アプリの登録をしておく。ここでしなくても、Fabricのインストール中に登録画面が出てくるので、そこでやっても同じ。
なお、アプリはTweetもするので、Read & Write になっている必要があります。デフォルトは Read なので、そのままにしておくと、POSTした時に 401 Authorization Required のエラーになります。
あと、Callback URL は何でも良いので入れておくこと、Allow this application to be used to Sign in with Twitter にチェックを入れておくこと。
Android Studioへのインストール
- Android Studio の Preferences を選ぶ。
- Plugins を選ぶ。
- Browse Repositories... を選ぶ。
- Fabric for Android Studio を選び、install を押す。( v2.3.1 でした)
- restart するかと聞かれるので、restartする。
- Configure で Plugins を見て、Fabric for Android Studio が入っていればOK
アプリの作り方
- Start a new Android Studio project を選ぶ。
- 適当な名前をつける(AndroidTwitterExample とした)
Organization を選んで Next
ここで、build して走らせてみろ、とメッセージが出るので、動かしてみる。エラーは出ない。
ログインボタン追加のコードが表示される。これを、今回は app/res/layout/activity_main.xml に入れれば良い。普通に activity_main.xml を選ぶとDesignの画面になっているので、下のタブでTextを選ぶ。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.tadashi.androidtwitterexample.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
</RelativeLayout>
Fabricの画面で、修正部分(色が最初から変わっている)をクリックするとコピーされるので、activiti_main.xml に行ってペーストすれば良い。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.tadashi.androidtwitterexample.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<com.twitter.sdk.android.core.identity.TwitterLoginButton
android:id="@+id/twitter_login_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
</RelativeLayout>
Hello World は要らないけど、とりあえず残してある。
(注意)importは自分で修正しないといけない。
package com.example.tadashi.androidtwitterexample;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.twitter.sdk.android.Twitter;
import com.twitter.sdk.android.core.*;
import com.twitter.sdk.android.core.identity.*;
import io.fabric.sdk.android.Fabric;
public class MainActivity extends AppCompatActivity {
// Note: Your consumer key and secret should be obfuscated in your source code before shipping.
private static final String TWITTER_KEY = " xxxxxxxxxxxxxxxxxxxxxx";
private static final String TWITTER_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
private TwitterLoginButton loginButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TwitterAuthConfig authConfig = new TwitterAuthConfig(TWITTER_KEY, TWITTER_SECRET);
Fabric.with(this, new Twitter(authConfig));
setContentView(R.layout.activity_main);
loginButton = (TwitterLoginButton) findViewById(R.id.twitter_login_button);
loginButton.setCallback(new Callback<TwitterSession>() {
@Override
public void success(Result<TwitterSession> result) {
// The TwitterSession is also available through:
// Twitter.getInstance().core.getSessionManager().getActiveSession()
TwitterSession session = result.data;
// TODO: Remove toast and use the TwitterSession's userID
// with your app's user model
String msg = "@" + session.getUserName() + " logged in! (#" + session.getUserId() + ")";
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
}
@Override
public void failure(TwitterException exception) {
Log.d("TwitterKit", "Login with Twitter failure", exception);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Make sure that the loginButton hears the result from any
// Activity that it triggered.
loginButton.onActivityResult(requestCode, resultCode, data);
}
}
TWITTER_KEYとTWITTER_SECRETは修正してあります。
- Next で、「動かしてみろ」と言われるが、これでログインできるようになっている。失敗したら、Twitter側の設定も確認する。
投稿
ただ単にtwitter公式アプリの投稿の画面を出すだけであれば、TweetComposer.Builderを呼べば良いらしいが、今回はポストまで全部アプリでやりたいので、
TwitterのFabric SDKをAndroid Studioで使ってみる
を参考にやってみました。要は、REST APIを呼べば良いということです。投稿するには、Statuses(Tweets)のupdateをすれば良いということです。
公式のドキュメントを見ると、
- loginする。
- TwitterApiClientを得る。
- StatusesServiceを得る。
- updateを呼ぶ。
という順番です。loginまでは成功しているので、その後ボタンを押したら定形の文章をポストする、という感じで作ります。投稿のソースコードは、先ほどの参考にしたページのを使わせてもらいます。
とりあえずPOSTのボタンを作る。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.tadashi.androidtwitterexample.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<com.twitter.sdk.android.core.identity.TwitterLoginButton
android:id="@+id/twitter_login_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Post Button"
android:id="@+id/post_button"
android:layout_below="@+id/twitter_login_button"
android:layout_alignStart="@+id/twitter_login_button"
android:layout_marginTop="30dp"
android:layout_alignEnd="@+id/twitter_login_button" />
</RelativeLayout>
- ロジックの追加 updateの引数の数が参考にしたソースより1つ増えてる。
package com.example.tadashi.androidtwitterexample;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.format.*;
import android.util.Log;
import android.view.View;
import android.widget.*;
import com.twitter.sdk.android.Twitter;
import com.twitter.sdk.android.core.*;
import com.twitter.sdk.android.core.identity.*;
import com.twitter.sdk.android.core.models.*;
import com.twitter.sdk.android.core.services.*;
import io.fabric.sdk.android.Fabric;
import java.util.*;
public class MainActivity extends AppCompatActivity {
// Note: Your consumer key and secret should be obfuscated in your source code before shipping.
private static final String TWITTER_KEY = " xxxxxxxxxxxxxxxxxxxxxx";
private static final String TWITTER_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
private TwitterLoginButton loginButton;
private Button postButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TwitterAuthConfig authConfig = new TwitterAuthConfig(TWITTER_KEY, TWITTER_SECRET);
Fabric.with(this, new Twitter(authConfig));
setContentView(R.layout.activity_main);
loginButton = (TwitterLoginButton) findViewById(R.id.twitter_login_button);
loginButton.setCallback(new Callback<TwitterSession>() {
@Override
public void success(Result<TwitterSession> result) {
// The TwitterSession is also available through:
// Twitter.getInstance().core.getSessionManager().getActiveSession()
TwitterSession session = result.data;
// TODO: Remove toast and use the TwitterSession's userID
// with your app's user model
String msg = "@" + session.getUserName() + " logged in! (#" + session.getUserId() + ")";
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
}
@Override
public void failure(TwitterException exception) {
Log.d("TwitterKit", "Login with Twitter failure", exception);
}
});
postButton = (Button) findViewById(R.id.post_button);
postButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
tweet("test post("
+DateFormat.format("yyyy/MM/dd kk:mm:ss", Calendar.getInstance()).toString()
+")");
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Make sure that the loginButton hears the result from any
// Activity that it triggered.
loginButton.onActivityResult(requestCode, resultCode, data);
}
private void tweet(String message) {
TwitterApiClient twitterApiClient = TwitterCore.getInstance().getApiClient();
StatusesService statusesService = twitterApiClient.getStatusesService();
statusesService.update(message, null, false, null, null, null, false, null, null, new Callback<Tweet>() {
@Override
public void success(Result<Tweet> result) {
Toast.makeText(getApplicationContext(), "post success", Toast.LENGTH_LONG).show();
}
public void failure(TwitterException exception) {
Toast.makeText(getApplicationContext(), "post fail", Toast.LENGTH_LONG).show();
}
});
}
}
時刻をつけているのは、どうも全く同じ文字列だと続けてTweetした時に失敗するらしかったからです。
ポスト成功
- エラー処理とか、ログインしているかどうかの確認とかはしていません。