Theta
THETAPlugin

【THETAプラグイン開発】THETAプラグインでHello World


はじめに

こんにちは、メロンパン大好きリコーの@meronpanです:melon:

THETA Vのプラグイン開発のハローワールド的なことをSDKを使って紹介したいと思います。

SDKをインストールする手順はこちらです。

最終的にピカピカ光るTHETAを作ります。



THETAプラグインをご存じない人はこちらの記事をご覧ください。

興味を持たれた方はtwitterのフォローと

THETAプラグイン開発コミュニティ(slack)への参加もよろしくおねがいします。

プラグインとは言いつつも、感覚的にはAndroidアプリを開発するイメージです。

ただし、通常のAndroidスマホと比べて以下のような点が異なり、若干の工夫が必要です。

- 360度の全天球カメラである(2つのカメラが同時に動く)

- 画面が無い

- いくつかのボタンとランプがある

- 4chのマイクがついている

これらのことから、主にCameraとAudio部分のAPIが追加変更となっています。

SDKにはpluginlibraryが含まれています。こちらは基本的に変更せずそのまま利用して、それ以外の部分を変更していきます。


目次



  • THETA Vのプラグインについて以下を説明したいと思います。


    • THETAのボタンの基本的な使い方

    • ランプの基本的な使い方

    • 無線ランプの色が変化するプラグインの作成

    • meronpanのつぶやき




ボタンの基本的な使い方

ここでは、ボタンの基礎学習と使い方の確認をします。


ボタンの基礎学習

ボタンを利用する上に覚えておきたいことが2つあります。


  • ボタンの種類

  • ボタン操作の種類

利用する際は、ご確認ください。


ボタンの種類

以下のようなボタンの種類があり、対応するキーコード定数を確認しましょう。

no
ボタン
キーコード定数

4
シャッターボタン
KeyReceiver.KEYCODE_CAMERA

12
無線ボタン
KeyReceiver.KEYCODE_WLAN_ON_OFF

13
モードボタン
KeyReceiver.KEYCODE_MEDIA_RECORD

nameOfCameraParts.png


ボタン操作の種類

ボタン操作に対し、以下のようなコールバック関数が用意されています。

ボタン操作
コールバック関数

ボタンを押す
onKeyDown

ボタンから離す
onKeyUp

モードボタンを長押しする
onKeyLongPress


ボタンの使い方

基本的には、ボタンの基礎学習で登場したボタンとボタン操作の種類を掛け合わせて利用するイメージです。

では、SDKを用いて使い方を確認しましょう。

SDKを実行すると最初に呼ばれるのがMainActivityですが、以下ボタンの説明に絞って部分的に紹介します。

メロンパンでも召し上がりながら、ご覧ください:melon:

    @Override

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

onCreateMainActivityが実行されると最初の一回だけ呼び出されます。

            @Override

public void onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyReceiver.KEYCODE_CAMERA) {
/*
* To take a static picture, use the takePicture method.
* You can receive a fileUrl of the static picture in the callback.
*/

new TakePictureTask(mTakePictureTaskCallback).execute();
}
}

onKeyDownはボタンが押された時に実行されます。

中では押したボタンがKEYCODE_CAMERAであればと場合分けをしており、new TakePictureTaskはシャッターボタンを押した時に実行されます。

            @Override

public void onKeyUp(int keyCode, KeyEvent event) {
/**
* You can control the LED of the camera.
* It is possible to change the way of lighting, the cycle of blinking, the color of light emission.
* Light emitting color can be changed only LED3.
*/

notificationLedBlink(LedTarget.LED3, LedColor.BLUE, 1000);
}

@Override
public void onKeyLongPress(int keyCode, KeyEvent event) {
notificationError("");
}

同様にonKeyUpはボタンを離した時に実行、 onKeyLongPressはボタンを長押しした時に実行されます。

onKeyDownの時のように場合分けしていないのでどのボタンを押しても実行されます。


ランプの基本的な使い方

ここでは、ランプの使い方を確認します。


結論から言うと以下3点を覚えてください。


  • オン、オフ、点滅の3種類の制御ができる。

  • 下部表のLED3〜8のランプを制御できる。

  • 下部表のLED3のランプは色を変更できる。

no
各部名称
LED No

6
無線ランプ
LED3

7
撮影モードランプ
(カメラ)LED4, (動画)LED5, (Live)LED6

8
動画記録ランプ
LED7

9
メモリー警告ランプ
LED8

nameOfCameraParts.png

SDKを使って使い方を確認しましょう。

SDKはこちらより


pluginlibraryではランプの制御について以下の関数が用意されています。

色を指定してLED3ランプをオンにする。

    public void notificationLed3Show(@NonNull LedColor ledColor)

LED3〜8ランプを選択してランプをオンにする。

    public void notificationLedShow(@NonNull LedTarget ledTarget)

ランプを点滅させる。

    public void notificationLedBlink(@NonNull LedTarget ledTarget, LedColor ledColor, int period)

ランプをオフにする。


public void notificationLedHide(@NonNull LedTarget ledTarget)


  • LedTarget

    enumで、LED3, LED4, ..., LED8のいずれかを指定します。

  • LedColor

    enumで、RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW, WHITEのいずれかを指定します。

    デフォルトは BLUEです。


  • period

    点滅制御を利用した時、1サイクルの時間(ms)を250-2000の範囲で指定します。

    250以下の値は250にセットされ、2000以上の値は2000にセットされます。



無線ランプの色が変化するプラグインの作成

以上学習してきたことを活かし、無線ランプの色がランダムに変化し、シャッターボタンで停止するプラグインを作りました。

記事の冒頭で紹介した動画です。

以下の2つについて変更を加えています。


  • MainActivity


  • AndroidManifest.xml



MainActivityの変更

MainActivityを以下のように変更しました。

package com.theta360.pluginapplication;

import android.os.Bundle;
import android.view.KeyEvent;
import com.theta360.pluginapplication.task.TakePictureTask;
import com.theta360.pluginapplication.task.TakePictureTask.Callback;
import com.theta360.pluginlibrary.activity.PluginActivity;
import com.theta360.pluginlibrary.callback.KeyCallback;
import com.theta360.pluginlibrary.receiver.KeyReceiver;
import com.theta360.pluginlibrary.values.LedColor;
import com.theta360.pluginlibrary.values.LedTarget;

import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends PluginActivity {

//スケジュール時間間隔を定義
private static final int TIMER_INTERVAL_PERIOD = 250;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//一定時間間隔でランプの色を更新するために、Timerをセット
Timer timer = new Timer();

Random ledColorRand = new Random();
Random ledTargetRand = new Random();
Random ledHideRand = new Random();

//250msごとにrunが実行されるように設定
timer.schedule(new TimerTask() {
@Override
public void run() {
//ランプの色をランダムで選択
int ledColorNum = ledColorRand.nextInt(LedColor.values().length);
//点灯させるランプをランダムで選択
int ledTargetNum = ledTargetRand.nextInt(LedTarget.values().length);
//消灯させるランプをランダムで選択
int ledHideNum = ledHideRand.nextInt(LedTarget.values().length);

//ランダムで選んだ色で、LED3ランプを点灯させる
notificationLed3Show(LedColor.values()[ledColorNum]);
//ランダムで選んだランプを点灯させる
notificationLedShow(LedTarget.values()[ledTargetNum]);
//ランダムで選んだランプを消灯させる
notificationLedHide(LedTarget.values()[ledHideNum]);
}
}, 0, TIMER_INTERVAL_PERIOD);

// Set a callback when a button operation event is acquired.
setKeyCallback(new KeyCallback() {
@Override
public void onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyReceiver.KEYCODE_CAMERA) {
//Timerを終了させることで、一定間隔でランダムに色を点滅させる処理を終了
timer.cancel();
//ランプを消灯させる
notificationLedHide(LedTarget.LED3);
notificationLedHide(LedTarget.LED4);
notificationLedHide(LedTarget.LED5);
notificationLedHide(LedTarget.LED6);
notificationLedHide(LedTarget.LED7);
notificationLedHide(LedTarget.LED8);
}
}

@Override
public void onKeyUp(int keyCode, KeyEvent event) {
}

@Override
public void onKeyLongPress(int keyCode, KeyEvent event) {
//Timerを終了させることで、一定間隔でランダムに色を点滅させる処理を終了
timer.cancel();
//ランプを消灯させる
notificationLedHide(LedTarget.LED3);
notificationLedHide(LedTarget.LED4);
notificationLedHide(LedTarget.LED5);
notificationLedHide(LedTarget.LED6);
notificationLedHide(LedTarget.LED7);
notificationLedHide(LedTarget.LED8);
//正常にプラグインが終了した時の通知
notificationSuccess();
}
});
}
}

細かいところを見ていくと、、、

        //250msごとにrunが実行されるように設定

timer.schedule(new TimerTask() {
@Override
public void run() {
//ランプの色をランダムで選択
int ledColorNum = ledColorRand.nextInt(LedColor.values().length);
//点灯させるランプをランダムで選択
int ledTargetNum = ledTargetRand.nextInt(LedTarget.values().length);
//消灯させるランプをランダムで選択
int ledHideNum = ledHideRand.nextInt(LedTarget.values().length);

//ランダムで選んだ色で、LED3ランプを点灯させる
notificationLed3Show(LedColor.values()[ledColorNum]);
//ランダムで選んだランプを点灯させる
notificationLedShow(LedTarget.values()[ledTargetNum]);
//ランダムで選んだランプを消灯させる
notificationLedHide(LedTarget.values()[ledHideNum]);
}
}, 0, TIMER_INTERVAL_PERIOD);

onCreate内に記載したため、timer.scheduleは実行後1度だけ呼び出されます。

しかし、中身のrunは定期的に呼ばれるようになります。

timer.schedulerunが250ms毎に実行されるようにしました。

            @Override

public void onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyReceiver.KEYCODE_CAMERA) {
//Timerを終了させることで、一定間隔でランダムに色を点滅させる処理を終了
timer.cancel();
//ランプを消灯させる
notificationLedHide(LedTarget.LED3);
notificationLedHide(LedTarget.LED4);
notificationLedHide(LedTarget.LED5);
notificationLedHide(LedTarget.LED6);
notificationLedHide(LedTarget.LED7);
notificationLedHide(LedTarget.LED8);
}
}

もともとはonKeyDownの中でカメラ撮影するコードが書かれていましたが、ランプを消灯する処理に書き換えました。

timer.cancelで定期的に実行されていたrunが停止します。

これにより、ランプの更新が止まります。

最後にnotificationLedHideよりランプをオフ!

            @Override

public void onKeyLongPress(int keyCode, KeyEvent event) {
//Timerを終了させることで、一定間隔でランダムに色を点滅させる処理を終了
timer.cancel();
//ランプを消灯させる
notificationLedHide(LedTarget.LED3);
notificationLedHide(LedTarget.LED4);
notificationLedHide(LedTarget.LED5);
notificationLedHide(LedTarget.LED6);
notificationLedHide(LedTarget.LED7);
notificationLedHide(LedTarget.LED8);
//正常にプラグインが終了した時の通知
notificationSuccess();
}

onKeyLongPressはモードボタンを長押しした時に呼ばれます。

onKeyLongPress内ではプラグインを終了する処理が実行されます。

timer.cancelnotificationLedHideonKeyDownと同じ目的の処理です。

最後に正常にプラグインが終了したことを知らせるためにnotificationSuccessを実行します。


AndroidManifest.xmlの変更

画面を持たないTHETAにおいて以下の工夫をしました。


AndroidManifest.xml

        <activity android:name=".MainActivity"

android:screenOrientation="portrait"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>


画面を固定させるためのandroid:screenOrientation="portrait"の記載を加えました。

このコードがないと、THETAを傾ける度に画面が回転したと認識されonCreateが実行されてしまいます。

Androidのライフサイクル上、画面が回転するとアプリが初期化されるためです。


meronpanのつぶやき

撮影ができず、ランプの点滅を楽しむカメラ、、、いかがでしょうか。

紹介したコードを使って、ボタンの種類、ボタンアクションの種類を変更して、オリジナルのLED点滅プラグインを作るだけでも結構面白いと思います。


これであなたもTHETAプラグインにメロメロン:melon:

THETAプラグイン開発に興味を持たれた方はぜひパートナープログラムにご登録ください!

なお、登録時に申請したシリアルナンバーのTHETAについてはメーカーサポート対象外になりますので、ご注意ください。