THETAプラグイン開発（theta-plugin-sdkについて）

githubで公開されている、THETAプラグイン開発用SDK([theta-plugin-sdk](https://github.com/ricohapi/theta-plugin-sdk))の内容を確認する。

2020年1月24日更新：最近のSDKに合わせて更新 (SDK ver.1.0.2->ver.2.1.0)。リンク切れを修正。

## 1. はじめに
　[RICOH THETA V](https://theta360.com/ja/about/theta/v.html)はAndroid OSでできており、当初プラグインには対応していなかったが、６月末の[RICOH THETAプラグインパートナープログラム開始](https://theta360.com/ja/info/news/2018-06-28-01/)によって、独自のAndroidアプリ（＝プラグイン）をインストールできるようになった。ここではSDKとドキュメントを確認する。

* SDK : https://github.com/ricohapi/theta-plugin-sdk
* ドキュメント：https://api.ricoh/docs/theta-plugin/how-to-develop/

開発したプラグインをadbコマンド経由でTHETA本体にインストールするにはTHETA Pluginの開発者登録する必要がある（THETA V or Z1実機の写真が必要）。サイトはRICOH Developer Connection上にあるが、プラグイン開発者登録は"RICOH Account"とは無関係なので、RICOH Accountを作る必要はない。

* プラグイン開発者登録: [RICOH THETA Plug-in Partner Program](https://www8.webcas.net/db/pub/ricoh/thetaplugin/create/input) 
* 登録アカウントの管理: [RICOH THETA Plug-in Partner Program (Profile)](https://www8.webcas.net/form/pub/ricoh/profile)
* 開発したプラグイン登録:[RICOH THETA Plug-in Partner Program (Partner Menu)](https://www8.webcas.net/form/pub/ricoh/partner)


## 2. theta-plugin-sdkの中身
　githubからcloneした[theta-plugin-sdk](https://github.com/ricohapi/theta-plugin-sdk)(ver.2.1.0)をAndroid Studioで開いてみる。
<img width="1680" alt="ThetaPluginSDKキャプチャ.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123458/de9cc8e7-91bc-c2ee-e46a-5c00bdffcb6a.png">
　ソースコードを見ると、appとpluginlibraryの２つに分かれている。[app](https://github.com/ricohapi/theta-plugin-sdk/tree/master/app)ではnetworkなどのクラス群が実装されている。SDKのver.1.xまでは直接ソースコードとしてpluginlibraryが含まれていたが、ver.2.xからは app/build.gradleで`implementation 'com.theta360:pluginlibrary:2.1.0'`のような形でセットアップされ、MainActivity.javaのなどのコード上で `import com.theta360.pluginlibrary.activity.PluginActivity;` のような形でimportするようになっている。

(↓ ver.1.0.2の場合はtheta-plugin-libraryがコード(pluginlibrary)として含まれていた。)
![theta-plugin-sdk.png](https://qiita-image-store.s3.amazonaws.com/0/123458/8205dd52-69bf-18d7-6159-c4c3f4b6ba36.png)

[theta-plugin-library](https://github.com/ricohapi/theta-plugin-library)ではプラグイン固有の仕様に対応した実装がされている。独自のプラグインを作る場合は主に[app](https://github.com/ricohapi/theta-plugin-sdk/tree/master/app)部分を開発し、もしも必要があれば[theta-plugin-library](https://github.com/ricohapi/theta-plugin-library)部分を修正できる。
　また、theta-plugin-sdkはTHETA Vのシャッターボタンを押して、静止画が撮影できるようになっている。

* app
    - [MainActivity.java](https://github.com/ricohapi/theta-plugin-sdk/blob/master/app/src/main/java/com/theta360/pluginapplication/MainActivity.java)（上の画面キャプチャ部分）
       - [PluginActivity](https://github.com/ricohapi/theta-plugin-sdk/blob/master/pluginlibrary/src/main/java/com/theta360/pluginlibrary/activity/PluginActivity.java)を継承したMainActivityになっており、onCreate(), onResume(), onPause()のみ実装されている。PluginActivityはpluginlibraryで定義されている。
        - onCreate()内の実装
            - setKeyCallbackが呼ばれ、[KeyCallback interface](https://github.com/ricohapi/theta-plugin-sdk/blob/master/pluginlibrary/src/main/java/com/theta360/pluginlibrary/callback/KeyCallback.java)の実装が行われている。
            - onKeyDown()
                 - シャッターボタン(KEYCODE_CAMERA)だった時は[AsyncTask](https://developer.android.com/reference/android/os/AsyncTask)を継承した[TakePictureTask](https://github.com/ricohapi/theta-plugin-sdk/blob/master/app/src/main/java/com/theta360/pluginapplication/task/TakePictureTask.java)が呼ばれる。
TakePictureTaskのdoInBackground()内ではlocalhost("127.0.0.1:8080")宛に[camera.takePicture](https://developers.theta360.com/ja/docs/v2.1/api_reference/commands/camera.take_picture.html)のWebAPIが呼び出されている。
                 - WebAPIとは[THETA向けのWebAPI](https://developers.theta360.com/ja/docs/v2.1/api_reference/)であり、Googleの[Open Spherical Camera API](https://developers.google.com/streetview/open-spherical-camera/reference/)を拡張したものとなっている。
                 - WebAPIの呼び出しには同じくapp内に実装されている[HttpConnector](https://github.com/ricohapi/theta-plugin-sdk/blob/master/app/src/main/java/com/theta360/pluginapplication/network/HttpConnector.java)クラスが使われている。このクラスはtakePicture以外のコマンドも実装されており、WebAPIの呼び出しが必要となった時に利用できるだろう。
            - onKeyUp()
                 - どこかのボタンを押し上げる（戻す）とnotificationLedBlinkが呼ばれる。
                 - notificationLedBlinkを用いて、LED3 ([Wireless Light](https://api.ricoh/docs/theta-plugin/how-to-develop/))を青色で点滅させる実装がされている。
            - onKeyLongPress()
                 - 特に実装されていない。pluginlibraryでモードボタンの長押しに対応するコードが実装されている。

* [theta-plugin-library (pluginlibrary)](https://github.com/ricohapi/theta-plugin-library)
    - pluginlibraryには[ドキュメント](https://api.ricoh/docs/theta-plugin/how-to-develop/)に記載されているTHETA独自のブロードキャストなどが定義されている。
    - [PluginActivity](https://github.com/ricohapi/theta-plugin-library/blob/master/library/src/main/java/com/theta360/pluginlibrary/activity/PluginActivity.java)は[AppCompatActivity](https://developer.android.com/reference/android/support/v7/app/AppCompatActivity)を継承しており、Androidアプリの[Activity Lifecycle](https://developer.android.com/guide/components/activities/activity-lifecycle)部分(onCreate, onResume, onPause)が実装されている。 `以下の図はdeveloper.android.comより引用`![(developer.android.com)[https://developer.android.com/guide/components/activities/activity-lifecycle]より引用](https://developer.android.com/guide/components/images/activity_lifecycle.png)
        - onCreate()
            - Androidの[UncaughtExceptionHandler](https://developer.android.com/reference/java/lang/Thread.UncaughtExceptionHandler)を継承した、UncaughtExceptionクラスが登録されており、何か例外が発生すると、エラーとなってプラグインが終了するようになっている。
        - onResume()
            - キーイベントの登録がされている。pluginlibraryに実装された[KeyReceiver](https://github.com/ricohapi/theta-plugin-library/blob/master/library/src/main/java/com/theta360/pluginlibrary/receiver/KeyReceiver.java)クラスが利用されており、このクラスに[Receiving Button Events](https://api.ricoh/docs/theta-plugin-reference/broadcast-intent/)に記載があるようなブロードキャストインテントを取得する部分が実装されている。onKeyReceiverがPluginActivityクラス内に定義されており、appのMainActivityで利用していたonKeyLongPressなどのコールバックはonKeyReceiver経由で行われる。
        - onPause()
            - isClosedの設定によっては、終了処理が呼び出される。
            - KeyReceiverクラスの登録を解除する。onPause以降はキーイベント（コールバック）が来なくなる。
    - その他、[PluginActivity](https://github.com/ricohapi/theta-plugin-library/blob/master/library/src/main/java/com/theta360/pluginlibrary/activity/PluginActivity.java)クラスには以下のようなメソッドが定義されている。[Broadcast Intent](https://api.ricoh/docs/theta-plugin-reference/broadcast-intent/)に記載されている多くの制御をメソッドの呼び出しで利用できる。
        - notificationWlanOffなどWLANを制御するメソッド
        - notificationLedShowなどのLEDを制御するメソッド
        - notificationAudioShutterなどの音を制御するメソッド
        - notificationCameraOpenなど、[Camera API](https://api.ricoh/docs/theta-plugin-reference/camera-api/)を使うときに必要なメソッド

　既存のAndroidアプリのプロジェクトをプラグインにする時は、theta-plugin-sdkからpluginlibraryなど必要な部分をプロジェクトへインポートorコピーして使えば良い。
        
## 3. スマホ or THETA Vで動かして見る
　AndroidスマホもしくはTHETA Vで動かして見る。手元のスマホはAndroid 7.0なので、minSdkVersionとtargetSdkVersionをAPI24に変更する必要があった。
　AndroidスマホでPluginSDKアプリを動かして見た。(Thetaには画面がないはずだが)Hello Worldが表示されている。同じようにAndroidアプリをTHETA上で動作させることもできる。THETAの画面表示には[Vysor](https://chrome.google.com/webstore/detail/vysor/gidgenkbbabolejbgbpnhbimgjbffefm)を使うことができる。
 <img src="https://qiita-image-store.s3.amazonaws.com/0/123458/6f7e69b9-b03d-31e8-873a-075243205b6b.jpeg" width=25%>

## 4. まとめ
　プラグイン開発は通常のAndroidアプリの開発と同様にAndroid Studioを用いて行うことができる。THETA Vのプラグインに固有の機能を実装したクラス群が[theta-plugin-sdk](https://github.com/ricohapi/theta-plugin-sdk)の中で定義されている。[PluginActivity](https://github.com/ricohapi/theta-plugin-library/blob/master/library/src/main/java/com/theta360/pluginlibrary/activity/PluginActivity.java)クラスを利用することでTHETAを制御でき、[HttpConnector](https://github.com/ricohapi/theta-plugin-sdk/blob/master/app/src/main/java/com/theta360/pluginapplication/network/HttpConnector.java)クラスで[WebAPI](https://developers.theta360.com/ja/docs/v2.1/api_reference/)で定義された機能を利用することができる。

## 参考
* [RICOH THETA プラグイン開発　ワークショップ　＃１ 資料](https://www.slideshare.net/RICOHTHETAPluginDevloperCommunity/ricoh-theta-120818517)