Tango Android Service Migration Guide

To ensure compatibility with future devices, the Tango service has been changed from a system service to a standard Android service.

One result of this change is that applications will need to handle the service binding and unbinding lifecycle explicitly. The code changes you need to make are explained below.

All applications

For all applications running Tango as an Android service, in the AndroidManifest.xml file, remove this element:

 <uses-library
      android:name="com.projecttango.libtango_device"
      android:required="true" />

... and replace it with this:

 <uses-library
      android:name="com.projecttango.libtango_device2"
      android:required="true" />

Note that the only difference is the 2 added to the end of "device" in the new element.

C/C++ applications

Any C/C++ application’s service binding code needs to be done from the Java layer. For JNI code, add a service binding function to the activity that starts Tango. For native C/C++, add the service binding function to the NativeActivity wrapper in Java. For more information, see the Android NativeActivity documentation.

We wrapped most of the binding functionality in TangoInitializationHelper.java in the C example code. We suggest that you reuse this part of the code without change. Note that Tango functions, including getting and setting ADF metadata and setting up the Tango configuration, can only be called after the service is bound.

To use TangoInitializationHelper, in the Activity class, add the following code:

// Tango Service connection.
ServiceConnection mTangoServiceConnection = new ServiceConnection() {
  public void onServiceConnected(ComponentName name, IBinder service) {
    // Synchronization around HelloMotionTrackingActivity object is to avoid
    // Tango disconnect in the middle of the connecting operation.
    synchronized (HelloMotionTrackingActivity.this) {
      // Set binder object to C API through JNI
      // Call TangoService_setBinder(env, service);

      // At this point we could call Tango functions.
      // For example:
      // TangoService_connect(config);
    }
  }
  public void onServiceDisconnected(ComponentName name) {
    // Handle this if you need to gracefully shut down/retry in the event
    // that Tango itself crashes/gets upgraded while running.
  }
};

@Override
protected void onResume() {
  super.onResume();
  TangoInitializationHelper.bindTangoService(this, mTangoServiceConnection);
}

@Override
protected void onPause() {
  super.onPause();
  synchronized (this) {
    unbindService(mTangoServiceConnection);
  }
}

Java applications

Java applications need the Tango Mira release libtango_client.jar. It contains the new Tango constructor function:

 Tango mTango;

 @Override
 protected void onResume() {
   super.onResume();

   // Initialize the Tango Service as a normal Android Service.
   // Since we call mTango.disconnect() in onPause, this will unbind the
   // Tango Service, so every time onResume is called, we should
   // create a new Tango object.
   mTango = new Tango(MotionTrackingActivity.this, new Runnable() {
       // Pass in a Runnable to be called from UI thread when Tango
       // is ready. This Runnable will be running on a new thread.
       // When Tango is ready, we can call Tango functions
       // safely here only when there are no UI thread changes involved.
       @Override
       public void run() {
         // Set up and start Tango.
         TangoConfig config = mTango.getConfig(mConfig.CONFIG_TYPE_CURRENT);
         mTango.connect(mConfig);
       }
     });
 }

 @Override
 Protected void onPause() {
   super.onPause();
   // Unbind the Tango Service. If you don't, you'll get a
   // service leak exception.
   mTango.disconnect();
 }

Unity applications

Unity developers need to import the Tango Mira release TangoUnitySDK.unitypackage. There are no code changes needed.