画像付きでTwitterに投稿したい、Titaniumで。


あけましておめでとうございます。
本年もよろしくお願い申し上げます。
歌と踊りが大好きな皆様の投稿を楽しみにしています。

やりたいこと

  • アプリから Twitter に投稿したい。
  • 投稿の際に画像を添付したい。
  • もちろん iOS/Android 両対応。

こまかいこと

  • 画像はアプリ内に内包しているものではなく、Web上に存在する。
  • Twitter 投稿に限定したいため、できれば Share Extensions や インテントチューザ は表示したくない。
  • Android の場合、明示的インテントを使用して Twitter 公式アプリを起動する。Twitter 公式アプリがインストールされていない場合、GooglePlay の該当ページを表示する。

iOS の場合

hntn氏の記事でも紹介されていますが、TiSocial モジュールを利用します。
今回は Share Extensions を表示しないため、 socialshare モジュールは利用しません。

var social = require('dk.napp.social');

var image = 'https://www.pakutaso.com/shared/img/thumb/BO15103026151030265020_TP_V.jpg',
    url = 'http://qiita.com/',
    text = 'TweetText';

if (!social.isTwitterSupported()) {
    Ti.API.warn('Twitter account is not set.');
    return;
}
social.twitter({
    text: text,
    image: image,
    url: url
});

これだけ。

超簡単。

Android の場合

とりあえずインテントを作成して、アクティビティを開始してみます。

var image = 'https://www.pakutaso.com/shared/img/thumb/BO15103026151030265020_TP_V.jpg',
    url = 'http://qiita.com/',
    text = 'TweetText';

var intent = Ti.Android.createIntent({
    action: Ti.Android.ACTION_SEND,
    packageName: 'com.twitter.android',
    flags: Ti.Android.FLAG_ACTIVITY_NEW_TASK,
    type: 'text/plain'
});

intent.putExtra(Ti.Android.EXTRA_TEXT, text + ' ' + url);
intent.putExtraUri(Ti.Android.EXTRA_STREAM, image);

try {
    Ti.Android.currentActivity.startActivity(intent);
} catch(e) {
    // GooglePlay
    Ti.Platform.openURL('https://play.google.com/store/apps/details?id=com.twitter.android');
}

問題が発生したようです。

01-06 09:56:34.037: E/AndroidRuntime(17424): FATAL EXCEPTION: main
01-06 09:56:34.037: E/AndroidRuntime(17424): Process: com.twitter.android, PID: 17424
01-06 09:56:34.037: E/AndroidRuntime(17424): java.lang.IllegalStateException: Media does not exist
・・・

めでぃあだずのっとえくじすと、画像が見つかんないっすか。

いろいろググってみたんですが、どうやらWeb上の画像をツィート時に指定できないのかもしれません。仕方がないので、一旦画像ファイルをダウンロードして指定することにしました。

ここでの注意点として、画像ファイルを Titanium.Filesystem.applicationDataDirectory 等に保存すると他のアプリから参照不可になるようなので、今回は一時ディレクトリ(Ti.Filesystem.tempDirectory)に保存しています。
参考:https://stephenfeather.com/blog/titanium-open-pdf-with-intents-resolved-android/

var image = 'https://www.pakutaso.com/shared/img/thumb/BO15103026151030265020_TP_V.jpg',
    url = 'http://qiita.com/',
    text = 'TweetText';

var start = function(tmpImage) {
    var intent = Ti.Android.createIntent({
        action: Ti.Android.ACTION_SEND,
        packageName: 'com.twitter.android',
        flags: Ti.Android.FLAG_ACTIVITY_NEW_TASK,
        type: 'text/plain'
    });

    intent.putExtra(Ti.Android.EXTRA_TEXT, text + ' ' + url);
    intent.putExtraUri(Ti.Android.EXTRA_STREAM, tmpImage.getNativePath());

    try {
        Ti.Android.currentActivity.startActivity(intent);
    } catch(e) {
        // GooglePlay
        Ti.Platform.openURL('https://play.google.com/store/apps/details?id=com.twitter.android');
    }
};

var client = Titanium.Network.createHTTPClient();
client.setTimeout(10000);
client.onload = function(){
    if (client.status == 200 ) {
        var name = image.match('.+/(.+?)([\?#;].*)?$')[1],
            tmpImage = Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory, name);

        tmpImage.write(this.responseData);
        start(tmpImage);
    } else {
        Ti.API.info('error: image not found');
    }
};
client.open('GET',image);
client.send();  

なんとかなりました。
大したことなさげですが、ここまでに随分ハマってしまいました。

結果、iOS、Android で同内容の投稿ができました。

問題点

  • iOS9 の Twitter 投稿ダイアログで位置情報を登録しようとすると、投稿画面がシュッと消える。(某ひっぱりハンティング系のゲームから起動した同様のダイアログも位置情報を指定するとシュッと消えたのでOSが悪い、きっと)

Gist