Android StudioとFabricでTweetする

  • 12
    いいね
  • 0
    コメント

以下の環境で、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 のエラーになります。

Kobito.XQvbMV.png

あと、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 とした)
  • 適当なフォームを選択(Phone and Tablet とした)
    Kobito.l3RrSm.png

  • 適当な Activity を選択(Empty Activity とした)
    Kobito.Z6beq9.png

  • Activity の名前を決める(デフォルトのままとした)Kobito.kB1ZmT.png

  • 最初の画面が出たら、右上のFabricのボタンKobito.gqUjoq.pngを押す

Kobito.LUfGzv.png

  • Fabticの画面が出るので、真ん中のボタンを押してログインする。
    Kobito.WUgFHp.png

  • Organization を選んで Next

  • Twitter を選ぶ
    Kobito.N67iU7.png

  • Twitter のライブラリを Install(一番上)
    Kobito.0g58zO.png

  • Twitterのアカウントを作る。すでに作ってあるので、一番下
    Kobito.fo7OUE.png

  • Twitter アカウントのキーとシークレットを入力してNext
    Kobito.Oc7vJl.png

  • Fabricが以下の修正をするよ、という画面。下のApplyボタンを押す。
    Kobito.GUFLc2.png

  • ここで、build して走らせてみろ、とメッセージが出るので、動かしてみる。エラーは出ない。

  • Fabricからloginのコードを見る。Log In with Twitter の Get Codeをクリック
    Kobito.Q0Xrvi.png

  • ログインボタン追加のコードが表示される。これを、今回は app/res/layout/activity_main.xml に入れれば良い。普通に activity_main.xml を選ぶとDesignの画面になっているので、下のタブでTextを選ぶ。
    Kobito.XFlo35.png

修正前のactivity_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!" />
</RelativeLayout>

Fabricの画面で、修正部分(色が最初から変わっている)をクリックするとコピーされるので、activiti_main.xml に行ってペーストすれば良い。
Kobito.xP4BsT.png

修正後のactivity_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 は要らないけど、とりあえず残してある。

  • Nextをクリックすると、ログインボタンのコールバックルーチンのための修正コードが表示される。(下のスクリーンショットは途中で切れているけど、もう少し下まである。) Kobito.GrOojX.png

(注意)importは自分で修正しないといけない。

修正後のMainActivity.java
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をすれば良いということです。

Access Twitter's REST API

公式のドキュメントを見ると、

  1. loginする。
  2. TwitterApiClientを得る。
  3. StatusesServiceを得る。
  4. updateを呼ぶ。

という順番です。loginまでは成功しているので、その後ボタンを押したら定形の文章をポストする、という感じで作ります。投稿のソースコードは、先ほどの参考にしたページのを使わせてもらいます。

とりあえずPOSTのボタンを作る。

activity_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"/>

    <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>

Kobito.xCyFRY.png

  • ロジックの追加 updateの引数の数が参考にしたソースより1つ増えてる。
MainActivity.java
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した時に失敗するらしかったからです。

ポスト成功

Kobito.KJjwZ0.png

  • エラー処理とか、ログインしているかどうかの確認とかはしていません。