Skip to content

Android

🚀 准备工作

硬件连接指引

有关头环设备的开关机操作、状态指示灯含义及各端 SDK 的设备配对说明,请在开发前优先查阅:设备使用说明与常见问题 (FAQ)

⚠️ 真机调试限制

由于 Android 官方模拟器(Emulator)本身不支持蓝牙底层硬件驱动,如需进行真实的物理设备联调(非纯 Mock 数据调试),请务必使用连接数据线的 Android 真机运行演示应用及您的业务工程,否则在扫描外设时将始终返回空数据,或在调用蓝牙接口时直接抛出环境报错。

编译环境要求

  • 宿主工程的 minSdkVersion 必须设置为 21 (Android 5.0) 或更高,方可支持本 SDK 的编译与运行。

安装和集成

导入 SDK

我们为您提供了在线 Maven 仓库引入(推荐)和本地 AAR 引入两种方式,请根据您的网络情况选择其一。

方式一:通过 Maven 仓库引入(推荐)

1. 配置仓库地址
编辑工程根目录层级的 build.gradle(或新版本 AS 的 settings.gradle),加入私服仓库凭证:

groovy
repositories {
    maven {
        credentials {
            username '<maven-username>'
            password '<maven-password>'
        }
        url = "https://nexus.ci.brainco.cn/repository/maven-public"
    }
}

2. 添加远程依赖
在应用模块层级(通常是 app/build.gradle)中引入 SDK 依赖:

groovy
dependencies {
    implementation 'tech.brainco:zenlitejna:1.5.2'
}

方式二:通过本地 AAR 引入(备选)

如果您不便使用私有 Maven 仓库,也可以将 SDK 下载到本地集成:

  1. 下载最新包zenlitejna-release.aar
  2. 放置文件:将下载好的 .aar 文件拷贝进入您的 App 模块下的 libs 目录。
  3. 添加本地依赖:编辑您的应用模块 build.gradle
groovy
dependencies {
    implementation files('libs/zenlitejna-release.aar')
}

同步与运行

无论您选择上述哪种引入方式,配置好后:

  1. 同步 Gradle:在 Android Studio 中点击右上角的 "Sync Now" 重新同步工程配置。
  2. 测试运行:连接 Android 真机并点击 Run,即可验证 SDK 是否引入成功。

所需权限

AndroidManifest.xml 中添加:

xml
<!-- 蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

<!-- 位置权限(Android 6.0+ 扫描 BLE 设备需要) -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<!-- 蓝牙功能 -->
<uses-feature
    android:name="android.hardware.bluetooth_le"
    android:required="true" />

API 核心组件参考

💡 SDK 架构说明

OxyZen Android SDK 在架构上划分为以下两个模块(代码中的 ZenLite 前缀为产品曾用名,包名与类名保持向后兼容):

  1. zenlitejna(通过 Maven 或本地 AAR 引入):闭源的核心引擎,负责蓝牙原始数据解析、信号滤波及各类算法指标(如专注度、冥想指数、睡眠分期等)的计算与输出。
  2. zenliteble(蓝牙通信层):负责设备扫描、连接管理与指令交互。该模块的完整源码已在 示例工程 中公开,开发者可根据自身需求对扫描策略、连接保活等逻辑进行自定义修改,也可以将其整体替换为自己的 BLE 通信实现。

ZenLiteSDK (Class)

全局 SDK 基础配置管理:

java
public class ZenLiteSDK {
    // 设置日志级别
    public static void setLogLevel(int level);
}

ZenLiteScanner (Class)

用于设备扫描和管理的主要扫描类:

java
public class ZenLiteScanner {
    // 扫描状态
    public static boolean isScanning;

    // 开始/停止扫描
    public static void startScan(BleScannerListener listener);
    public static void startScan(BleScannerListener listener, List<ScanFilter> filters);
    public static void stopScan();

    // 注册/注销蓝牙状态接收器
    public static void registerBLEStateReceiver(Context context);
    public static void unregisterBLEStateReceiver(Context context);
}

ZenLiteDevice (Class)

封装设备控制和数据通信的核心设备对象:

java
public class ZenLiteDevice {
    // 连接
    public void connect(Context context);
    public void disconnect();
    public boolean isConnected();
    public boolean isNotConnected();

    // 配对
    public void pair(ZenLiteResponseCallback callback);
    public void validatePairInfo(ZenLiteResponseCallback callback);

    // EEG 数据流
    public int startEEG(ZenLiteResponseCallback callback);
    public int stopEEG(ZenLiteResponseCallback callback);

    // IMU 数据流
    public int startIMU(ZenLiteResponseCallback callback);
    public int stopIMU(ZenLiteResponseCallback callback);

    // PPG 数据流
    public int startPPG(PPGSampleRate sr, ZenLiteResponseCallback callback);
    public int stopPPG(ZenLiteResponseCallback callback);

    // 设备设置
    public int setDeviceName(String name, ZenLiteResponseCallback callback);
    public int setSleepIdleTime(int timeSec, ZenLiteResponseCallback callback);

    // 固件升级
    public boolean isNewFirmwareAvailable();
    public void startDfu(Context context, DFUCallback callback);
    public void abortDfu();

    // 设备状态
    public boolean isInPairingMode();
    public boolean isInNormalMode();
    public int getContactState();
}

ZenLiteDeviceListener (Interface)

用于接收设备数据的数据回调监听器:

java
public interface DeviceListener {
    // 错误处理
    void onError(ZenLiteError error);

    // 连接状态
    void onConnectivityChange(Connectivity connectivity);

    // 接触状态(在 startEEG 后调用)
    void onContactStateChange(ContactState contactState);

    // 方向(在 startIMU 后调用)
    void onOrientationChange(Orientation orientation);

    // 设备信息
    void onDeviceInfoReady(DeviceInfo info);

    // 电池电量(0-100,-1 = 未知)
    void onBatteryLevelChange(int batteryLevel);

    // IMU 数据
    void onIMUData(IMU data);

    // PPG 数据(心率、血氧、呼吸等)
    void onPPGData(PPG data);

    // EEG 数据(滤波后)
    void onEEGData(EEG data);

    // 原始 EEG 数据(未滤波)
    void onRawEEGData(EEG data);

    // 脑波数据
    void onBrainWave(BrainWave wave);

    // 专注度指数
    void onAttention(float attention);

    // 冥想指数
    void onMeditation(float meditation, float calmness, float awareness);

    // 睡眠分期(分期类型,置信度 0-100%,困倦度)
    void onSleep(int stage, float conf, float drowsiness);
}

ZenLiteOTA (Class) & DFUCallback (Interface)

用于固件云端升级(OTA)的常量与回调定义:

java
public class ZenLiteOTA {
    public static String latestVersion;  // 云端最新版本号
    public static String desc;           // 升级描述信息
}

public interface DFUCallback {
    void onSuccess();                    // 升级成功
    void onFailure(Exception e);         // 升级失败
    void onProgress(int progress);       // 升级进度回调 (0-100)
}

数据模型

DeviceInfo 设备信息

java
public class DeviceInfo {
    private String manufacturerName;    // 制造商名称
    private String modelNumber;         // 型号
    private String serialNumber;        // 序列号
    private String hardwareRevision;    // 硬件版本
    private String firmwareRevision;    // 固件版本
}

EEG 脑电波数据

java
public class EEG {
    private int sequenceNumber;         // 序列号
    private double sampleRate;          // 采样率
    private float[] eegData;            // EEG 数据,每组 30 个样本
}

BrainWave 脑波频段指标

java
public class BrainWave {
    private double delta;               // Delta 波 (0.5-4 Hz)
    private double theta;               // Theta 波 (4-8 Hz)
    private double alpha;               // Alpha 波 (8-13 Hz)
    private double lowBeta;             // Low Beta 波 (13-17 Hz)
    private double highBeta;            // High Beta 波 (17-30 Hz)
    private double gamma;               // Gamma 波 (30-50 Hz)
}

IMU 惯性测量单元数据

java
public class IMU {
    public ACCData acc_data;            // 加速度计数据
    public GyroData gyro_data;          // 陀螺仪数据
    public EulerAngle euler_angle_data; // 欧拉角数据
    public float sample_rate;           // 采样率
}

// 加速度计数据
public class ACCData {
    public int sequenceNumber;          // 序列号
    public float[] x, y, z;             // 三轴加速度
}

// 陀螺仪数据
public class GyroData {
    public int sequenceNumber;          // 序列号
    public float[] x, y, z;             // 三轴角速度
}

// 欧拉角数据
public class EulerAngle {
    public float[] yaw;                 // 偏航角 (-180 ~ 180)
    public float[] pitch;               // 俯仰角 (-180 ~ 180)
    public float[] roll;                // 翻滚角 (-180 ~ 180)
}

PPG 光电容积脉搏波数据

java
public class PPG {
    public int sequence_num;            // 序列号
    public float sample_rate;           // 采样率
    public float report_rate;           // 上报频率
    public List<PPGRaw> raw_data;       // 原始数据
    public List<PPGAlgo> algo_data;     // 算法指标
    public float respiratory_rate;      // 呼吸频率
    public float[] respiratory_curve;   // 呼吸曲线
    public RespiratoryState respiratory_state; // 呼吸状态
}

// PPG 算法指标
public class PPGAlgo {
    public float hr;                    // 心率
    public int hr_conf;                 // 心率置信度
    public float rr;                    // 呼吸率
    public int rr_conf;                 // 呼吸率置信度
    public int activity;                // 活动状态
    public float spo2;                  // 血氧饱和度
    public float spo2_r;                // 血氧 R 值
    public int spo2_conf;               // 血氧置信度
    public int spo2_progress;           // 血氧测量进度
    public float hrv;                   // 心率变异性
    public float hrv_stress;            // HRV 压力指数
    public float stress;                // 压力指数
    public int spo2_state;              // 血氧状态
    public int contact_state;           // 接触状态
}

// PPG 原始数据
public class PPGRaw {
    public int green1;                  // 绿光 1 计数
    public int green2;                  // 绿光 2 计数
    public int ir;                      // 红外光计数
    public int red;                     // 红光计数
}

枚举常量类

连接状态

java
public enum Connectivity {
    CONNECTING(0),      // 连接中
    CONNECTED(1),      // 已连接
    DISCONNECTING(2),  // 断开中
    DISCONNECTED(3);   // 已断开
}

接触状态

java
public enum ContactState {
    UNKNOWN(0),         // 未知
    OFF(1),            // 未正确佩戴
    EEG(2),            // EEG 接触良好
    ALL(3);            // EEG & PPG 接触良好
}

方向

java
public enum Orientation {
    UNKNOWN(0),         // 未知
    UPWARD(1),         // 设备佩戴正确
    DOWNWARD(2);        // 设备佩戴反了
}

睡眠分期

java
public enum SleepStageType {
    UNKNOWN(-1),        // 未知
    AWAKE(0),          // 清醒
    REM(1),            // REM 睡眠
    LIGHT(2),          // 浅睡眠
    DEEP(3);           // 深睡眠
}

PPG 采样率

java
public enum PPGSampleRate {
    NONE(0),            // 无
    OFF(1),             // 关闭
    SR1(2),             // 1 Hz
    SR5(3),             // 5 Hz
    SR25(4),            // 25 Hz
    SR50(5),            // 50 Hz(HRV 等需要更高频率)
    SR100(6);           // 100 Hz
}

IMU 采样率

java
public enum IMUSampleRate {
    NONE(0),            // 无
    OFF(1),             // 关闭
    SR25(2),            // 25 Hz
    SR50(3),            // 50 Hz
    SR100(4),           // 100 Hz
    SR200(5),           // 200 Hz
    SR400(6),           // 400 Hz
    SR800(7);           // 800 Hz
}

IMU 模式

java
public enum IMUMode {
    NONE(0),            // 无
    ACC(1),             // 仅加速度计
    GYRO(2),            // 仅陀螺仪
    ACC_GYRO(3),        // 加速度计 + 陀螺仪
    EULER(4);           // 欧拉角
}

PPG 模式

java
public enum PPGMode {
    NONE(0),            // 无
    RAW_DATA(1),        // 原始数据
    ALGO(2),            // 算法指标
    SPO2(3),            // 仅血氧
    HR(4),              // 仅心率
    HRV(5);             // 心率变异性
}

呼吸状态

java
public enum RespiratoryState {
    UNKNOWN(0),         // 未知
    NORMAL(1),          // 正常
    ABNORMAL(2);        // 异常
}

故障排查与注意事项

常见连接与配对问题

若出现“无法扫描到设备”、“连接失败”或“配对失败”等通用蓝牙排障场景,请优先参考全局指南中的时序说明和问题排查指引:

👉 设备使用说明与常见问题 (FAQ)

Gradle 构建失败

若在构建项目时遇到同步阻塞或依赖获取失败:

  1. 请验证当前网络环境,并确认 build.gradle 中的 Maven 凭据已正确配置。
  2. 尝试在终端清空缓存并执行重新构建:
    bash
    ./gradlew clean
    ./gradlew build

Android 平台开发注意事项

  • UI 线程更新:SDK 中所有的数据回调(如 onEEGDataonPPGData 等)均在后台 IO 线程触发。若需将接收到的数据渲染至界面视图(如图表更新、状态显示),开发者必须通过 runOnUiThread 或其他调度机制(如 RxJava, Kotlin Coroutines)切换回主线程(UI 线程)执行,以免违反 Android 线程安全要求导致应用异常崩溃。
  • 资源释放与生命周期管理:为避免内存泄漏,请务必在宿主组件(如 ActivityService)销毁时(onDestroy),调用对应的中止方法(如 stopEEGStream)停止数据流,并在不再需要时执行 disconnect() 释放底层连接与回调资源。
  • 系统权限与后台运行策略
    • Android 12 及以上版本引入了更为严密的附近设备权限管理。在使用外设功能前,须确保已正确请求相关权限并正确处理 onRequestPermissionsResult 的回调响应。
    • 后台扫描与保活限制:在部分深度定制机型(如小米、华为等)中,App 切入后台或锁屏后,系统省电策略可能直接挂起 BLE 扫描(回调返空)或主动切断已有连接。若业务需要在后台保持长时间稳定的扫描与连接,需在应用层启动前台服务(Foreground Service,绑定常驻通知栏),并在高版本系统中申请 ACCESS_BACKGROUND_LOCATION 权限,或引导用户将应用加入系统电池无限制白名单。

📖 完整集成示例

以上 API 参考涵盖了 SDK 核心组件的功能定义。为了协助开发者更直观地将各个模块组合应用至实际工程中,我们在此提供了一套完整的开源参考实现。

提供的开源示例工程演示了以下集成场景:

  • 完整连接流程演示:展示了 Android 多版本体系下的蓝牙与定位动态权限请求,以及设备扫描、连接、配对的完整调用参考。
  • 组件生命周期绑定:展示了 SDK 管理实例应当如何正确的与宿主 ActivityService 生命周期相绑定,以及正确执行资源销毁的终止策略。
  • 主线程 UI 渲染:演示了在接收到处于子线程的生理指标(如脑波、心率)回调后,如何安全地切换至主线程并完成图表与数值的实时刷新。

关于上述场景的具体代码与完整应用层实现,请查阅示例仓库:

👉 OxyZen Android 示例工程