# Duooomi Android BLE SDK Duooomi 蓝牙 BLE SDK 的 Android 版本。 ## 环境要求 **SDK 集成要求(消费方最低版本):** | 项目 | 最低要求 | |------|---------| | Kotlin | 1.9.0+ | | AGP | 7.4.2+ | | minSdk | 23 (Android 6.0) | | JDK | 11+ | **SDK 开发构建环境:** | 项目 | 要求 | |------|------| | Android Studio | Hedgehog (2023.1.1) 或更高 | | Kotlin | 1.9.22 | | AGP | 8.2.2 | | Gradle | 8.x | | JDK | 17 | | compileSdk / targetSdk | 34 | ## 项目结构 ``` duooomi-android-sdk/ ├── sdk/ # SDK 库模块 (com.android.library) │ └── src/main/kotlin/com/duooomi/ble/ │ ├── DuooomiBleSDK.kt # 公开 API 入口 │ ├── DuooomiBleConfig.kt # SDK 配置 │ ├── core/ # BLE 核心层 (BleClient, 类型定义, 错误类型) │ ├── protocol/ # BLE 协议层 (帧格式, UUID, 协议管理) │ ├── services/ # 服务层 (设备信息, 文件传输, ANI转换, 固件) │ ├── models/ # 数据模型 │ └── utils/ # 日志工具 ├── demo/ # 演示 App (Jetpack Compose) └── build.gradle.kts ``` ## 依赖 SDK 仅依赖一个外部库: ``` org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3 ``` 其余全部使用 Android 内置 API(BLE、JSON、HttpURLConnection)。 ## 快速开始 ### 1. 引入 SDK 在 `settings.gradle.kts` 中: ```kotlin include(":sdk") ``` 在 app 模块的 `build.gradle.kts` 中: ```kotlin dependencies { implementation(project(":sdk")) } ``` ### 2. 添加权限 在 `AndroidManifest.xml` 中添加: ```xml ``` > **注意:** 运行时仍需动态申请 `BLUETOOTH_SCAN`、`BLUETOOTH_CONNECT`(Android 12+)和 `ACCESS_FINE_LOCATION` 权限。 ### 3. 初始化 SDK ```kotlin val sdk = DuooomiBleSDK( context = this, config = DuooomiBleConfig( apiKey = "YOUR_API_KEY" ) ) ``` ### 4. API Key 说明 | 参数 | 说明 | |------|------| | `apiKey` | **必填**。用于 ANI 转换和固件查询等后端 API 鉴权。| | `apiHost` | 默认 `https://api.duooomi.com`,一般无需修改 | | `cdnHost` | 默认 `https://cdn.bowong.cc/`,一般无需修改 | | `firmwareIdentifier` | 默认 `duomi`,设备固件标识符 | | `firmwareStatus` | 默认 `DRAFT`,可选 `PUBLISHED` | | `aniWidth` | ANI 转换宽度,默认 `360` | | `aniHeight` | ANI 转换高度,默认 `360` | | `aniFps` | ANI 转换帧率,默认 `"24"` | ## API 参考 ### 可观察状态 (StateFlow) ```kotlin sdk.btState // ConnectionState: IDLE, SCANNING, CONNECTING, CONNECTED, ... sdk.discoveredDevices // List sdk.connectedDevice // DiscoveredDevice? sdk.deviceInfo // DeviceInfo? sdk.version // String sdk.isActivated // Boolean sdk.transferProgress // Int (0-100) sdk.error // String? ``` ### 扫描与连接 ```kotlin // 开始扫描 (自动过滤 Duooomi 设备) sdk.scan() // 停止扫描 sdk.stopScan() // 连接设备 (suspend) val device = sdk.connect(deviceId) // 断开连接 (suspend) sdk.disconnect() ``` ### 设备操作 (均需先连接) ```kotlin // 获取设备信息 val info = sdk.getDeviceInfo() // info.brand, info.name, info.size, info.powerlevel, info.freespace, info.allspace // 获取固件版本 val versionInfo = sdk.getVersion() // versionInfo.version, versionInfo.type // 绑定设备 val bindResult = sdk.bind(userId) // bindResult.sn, bindResult.contents (设备文件列表) // 解绑设备 sdk.unbind(userId) // 删除设备文件 sdk.deleteFile(fileKey) ``` ### 文件传输 ```kotlin // 传输媒体文件 (格式校验 → ANI 转换 → prepare → transfer) sdk.transferMedia(fileUrl) // 监听进度 sdk.transferProgress.collect { percent -> /* 0-100 */ } ``` **支持的媒体格式:** JPEG、PNG、GIF、MP4、WebM、WebP 格式校验规则: - 优先从 URL path 提取扩展名(自动忽略查询参数) - 无扩展名时通过 HEAD 请求检查 `Content-Type` - 不支持的格式抛出 `DuooomiBleError.UnsupportedFormat` ### 固件升级 ```kotlin // 查询最新固件 val firmware = sdk.fetchLatestFirmware(identifier, status) // firmware?.version, firmware?.fileUrl, firmware?.fileSize // 检查是否有新版本 (对比版本号末尾10位时间戳) val needUpdate = sdk.hasNewerFirmware( deviceVersion = sdk.version.value, // 当前设备版本 serverVersion = firmware?.version // 服务端最新版本 ) // 参数为空/null/格式不合法时返回 false // 执行 OTA 升级 sdk.upgradeFirmware(firmware.fileUrl) ``` ### 错误处理 所有 suspend 方法在失败时抛出 `DuooomiBleError`: ```kotlin try { sdk.connect(deviceId) } catch (e: DuooomiBleError.BluetoothNotPoweredOn) { /* 蓝牙未开启 */ } catch (e: DuooomiBleError.ConnectionFailed) { /* 连接失败 */ } catch (e: DuooomiBleError.NotConnected) { /* 未连接 */ } catch (e: DuooomiBleError.Timeout) { /* 超时 */ } catch (e: DuooomiBleError.PermissionDenied) { /* 权限不足 */ } ``` ## 运行 Demo ```bash # 构建 ./gradlew :demo:assembleDebug # 安装到设备 adb install demo/build/outputs/apk/debug/demo-debug.apk ``` ## BLE 协议简述 - **Service UUID:** `000002c4-0000-1000-8000-00805f9b34fb` - **Write Characteristic:** `000002c5-...` - **Read Characteristic (Notify):** `000002c6-...` - **帧格式:** `[head:1][type:1][subpageTotal:2][curPage:2][dataLen:2][data:N][checksum:1]` - **校验和:** 二进制补码 `(~sum + 1) & 0xFF` - **大数据分片:** 自动拆分,帧间延迟 35ms ## License Proprietary - Duooomi