For several gaze-based MdkTargets, such as EyeMovementML, EyePull, and EyeJoyStick, the mdk may not function properly unless the state of looking at the screen center is obtained as a reference value within the app process—or a previously acquired reference value is saved and passed into MdkOptions. Since the process of acquiring this reference point must be implemented separately from the usual MdkTarget implementation, please take care.

This document explains the specific method for doing so.

Acquiring and Registering the Reference Value

Prepare a dedicated screen for acquiring the reference value, and add MdkView to that screen.

@Composable
fun CalibrationScreen(
    modifier: Modifier = Modifier,
) {
    Box(
        modifier = modifier.fillMaxSize()
    ) {
        // Add MdkView here
        
        // Additional UI components for calibration can be added here
    }
}

Add one of the MdkTargets, RegisterCenterReference, as an active target.

private val reference = MdkTarget.RegisterCenterReference // <- Added

@Composable
fun CalibrationScreen(
    modifier: Modifier = Modifier,
) {
    Box(
        modifier = modifier.fillMaxSize()
    ) {
        MdkView( // <- Added
		        modifier = Modifier.size(100.dp).alpha(0f),
            options = MdkOptions.Builder()
                .setEnabledMdkTargets(
                    setOf(
                        reference,
                    )
                )
                .build()
        
        
        // Additional UI components for calibration can be added here
    }
}

While an MdkView with the target MdkTarget.RegisterCenterReference is running, call the function MdkCalibration.registerCenterReference() to register the reference value. When calling this function, you must first prompt the user to look at the center of the screen.

Please note that the registered reference value will be reset when the app process restarts. (See below for how to save it.)

This function is a suspend function, so you need to account for a delay until it completes. Once the acquisition is complete, the onFinished callback will be invoked. .registerCenterReference() : 1 second (default value; can be changed via arguments)

When using Jetpack Compose, it is common to execute this in LaunchedEffect or similar.

private val reference = MdkTarget.RegisterCenterReference

@Composable
fun CalibrationScreen(
    modifier: Modifier = Modifier,
) {
    Box(
        modifier = modifier.fillMaxSize()
    ) {
        MdkView(
		        modifier = Modifier.size(100.dp).alpha(0f),
            options = MdkOptions.Builder()
                .setEnabledMdkTargets(
                    setOf(
                        reference,
                    )
                )
                .build()
        
        LaunchedEffect(Unit) { // <- Added
            delay(1000L) // <- Adding a delay is recommended
            MdkCalibration.registerCenterReference { ref ->
		            // Do something with registered reference value
                println("New reference point saved $ref")
            }
        }
        
        // Additional UI components for calibration can be added here
    }
}

Saving the Reference Value

Since re-acquiring the reference value every time the app launches is cumbersome, it is recommended to store the value locally. Below is an implementation example using SharedPreferences. Saving is easy when using Gson.

object Preferences(context: Context) {
    private lateinit var preferences: SharedPreferences
    fun init(context: Context) {
        preferences = context.getSharedPreferences("mdk_prefs", Context.MODE_PRIVATE)
    }
    
    private val gson = Gson()

		// Save CenterReference value
    private val CENTER_REFERENCE_LOCAL = "center_reference_local"
    var centerReferenceLocal: MdkFaceForReference?
        get() {
            val json = preferences.getString(CENTER_REFERENCE_LOCAL, null)
            return json?.let {
                gson.fromJson(it, MdkFaceForReference::class.java)
            }
        }
        set(value) {
            preferences.edit {
                if (value == null) {
                    remove(CENTER_REFERENCE_LOCAL)
                } else {
                    putString(CENTER_REFERENCE_LOCAL, gson.toJson(value))
                }
            }
        }
}

Using the Reference Value

The saved reference value can be passed as an Option for the MdkTarget, allowing its behavior to account for that reference.

For example, with MdkTarget.EyeMovementML, you can pass it as follows:

private val movementML = MdkTarget.EyeMovementML

@Composable
fun SampleScreen(
    modifier: Modifier = Modifier,
) {
    Box(
        modifier = modifier.fillMaxSize()
    ) {
        MdkView(
            modifier = Modifier.size(100.dp).alpha(0f),
            options = MdkOptions.Builder()
                .setEnabledMdkTargets(
                    setOf(
                        movementML,
                    )
                )
                .setActionParams(
                    movementML,
                    MdkOptions.MovementMLActionParams(
		                    // Set reference here
                        centerReference = Preferences.centerReferenceLocal
                    )
                )
                .build()
        )

        // Additional UI components for screen can be added here
    }
}