Skip to content

Basic Usage

This section describes the VIRNECT Track setup for Android application development with Android Studio. All code samples are written in Kotlin.

Scope

This guide describes the essential module integration and initialization of VIRNECT Track for an existing Application. This guide does not cover visualization of tracking results.

1. Import Library

  • Open or create a Android Studio project
  • Download the AAR library and extract the libraries to the lib folder of the project
  • Add the lines
    implementation files('libs/Track-1.7.0.aar')
    implementation files('libs/Track-Hardware-1.7.0.aar')
    to the build.gradle file of your app
  • Perform a gradle-sync

After setting up the project configuration, import VIRNECT Track to your APP with the following statement:

import com.virnect.Track

2. Request Permissions

Please ensure to request the following APP permissions before using VIRNECT Track in your APP.

  • CAMERA needed to access the back-facing camera
  • WRITE_EXTERNAL_STORAGE needed to write target files to cache
  • READ_EXTERNAL_STORAGE needed to read target files from file system or cache

3. Register the License Key

To enable usage of the Track framework, your License Key needs to be registered first:

// Set license key
Track.setLicenseKey(licenseKey)

Calling this method will perform a network request to check the validity of your key.

Internet access required

Your APP always needs internet access to validate the license key before running the Track framework.

How to improve key security

When your source code is managed via a version control software (e.g. git), the defined license key might be exposed. Also, when the application is compiled without further code obfuscation, the API key may be extracted with reverse-engineering attacks. To protect your license key, we strongly encourage you to encrypt your license key instead of saving it as clear text.

4. Specify Tracking Targets

Download or train one or multiple trackable targets. See Section Target Trainer for more detail.

To specify which targets should be tracked, use the designated Target name without the .track extension.

// Setup Target configuration for framework
Track.setTargetNames(arrayOf<String>("TRACK_IMAGE_000", "TRACK_QR_Code_000"))

Place the target files in a designated targets folder on your device, or add them to a resources folder of your APP:

Access targets directly if they are saved on the device:

// Use direct path to file system
Track.setTargetDataPath("/sdcard/TrackTargets/")

Use the FileAccessHelper for targets embedded as a resource:

import com.virnect.FileAccessHelper

// Copy target files from APP assets to cache directory 
Track.setTargetDataPath(FileAccessHelper.prepareTargetData(this, "assetPath/targetFolder/"))

5. Initialize the Framework

After setting up the configuration, initialize the framework with the application context

// Initialize Track framework
val success = Track.initialize(context)

The initialize function returns the result of the initialization process. If the function returns false, determine the reason by retrieving the retrieving the framework log messages.

Framework initialization enables the back-facing camera as an image source. Each camera frame is processed by the Track framework automatically.

To use a file sequence as an image source please refer to this guide.

6. Register a Callback Function

Register a callback function to retrieve the latest tracking result. The framework calls this function after processing each frame.

// Define callback function
val callbackFunction  = Runnable{
    // Prepare target result array from "targets" string array
    val trackerResults = targets.map { Common.TrackerResult(it) }.toTypedArray()

    // Retrieve tracking results with empty array
    Track.getTrackingResult(trackerResults)

    // Initialize result placeholder
    var logText = ""

    // Get status log for each tracking result
    for (i in trackerResults.indices) 
        trackerResults[i].also {
            logText += "%s - %s\n".format(it.mTargetName, it.mStatus.name)
        }

    // Display tracking result as text
    runOnUiThread {
        TextView.text = logText;
    }
}

Track.setProcessingCallback(callbackFunction)

Warning

Note that any UI access from within the callback is restricted and needs to be performed on the UI thread.

7. Start processing

Call Track.startProcessing() to start VIRNECT Track, Track.stopProcessing() to stop again.

8. Handle Android Lifecycle Events

To comply with the Android Activity Lifecycle, stop the processing loop of the tracking framework when the app gets paused. When the app exits, the framework needs to be closed to free all resources:

/**
 * Stop processing on pause
 */
override fun onPause() {
    super.onPause()
    Track.stopProcessing()
}

/**
 * Free all resources on destruction
 */
override fun onStop() {
    super.onStop()
    Track.close()
}

Minimum working example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// by VIRNECT CO., LTD.

import android.content.Context
import android.widget.TextView
import com.virnect.Common
import com.virnect.Track

// Declare list of trackable targets
val targets=arrayOf("TRACK_IMAGE_000")

fun initializeAndStartTrackFramework( context: Context){
    // Set license key
    Track.setLicenseKey("XXXX-XXXX-XXXX-XXXX")
    // Setup Target configuration for framework
    Track.setTargetNames(targets)
    // Use direct path to file system
    Track.setTargetDataPath("/sdcard/target/")
    // Initialize Track framework
    Track.initialize(context)
    // Define callback function
    val callbackFunction  = Runnable{
        // Prepare target result array from "targets" string array
        val trackerResults = targets.map { Common.TrackerResult(it) }.toTypedArray()
        // Retrieve tracking results with empty array
        Track.getTrackingResult(trackerResults)
        // Initialize result placeholder
        var logText = ""
        // Get status log for each tracking result
        for (i in trackerResults.indices)
            trackerResults[i].also {
                logText += "%s - %s\n".format(it.mTargetName, it.mStatus.name)
            }
        // Display tracking result as text
        runOnUiThread {
            findViewById<TextView>(R.id.textView).text = logText;
        }
    }
    // Add callback function
    Track.setProcessingCallback(callbackFunction)
    // Start framework
    Track.startProcessing()
}