1. ueue

    Posted

    ueue
Changes in title
+THETAを使ってLINE経由で愛を伝える
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,270 @@
+# 【THETAプラグイン開発】LINEで愛を伝える
+
+## はじめに
+
+リコーの@ueueです。夏バテを年末まで引きずるタイプの中年です。
+突然ですがみなさんは奥さまに愛を伝えていますか?
+中年にもなると奥さまに面と向かって「愛してる」と伝えるのは恥ずかしいですね。
+そんな中年の皆さんのためにRICOH THETAを使ってLINE経由で愛を伝えるプラグインを作成してみました。
+
+具体的にはTHETAを無線LANクライアントモードにしてネットワークにつないだ状態で、 LINEのMessaging APIを利用してメッセージを送信するプラグインです。
+↓ こんなイメージです。
+
+![](./image/plugin-zentaizu.png)
+![plugin-zentaizu.png](https://qiita-image-store.s3.amazonaws.com/0/264025/8026fa17-9eb1-06d8-b944-419419f41747.png)
+
+「THETAプラグイン is 何?」という方のためにざっくりと説明すると、現時点(2018/08/06)の最新機種であるTHETA VはAndroidベースのOSを採用しており、Androidアプリをインストールすることで機能拡張が可能になっています。
+このアプリのことをTHETAプラグインと呼んでいます。
+THETAプラグイン開発に興味を持たれた方はぜひ[パートナープログラム](https://api.ricoh/products/theta-plugin/)にご登録ください。
+
+
+さて、この記事のポイントは開発のためにTHETAをUSBでPCにつなぎつつ、同時にWi-Fiにつなぐ方法です。
+THETAはUSB接続時はWi-Fiに接続できない仕様になっています。
+ですが、これではネットワークにアクセスするプラグインの開発がやりづらいので、開発者モードでのみ利用可能な裏技を利用して、USBとWi-Fiの両方に接続する方法を説明します。
+今回紹介する技を使えば↓こんな感じで開発が進められます。
+
+![](./image/kaihatu-zentaizu.png)
+![kaihatu-zentaizu.png](https://qiita-image-store.s3.amazonaws.com/0/264025/8672a9cb-2770-d34a-91c0-c19e65b8827a.png)
+
+
+## LINE Messaging APIの準備
+
+まずはLINEにメッセージを送るための準備をします。
+[LINE Developer コンソール](https://developers.line.me/ja/)からプロバイダとチャンネルを作成し、アクセストークン(ロングターム)を発行してください。
+一連の手続きについては[こちら](https://qiita.com/nkjm/items/38808bbc97d6927837cd)の記事を参考にさせていただきました。
+
+とりあえず、自分向けにテストする場合は、Developer コンソールのチャンネル基本設定にあるUser IDを控えてください。
+このUser ID宛にメッセージを送れば、自分宛てに送信されます。
+
+奥さま宛に送るにはWebhookを設定し、同じくチャンネル基本設定にあるQRコードを使って、チャンネル(アプリ)を友達に登録するようにいい感じに奥さまを誘導してください。
+奥さまが友達に追加したタイミングでWebhookに奥さまのUser IDが送られますので、そちらを控えてください。
+
+作成したアプリからメッセージを送る方法は
+[Messaging API リファリエンスの「プッシュメッセージを送る」](https://developers.line.me/ja/reference/messaging-api/#anchor-0c00cb0f42b970892f7c3382f92620dca5a110fc)の項に記載されています。
+今回送信するメッセージを、curlコマンドで送る場合は、以下のようになります。
+
+```
+curl -v -X POST https://api.line.me/v2/bot/message/push \
+-H 'Content-Type:application/json' \
+-H 'Authorization: Bearer <アクセストークン>' \
+-d '{
+ "to": "<User ID>",
+ "messages":[
+ {
+ "type":"text",
+ "text":"愛してる"
+ },
+ {
+ "type":"text",
+ "text":"めちゃめちゃ愛してる"
+ },
+ {
+ "type": "sticker",
+ "packageId": "1",
+ "stickerId": "409"
+ }
+ ]
+}'
+```
+
+<アクセストークン>には上記で発行したアクセストークンを入力し、\<User ID\>には控えておいたUser IDを入力してください。
+まずは、テストのために自分のUser IDを入力しましょう。
+
+メッセージオブジェクトについては[こちら](https://developers.line.me/ja/reference/messaging-api/#message-objects)を参照してください。
+スタンプを送る場合はtypeの値として"sticker"を入力し、送りたいスタンプのpackageIDとstickerIDを入力します。
+スタンプとpakcageID,stickerIDの対応は[こちらの表](https://developers.line.me/media/messaging-api/messages/sticker_list.pdf)にあります。
+
+ターミナルから上記のcurlコマンドを入力して、LINEでメッセージが受け取れれば成功です。
+
+## THETAをネットワークに接続する
+
+THETAを無線LANクライアントモードに切り替えることで、THETAをネットワークに接続させることが可能です。
+手順については以下のリンク先をごらんください。
+[THETAを無線LANに接続する手順](https://theta360.com/ja/support/manual/v/content/prepare/prepare_06.html)
+
+## THETAのWi-FiをUSB接続中に有効化する方法
+
+開発のためにTHETAをUSBでPCと接続してください。
+接続するとTHETAのWi-Fiマークが消えます。
+![](image/theta_no_wifi.png)
+![theta_no_wifi.png](https://qiita-image-store.s3.amazonaws.com/0/264025/985cfd82-e95f-d6c4-ff3b-36de8013a6b6.png)
+
+このようにUSBに接続するとWi-Fiが無効になる、というのがTHETAの仕様なのですが、これだとネットワークに接続するプラグインの開発がやりづらくなります。
+ですが、開発者モードの場合は以下のコマンドを入力することでUSBにつないだ状態でWi-Fiを有効にすることが可能です。
+
+```
+adb shell settings put global usb_debug true
+```
+
+一度、THETAからUSBを外して、Wi-Fiが有効になるのを待ち、再度、USBに接続してください。
+さきほどは消えたWi-Fiマークが消えずに点灯していれば成功です。
+
+![](image/theta_on_wifi.png)
+![theta_on_wifi.png](https://qiita-image-store.s3.amazonaws.com/0/264025/0b1b5332-2be9-3e2b-8625-b96705780e76.png)
+
+この状態であればUSBとWi-Fiの両方の接続が有効になっているので、Android Studioからapkをインストールし、ネットワークに接続する処理の確認を行うことが可能です。
+
+## プラグインコードの説明
+以下が、今回のプラグインのソースコードです。
+
+```java
+package com.theta360.pluginapplication;
+
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+
+import com.theta360.pluginlibrary.activity.PluginActivity;
+import com.theta360.pluginlibrary.callback.KeyCallback;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+public class MainActivity extends PluginActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setKeyCallback(new KeyCallback() {
+
+ @Override
+ public void onKeyDown(int keyCode, KeyEvent event) {
+ new SendMessageTask().execute();
+ }
+
+ public void onKeyUp(int keyCode, KeyEvent event) {
+ }
+
+ public void onKeyLongPress(int keyCode, KeyEvent event) {
+ }
+ });
+ }
+
+ private static class SendMessageTask extends AsyncTask<Void, Void, Void> {
+
+ @Override
+ public Void doInBackground(Void... params) {
+ final String token = "<アクセストークン>";
+ final String user_id = "<User ID>";
+
+ final String data = "{"
+ + "\"to\":\""
+ + user_id
+ + "\","
+ + "\"messages\":["
+ + "{\"type\":\"text\",\"text\":\"愛してる\"},"
+ + "{\"type\":\"text\",\"text\":\"めちゃめちゃ愛してる\"},"
+ + "{\"type\":\"sticker\",\"packageId\":\"1\",\"stickerId\":\"4\"}"
+ + "]}";
+ try {
+ final String url = "https://api2.line.me/v2/bot/message/push";
+ HttpURLConnection connection = createConnection(url, token);
+ sendData(data, connection);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private HttpURLConnection createConnection(String url, String token) throws IOException {
+ HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
+ // 接続するための設定
+ connection.setRequestMethod("POST");
+ connection.setRequestProperty("Content-Type", "application/json");
+ connection.setRequestProperty("Authorization", "Bearer " + token);
+ connection.setRequestProperty("Accept", "application/json");
+
+ // APIからの戻り値と送信するデータの設定を許可する
+ connection.setDoOutput(true);
+
+ return connection;
+ }
+
+ private void sendData(String data, HttpURLConnection connection) throws IOException {
+ try (OutputStream out = connection.getOutputStream()) {
+ // 接続
+ connection.connect();
+
+ // 送信するデータの書き込み
+ out.write(data.getBytes("UTF-8"));
+ out.flush();
+ connection.getResponseCode();
+ } finally {
+ connection.disconnect();
+ }
+ }
+ }
+}
+```
+
+以下、注意点です。
+APIのURL指定部分に公式のMessaging APIのドメインapi.line.meを設定するとエラーになったので、CNAMEとして登録されているapi2.line.meに変更しました。
+
+```java
+final String url = "https://api2.line.me/v2/bot/message/push";
+```
+
+今回のサンプルコードではアクセストークンの値やUser IDを直書きしていますが、良い子の皆さんは真似しないでください。
+
+```java
+final String token = "<アクセストークン>";
+final String user_id = "<User ID>";
+```
+
+
+アクセストークンやUser IDなどのパラメータは[こちらの手順書](https://theta360.com/ja/support/manual/v/content/plugin/plugin_02.html)の5の部分で説明している方法で設定できるようにするのがおすすめです。
+プラグイン側としては[こちら](https://api.ricoh/docs/theta-plugin/how-to-use/#using-a-web-server)に記載の通りWebサーバーを内部で起動することになります。
+実装方法については今後[RICOH THETAプラグイン開発者コミュニティ](https://qiita.com/organizations/theta-plugin)の誰かが説明してくれると思います。(他力本願)
+
+あと、例外処理は手抜きしているので、皆さんはいい感じに実装してください。
+
+
+## プラグイン動作実験
+では、自分が実験台となって、うちの奥さまに愛を伝えようと思います。
+まずは、今回作成したチャンネル(アプリ)を友達登録してもらうため、QRコードを送ります。
+
+![](image/sukusho_yome.png)
+![sukusho_yome.png](https://qiita-image-store.s3.amazonaws.com/0/264025/08b33809-b4bb-d180-144a-30c1a93812b8.png)
+
+ぐぬぬ。
+ここでつまづくとは。。
+ネット詐欺かなんかと思っているらしい。
+ネットのことはよくわからないが、ネット詐欺にはことさら警戒心の強いうちの奥さまにこのアプリを友達登録してもらうことはできませんでした。[^iiwake]
+
+しかたがないので、User IDを自分のものに変えて動作させたスクショを貼っておきます。
+
+![](image/sukusho_self.png)
+![sukusho_self.png](https://qiita-image-store.s3.amazonaws.com/0/264025/0ac2f765-a245-6c1a-85f7-cbb5129b5c51.png)
+
+おっさん同士が愛を交わしている絵にも見えますが、
+自分で送って、自分で返信しているだけです。念の為。
+
+あと、自分で返信してみて気づいたのですが返信はTHETAでは確認できないですね。。[^henshin]
+まぁ、後で奥さまに、なんて返したのか聞いてください。
+
+なんか、いろいろグダグダですみません。
+
+そのうち続編としてLINEで360度画像を送る方法を書く予定です。
+LINEは360度画像をグリグリ動かすビューに対応しているので、いい感じになると思います。
+そのときははグダッとしないようにします。たぶん。
+
+
+## まとめ
+- 開発者モードのTHETAをUSBでPCにつなぎつつ、Wi-Fiにも接続する方法を説明しました。
+- THETAをWi-FiにつないでLINEにメッセージを送るプラグインを作成しました。
+- LINEだけでなくさまざまなクラウドサービスのAPIに応用可能です。
+
+
+この記事を見てTHETAプラグイン開発に興味を持たれた方はぜひパートナープログラムにご登録ください。
+なお、登録時に申請したシリアルナンバーのTHETAについてはメーカーサポート対象外になりますので、ご注意ください。
+- パートナープログラムの詳細は[こちら](https://api.ricoh/products/theta-plugin/)
+- 登録フォームは[こちら](https://www8.webcas.net/db/pub/ricoh/thetaplugin/create/input)
+
+
+[^iiwake]: ガチ感を出すために事前に何も言わなかったのが逆にあだとなってしまいました。
+[^henshin]: WebhookのURLには送られています。
+