「LINEで送る」をTitaniumで（2014年版）

Titanium製のアプリからLINEへ画像を送るといえば、@yagi_さんの[このブログエントリ](http://selfkleptomaniac.org/archives/2497)ですね。異論はありません。

ただ残念ながらこの記事の内容、今は動きませんでした。。。正確に言うと、iOS7以降の端末では動かないんです。記事内で紹介されている[TiCustomPasteboard](https://github.com/donayama/TiCustomPasteboard)がラップしているUIPasteboardがiOS7のタイミングで大幅に仕様を変更したことが原因です。このときの変更以来、アプリをまたいでのクリップボード共有にはGeneralPasteboardという仕組みを使うことが必須となっています。

最近つくったアプリで必要になったため色々調べて動くようにした顛末をまとめました。


## TiCustomPasteboardでアプリ間共有

ここを長々と書いてもしょうがないので結論だけ。モジュールを改修しました。~~まだ本家にマージされていませんので[ここにおいてあるのを](https://github.com/hoyo/TiCustomPasteboard)ダウンロードすれば使えます。なお、きっと近いうちに@donayamaさんがマージしてくれると思いますので、マージされたら本家のほうから落としてくることをオススメします。~~ 変更したコードを@donayamaさんに[TiCustomPasteboard](https://github.com/donayama/TiCustomPasteboard)にマージしていただきましたので、最新版を落としてくれば大丈夫です。(12/13追記)


## 本題：LINEへ画像をおくる（2014年版）

Alloyを使った場合の実装例です。画面に表示したImageViewをタップするとその画像をLINEに送るシンプルなものです。なお画像ファイルは`app/assets/stamp.png`のファイル名で格納しておくものとします。

```js:alloy.js
Alloy.Globals.Pasteboard = require('jp.hsj.ticustompasteboard');
```

```xml:views/index.xml
<Alloy>
  <Window>
    <ImageView id="stamp"></ImageView>
  </Window>
</Alloy>
```

```js:style/index.tss
"#stamp": {
  height: 320,
  image: 'stamp.png',
  width: 370
}
```

```js:controllers/index.js
var PB_NAME = Alloy.Globals.Pasteboard.getGeneralPasteboardName();

$.stamp.addEventListener('click', function(e) {
  if (Ti.Platform.canOpenURL('line://msg/text/a')) {
    Alloy.Globals.Pasteboard.setGeneralImage(e.source.toBlob());
    Ti.Platform.openURL('line://msg/image/' + PB_NAME);
  } else {
    alert('LINEがインストールされていません。');
  }
});

$.index.open();
```

ここで出てくる`setGeneralImage()`というのが今回のキモです。他のアプリから上書きされる可能性がある領域なので、`openURL()`を実行する直前に画像のバイナリを渡してあげます。なおLINEに送信するPastboardNameは`getGeneralPasteboardName()`で取得できます。


## ちなみにiOS・Android両対応版は

せっかくTitaniumでつくるんだからAndroidにも対応したいですよね。こちらは画像ファイルをテンポラリ領域にコピーしてパスを渡せばいいだけなので簡単です。ということで、両プラットフォーム対応版にするとこんな感じになります。

```js:alloy.js
if (OS_IOS) {
  Alloy.Globals.Pasteboard = require('jp.hsj.ticustompasteboard');
}
```


```xml:views/index.xml
<Alloy>
  <Window>
    <ImageView id="stamp"></ImageView>
  </Window>
</Alloy>
```

```js:style/index.tss
"#stamp": {
  height: '320dp',
  image: 'stamp.png',
  width: '370dp'
}
```

```js:controllers/index.js
if (OS_IOS) {
  var PB_NAME = Alloy.Globals.Pasteboard.getGeneralPasteboardName();
}

$.stamp.addEventListener('click', function(e) {
  if (OS_IOS) {
    if (Ti.Platform.canOpenURL('line://msg/text/a')) {
      Alloy.Globals.Pasteboard.setGeneralImage(e.source.toBlob());
      Ti.Platform.openURL('line://msg/image/' + PB_NAME);
    } else {
      alert('LINEがインストールされていません。');
    }
  } else {
    var src = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory + '/stamp.png');
    var tmp = Ti.Filesystem.tempDirectory + '/tmp_stamp.png';
    src.copy(tmp);
    if (!Ti.Platform.openURL('line://msg/image/' + tmp)) {
      alert('LINEがインストールされていません。');
    }
  }
});

$.index.open();
```

実際にアプリに組み込むときには複数の画像から選択して、それを送るようなフローになることが多いかと思います。その場合、Androidでは`Ti.Filesystem.tempDirectory`の中に保存するファイル名を都度変えてあげる必要があるようです。キャッシュが残っているのか、送信元の端末のLINE画面には別々の画像が表示されているのに、送信先のユーザの手元には最初に送ったものと同じ画像が表示される現象が発生しました。詳しく検証できていませんが要注意ということで。


さて、明日のTitanium Advent Calendarは[star__hoshi](http://qiita.com/star__hoshi)さんです。