Theta4j Minimal Plug-in Example in Java

Yesterday, I wrote about an example from @shrhdk (Shiro) of using Kotlin to write a minimal plug-in. As Kotlin is new and I’m still learning Java, I decided to build an example in Java starting from a new empty activity, not from the plug-in SDK. This is like a “Hello, World” example for the plug-in that just takes a picture.

ExecutorService

Unfortunately, I wasn’t able to add a simple theta.takePicture() command into
KeyCallback.onKeyDown and be finished with the example. Sadly, I needed to use ExecutorService.

private ExecutorService executor = Executors.newSingleThreadExecutor();

In onKeyDown, I needed to do this:

   @Override
    public void onKeyDown(int keyCode, KeyEvent keyEvent) {
        if (keyCode == KeyReceiver.KEYCODE_CAMERA) {
            // use lambda expression with Java 1.8
            executor.submit(() -> {
                Log.d("THETA", "take picture");
                try {
                    theta.takePicture();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });

The above snippet was a little intimidating for me at first because I didn’t know what this line meant.

  executor.submit(() -> {

I skimmed this article on Lambda expressions and was able to figure out that it’s a shortcut for a Runnable in this case.

The only new concept is to put theta.takePicture() on a new thread. Wish it could be easier and just dump the entire KeyCallBack into onCreate or onResume, but that’s how it is.

Getting the pluginlibrary and theta4j libraries

As I started from a new empty Activity and not from the Plug-in SDK, I also needed to get the libraries with the gradle config files.

In build.gradle project

allprojects {
    repositories {
        google()
        jcenter()
        maven { url 'https://github.com/ricohapi/theta-plugin-library/raw/master/repository' }
    }
}

In build.gradle app

dependencies {
     implementation 'com.theta360:pluginlibrary:2.0.0'
    implementation 'org.theta4j:theta-web-api:1.2.2'
}

I also added this:

android {
    compileOptions {
        sourceCompatibility 1.8
        targetCompatibility 1.8
    }
}

Getting the Response

Shiro provides an example to get the response. I added it in a branch.

import org.theta4j.osc.CommandResponse;
import org.theta4j.osc.CommandState;
import org.theta4j.webapi.TakePicture;
...
CommandResponse<TakePicture.Result> response = theta.takePicture();
while(response.getState() != CommandState.DONE) {
    response = theta.commandStatus(response);
    Thread.sleep(100);
}
System.out.println("fileUrl: " + response.getResults().getFileUrl());

Setting Options

I have another branch to set the camera options. I received help from the developer of theta4j and I can now set CAPTURE_MODE, EXPOSURE_COMPENSATION, ISO, and EXPOSURE_PROGRAM.

The main section is listed below. It’s easy to set the options.

            theta.setOption(CAPTURE_MODE, CaptureMode.IMAGE);
            CaptureMode captureMode = theta.getOption(CAPTURE_MODE);
            Log.d(TAG, captureMode.toString());

            theta.setOption(EXPOSURE_COMPENSATION, ExposureCompensation.MINUS_1_0);
            ExposureCompensation exposureCompensation = theta.getOption(EXPOSURE_COMPENSATION);
            Log.d(TAG, exposureCompensation.toString());

            // make sure CaptureMode is set to IMAGE
            // https://developers.theta360.com/en/docs/v2.1/api_reference/options/exposure_program.html
            
            theta.setOption(EXPOSURE_PROGRAM, ExposureProgram.MANUAL);
            theta.setOption(ISO, _200);
            Log.d(TAG, "ISO Speed Changed: " + theta.getOption(ISO).toString());

Summary

For people like like to start with an empty activity, the bare minimal code, theta4j provides a good structure to access the THETA webAPI from inside the camera. The only funky part for some people will be the need to use a separate thread. Once you get by that hurdle, accessing the rest of the API looks straightforward.

@codetricity Thanks for posting this. I like the idea of working from a blank project.

As a first step, I download the zipped up repo from GitHub, imported into Android Studio, built the apk, installed it in my THETA V, set it as the primary plug-in using the RICOH desktop app (on using a mid 2010 iMac running macOS 10.13.6 and the RICOH THETA desktop app is Version 3.9.0).

11%20PM

It works!

Just for fun, I went through and renamed the project to helloworld, changed the icon, and changed the Hello World! text.

New name:

36%20PM

New icon:

New Hello World! text (click on the image to get a bigger image):

And, yea, it still works:

1 Like

Nice. Note that there are four branches on the repo:

  • master - the minimal needed
  • response branch shows how to get the camera HTTP response from the WebAPI command. It shows how to receive the URI for the last picture taken.
  • options branch shows to to get and set camera settings. ISO, exposure compensation, capture mode.
  • indicators branch shows use of a camera beep and magenta LED to show the start of a multi-picture loop.
2 Likes

theta4j 1.3 just released with Z1 support

theta4j developer @shrhdk just released a new version of theta4j with support for the new Z1 APIs. :slight_smile: :thetadev::theta:

The theta4j 1.3 release adds support for the RICOH THETA Z1 and for new features for the THETA V such as imageStitching.

Using Library

in build.gradle (app)

Additional Changes

Many changes for the Z1, including

  • plug-in order (the Z1 stores the order of 3 plug-ins)
  • RAW/DNG image support with resolution of 6720x3360
  • Timeshift and lens shooting order
  • DNG file URL
  • Aperture control
  • Support for Dynamic and Static image and video stitching

More information is available in his GitHub commit.

1 Like