Bladeren bron

add README.md

master
suzhi 1 jaar geleden
bovenliggende
commit
fe31179458
2 gewijzigde bestanden met toevoegingen van 1333 en 0 verwijderingen
  1. 691
    0
      README-CN-Android.md
  2. 642
    0
      README-EN-Android.md

+ 691
- 0
README-CN-Android.md Bestand weergeven

@@ -0,0 +1,691 @@
[TOC]
# AILink Health Ring SDK Usage Guide - Android


Latest version of AILinkSDKRepositoryAndroid: [![](https://jitpack.io/v/elinkthings/AILinkSDKRepositoryAndroid.svg)](https://jitpack.io/#elinkthings/AILinkSDKRepositoryAndroid) [AILinkSDKRepositoryAndroid aar](https://github.com/elinkthings/AILinkSDKRepositoryAndroid/releases)

AILinkSDKOtaLibraryAndroid库最新版: [![](https://jitpack.io/v/elinkthings/AILinkSDKOtaLibraryAndroid.svg)](https://jitpack.io/#elinkthings/AILinkSDKOtaLibraryAndroid)[AILinkSDKOtaLibraryAndroid aar](https://github.com/elinkthings/AILinkSDKOtaLibraryAndroid/releases)

AILinkSDKHealthRingLibraryAndroid库最新版: [![](https://jitpack.io/v/elinkthings/AILinkSDKHealthRingLibraryAndroid.svg)](https://jitpack.io/#elinkthings/AILinkSDKHealthRingLibraryAndroid)[AILinkSDKHealthRingLibraryAndroid aar](https://github.com/elinkthings/AILinkSDKHealthRingLibraryAndroid/releases)



Android sdk demo git下载指令
```
git clone http://git.elinkthings.com/elink/HealthRing-bleSDK-android-Demo.git
```



## 使用条件
1. Android SDK最低版本android5.0(API 21)。
2. 设备所使用蓝牙版本需要4.0及以上。
3. 配置java1.8


## 注意事项

- AILinkSDKRepositoryAndroid库和AILinkSDKOtaLibraryAndroid库使用请[参考文档](http://doc.elinkthings.com/web/#/12?page_id=49)
- 更多操作请参考demo

## 导入SDK


```


1.将JitPack存储库添加到您的构建文件中
将其添加到存储库末尾的root build.gradle中:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}

2.添加依赖项,最新版本号请参考文档开头
dependencies {
implementation 'com.github.elinkthings:AILinkSDKRepositoryAndroid:Tag'//蓝牙库(必须)
implementation 'com.github.elinkthings:AILinkSDKOtaLibraryAndroid:Tag'//OTA库(必须)
implementation 'com.github.elinkthings:AILinkSDKHealthRingLibraryAndroid:Tag'//健康戒指库(必须,依赖蓝牙库和OTA库)
}

3.在gradle中配置java1.8
android {
...
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
repositories {
flatDir {
dirs 'libs'
}
}
}


也可以使用aar包依赖,请自行下载放到项目的libs中,下载地址在文档顶部

dependencies {
//implementation(name: 'aar包名', ext: 'aar')
}

```

## 权限设置

```

<!--兼容6.0以上的手机Ble-->
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION" />
<!--android12需要增加maxSdkVersion-->
<uses-permission
android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission
android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<!--android12还需要增加如下权限,也需求动态申请-->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation"
tools:targetApi="s"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!--android10,11需要后台扫描的,需要添加如下权限-->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="false" />
<uses-feature
android:name="android.hardware.bluetooth"
android:required="false" />

```

- <font color="#FF0000">6.0及以上系统必须要定位权限,需要开发者向系统申请权限,否则会搜索不到设备(动态申请ACCESS_FINE_LOCATION)</font>
- <font color="#FF0000">12.0及以上系统可以不用定位权限,但是需要连接附近设备权限,需要开发者向系统申请权限,否则会导致闪退(动态申请BLUETOOTH_SCAN)</font>

## 开始集成

> 在AndroidManifest.xml application标签下面增加

```
<application>
...

<service android:name="com.pingwang.bluetoothlib.server.ELinkBleServer"/>

</application>

```


### SDK初始化

- <font color="#FF0000">初始化成功后才可以执行其他操作,例如setOnCallbackBle,startScan 等方法</font>

```

AILinkSDK.getInstance().init(mContextApplication);
AILinkBleManager.getInstance().init(mContext, new AILinkBleManager.onInitListener() {
@Override
public void onInitSuccess() {
//初始化成功
}

@Override
public void onInitFailure() {
//初始化失败
}
});

```

### BLE状态接口(搜索,连接,断开)

- 设置接口AILinkBleManager.getInstance().setOnCallbackBle();实现OnCallbackBle接口可以获取搜索,连接,断开等状态和数据

```
/**
* 蓝牙搜索,连接等操作接口
*/
public interface OnCallbackBle extends OnCallback {
/**
* 开始扫描设备
*/
default void onStartScan(){}
/**
* 每扫描到一个设备就会回调一次
*/
default void onScanning(BleValueBean data){}
/**
* 扫描超时(完成)
*/
default void onScanTimeOut(){}

/**
* 扫描异常
*
* @param time 多少ms后才可以再次进行扫描
* @param type 类型 {@link com.pingwang.bluetoothlib.config.BleConfig#SCAN_FAILED_SCANNING_TOO_FREQUENTLY} 太频繁
* {@link com.pingwang.bluetoothlib.config.BleConfig#SCAN_FAILED_TOO_THREE} 扫描失败超过3次
* {@link com.pingwang.bluetoothlib.config.BleConfig#SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES} 硬件不支持(也可能是权限问题)
*/
default void onScanErr(int type, long time){}
/**
* 正在连接
*/
default void onConnecting(String mac){}
/**
* 连接断开,在UI线程
* @param mac mac地址
* @param code -1连接超时,其他错误码请参考BLE协议栈
*/
default void onDisConnected(String mac, int code){}

/**
* 连接成功(发现服务),在UI线程
*/
default void onServicesDiscovered(String mac){}

/**
* 已开启蓝牙,在触发线程
*/
default void bleOpen(){}

/**
* 未开启蓝牙,在触发线程
*/
default void bleClose(){}
}
```

### 扫描设备

- 搜索 AILinkBleManager.getInstance().startScan(long timeOut);//timeOut(毫秒)

```
/**
* 搜索设备(不过滤)
* 扫描过于频繁会导致扫描失败
* 需要保证5次扫描总时长超过30s
* @param timeOut 超时时间,毫秒(搜索多久去取数据,0代表一直搜索)
*/
startScan(long timeOut)

/**
* 搜索设备
* 扫描过于频繁会导致扫描失败
* 需要保证5次扫描总时长超过30s
* @param timeOut 超时时间,毫秒(搜索多久去取数据,0代表一直搜索)
* @param scanUUID 过滤的UUID(空数组代表不过滤)
*/
startScan(long timeOut, UUID scanUUID)

例:只搜索AILink的设备
//BleConfig.UUID_SERVER_AILINK是AILink的连接类设备
//BleConfig.UUID_SERVER_BROADCAST_AILINK是AILink的广播类设备
startScan(30000, BleConfig.UUID_SERVER_AILINK,BleConfig.UUID_SERVER_BROADCAST_AILINK)


```

- 扫描的设备回调,可以在OnCallbackBle接口或者OnScanFilterListener接口中获取

```

//OnCallbackBle接口
onScanning(BleValueBean data){
//每扫描到设备就会从这个返回,可以用于获取广播数据以及刷新信号值
//需要开发者自己过滤去重(可以通过mac地址去重)

}


//OnScanFilterListener接口
//建议在不需要连接的时候实现此接口,可以减少接口实现
onScanRecord(BleValueBean bleValueBean){
//每扫描到设备就会从这个返回,可以用于获取广播数据以及刷新信号值
//需要开发者自己过滤去重(可以通过mac地址去重)
}

/**
* 过滤计算->可以对广播数据进行帅选过滤
*
* @param bleValueBean 蓝牙广播数据
* @return 是否有效,true有效,false无效,丢弃
*/
onFilter(BleValueBean bleValueBean){

}

```

### 连接设备

- 连接AILinkBleManager.getInstance().connectDevice(BleValueBean bleValueBean);或者connectDevice(String mAddress);

```
//注:连接之前建议停止搜索,这样连接过程会更稳定
AILinkBleManager.getInstance().stopScan()


//连接成功并获取服务成功后会在OnCallbackBle接口中回调
onServicesDiscovered(String mac){
//连接成功,并且获取服务UUID成功
//可以进行发送和接收数据了
}

```

### 断开连接


```
//断开所有连接,AILink库支持连接多个蓝牙设备.
AILinkBleManager.getInstance().disconnectAll();


//所以AILinkBleManager对象只提供断开所有设备的方法,断开某个设备可用BleDevice.disconnect();方法断开连接
//可以通过这样获取BleDevice对象
AILinkBleManager.getInstance().getBleDevice(String mac);

```


### 发送数据

- 获取到连接对象后可以对设备进行收发数据

``` kotlin
//BleDevice对象拥有对此设备的所有操作,包括断开连接,发送指令,接收指令等操作
val bleDevice = AILinkBleManager.getInstance().getBleDevice(mAddress);
val ringBleData: ElinkHealthRingBleData = ElinkHealthRingBleData(bleDevice)

//查询设备状态
ringBleData.getDeviceState()

//获取日常监测周期
ringBleData.getCheckupDuration()

//获取版本信息
ringBleData.getSensorVersion()

//获取日常监测模式
ringBleData.getCheckupType()

//获取日常监测状态
ringBleData.getAutoCheckState()

//开启日常监测
ringBleData.openAutoCheck()

//关闭日常监测
ringBleData.closeAutoCheck()

//设置日常监测周期
ringBleData.setCheckupDuration(duration: Int) //单位: 分钟

//设置日常监测模式
ringBleData.setCheckupType(type: ElinkCheckupType) //ElinkCheckupType.COMPLEX: 全面监测, ElinkCheckupType.FAST: 快速监测

//获取历史数据
ringBleData.getHistory()

//获取下一页历史数据
ringBleData.getNextHistory()

//获取历史数据结束
ringBleData.getHistoryOver()

//删除历史数据
ringBleData.deleteHistory()

//开始体检
ringBleData.startCheckup()

//结束体检
ringBleData.stopCheckup()

//同步Unix时间
ringBleData.syncUnixTime()

//传感器OTA
ringBleData.startSensorOTA(fileData: ByteArray)

//传感器OTA回调
ringBleData.setImplSensorOTA(object : ImplSensorOTA {
override fun onFailure(type: ElinkSensorOTAErrorType) {}
override fun onSuccess() {}
override fun onProgress(progress: Int) {}
})

//蓝牙OTA
ringBleData.startBleOTA(filePath: String, object : OnBleOTAListener {
override fun onOtaSuccess() {}
override fun onOtaFailure(cmd: Int, err: String?) {}
override fun onOtaProgress(progress: Float, currentCount: Int, maxCount: Int,) {}
override fun onOtaStatus(status: Int) {}
override fun onReconnect(mac: String?) {}
})


//断开当前设备的连接
BleDevice.disconnect();

```

### 设备指令回复回调说明
```kotlin
ringBleData?.setImplHealthRingResult(object : ImplHealthRingResult {
/**
* 开始体检回调
*
* @param success 结果
*/
override fun startCheckup(success: Boolean) {}
/**
* 结束体检回调
*
* @param success 结果
*/
override fun stopCheckup(success: Boolean) {}
/**
* 体检实时数据回调
*
* @param data ElinkCheckupRealtimeData
*/
override fun onGetRealtimeData(data: ElinkCheckupRealtimeData) {}
/**
* 体检包回调
*
* @param data ByteArray
*/
override fun onGetCheckupPackets(data: ByteArray) {}
/**
* (查询和设置)日常监测周期回调
*
* @param duration 单位(分钟)
*/
override fun onGetCheckupDuration(duration: Int) {}
/**
* 获取历史数据回调,根据total和sentCount对比判断是否有更多历史数据
* 如果有就调用getNextHistory()
* 如果没有就调用getHistoryOver()
* 结束获取历史数据后调用deleteHistory()删除历史数据
*
* @param histories 历史数据列表
* @param total 总数
* @param sentCount 已获取数
*/
override fun onGetHistory(
histories: List<ElinkRingHistoryData>,
total: Int,
sentCount: Int,
) {}
/**
* 获取设备状态回调
*
* @param status
*/
override fun onGetDeviceStatus(status: ElinkRingDeviceStatus) {}
/**
* 获取传感器版本回调
*
* @param version
*/
override fun onGetSensorVersion(version: String) {}
/**
* (查询、开启和关闭)日常监测状态回调
*
* @param open
*/
override fun onGetAutoCheckupStatus(open: Boolean) {}
/**
* (查询和设置)日常监测模式回调
*
* @param type ElinkCheckupType.COMPLEX: 全面监测, ElinkCheckupType.FAST: 快速监测
*/
override fun onGetCheckupType(type: ElinkCheckupType) {}

/**
* 设备产生历史数据通知回调
*/
override fun onNotifyHistoryGenerated() {}

/**
* 同步UnixTime回调
*
* @param success
*/
override fun onSetUnixTimeResult(success: Boolean) {}

})
```

### 相关类说明

#### ElinkCheckupRealtimeData
```kotlin
data class ElinkCheckupRealtimeData(
val heartRate: Int, //心率
val bloodOxygen: Int, //血氧
val heartList: List<Int>, //心律
val rr: Int,
val rri: List<Int>,
)
```

#### ElinkRingDeviceStatus
```kotlin
data class ElinkRingDeviceStatus(
val state: ElinkRingHistoryState, //历史数据状态
val batteryLevel: Int, //电量
val isCharging: Boolean, //是否在充电
val wearingStatus: ElinkWearingStatus, //佩戴状态
)
```

#### ElinkRingHistoryState
```kotlin
enum class ElinkRingHistoryState {
NOT_READY, //历史时间未就绪(未获取unix时间)
PROCESSING, //历史时间正在处理中(已获取unix时间,在处理历史数据)
READY, //历史时间已就绪(此状态才可获取设备历史记录)
}
```
- <font color="#FF0000">ElinkRingHistoryState.NOT_READY状态下,需要调用ringBleData.syncUnixTime()主动同步时间,不然获取到的历史数据时间会是错误的</font>

#### ElinkRingHistoryData
```kotlin
data class ElinkRingHistoryData(
val heartRate: Int, //心率
val bloodOxygen: Int, //血氧
val bk: Int, //微循环
val sbp: Int, //收缩压(高压)
val dbp: Int, //舒张压(低压)
val rr: Int, //呼吸率
val sdann: Int,
val rmssd: Int,
val nn50: Int,
val pnn50: Int,
val time: Long, //时间
val rri: List<Int>,
)
```

#### ElinkCheckupType
```kotlin
enum class ElinkCheckupType(val size: Byte) {
COMPLEX(72), //全面体检
FAST(30), //快速体检
}
```

#### ElinkSensorOTAErrorType
```kotlin
enum class ElinkSensorOTAErrorType {
START_OTA_FAIL,
CHECK_FAIL,
WRITE_ERROR,
ERASE_ERROR,
}
```

#### ElinkWearingStatus
```kotlin
enum class ElinkWearingStatus() {
UNSUPPORTED, //不支持
NOT_WEARING, //未佩戴
WEARING, //佩戴中
}
```

### 前台服务设置(非必须)

```
/**
* 设置前台服务相关参数
* @param id id
* @param icon logo
* @param title 标题
* @param activityClass 跳转的activity
*/
AILinkBleManager.getInstance().initForegroundService(int id, @DrawableRes int icon, String title, Class<?> activityClass)

//启动前台服务,
AILinkBleManager.getInstance().startForeground();

//停止前台服务
AILinkBleManager.getInstance().stopForeground();
```

- BleDevice 中的setOnBleVersionListener(OnBleVersionListener bleVersionListener)//设备版本号,单位接口

```
public interface OnBleVersionListener {
/**
* BM 模块软、硬件版本号
*/
default void onBmVersion(String version){}
/**
* mcu 支持的单位(默认支持所有)
* @param list null或者空代表支持所有
*/
default void onSupportUnit(List<SupportUnitBean> list) {}
}

```

## 版本历史

- AILinkSDKHealthRingLibraryAndroid库

| 版本号 | 更新时间 | 作者 |更新信息|
|:-------|:------------|:------|-----|
| 1.0.0 | 2024/03/14 | suzy | 初始版本
---

## FAQ

- 扫描不到蓝牙设备?

1. 查看App权限是否正常,6.0及以上系统必须要定位权限,且需要手动获取权限,android 7.0 后不能在30秒内扫描+停止超过5次,android 9.0以后搜索需要精准定位权限
2. 查看手机的定位服务是否开启,部分手机可能需要打开GPS;
3. ELinkBleServer是否在在AndroidManifest中注册;
4. 设备是否被其他手机连接;
5. 是否调用搜索方法太频繁, scanLeDevice方法需要保证5次扫描总时长超过30s(各别手机有差异,建议尽量减少频率);
6. 重启手机蓝牙再试试,部分手机需要整个手机重启;

---

- SDK搜索不到其他第三方设备?

1. scanLeDevice(long timeOut, UUID... scanUUID); scanUUID写成第三方的广播UUID或者不写

---


```
在gradle中配置java1.8
android {
...
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
repositories {
flatDir {
dirs 'libs'
}
}
}
```

---

- java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/aicare.net.cn.sdk.ailinksdkdemoandroid-duDywZpVbVzKW4Q18GgfFA==/base.apk"],nativeLibraryDirectories=[/dat
![](http://doc.elinkthings.com/server/../Public/Uploads/2021-08-04/610a331294e02.png)

---

- SDK连接第三方设备发送后断开或者发送不了数据?

1. 联系商务

## SDK混淆配置(proguard-rules.pro)

```
-keep class com.pinwang.ailinkble.**{*;}

-keep class com.pingwang.bluetoothlib.annotation.**{*;}
-keep class com.pingwang.bluetoothlib.bean.**{*;}
-keep class com.pingwang.bluetoothlib.config.**{*;}
-keep class com.pingwang.bluetoothlib.device.**{*;}
-keep class com.pingwang.bluetoothlib.listener.**{*;}

-keep public class com.pingwang.bluetoothlib.AILinkBleManager{*;}
-keep public class com.pingwang.bluetoothlib.AILinkSDK{*;}
-keep public class com.pingwang.bluetoothlib.utils.BleLog{*;}
-keep public class com.pingwang.bluetoothlib.utils.UuidUtils{*;}
-keep public class com.pingwang.bluetoothlib.utils.BleDataUtils{*;}
-keep public class com.pingwang.bluetoothlib.utils.BleCheckUtils{*;}

-keep class cn.net.aicare.algorithmutil.**{*;}
-keep class cn.net.aicare.**{*;}
-keep class com.besthealth.bhBodyComposition120.**{*;}
-keep class com.holtek.**{*;}
-keep class com.elinkthings.toothscore.**{*;}
-keep class cn.net.aicare.modulelibrary.module.**{*;}

-keep class com.elinkthings.healthring.**{*;}

```


## 联系我们
深圳市易连物联网有限公司

电话:0755-81773367

微信号:ElinkThings08

官网:www.elinkthings.com

邮箱:app@elinkthings.com

+ 642
- 0
README-EN-Android.md Bestand weergeven

@@ -0,0 +1,642 @@
[TOC]
# AILink Health Ring SDK Usage Guide - Android


Latest version of AILinkSDKRepositoryAndroid: [![](https://jitpack.io/v/elinkthings/AILinkSDKRepositoryAndroid.svg)](https://jitpack.io/#elinkthings/AILinkSDKRepositoryAndroid) [AILinkSDKRepositoryAndroid aar](https://github.com/elinkthings/AILinkSDKRepositoryAndroid/releases)

Latest version of AILinkSDKOtaLibraryAndroid: [![](https://jitpack.io/v/elinkthings/AILinkSDKOtaLibraryAndroid.svg)](https://jitpack.io/#elinkthings/AILinkSDKOtaLibraryAndroid)[AILinkSDKOtaLibraryAndroid aar](https://github.com/elinkthings/AILinkSDKOtaLibraryAndroid/releases)

Latest version of AILinkSDKHealthRingLibraryAndroid: [![](https://jitpack.io/v/elinkthings/AILinkSDKHealthRingLibraryAndroid.svg)](https://jitpack.io/#elinkthings/AILinkSDKHealthRingLibraryAndroid)[AILinkSDKHealthRingLibraryAndroid aar](https://github.com/elinkthings/AILinkSDKHealthRingLibraryAndroid/releases)



Download the Android SDK demo from Git:
```
git clone http://git.elinkthings.com/elink/HealthRing-bleSDK-android-Demo.git
```



## Requirements
1. Minimum Android SDK version: Android 5.0 (API 21).
2. Bluetooth version 4.0 or higher is required for the device.
3. Java version 1.8 is required.


## Notes

- For usage of AILinkSDKRepositoryAndroid and AILinkSDKOtaLibraryAndroid, please refer to the [documentation](http://doc.elinkthings.com/web/#/12?page_id=50)
- For more operations, please refer to the demo.

## SDK Integration
```
1.Add the JitPack repository to your build file
Add it to the end of the repositories in the root build.gradle:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}

2.Add dependencies, refer to the latest version in the documentation header
dependencies {
implementation 'com.github.elinkthings:AILinkSDKRepositoryAndroid:Tag'//Bluetooth library (required)
implementation 'com.github.elinkthings:AILinkSDKOtaLibraryAndroid:Tag'//OTA library (required)
implementation 'com.github.elinkthings:AILinkSDKHealthRingLibraryAndroid:Tag'//Health ring library (required, depends on Bluetooth library and OTA library)
}

3.Configure Java 1.8 in Gradle
android {
...
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
repositories {
flatDir {
dirs 'libs'
}
}
}


Alternatively, you can use aar package dependencies by downloading and placing them in the libs directory of your project. Download links are provided at the top of the document.

dependencies {
//implementation(name: 'aar包名', ext: 'aar')
}
```

## Permission settings

```

<!-- For BLE compatibility on Android 6.0 and above -->
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- For Android 12, add maxSdkVersion -->
<uses-permission
android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission
android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<!-- For Android 12, additional permissions are required and need to be dynamically requested -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation"
tools:targetApi="s"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- For Android 10 and 11, background scanning requires the following permission -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="false" />
<uses-feature
android:name="android.hardware.bluetooth"
android:required="false" />

```

- <font color="#FF0000">Location permission is mandatory for Android 6.0 and above. Developers need to manually request this permission, otherwise devices may not be discovered (dynamic request for ACCESS_FINE_LOCATION).</font>
- <font color="#FF0000">For Android 12 and above, location permission is not required, but permission to connect to nearby devices is needed. Developers need to request this permission, otherwise it may cause app crashes (dynamic request for BLUETOOTH_SCAN).</font>

## Getting Started

> Add the following code snippet inside the <application> tag of your AndroidManifest.xml file:

```
<application>
...

<service android:name="com.pingwang.bluetoothlib.server.ELinkBleServer"/>

</application>

```


### SDK Initialization

- <font color="#FF0000">Ensure that initialization is successful before executing other operations, such as setOnCallbackBle and startScan methods.</font>

```

AILinkSDK.getInstance().init(mContextApplication);
AILinkBleManager.getInstance().init(mContext, new AILinkBleManager.onInitListener() {
@Override
public void onInitSuccess() {
// Initialization successful
}

@Override
public void onInitFailure() {
// Initialization failed
}
});

```

### BLE State Interface (Scan, Connect, Disconnect)

- Implement the OnCallbackBle interface by setting the interface AILinkBleManager.getInstance().setOnCallbackBle(); to receive status and data such as scanning, connecting, and disconnecting.

```
/**
* Bluetooth scan, connection, and other operation interface
*/
public interface OnCallbackBle extends OnCallback {
/**
* Start scanning for devices
*/
default void onStartScan(){}
/**
* Callback for each scanned device
*/
default void onScanning(BleValueBean data){}
/**
* Scan timeout (complete)
*/
default void onScanTimeOut(){}

/**
* Scan error
*
* @param time Time after which scanning can be performed again
* @param type 类型 {@link com.pingwang.bluetoothlib.config.BleConfig#SCAN_FAILED_SCANNING_TOO_FREQUENTLY} Too frequent
* {@link com.pingwang.bluetoothlib.config.BleConfig#SCAN_FAILED_TOO_THREE} Scanning failed more than 3 times
* {@link com.pingwang.bluetoothlib.config.BleConfig#SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES} Hardware not supported (may also be a permission issue)
*/
default void onScanErr(int type, long time){}
/**
* Connecting
*/
default void onConnecting(String mac){}
/**
* Connection disconnected, in the UI thread
* @param mac Mac address
* @param code -1 Connection timeout, other error codes please refer to BLE protocol stack
*/
default void onDisConnected(String mac, int code){}

/**
* Connection successful (service discovered), in the UI thread
*/
default void onServicesDiscovered(String mac){}

/**
* Bluetooth is turned on, triggered on the thread
*/
default void bleOpen(){}

/**
* Bluetooth is not turned on, triggered on the thread
*/
default void bleClose(){}
}
```

### Device Scanning

- Start scanning: AILinkBleManager.getInstance().startScan(long timeOut); (timeOut in milliseconds)

```
/**
* Search for devices (no filtering)
* Scanning too frequently may cause scanning failure
* Ensure that the total scanning time of 5 scans exceeds 30s
* @param timeOut Timeout, in milliseconds (how long to search for data, 0 means continuous scanning)
*/
startScan(long timeOut)

/**
* Search for devices
* Scanning too frequently may cause scanning failure
* Ensure that the total scanning time of 5 scans exceeds 30s
* @param timeOut Timeout, in milliseconds (how long to search for data, 0 means continuous scanning)
* @param scanUUID UUID to filter (an empty array means no filtering)
*/
startScan(long timeOut, UUID scanUUID)

Example: Searching for AILink devices only
// BleConfig.UUID_SERVER_AILINK is the connection class device for AILink
// BleConfig.UUID_SERVER_BROADCAST_AILINK is the broadcast class device for AILink
startScan(30000, BleConfig.UUID_SERVER_AILINK,BleConfig.UUID_SERVER_BROADCAST_AILINK)
```

- Scanned device callback: You can obtain it in the OnCallbackBle interface or OnScanFilterListener interface.

```

//OnCallbackBle interface
onScanning(BleValueBean data){
// Returns each scanned device, can be used to get broadcast data and refresh signal value
// Developers need to filter and deduplicate by themselves (can be deduplicated by MAC address)

}


// OnScanFilterListener interface
// It is recommended to implement this interface when you don't need to connect, which can reduce the number of interface implementations
onScanRecord(BleValueBean bleValueBean){
// Returns each scanned device, can be used to get broadcast data and refresh signal value
// Developers need to filter and deduplicate by themselves (can be deduplicated by MAC address)
}

/**
* Filter calculation -> can filter and select broadcast data
* @param bleValueBean Bluetooth broadcast data
* @return Whether it is valid, true for valid, false for invalid, discarded
*/
onFilter(BleValueBean bleValueBean){

}

```

### Connecting to a Device

- Connect: AILinkBleManager.getInstance().connectDevice(BleValueBean bleValueBean); or connectDevice(String mAddress);

```
// Note: It is recommended to stop scanning before connecting to make the connection process more stable
AILinkBleManager.getInstance().stopScan()


// Connection successful and service discovery will be called back in the OnCallbackBle interface
onServicesDiscovered(String mac){
// Connection successful, and service UUID is obtained successfully
// Data transmission and reception can be performed
}

```

### Disconnecting
```
// Disconnect all connections, AILink library supports connecting multiple Bluetooth devices.
AILinkBleManager.getInstance().disconnectAll();

// The AILinkBleManager object provides only the method to disconnect all devices. To disconnect a specific device, you can use the BleDevice.disconnect() method.
// You can get the BleDevice object in this way
AILinkBleManager.getInstance().getBleDevice(String mac);
```


### Sending Data

- After obtaining the connection object, you can send and receive data from the device.

``` kotlin
// The BleDevice object has all operations on this device, including disconnecting, sending commands, and receiving commands.
val bleDevice = AILinkBleManager.getInstance().getBleDevice(mAddress);
val ringBleData: ElinkHealthRingBleData = ElinkHealthRingBleData(bleDevice)

//Query device status
ringBleData.getDeviceState()

//Get daily monitoring period
ringBleData.getCheckupDuration()

//Get sensor version
ringBleData.getSensorVersion()

//Get daily monitoring mode
ringBleData.getCheckupType()

//Get daily monitoring status
ringBleData.getAutoCheckState()

//Start daily monitoring
ringBleData.openAutoCheck()

//Stop daily monitoring
ringBleData.closeAutoCheck()

//Stop daily monitoring
ringBleData.setCheckupDuration(duration: Int) //Unit: Minutes

//Set daily monitoring mode
ringBleData.setCheckupType(type: ElinkCheckupType) //ElinkCheckupType.COMPLEX: Comprehensive monitoring, ElinkCheckupType.FAST: Quick monitoring

//Get history data
ringBleData.getHistory()

//Get the next page of history data
ringBleData.getNextHistory()

//End of history data
ringBleData.getHistoryOver()

//Delete history data
ringBleData.deleteHistory()

//Start health checkup
ringBleData.startCheckup()

//End health checkup
ringBleData.stopCheckup()

//Synchronize Unix time
ringBleData.syncUnixTime()

//Sensor OTA
ringBleData.startSensorOTA(fileData: ByteArray)

//Sensor OTA callback
ringBleData.setImplSensorOTA(object : ImplSensorOTA {
override fun onFailure(type: ElinkSensorOTAErrorType) {}
override fun onSuccess() {}
override fun onProgress(progress: Int) {}
})

//Bluetooth OTA
ringBleData.startBleOTA(filePath: String, object : OnBleOTAListener {
override fun onOtaSuccess() {}
override fun onOtaFailure(cmd: Int, err: String?) {}
override fun onOtaProgress(progress: Float, currentCount: Int, maxCount: Int,) {}
override fun onOtaStatus(status: Int) {}
override fun onReconnect(mac: String?) {}
})


//Disconnect the connection of the current device
BleDevice.disconnect();

```

### Device Command Reply Callback Explanation
```kotlin
ringBleData?.setImplHealthRingResult(object : ImplHealthRingResult {
/**
* Callback for starting health checkup
*
* @param success result
*/
override fun startCheckup(success: Boolean) {}
/**
* Callback for ending health checkup
*
* @param success result
*/
override fun stopCheckup(success: Boolean) {}
/**
* Callback for real-time health checkup data
*
* @param data ElinkCheckupRealtimeData
*/
override fun onGetRealtimeData(data: ElinkCheckupRealtimeData) {}
/**
* Health checkup packet callback
*
* @param data ByteArray
*/
override fun onGetCheckupPackets(data: ByteArray) {}
/**
* Callback for querying and setting daily monitoring period
*
* @param duration Unit (minutes)
*/
override fun onGetCheckupDuration(duration: Int) {}

/**
* Callback for obtaining history data, judge whether there is more history data based on total and sentCount
* If there is, call getNextHistory()
* If not, call getHistoryOver()
* After the end of history data acquisition, call deleteHistory() to delete history data
*
* @param histories List of historical data
* @param total Total
* @param sentCount Already acquired count
*/
override fun onGetHistory(
histories: List<ElinkRingHistoryData>,
total: Int,
sentCount: Int,
) {}
/**
* Callback for obtaining device status
*
* @param status
*/
override fun onGetDeviceStatus(status: ElinkRingDeviceStatus) {}
/**
* Callback for obtaining sensor version
*
* @param version
*/
override fun onGetSensorVersion(version: String) {}
/**
* Callback for querying, starting, and stopping daily monitoring status
*
* @param open
*/
override fun onGetAutoCheckupStatus(open: Boolean) {}
/**
* Callback for querying and setting daily monitoring mode
*
* @param type ElinkCheckupType.COMPLEX: Comprehensive monitoring, ElinkCheckupType.FAST: Quick monitoring
*/
override fun onGetCheckupType(type: ElinkCheckupType) {}

/**
* Notification callback for generating historical data on the device
*/
override fun onNotifyHistoryGenerated() {}

/**
* Callback for synchronizing UnixTime
*
* @param success
*/
override fun onSetUnixTimeResult(success: Boolean) {}

})
```

### 相关类说明

#### Related Class Descriptions
```kotlin
data class ElinkCheckupRealtimeData(
val heartRate: Int, //Heart rate
val bloodOxygen: Int, //Blood oxygen
val heartList: List<Int>, //Heart rhythm
val rr: Int,
val rri: List<Int>,
)
```

#### ElinkRingDeviceStatus
```kotlin
data class ElinkRingDeviceStatus(
val state: ElinkRingHistoryState, //Historical data status
val batteryLevel: Int, //Battery
val isCharging: Boolean, //Whether it is charging
val wearingStatus: ElinkWearingStatus, //wearing status
)
```

#### ElinkRingHistoryState
```kotlin
enum class ElinkRingHistoryState {
NOT_READY, //The historical time is not ready (unix time is not obtained)
PROCESSING, //Historical time is being processed (unix time has been obtained and historical data is being processed)
READY, //The historical time is ready (only in this state can the device history be obtained)
}
```
- <font color="#FF0000">In the ElinkRingHistoryState.NOT_READY state, you need to call ringBleData.syncUnixTime() to actively synchronize the time, otherwise the historical data time obtained will be wrong</font>

#### ElinkRingHistoryData
```kotlin
data class ElinkRingHistoryData(
val heartRate: Int, //Heart rate
val bloodOxygen: Int, //blood oxygen
val bk: Int, //Microcycle
val sbp: Int, //systolic blood pressure (high pressure)
val dbp: Int, //diastolic blood pressure (low pressure)
val rr: Int, //respiration rate
val sdann: Int,
val rmssd: Int,
val nn50: Int,
val pnn50: Int,
val time: Long, //time
val rri: List<Int>,
)
```

#### ElinkCheckupType
```kotlin
enum class ElinkCheckupType(val size: Byte) {
COMPLEX(72), //Comprehensive monitoring
FAST(30), //Quick monitoring
}
```

#### ElinkSensorOTAErrorType
```kotlin
enum class ElinkSensorOTAErrorType {
START_OTA_FAIL,
CHECK_FAIL,
WRITE_ERROR,
ERASE_ERROR,
}
```

#### ElinkWearingStatus
```kotlin
enum class ElinkWearingStatus {
UNSUPPORTED, //not supported
NOT_WEARING, //not wearing
WEARING, //Wearing
}
```

### Front desk service settings (optional)

```
/**
*Set front-end service related parameters
* @param id id
* @param icon logo
* @param title title
* @param activityClass jump activity
*/
AILinkBleManager.getInstance().initForegroundService(int id, @DrawableRes int icon, String title, Class<?> activityClass)

//Start the foreground service,
AILinkBleManager.getInstance().startForeground();

//Stop the foreground service
AILinkBleManager.getInstance().stopForeground();
```

- setOnBleVersionListener(OnBleVersionListener bleVersionListener) in BleDevice//Device version number, unit interface

```
public interface OnBleVersionListener {
/**
*BM module software and hardware version number
*/
default void onBmVersion(String version){}
/**
* Units supported by mcu (all supported by default)
* @param list null or empty means all are supported
*/
default void onSupportUnit(List<SupportUnitBean> list) {}
}

```

## Version history

- AILinkSDKHealthRingLibraryAndroid library

| Version number | Update time | Author | Update information |
|:-------|:------------|:------|-----|
| 1.0.0 | 2024/03/14 | suzy | Initial version
---

## FAQ

- Can't scan for Bluetooth devices?

1. Check whether the App permissions are normal. Systems 6.0 and above must require positioning permissions and need to obtain permissions manually. After android 7.0, you cannot scan + stop more than 5 times within 30 seconds. Searching after android 9.0 requires precise positioning permissions.
2. Check whether the mobile phone’s positioning service is turned on. Some mobile phones may need to turn on GPS;
3. Is ELinkBleServer registered in AndroidManifest;
4. Whether the device is connected to other mobile phones;
5. Whether the search method is called too frequently, the scanLeDevice method needs to ensure that the total duration of 5 scans exceeds 30s (each phone has differences, it is recommended to reduce the frequency as much as possible);
6. Restart the phone’s Bluetooth and try again. Some phones require the entire phone to be restarted;

## SDK obfuscation configuration (proguard-rules.pro)

```
-keep class com.pinwang.ailinkble.**{*;}

-keep class com.pingwang.bluetoothlib.annotation.**{*;}
-keep class com.pingwang.bluetoothlib.bean.**{*;}
-keep class com.pingwang.bluetoothlib.config.**{*;}
-keep class com.pingwang.bluetoothlib.device.**{*;}
-keep class com.pingwang.bluetoothlib.listener.**{*;}

-keep public class com.pingwang.bluetoothlib.AILinkBleManager{*;}
-keep public class com.pingwang.bluetoothlib.AILinkSDK{*;}
-keep public class com.pingwang.bluetoothlib.utils.BleLog{*;}
-keep public class com.pingwang.bluetoothlib.utils.UuidUtils{*;}
-keep public class com.pingwang.bluetoothlib.utils.BleDataUtils{*;}
-keep public class com.pingwang.bluetoothlib.utils.BleCheckUtils{*;}

-keep class cn.net.aicare.algorithmutil.**{*;}
-keep class cn.net.aicare.**{*;}
-keep class com.besthealth.bhBodyComposition120.**{*;}
-keep class com.holtek.**{*;}
-keep class com.elinkthings.toothscore.**{*;}
-keep class cn.net.aicare.modulelibrary.module.**{*;}

-keep class com.elinkthings.healthring.**{*;}

```

## Contact us
Shenzhen ElinkThings Co., Ltd.

Tel: 0755-81773367

WeChat: ElinkThings08

Website: www.elinkthings.com

E-mail: app@elinkthings.com

Laden…
Annuleren
Opslaan