Secondary Display SDK

Secondary Display SDK

The Secondary Display SDK lets Android applications display content on the customer-facing screen of supported Dejavoo dual-display terminals. Integrators can initialize the display, show images or custom Android views, clear the screen, and release the display when it is no longer needed.

Prerequisites

Before using the Secondary Display SDK, ensure you have the following:

For Sandbox (UAT)

Users should be onboarded on the iPOSpays sandbox (UAT) environment as a merchant and have a valid TPN.

For Production (Live)

Users should be onboarded on the iPOSpays production environment as a merchant and have a valid TPN.

If you do not have a TPN, contact your ISO or devsupport@dejavoo.io.

The peripheral_sdk_v5.0.aar file is provided with the kit. Download from here (opens in a new tab)

Downloading the Secondary Display SDK

  1. Locate the peripheral_sdk_v5.0.aar (opens in a new tab) file provided with your Secondary Display SDK kit.
  2. Copy the file to your Android project.
  3. Place the file in the project's libs folder.

Configuring Gradle Dependencies

Open your module-level build.gradle file and add the SDK inside the dependencies block:

implementation files "libs/peripheral_sdk_v5.0.aar"

Synchronize Gradle

In Android Studio, select Sync Project with Gradle Files.

This loads the Secondary Display SDK and makes its APIs available to your application.

Initialize the Secondary Display

Create one SecondaryDisplay instance and keep it for the screen or application lifecycle.

Initialization is asynchronous. Wait for the initialization callback to confirm that the display is ready before calling showImage(), showView(), or clear().

private val secondaryDisplay = SecondaryDisplay()
 
secondaryDisplay.init(applicationContext) { code, message ->
    runOnUiThread {
        if (code == 0 && secondaryDisplay.isReady) {
            // Ready to show an image or view
        } else {
            Log.e("SecondaryDisplay", "Init failed: $code $message")
        }
    }
}

Do not call isReady() immediately after init(). Wait for the initialization callback and confirm that code == 0 and the display is ready.

Display an Image

Use showImage() to display a PNG or GIF image on the secondary display. The method requires an absolute file path to the image.

Storage Permissions

No storage permission is required when using app-owned files, such as files stored in filesDir or cacheDir.

If the application reads images directly from shared storage, declare and request the permission appropriate for the Android version:

<uses-permission
    android:name="android.permission.READ_EXTERNAL_STORAGE"
    android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

For better compatibility with Android scoped storage, copy packaged assets or user-selected content into an app-owned file and pass the absolute path to showImage().

val imagePath = File(filesDir, "customer_ad.gif").absolutePath
 
val code = secondaryDisplay.showImage(imagePath)
if (code != 0) {
    Log.e("SecondaryDisplay", "showImage failed: $code")
}

Recommended image size: Match the physical resolution of the secondary display. For the P8 integration sample, use 378 × 172 pixels to avoid unexpected scaling or cropping.

Display a Custom View

Use showView() to display a custom Android view hierarchy on the secondary display. The SDK measures and lays out the view based on the detected secondary-display resolution. Create and submit views on the main thread.

private fun showWelcomeView() {
    val root = LinearLayout(this).apply {
        orientation = LinearLayout.VERTICAL
        gravity = Gravity.CENTER
        setBackgroundColor(Color.WHITE)
        layoutParams = ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT
        )
    }
 
    root.addView(TextView(this).apply {
        text = "Welcome"
        textSize = 26f
        gravity = Gravity.CENTER
        setTextColor(Color.BLACK)
        setTypeface(typeface, Typeface.BOLD)
    })
 
    root.addView(TextView(this).apply {
        text = "Thank you for shopping with us"
        textSize = 14f
        gravity = Gravity.CENTER
        setTextColor(Color.DKGRAY)
    })
 
    val code = secondaryDisplay.showView(root)
    if (code != 0) {
        Log.e("SecondaryDisplay", "showView failed: $code")
    }
}

Clear the Display

Use clear() to replace the currently displayed image or view with a blank screen.

val code = secondaryDisplay.clear()
if (code != 0) {
    Log.e("SecondaryDisplay", "clear failed: $code")
}

Calling clear() does not make the SDK instance unusable. You can continue using the instance after clearing the display.

Release Resources

Use release() when the hardware connection is no longer needed. This releases the secondary-display service and associated resources.

Release the SDK when the lifecycle that owns the display ends or when the application intentionally stops using the secondary display.

override fun onDestroy() {
    secondaryDisplay.release()
    super.onDestroy()
}

After calling release(), you must initialize the SDK again and wait for the initialization callback before displaying new content.

secondaryDisplay.release()
 
secondaryDisplay.init(applicationContext) { code, message ->
    if (code == 0 && secondaryDisplay.isReady) {
        secondaryDisplay.showImage(imagePath)
    }
}

Lifecycle rule: Do not call showImage(), showView(), or clear() after release() until a new initialization callback confirms that the display is ready.

Complete Integration Example

The following examples show how to initialize the SDK, display content, clear the display, and release resources.

class CustomerDisplayActivity : AppCompatActivity() {
 
    private val display = SecondaryDisplay()
    private var pendingAction: (() -> Unit)? = null
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initializeDisplay()
    }
 
    private fun initializeDisplay() {
        display.init(applicationContext) { code, message ->
            runOnUiThread {
                val action = pendingAction
                pendingAction = null
 
                if (code == 0 && display.isReady) {
                    action?.invoke()
                } else {
                    Log.e("SecondaryDisplay", "Init failed: $code $message")
                }
            }
        }
    }
 
    private fun whenDisplayReady(action: () -> Unit) {
        if (display.isReady) {
            action()
        } else {
            pendingAction = action
            initializeDisplay()
        }
    }
 
    fun showImage(path: String) = whenDisplayReady {
        val code = display.showImage(path)
        if (code != 0) Log.e("SecondaryDisplay", "showImage: $code")
    }
 
    fun showView(view: View) = whenDisplayReady {
        val code = display.showView(view)
        if (code != 0) Log.e("SecondaryDisplay", "showView: $code")
    }
 
    fun clearAndRelease() {
        if (display.isReady) {
            display.clear()
            display.release()
        }
    }
 
    override fun onDestroy() {
        pendingAction = null
        if (display.isReady) display.release()
        super.onDestroy()
    }
}

API Methods

MethodDescription
init(Context)Starts asynchronous initialization of the secondary display without a result callback.
init(Context, InitCallback)Starts asynchronous initialization and provides a callback when initialization completes. This is the preferred overload.
isReady()Returns true when the secondary display is initialized and ready to receive display commands.
showImage(String)Displays a PNG or GIF image using an absolute file path.
showView(View)Displays a custom Android view hierarchy on the secondary display.
clear()Clears the current content and displays a blank screen.
release()Releases the secondary-display service and associated resources.

Error Codes

CodeMeaningAction
0Request accepted successfully.No action required.
-1Invalid input or general operation failure.Check the context, file path, view, and device logs.
-2Unsupported image extension.Use a PNG or GIF image.
-10SDK is not initialized or the display is not ready.Call init() and wait for the successful initialization callback.
Other non-zeroDevice- or driver-specific failure.Record the error code and collect Logcat output.