MOVERIO
BT-40/40CS Support Tools

2. Developing Android Apps

2.1. Android application software development procedure

This section describes required procedure for the application development of the Moverio controller.

2.1.1. Install Android SDK

The description explains how to install Android SDK using Windows 10 PC as an example.

Download Android Studio

Android Studio will be downloaded from following Android developer's site.
https://developer.android.com/studio/

Install Android Studio

Follow an installer instruction and install Android Studio on your PC.
The later explanation is based on the SDK is installed in the following folder
C:\Users\<user name>\AppData\Local\Android\Sdk

Android Studio proxy settings

When developing an application in a network environment that requires proxy settings, set the Android Studio proxy settings. Please check the detailed procedure on the site below.
https://developer.android.com/studio/intro/studio-config#gradle-plugin
If you do not know the proxy settings, ask your network administrator how to connect to the external network using the proxy.

Acquiring/updating tools with Android SDK Manager

Use the Android SDK Manager for the tools required for application development. Please check the detailed procedure on the site below.
https://developer.android.com/studio/intro/update#sdk-manager

2.1.2. Connect with PC

Use the ADB connection confirmation command to check if the computer and host device are connected. Start a command prompt and run;
"cd C:\Users\<user name>\AppData\Local\Android\sdk\platform-tools"
*It is convenient to set the above path as an environment variable.

If you execute "adb devices" and the device name is displayed in the list, ADB connection is established.

If it is not displayed, reconnect the host device with USB and execute "adb devices" again.

2.1.3. Embed the Moverio Controller Function SDK

Moverio Controller Function SDK has dedicated API for controlling the Moverio controller. Describe the method for using dedicated API.
Following description is based on using Android Studio.
Display the Project View of Android Studio and create a "libs" folder from [File]-[New]-[Directory].
After C:¥Users¥<user name>¥AndroidStudioProjects¥<application name>¥app¥libs is created.
Put MoverioControllerFunctionSDK_1.0.0.aar there.
Then define your application's minimum API level at 28 and add MoverioControllerFunctionSDK_1.0.0.aar to your application's dependencies.

apply plugin: 'com.android.application' 
android { 
: 
// Add API level 28
minSdkVersion 28
: 
} 
dependencies { 
: 
// Add Moverio Controller Function SDK.aar 
implementation files('libs/MoverioControllerFunctionSDK_1.0.0.aar') 
: 
: 
} 

Press the Sync Project with Gradle Files button at the top of Android Studio to reflect Gradle changes to the project.

2.1.4. Debug the application via network

When developing an application for a headset model (USB connection type Moverio headset), confirm the application behavior in the state of connecting Moverio headset and the Moverio controller via USB. However, the PC and the Moverio controller are not connected by USB, so wired debugging cannot be performed at this time.
This section describes how to develop and debug application software for headset models and the Moverio controller that are connected via USB by connecting to the Moverio controller via a network. Please check the following sites as well.
https://developer.android.com/studio/command-line/adb#wireless

  1. Connect your computer and the Moverio controller to the same network.
  2. Connect your computer and the Moverio controller via USB.
    *Hereafter, it will be described on the assumption that there is only the Moverio controller connected to the computer.
  3. Execute the following command on the personal computer to enable adb connection to the Moverio controller via the network.
    # adb tcpip 5555
  4. Terminate the USB connection between your computer and the Moverio controller.
  5. Confirm the IP address of the Moverio controller.
  6. Execute the following command on the personal computer to connect adb to the Moverio controller via the network.
    # adb connect ip_address (e.g. adb connect 192.168.1.10#5555)
  7. Execute the following command on the personal computer and confirm that the Moverio controller is connected to the personal computer by adb. Make sure the device you just connected is listed.
    If not connected (not listed), check the following:
    • Are your computer and the Moverio controller connected to the same network?
    • Repeat the procedure from step 3 several times
    • Is the IP address entered in 6. correct?
  8. Install the application on the Moverio controller and check the application operation using Android Studio.

2.2. Description of Moverio Controller Function SDK's dedicated API

2.2.1 Key operation lock

Firstly, please import com.epson.moverio.btcontrol.BtCustomKey such as below.

import com.epson.moverio.btcontrol.BtCustomKey;

Next, please create an instance of BtCustomKey class and specify the key constants in the table below in the first argument of the setKeyEnable() method, and specify a boolean type lock (false) and unlock (true) in the second argument and call it.

Constants Description
BtCustomKey.VOLUME_UP Volume up key
BtCustomKey.VOLUME_DOWN Volume down key
BtCustomKey.TRIGGER Function key
BtCustomKey.HOME Home key
BtCustomKey.BACK Back key
BtCustomKey.APP_SWITCH History key
BtCustomKey.POWER Power button
BtCustomKey.ALLKEY Used to specify all physical keys
public class UIControlActivity extends Activity {
    private BtCustomKey mBtCustomKey = null;
    private Button mButton_powerKeyLock = null;

    @Override
    public final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBtCustomKey = new BtCustomKey(this);
        mButton_powerKeyLock = (Button) findViewById(R.id.button_powerKeyLock);
        mButton_powerKeyLock.setOnClickListener(new View.OnClickListener() {
        
            @Override
            public void onClick(View view) {
                mBtCustomKey.setKeyEnable(BtCustomKey.POWER, false); /* Disable power key. */
            }
        });
    }
    :
    :
}

2.2.2 Key code customization

This API can change the key code assigned to the physical key of the Moverio controller. However, it is impossible to change the key code of the power button.

Firstly, please import com.epson.moverio.btcontrol.BtCustomKey such as below.

import com.epson.moverio.btcontrol.BtCustomKey;

Next, please create an instance of the BtCustomKey class and specify the target physical key in the table below as the first argument of the setKeyAssign() method, and specify the key code as the second argument.

Target Physical Key Key Code
BtCustomKey.VOLUME_UP KeyEvent.KEYCODE_VOLUME_UP
BtCustomKey.VOLUME_DOWN KeyEvent.KEYCODE_VOLUME_DOW
BtCustomKey.TRIGGER KeyEvent.KEYCODE_FUNCTION
BtCustomKey.HOME KeyEvent.KEYCODE_HOME
BtCustomKey.BACK KeyEvent.KEYCODE_BACK
BtCustomKey.APP_SWITCH KeyEvent.KEYCODE_APP_SWITCH KeyEvent.KEYCODE_F1
KeyEvent.KEYCODE_F2
KeyEvent.KEYCODE_F3
KeyEvent.KEYCODE_F4
public class UIControlActivity extends Activity {
    private BtCustomKey mBtCustomKey = null;
    private Button mButton_appSwitch2Home = null;
    
    @Override public final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBtCustomKey = new BtCustomKey(this);
        mButton_appSwitch2Home = (Button) findViewById(R.id.button_appSwitch2Home);
        mButton_appSwitch2Home.setOnClickListener(new View.OnClickListener() {
        
            @Override public void onClick(View view) {
                mBtCustomKey.setKeyAssign(BtCustomKey.APP_SWITCH, KeyEvent.KEYCODE_HOME);
            }
        });
    }
    :
    :
}

2.2.3 LED indicator of the Moverio controller

This API can control LED indicator of the Moverio controller (Lighted mode/Not lighted mode) .

Firstly, please import com.epson.moverio.btcontrol.BtControllerLedMode.

import com.epson.moverio.btcontrol.BtControllerLedMode;

Next, please create an instance of BtControllerLedMode class and specify constants in the table below as the first argument of the setControllerLedMode() method.

Constants Description
BtControllerLedMode.MODE_OFF Not lighted mode
BtControllerLedMode.LED_MODE_NORMAL Lighted mode
public class UIControlActivity extends Activity {
    private BtControllerLedMode mBtLed = null;
    private Button mButton_ledOff = null;
    
    @Override public final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBtLed = new BtControllerLedMode (this);
        mButton_ledOff = (Button) findViewById(R.id.button_appSwitch2Home);
        mButton_ledOff.setOnClickListener(new View.OnClickListener() {
            @Override public void onClick(View view) {
            mBtLed.setControllerLedMode(BtControllerLedMode.MODE_OFF);
            }
        });
    }
    :
    :
}

Switching UI mode of the Moverio controller

The Moverio controller has Mirror mode (Same picture is shown between headset and controller) and Trackpad mode(Usable trackpad on controller screnn).
This API can switch these modes.

Firstly, please import com.epson.moverio.btcontrol.UIControl.

import com.epson.moverio.btcontrol.UIControl;

Next, please create an instance of UIControl class and specify constants in the table below as the first argument of the setUiMode() method.

Constants Description
UIControl.UI_MODE_MIRROR Switch to Mirror mode
UIControl. UI_MODE_TRACK Switch to Trackpad mode
public class UIControlActivity extends Activity {
    private UIControl mUiMode = null;
    private Button mButton_modeTrack = null;
    
    @Override public final void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState);
        mUiMode = new UIControl (this);
        mButton_modeTrack = (Button) findViewById(R.id.button_appSwitch2Home);
        mButton_modeTrack.setOnClickListener(new View.OnClickListener() { 
            @Override public void onClick(View view) { 
                mUiMode.setUiMode(UIControl. UI_MODE_TRACK); 
            } 
        }); 
    } 
    :
    : 
}

Note : When the modes are switched by this AP, the application is closed automatically to application screen reconstruction. After completed to switch mode, the application screen (Activity) before closed is shown again automatically.

2.3. Camera Control by Android CameraAPI

BT-35E and BT-45C have front facing headset camera. The Moverio controller can get camera data (picture, video) by Android Camera API or Moverio SDK. In addition, the camera data can be applied to various uses (e.g. marker recognition, etc.).
This section describes how to control BT-35E camera and BT-45C camera with the Moverio controller.
*Note : This document is for OS version 2.0.00 of the Moverio controller.

2.3.1 BT-45C/BT-35E camera control using BO-IC400

The Moverio controller can control BT-45C/BT-35E camera using Android CameraAPI or Moverio Basic Function SDK. Please refer to MoverioBasicFunctionSDK_DevelopersGuide_JA_1.2.0 for the camera control. However, camera control by Android CameraAPI and Moverio Basic Function SDK cannot use at the same time. After controlling the camera with the Moverio Basic Function SDK, Android CameraAPI cannot detect the camera. When using Android CameraAPI after using camera control by Moverio Basic Function SDK, please reconnect BT-45C / BT-35E.

There are CameraAPI1 and CameraAPI2 available for Android CameraAPI. Please refer to following information for the usages of each API.

Android CameraAPI1(android.hardware.Camera)

https://developer.android.com/training/camera
*Note:CameraAPI1 is deprecated

Android CameraAPI2(android.hardware.camera2)

https://developer.android.com/training/camera2
https://medium.com/google-developers/detecting-camera-features-with-camera2-61675bb7d1bf#.2x3icoqnc

Sample source code of Android Camera API2

The following information is sample code for a camera application using CameraAPI2. Build and run app to the Moverio controller and launch the application with BT-45C/BT-35E connected, BT-45C/BT-35E camera can now be used. Please refer to this for implementing application.
https://github.com/googlearchive/android-Camera2Basic?utm_campaign=adp_series_cameragithub_030916&utm_source=gdev&utm_medium=yt-desc

2.3.2 Android API versus Moverio Basic Function SDK

It is possible to control the BT-45C/BT-35E camera in the Moverio controller by Android CameraAPI2. However, it is impossible to change some settings from Android CameraAPI2. Please use Moverio Basic Function SDK if want to change these settings. The spec of BT-45C/BT-35E camera and controllability of the settings by each API / SDK are described in "The correspondence table of setting controllability by Android CameraAPI2 / Moverio SDK".
The correspondence table of setting controllability by Android CameraAPI2 / Moverio Basic Function SDK

Settings BT-35E BT-45C Android CameraAPI Moverio Basic Function SDK
Resolution 640x480 640x480
1280x720 1280x720
  1600x1200
1920x1080 1920x1080
  2560x1440
2592x1944  
  3264x2448
Exposure compensation auto/manual auto/manual auto only
The step of manual
exposure compensation
-5 ~ +5 -7 ~ +5  
Focus mode Off (Pan) auto/manual auto only
Manual focus   +50 ~ +3000[mm]  
Sharpness 0 ~ +128    
Brightness -127 ~ +127 0 ~ +255  
Gain 0 ~ +255 +1024 ~ +16383  
White balance auto/cloudy_daylight(6000K)/
daylght(5500K)/fluorescent(4200K)/
incandescent(3200K)/twilight(3500K)
auto/cloudy_daylight(6000K)/
daylight(5500K)/fluorescent(4200K)/
incandescent(3200K)/twilight(3500K)
auto only
Power frequency 50Hz/60Hz 50Hz/60Hz/Disable  
Indicator mode auto Auto/on/off  

2.3.3 BT-45C/BT-35E camera control specification for the Moverio controller using Android CameraAPI

The specification of some Android CameraAPI of the Moverio controller are different with standard Android CameraAPI. This topic explains about this specification on CameraAPI2.

About using BT-45C/BT-35E camera

The code snippet for getting camera characteristics

CameraManager manager = (CameraManager)getSystemService(CAMERA_SERVICE);
try {
    for (String cameraId : manager.getCameraIdList()) {
        CameraCharacteristics chars = manager.getCameraCharacteristics(cameraId);
        // Do something with the characteristics
    }
} catch (CameraAccessException e) {
    e.printStackTrace();
}

"The code snippet for getting camera characteristics" specify the cameraId and get camera characteristics. The Moverio controller has two USB port (Bottom port, Side port) and it is possible to control the BT-45C/BT-35E camera and USB camera by connecting these. However, BT-45C/BT-35E is supported on Bottom port only.
When BT-45C/BT-35E is connected to Bottom port, the cameraId is assigned such as "The cameraId at connecting BT-45C/BT-35E".

The cameraId at connecting BT-45C/BT-35E

Camera API The Moverio controller Back Camera Bottom port Side port *
Camera API1 1 0 2
Camera API2 /dev/video3 0 /dev/video4

* In case of connecting USB camera to Side port

The Moverio controller gets camera characteristics from CameraCharacteristics and can select intended camera.

The code snippet for getting camera lends direction

CameraCharacteristics chars = manager.getCameraCharacteristics(cameraId);
Integer facing = chars.get(CameraCharacteristics.LENS_FACING);

"The code snippet for getting camera lens facing" specify cameraId and get the lens facing from camera characteristics.
When BT-45C/BT-35E is connected to Bottom port, the lens facing is assigned such as "The lens facing at connecting BT-45C/BT-35E".

The lens facing at connecting BT-35E

Camera API BO-IC400 Back Camera Bottom Bottom port Side port *
Camera API1 FRONT BACK FRONT
Camera API2 EXTERNAL BACK EXTERNAL

"The code snippet for using BT-45C/BT-35E camera" is that code snippet in case of using BT-45C/BT-35E camera.

The code snippet for using BT-45C/BT-35E camera

CameraManager manager = (CameraManager)getSystemService(CAMERA_SERVICE);
try {
    for (String cameraId : manager.getCameraIdList()) {
        CameraCharacteristics chars = manager.getCameraCharacteristics(cameraId);
        Integer facing = chars.get(CameraCharacteristics.LENS_FACING);
        if (facing != null && facing == CameraCharacteristics.LENS_FACING_BACK) {
        // Open BT-45C/BT-35E camera (Please refer to upper link)
        }
    }
} catch (CameraAccessException e) {
    e.printStackTrace();
}

The information of cameraId is used for not only opening camera but setTorchMode API that uses camera flash light. The table "The cameraId at connecting BT-45C/BT-35E" is applied for setTorchMode too. When want to use back flash light of the Moverio controller with connecting BT-45C/BT-35E, need to specify "/dev/video3" as cameraId.

About using USB camera

When USB camera is connected to USB port (Bottom or Side), the cameraId is assigned such as "The cameraId at connecting USB camera".

The cameraId at connecting USB camera

Camera API The Moverio controller Back Camera Bottom Port * Side Port *
Camera API1 0 1 or 2 1 or 2
Camera API2 0 /dev/video3 or 4 /dev/video3 or 4

* cameraId can be assigned a lower number Id from the first recognized device

The lens facing is assigned such as "The lens facing at connecting USB camera".

The lens facing at connecting USB camera

Camera API The Moverio controller Back Camera Bottom Port Side Port
Camera API1 BACK FRONT FRONT
Camera API2 BACK EXTERNAL EXTERNAL

If the Moverio controller use USB camera, please specify the parameters of "The cameraId at connecting USB camera" and "The lens facing at connecting USB camera" to the source code of "The code snippet for using BT-45C/BT-35E camera".

About the screen rotation process

At Android CameraAPI2 sample source code, the screen rotation process depending on the Moverio controller rotate state is executed in order to do appropriate camera preview.
However, when the same process is executed using BT-45C/BT-35E camera, the Moverio controller rotate state and BT-35E rotate state don't synchronize. As a result, the mismatch of camera preview is occurred. Therefore, when the Moverio controller use BT-35E camera, recommend to not include the screen rotation process such as "The source code of not including screen rotation process" (Comment out "matrix.postRoatate()").

The source code of not including screen rotation process

if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
    bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
    matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
    float scale = Math.max((float) viewHeight / mPreviewSize.getHeight(), (float) viewWidth / mPreviewSize.getWidth());
    matrix.postScale(scale, scale, centerX, centerY);
    // matrix.postRotate(90 * (rotation - 2), centerX, centerY);
}

In addition, the return values of AndroidAPI regarding screen rotation are fixed value on Trackpad mode like "The AndroidAPI regarding screen rotation".

The AndroidAPI regarding screen rotation

Android API Return value
Display#getRotation() ROTATION_0
Configuration#orientation ORIENTATION_LANDSCAPE

About the aspect ratio of preview

The mounting angle differs between the camera mounted on the Moverio controller and the camera mounted on BT-45C/BT-35E. Please refer to the table below for details.

The return value of CameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION)

Type of Camera Return value
The Moverio controller Back Camera 90
BT-45C/BT-35E Camera 0

Therefore, if use BT-45C/BT-35E camera and preview the image assuming 90-degree mounting angle, the preview screen may be distorted. For example, a square object will appear as a rectangle. It is recommended that pay attention to the mounting angle and preview the image appropriately for the resolution of the acquired image.
The Android CameraAPI2 sample source code assumes a 90-degree mounting angle for previewing. With the following modification such as "The code of changing appropriate aspect ratio", the BT-45C/BT-35E camera can preview with the proper aspect ratio.

The code of changing appropriate aspect ratio

if(mSensorOrientation != 0){
    // When the mounting angle is not 0-degree, it is BO-IC400 back camera, so it should be the same as the original source code.
    if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
        mTextureView.setAspectRatio(mPreviewSize.getWidth(),mPreviewSize.getHeight());
    } else {
        mTextureView.setAspectRatio(
        mPreviewSize.getHeight(), mPreviewSize.getWidth());
    }
} else {
    // When the mounting angle is 0-degree, it is determined to be BT-35E camera (USB camera).
    //BT-35E camera doesn't rotate regardless of the device state, so the aspect ratio is always assumed to be horizontal preview.
    mTextureView.setAspectRatio(
    mPreviewSize.getWidth(), mPreviewSize.getHeight());
}
if(mSensorOrientation !=0) {
    // For BT-35E camera, the following process is not necessary because BT-35E camera doesn't rotate regardless of the device state.
    if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
        bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
        matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
        float scale = Math.max((float) viewHeight / mPreviewSize.getHeight(), (float) viewWidth / mPreviewSize.getWidth());
        matrix.postScale(scale, scale, centerX, centerY);
        matrix.postRotate(90 * (rotation - 2), centerX, centerY);
    } else if (Surface.ROTATION_180 == rotation) {
        matrix.postRotate(180, centerX, centerY);
    }
}
Go to Top