Android phone-side CXR Bluetooth connection library for Rokid Glasses.
This project extracts the phone-side connection layer from jLink mobile work and keeps it focused on BLE scan, CXR endpoint resolution, Bluetooth connect, reconnect, disconnect, endpoint cache, state exposure, and a minimal sample app.
中文说明:这是一个面向 Android 手机端的 Rokid Glasses CXR 蓝牙连接库。它不是眼镜端项目,也不是 jLink 协作链路。
Included:
- CXR BLE scan for Rokid Glasses.
- CXR endpoint resolution through Rokid CXR SDK callbacks.
- Bluetooth connect, reconnect, disconnect, and lifecycle cleanup.
- Saved endpoint cache for reconnect.
StateFlowstate and device list exposure.- Stable failure model with
Failed(stage, code, detail). - XML sample app for local credential and connection checks.
Not included:
- jLink business messages.
- P2P.
- Janus or WebRTC.
- ADB.
- File transfer.
- Glasses-side app or bridge code.
- Rokid Security SDK classic Bluetooth.
- Glass3 model branching.
The screenshots below are captured from the sample app on a real Android phone. Device identifiers are redacted. They only prove the phone-side CXR Bluetooth layer and do not represent the full jLink collaboration stack.
| Ready / Disconnected | Connected |
|
|
| Credentials, permissions, Bluetooth, endpoint cache, and last error are visible. | The sample shows State: Connected after CXR Bluetooth connection succeeds. |
glasses-bt-core: reusable Android library.sample-app: plain Android XML/ViewBinding demo app.
Published artifact coordinates are intended to be:
implementation "xyz.jumu.rokid:glasses-bt-core:0.1.0-SNAPSHOT"During local development you can publish to Maven local:
./gradlew :glasses-bt-core:publishToMavenLocalWindows:
.\gradlew.bat :glasses-bt-core:publishToMavenLocalThe reusable artifact is produced from glasses-bt-core only. The sample app is not published.
The normal dependency path is:
com.rokid.cxr:client-m:1.2.1The Rokid Maven repository is:
https://maven.rokid.com/repository/maven-public/If the Rokid Maven endpoint is temporarily unavailable from a local machine, place an uncommitted fallback AAR at:
local-libs/client-m-1.2.1.aar
That file is ignored by git and is only used as a local development fallback.
Declare Bluetooth permissions in the consuming app. Android 12 and above require runtime Bluetooth permissions.
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />Use RokidGlassesBtPermission.requiredPermissions() to request the correct runtime permissions for the current Android version.
Real CXR credentials are not committed.
- Copy
local.properties.sampletolocal.properties. - Fill
ROKID_CLIENT_SECRET. - Point
ROKID_AUTH_BLOB_FILEto your local CXR auth blob.
ROKID_CLIENT_SECRET=your-client-secret
ROKID_AUTH_BLOB_FILE=/absolute/path/to/your-auth-blob.lc
ROKID_AUTH_BLOB_ASSET=rokid_cxr_auth.lcThe configured .lc file is copied into generated sample assets under sample-app/build/generated/rokid-auth-assets/ during local builds. The source tree still does not contain the real auth blob.
Manual fallback: if ROKID_AUTH_BLOB_FILE is empty, put your CXR auth blob at:
sample-app/src/main/assets/rokid_cxr_auth.lc
sample-app/src/main/assets/*.lc, local.properties, and local-libs/*.aar are ignored by git.
Run the explicit sample credential check only on machines with local Rokid credentials:
./gradlew :sample-app:verifyRokidSampleCredentialsWindows:
.\gradlew.bat :sample-app:verifyRokidSampleCredentialsThis check is not wired into normal compile tasks so CI and open-source builds do not depend on private credentials.
val manager = RokidGlassesBtManager(
context = context,
config = RokidGlassesBtConfig(
clientSecret = clientSecret,
authBlob = authBlobBytes,
bluetoothClientName = "My Rokid Glasses App"
)
)
manager.startScan()
manager.connect(device)
manager.reconnect()
manager.disconnect(clearSavedEndpoint = false)
manager.close()Observe state and scan results as flows:
manager.state.collect { state ->
when (state) {
RokidGlassesBtState.Connected -> showConnected()
is RokidGlassesBtState.Failed -> showError(state.code, state.detail)
else -> showProgress(state)
}
}
manager.devices.collect { devices ->
renderDevices(devices)
}Call manager.close() when the owning Activity, Fragment, or ViewModel is destroyed.
Normal fresh connection flow:
Idle -> Scanning -> ResolvingEndpoint -> Connecting -> Connected
Reconnect flow:
Idle or Disconnected -> Connecting -> Connected
Failure state:
RokidGlassesBtState.Failed(
stage = RokidGlassesBtStage.CONNECT,
code = RokidGlassesBtErrorCode.SOCKET_CONNECT_FAILED,
detail = "SDK_DETAIL"
)Use code for program decisions and detail for local diagnostics. Do not parse localized log strings.
Prefer these signals:
- Sample app shows
State: Connected. - CXR SDK logcat contains
BLUETOOTH_AVAILABLEandbluetooth connected. - CXR SDK logcat contains
getGlassInfo onResponse.
Do not rely only on dumpsys bluetooth_manager showing Connections: 0. Some CXR socket states are not reflected as a normal Android Bluetooth profile connection.
Useful logcat filter:
adb logcat -v time | grep -E 'CxrApi|CxrController|BluetoothController|BLUETOOTH_|getGlassInfo|connectBluetooth|initBluetooth'Redact secrets before sharing logs.
macOS/Linux:
./gradlew :glasses-bt-core:testDebugUnitTest :glasses-bt-core:compileDebugKotlin
./gradlew :sample-app:assembleDebugWindows:
.\gradlew.bat :glasses-bt-core:testDebugUnitTest :glasses-bt-core:compileDebugKotlin
.\gradlew.bat :sample-app:assembleDebugThis project does not distribute Rokid authorization files, auth blobs, CXR client secrets, private Maven credentials, internal jLink hosts, or glasses device credentials.
Runtime use depends on:
- Your own Rokid CXR credentials.
- Your own
.lcauth blob. - Rokid CXR SDK availability through Rokid Maven or a local uncommitted fallback AAR.
Apache-2.0

