LoginSignup
30
30

More than 5 years have passed since last update.

Fabric from Android で写真を Tweet する。

Last updated at Posted at 2015-08-13

Fabric

introducing-fabric-homepage.png
Fabric.io

Fabric は Twiter が提供しているツールで、アプリ開発時にアプリケーションをチームへスキームすることが可能です。
また、クラッシュログやアプリの配布に、Twitter ログインなど様々な機能が備わっています。

Fabric Kits

Fabric の中にはとても優れている Framework が存在します。

そんな中、今回お伝えするのは、Fabric の機能のでもある、Twitter Kit で画像データーを Tweet する処理を作ったので、その時の覚書にはなりますが、お伝えしたいと思います。

Twitter Kit

twitter_kit-2bb33c7ef570f985b3ce40cbef3f04e4.png

Twitter Kit

主な機能

  • Authentication
  • Use OAuth Echo
  • Request a User's Email Address
  • Access Twitter's REST API
  • Show Tweets
  • Show Timelines
  • Compose Tweets

目立った機能はここら辺です。
それぞれの機能の簡単な説明です。

Authentication

  • Log in with Twitter
    • 標準のログインボタンが用意され簡単にTwitter Log in が実装できる
    • ゲストログインが可能で、アカウントのないユーザーでもTwitterの機能の一部分を利用することができる。

Use OAuth Echo

  • OAuth 処理を簡単に実装できる
    • リクエストへ必要な Auth 情報を利用できる。

Request a User's Email Address

  • Email アドレスの要請

Access Twitter's REST API

  • サポートされている Twitter API を簡単に実装できる
  • 拡張し標準でサポートされていない Twitter API も作成可能

Show Tweets

  • 公式標準の TweetUI を開発者のアプリケーションに簡単に埋め込むことが可能
  • リスト表示にも対応
  • ダークモードに対応
  • デザインのカスタマイズに対応
  • Tweet Action に対応

Show Timelines

  • タイムラインを検索し一覧表示することができる

Compose Tweets

  • Tweet 機能を開発者のアプリケーションに簡単に組み込むことが可能
  • メッセージと画像投稿に対応

Access Twitter’s REST API

今回のメインはこちらになります。
Fabric の機能で REST API が利用可能なので、こちらの機能を使って対応を進めていくことにします。

まず、標準で対応してれば、標準で対応したいと思います。
(対応していれば苦労しなかったんですけどねw)

標準対応している API

  • Statuses (Tweets)
    • mentionsTimeline
    • userTimeline
    • homeTimeline
    • retweetsOfMe
    • show
    • lookup
    • update
    • retweet
    • unretweet
    • destroy
  • Favorites
    • list
    • create
    • destroy
  • Search
    • tweets
  • Lists
    • statuses
  • Collections
    • entries

この一覧が何を示しているかよくわからない人のために!
こちらは、Twitter API の URL Path になり、それぞれ Path ごとで機能が分かれています。
具体的な内容については、REST APIs をご覧ください。

Statuses (Tweet)

ざっくりとですが、Tweet関連の機能がまとめられている API 群です。

POST statuses/update_with_media

POST statuses/update_with_media

Tweet 投稿と一緒にメディアを投稿するためのAPIになります。

今までのうる覚えで使おうと思っていたのですが、Twitter Kit では標準対応されていません。
また、お気付きの方がいると思いますが、こちらの API は deprecated になっていました。
こちらの API は非推奨なので利用するのはやめましょう。

ということは、別の対応方法が存在します。

POST media/upload

POST media/upload

Twitter へメディアを登録するAPIになります。

60分間サーバーに保持してくれる?ので、その間にアップロードした画像を Tweet へ反映させなければいけません。

POST statuses/update

POST statuses/update

Tweet を投稿するAPIになります。

Tweet する際に MediaID を同梱することで、メディア付きな Tweet を投稿することが可能です。

この二つのAPI を利用することで画像投稿が可能になります。

実装編

※実際に実装したソースコードを抜粋しているため、導入する際は、よしなにしてください!

Twitter Login

Twitter ログインを行う。
Twitter ログインページを表示しアカウント情報を入力する画面が表示される。

TwitterCore twitterCore = TwitterCore.getInstance();
twitterCore.logIn(activity, new Callback<TwitterSession>() {
    @Override
    public void success(Result<TwitterSession> result) {
        // ログイン処理に成功
    }

    @Override
    public void failure(TwitterException e) {
        // ログイン処理に失敗
    }
})

Twitter Tweet (POST statuses/update)

Twitte Kit 標準で用意されている、Twitter へ Tweet する処理。
※ユーザーログイン処理がが完了していること!

TwitterSession twitterSession = TwitterCore.getInstance().getSessionManager().getActiveSession();
StatusesService statusesService = new TwitterApiClient(twitterSession).getStatusesService();
statusesService.update("Tweet Message.", null, false, null, null, null, false, false, new Callback<Tweet>() {
    @Override
    public void success(Result<Tweet> result) {
        // 投稿処理成功
    }

    @Override
    public void failure(TwitterException e) {
        // 投稿処理失敗
    }
});

Tweet ですが、こちらの標準だと、メディアを追加することができません。
ということから、こちらの処理を自前実装します。

StatusesService の拡張

標準で用意されている'StatusesService#update'に'media_ids'が対応していませんでしたので、
再定義し自身のinterfaceクラスを定義します。

Twitter Kit の通信処理では、Square の Retrofit を利用しています。

public interface SKNStatusesService {
...
@FormUrlEncoded
@POST("/1.1/statuses/update.json")
void update(
@Field("status") String status,
@Field("in_reply_to_status_id") Long inReplyToStatusId,
@Field("possibly_sensitive") Boolean possiblySensitive,
@Field("lat") Double lat,
@Field("long") Double longDouble,
@Field("place_id") String placeId,
@Field("display_cooridnates") Boolean displayCooridnates,
@Field("trim_user") Boolean trimUser,
@Field("media_ids") String mediaIds,
Callback<Tweet> cb);

TwitterApiClient の拡張

実際に先ほど作った、SKNStatusesService.class を生成する処理を実装します。
SKNStatusesServiceを使うときは必ず、このメソッドを利用します。

public class SKNTwitterApiClient extends TwitterApiClient {
...
public SKNStatusesService getfalStatusesService() {
    return (SKNLStatusesService)this.getService(SKNStatusesService.class);
}

Twitter Tweet with MediaID (POST statuses/update)

#extensions

先ほど作った、SKNStatusesService と SKNTwitterApiClient を使うぐらいで、あとは標準のと変わりありませんね!
案外簡単に拡張することが可能なのがわかります。

TwitterSession twitterSession = TwitterCore.getInstance().getSessionManager().getActiveSession();
SKNStatusesService statusesService = new SKNTwitterApiClient(twitterSession).getfalStatusesService();
statusesService.update("Tweet Message.", null, false, null, null, null, false, false, "media_id_string1,media_id_string2,media_id_string3,media_id_string4", new Callback<Tweet>() {
    @Override
    public void success(Result<Tweet> result) {
        // 投稿処理成功
    }

    @Override
    public void failure(TwitterException e) {
        // 投稿処理失敗
    }
});

ここまですんなりできたでしょうか?
さて、次に問題になってくるのが、MediaIDの取得です。
Android -> 画像 -> TypeFile -> POST -> Twitter -> MediaID
この流れで実際の画像から MediaID を生成し取得する必要があります。

画像を Twitter へ登録する

POST media/upload

残念ながら Twitter Kit では media/upload API に標準で対応していません。
対応していないのなら作るのが仕事!
さて作りましょう!
手順は先ほど statuses/update で対応した内容に +α します。

MediaService 作成

今回の API は画像のバイトデーターを送信するので、マルチパートにします。

public interface SKNMediaService {
...
@Multipart
@POST("/1.1/media/upload.json")
void upload(@Part("media") TypedFile media, Callback<Media> cb);

API Response Media の作成

media/Upload の Response の値を格納するモデルクラスを作成します。

public class Media {
    @SerializedName("media_id")
    public final long mediaId;
    @SerializedName("media_id_string")
    public final String mediaIdString;
    @SerializedName("size")
    public final long size;
    @SerializedName("image")
    public final Media.Image image;

    public Media(long mediaId, String mediaIdString, long size, Image image) {
        this.mediaId = mediaId;
        this.mediaIdString = mediaIdString;
        this.size = size;
        this.image = image;
    }

    public static class Image {
        @SerializedName("w")
        public final long width;
        @SerializedName("h")
        public final long height;
        @SerializedName("image_type")
        public final String imageType;

        public Image(long width, long height, String imageType) {
            this.width = width;
            this.height = height;
            this.imageType = imageType;
        }
    }
}

FALTwitterApiClient の拡張

media/upload API では、Twitter API の HOST 名を変更する必要があります。
すんなり変更できると思ったのですが、今のところ、私がわかっているのは、こちらの方法です。

public class SKNTwitterUploadApiClient {
...
    final ConcurrentHashMap<Class, Object> services;
    final RestAdapter adapter;

    static final String TWITTER_API_HOST_NAME = "https://upload.twitter.com";

    SKNTwitterUploadApiClient(TwitterAuthConfig authConfig, Session session, TwitterApi twitterApi, SSLSocketFactory sslSocketFactory, ExecutorService executorService) {
        if(session == null) {
            throw new IllegalArgumentException("Session must not be null.");
        } else {
            this.services = new ConcurrentHashMap();
            Gson gson = (new GsonBuilder()).registerTypeAdapterFactory(new SafeListAdapter()).registerTypeAdapterFactory(new SafeMapAdapter()).create();
            this.adapter = (new RestAdapter.Builder()).setClient(new AuthenticatedClient(authConfig, session, sslSocketFactory)).setEndpoint(twitterApi.getBaseHostUrl()).setConverter(new GsonConverter(gson)).setExecutors(executorService, new MainThreadExecutor()).build();
        }
    }

    public SKNTwitterUploadApiClient(Session session) {
        this(TwitterCore.getInstance().getAuthConfig(), session, new TwitterApi(TWITTER_API_HOST_NAME), TwitterCore.getInstance().getSSLSocketFactory(), TwitterCore.getInstance().getFabric().getExecutorService());
    }

    public SKNMediaService getMediaService() {
        return (SKNMediaService)this.getService(SKNMediaService.class);
    }

    protected <T> T getService(Class<T> cls) {
        if(!this.services.contains(cls)) {
            this.services.putIfAbsent(cls, this.adapter.create(cls));
        }

        return (T) this.services.get(cls);
    }s

POST media/upload 実装編

※ユーザーログイン処理がが完了していること!

File mediaFile ...
TypedFile typedFile = new TypedFile("multipart/form-data", mediaFfile);
...

TwitterSession twitterSession = TwitterCore.getInstance().getSessionManager().getActiveSession();
SKNMediaService mediaService = new SKNTwitterUploadAPIClient(twitterSession).getMediaService();
mediaService.upload(typedFile, new Callback<Media>() {
    @Override
    public void success(Result<Media> result) {
        // メディア登録完了           
    }

    @Override
    public void failure(TwitterException e) {
        // メディア登録失敗
    }
});

以上長くなってしまいましたが、こちらが、Fabric で 画像を Tweet する処理になります。

まとめ

  • Fabric
  • Retrofit
  • POST statuses/update の拡張
  • POST media/upload の作成
  • TwitterUploadApiClient の拡張
  • Media モデルクラスの作成
  • MediaService の作成

わかると意外に簡単ですが、意外に情報が無く結局自分でコードを読むことで解決することができました。
みなさんの参考になればと思います。

30
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
30