Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

はじめに

こんにちは、メロンパン大好きリコーの@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についてはメーカーサポート対象外になりますので、ご注意ください。

meronpan
theta-plugin
株式会社リコーの技術者有志による、RICOH THETAプラグイン技術情報の提供を目的としたコミュニティです。
https://api.ricoh/products/theta-plugin/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away