CXR-L(EN)
cxr-l-sdk · v1.0.1 · snapshot 2026-05-13· ↗ source

Glasses Custom APP

Android: Glasses-side Custom App

Scenario

In a CUSTOMAPP session, specify the target glasses-side package name and use the SDK on the glasses to query installation status, upload & install an APK, start an Activity, stop, and uninstall. In CXRLSample, the target package is com.rokid.cxrswithcxrl and the entry Activity is .activities.main.MainActivity (see CONSTANT).

Prerequisites

  • You have completed “Connection and Session”, and configCXRSession uses CUSTOMAPP with the correct packageName.
  • IGlassAppCbk is registered to receive asynchronous results.

Key APIs

MethodDescription
appIsInstalled(IGlassAppCbk)Query whether the target package is installed.
appUploadAndInstall(apkAbsolutePath, IGlassAppCbk)Upload a local APK and install it.
appStart(entryUriOrComponent, IGlassAppCbk)The Sample starts using the form ”${packageName}${MAIN_PAGE}”.
appStop(IGlassAppCbk)Request to stop the app.
appUninstall(IGlassAppCbk)Request to uninstall.

Callbacks (IGlassAppCbk)

Handled by CustomAppTypeViewModel in the Sample:

  • onInstallAppResult: on success, calls checkApkInstalled again; on failure, clears the “installing” state.
  • onOpenAppResult / onStopAppResult / onGlassAppResume: maintains “app in foreground” style states.
  • onQueryAppResult: updates _appInstalled.
  • onUnInstallAppResult: logs.

APK path resolution (Sample)

installApp() tries readable files returned by resolveInstallApkCandidates() in order:

  1. context.getExternalFilesDir(“DCIM/Rokid”)/cxrL.apk
  2. context.filesDir/cxrL.apk
  3. Hardcoded /sdcard/DCIM/Rokid/cxrL.apk
  4. Environment.getExternalStoragePublicDirectory(“DCIM/Rokid”)/cxrL.apk

Integration recommendation: choose an app-specific directory for APK storage according to your target Android versions to avoid read failures under Scoped Storage. Use runCatching for appUploadAndInstall to capture FileNotFoundException (the Sample already demonstrates this).

Constraints

  • packageName and the entry Activity must match the glasses-side APK Manifest.
  • For large APK installs, consider Bluetooth bandwidth and timeouts/retry strategy (business-layer implementation).
  • In the Sample, custom commands (see “Custom Command”) are demonstrated only when using the same CXRLink instance for this session.
  • Scene building: only after openApp succeeds and the glasses-side app is interactive (in the Sample, appOpened == true maintained via IGlassAppCbk) should you enter Audio, Photo, and Custom Command (CustomAppTypeScreen shows these entry buttons only when appOpened is true).

Sample reference paths

  • activities/customAppType/CustomAppTypeViewModel.kt
  • dataBean/CONSTANT.kt (APP_PACKAGE_NAME, MAIN_PAGE)
Marcin Miazga