Skip to main content

ProGlove documentation

Getting started with MAI integration

MAI companion device can be integrated using the same integration paths as all other ProGlove devices. For more general integration details about how to connect, configure, receive scanned barcode data, etc., refer to INSIGHT Mobile (Android) Integration.

Introduction to MAI integration

MAI integration is designed to be interactive, efficient, and simple to implement. This is achieved by simply displaying relevant information on the screen and receiving and reacting to user input from the workers.

Using different integration paths, screen templates with custom content can be set on MAI to inform workers about the workflow step(s), list content in a scrollable list, or notify them about an event. Also, when configuring the screen, four physical buttons can be assigned and used as an additional input from the worker.

Through the same integration paths, events can be received as inputs from the workers, so the integrator can build the flow efficiently. All features and event types available on other ProGlove devices are supported on MAI, such as scan event, button press event, etc., but MAI also supports additional screen events such as component clicked, data updated, etc.

Caution

Templates v1 that are explained in Display - SDK/Intent API are not recommended to be used with MAI. Templates v2 should be used instead.

However, all other display integration details explained in Display - SDK/Intent API apply to MAI.

Differences from other ProGlove devices

MAI companion device is our most advanced device yet. It is capable of much more than any other ProGlove device, while remaining wearable and maintaining an ergonomic form factor.

Display v2

One of the biggest hardware features of MAI is its display. Compared to our previous display device, MARK Display, which has an e-ink static display, MAI has a larger, touch-sensitive, color display. Since the improvement is significant, we consider the MAI display as Display v2.

This new display enables better content presentation and user interaction by:

Physical buttons

Besides Display v2, MAI has four physical buttons. They are located on the left and right side, two on each side.

These buttons can be assigned while setting the screen to be used as an additional input from the workers, especially in cases where touch-screen is not preferred. Since they are set for each screen (inside Set Screen Request), they are relevant for that screen only.

Distinguish MAI from other ProGlove devices

MAI connection status can be determined by first subscribing to display events to receive the display connection state. When a display connected event is received, the display type (v1 or v2) must be checked.

SDK
Display device connection state

Display connection states are received by subscribing to display events.

Subscribe by calling pgManager.subscribeToDisplayEvents() with your IDisplayOutput implementation. Override the callback methods of interest. The onDisplayConnected() callback is triggered when a display device connects, either v1 (e.g., MARK Display) or v2 (e.g., MAI).

Note that this subscribes not only to display connection state but to all display events as well, such as screen events (MAI-specific feature).

Make sure you unsubscribe from display events once you donʼt need them anymore to prevent memory leaks, e.g., inside the onDestroy or onClear callback functions.

Check the display device type

Since onDisplayConnected() is triggered when any display device is connected, the next step is to check which display device type is connected.

To check the type of the display that is connected, call pgManager.getConnectedDisplayType(). This function returns the DisplayType enum, where:

  • DisplayType.V1 represents Display v1 used in MARK Display (e-ink static display that supports Templates v1)

  • DisplayType.V2 represents Display v2 used in MAI (touch-sensitive color display)

  • DisplayType.NOT_DISPLAY_DEVICE is returned when the connected device is not a display device (e.g., MARK 3)

  • DisplayType.NOT_CONNECTED is returned when there is no device connected

  • DisplayType.UNKNOWN is returned when there is no clear information if a display device is connected, or which display device type is connected (usually when the latest SDK version is used along with an old version of INSIGHT Mobile)

Checking the connected display type by calling the pgManager.getConnectedDisplayType() is safe to be done anywhere in the code.

Code example (Kotlin)
//...

val displayOutput = object : IDisplayOutput {

    override fun onDisplayConnected() {
        val displayType = pgManager.getConnectedDisplayType()
        when (displayType) {
            DisplayType.V1 -> {
                // Inform the user that a Display v1 device is connected (MARK Display)
               }
            DisplayType.V2 -> {
                // Inform the user that a Display v2 device is connected (MAI)
            }
            DisplayType.NOT_DISPLAY_DEVICE -> {
                // Inform the user that the connected device is not a display device
            }
            DisplayType.NOT_CONNECTED -> {
                // Inform the user that there is no device connected
            }
            DisplayType.UNKNOWN -> {
                // No clear information about connected display device type.
                // If you receive this, you should probably update
                // INSIGHT Mobile and SDK to the latest version.
            }
        }
    }

    override fun onDisplayDisconnected() {
        // Inform the user that the display has been disconnected
    }
}

override fun onCreate(savedInstanceState: Bundle?) {
    //...
    pgManager.subscribeToDisplayEvents(displayOutput)

    //...
}

override fun onDestroy() {
    super.onDestroy()
    pgManager.unsubscribeFromDisplayEvents(displayOutput)

    //...
}

//...
Intent
Display device connection state and display device type

Display connection state can be read from the implicit Intent with:

  • Action: com.proglove.api.DISPLAY_STATE

  • Extras:

    Extra Key

    Extra Value Type

    Description

    com.proglove.api.extra.DISPLAY_STATE

    String

    • CONNECTED - Display device is connected, either v1 (e.g., MARK Display) or v2 (e.g., MAI)

    • DISCONNECTED - Display device is disconnected. Note that this is returned if there is a non-display device connected (e.g., MARK 3, LEO etc.)

    • Other less important states: SEARCHING, CONNECTING, RECONNECTING, ERROR

    com.proglove.api.extra.DISPLAY_DEVICE_TYPE

    String

    • DISPLAY_V1 - Represents Display v1 used in MARK Display (e-ink static display that supports Templates v1)

    • DISPLAY_V2 - Represents Display v2 used in MAI (touch-sensitive color display)

    • NOT_DISPLAY_DEVICE - Returned when connected device is not a display device (e.g., MARK 3)

    • NOT_CONNECTED - Returned when there is no device connected

    • UNKNOWN - Returned when there is no clear information if a display device is connected, or which display device type is connected (usually when an old version of INSIGHT Mobile is used)

This Intent is received after the display device connection state is changed or after requesting the state by broadcasting an implicit Intent with action com.proglove.api.GET_DISPLAY_STATE.

To request just the connected display type without the state info, broadcast an implicit Intent with action com.proglove.api.GET_DISPLAY_DEVICE_TYPE. Response will be sent in the implicit Intent with action com.proglove.api.DISPLAY_DEVICE_TYPE and relevant extras from the table above.

Code example (Kotlin)
//...

// 1. Implement a broadcast receiver:
val broadcastReceiver = object : BroadcastReceiver() {

    override fun onReceive(context: Context?, intent: Intent?) {
        if (intent != null && intent.action == "com.proglove.api.DISPLAY_STATE") {
            val displayState = intent.getStringExtra("com.proglove.api.extra.DISPLAY_STATE")
            if (displayState != null) {
                // use displayState
                when (displayState) {
                    "CONNECTED" -> {
                        val displayType = intent.getStringExtra("com.proglove.api.extra.DISPLAY_DEVICE_TYPE")
                        when (displayType) {
                            "DISPLAY_V1" -> {
                                // Inform the user that a Display v1 device is connected (MARK Display)
                            }
                            "DISPLAY_V2" -> {
                                // Inform the user that a Display v2 device is connected (MAI)
                            }
                            "NOT_DISPLAY_DEVICE" -> {
                                // Inform the user that the connected device is not a display device 
                            }
                            "NOT_CONNECTED" -> {
                                // Inform the user that there is no device connected
                            }
                            "UNKNOWN" -> {
                                // No clear information about connected display device type.
                                // If you receive this, you should probably update
                                // INSIGHT Mobile to the latest version.
                            }
                        }
                    }
                    "DISCONNECTED" -> {
                        // Inform the user that the display has been disconnected
                    }
                    else -> {
                        // remaining display states
                    }
                }
            }
        }
    }
}

// 2. Define an `IntentFilter` for the desired actions:
val filter = IntentFilter().apply {
    filter.addAction("com.proglove.api.DISPLAY_STATE")
    filter.addCategory(Intent.CATEGORY_DEFAULT)
}

// 3. Finally, register the broadcast receiver instance. The usual place for this call would be in the `onCreate` method of a
`Service` or an `Activity` class:
override fun onCreate(savedInstanceState: Bundle?) {
    //...
    registerReceiver(broadcastReceiver, filter)

    //...
}

// 4. Do not forget to unregister the receiver, for example in `onDestroy`:
override fun onDestroy() {
    super.onDestroy()
    unregisterReceiver(broadcastReceiver)

    //...
}


//..