将硬件端采集到的脑电和心率原始数据传入情感离线算法SDK,可以计算出实时分析值和最终报表值。
在开始开发前,你需要联系管理员注册好测试应用。确定好你的应用中所需要的服务,然后在管理后台[下载授权文件],然后再进行开发。
-keep class cn.entertech.affectivesdk.authentication.bean.** { *; }
算法核心功能实现依赖 so 库。在使用 SDK ,以及向工程中添加 so 时请注意以下几点:
官方发布新版 SDK 时一定会同时更新 jar 文件和 so 文件,您需要做的是更新这些文件到您的工程中,不要出现遗漏。您可以参考Eclipse、Android Studio 配置工程提到的添加方法进行操作。
arm与x86,这代表核心处理器(cpu)的两种架构,对不同的架构需要引用不同的 so 文件,如果引用出现错误是不能正常使用 SDK 的。
解决这个问题最简单的办法是在 libs 或 jnilibs 文件夹下只保留 arm64-v8a 一个文件夹。
将Demo中app/libs目录下的affective-offline-sdk-1.1.4.aar文件
在项目根目录的build.gradle文件下添加以下依赖:
repositories {
mavenCentral()
}
在所需的module中的build.gradle文件下添加以下依赖:
implementation 'cn.entertech.android:affective-offline-sdk:1.1.4'
IAffectiveDataAnalysisService.getService(AffectiveServiceWay.AffectiveLocalService)
IAffectiveDataAnalysisService.connectAffectiveServiceConnection(
IConnectionServiceListener,
//以默认值就行
EnterAffectiveConfigProxy
)
interface IConnectionServiceListener {
/**
* 连接成功
* @param sessionId sessionId
* */
fun connectionSuccess(sessionId:String?)
/**
* 连接失败
* */
fun connectionError(error: Error?)
}
用户点击管理后台[下载授权文件]按钮,服务端创建一个授权文件。其中包含用户的授权信息,例如用户ID、授权日期、授权期限、授权算法等,并对这个文件进行私钥签名。
private val authenticationInputStream: InputStream? by lazy {
resources.openRawResource(R.raw.check)
}
private val authenticationInputStream: InputStream? by lazy {
resources.assets.open(fileName)
}
private val authenticationInputStream: InputStream? by lazy {
FileInputStream(File)
}
IAffectiveDataAnalysisService.startAffectiveService(
authenticationInputStream,
Context, IStartAffectiveServiceLister
)
interface IStartAffectiveServiceLister {
/**
* 启动成功
* */
fun startSuccess()
/**
* 启动生物基础服务失败
* */
fun startBioFail(error: Error?)
/**
* 启动生理基础服务失败
* */
fun startAffectionFail(error: Error?)
/**
* 启动失败
* */
fun startFail(error: Error?)
}
IAffectiveDataAnalysisService.subscribeData(
//生物基础数据
bdListener: ((RealtimeBioData?) -> Unit)? = null,
//生理数据
listener: ((RealtimeAffectiveData?) -> Unit)? = null
)
/**
* 取消订阅
* */
IAffectiveDataAnalysisService.unSubscribeData(
bdListener: ((RealtimeBioData?) -> Unit)? = null,
listener: ((RealtimeAffectiveData?) -> Unit)? = null
)
/**
* 重启离线计算服务
* */
IAffectiveDataAnalysisService.restoreAffectiveService(listener: IStartAffectiveServiceLister)
IAffectiveDataAnalysisService.finishAffectiveService(listener: IFinishAffectiveServiceListener)
/**
* @param inputStream 待分析的数据流
* @param callback 结果回调
* @param appSingleData 处理单个数据,若返回true,则表示消耗该数据,不添加到all数据里面
* @param case 数据流读取出来的字符串转成需要的类型R
* @param appendAllData 处理所有未被消耗的数据
* */
fun <R> readFileAnalysisData(inputStream: InputStream,
appSingleData: ((R) -> Boolean)? = null,
appendAllData: (List<R>) -> Unit,
case: (String) -> R,
callback: Callback,
)
/**
* 发送数据
* */
fun appendEEGData(brainData: ByteArray)
/**
* 发送单个数据
* */
fun appendEEGData(brainData: Int)
/**
* 单通道数据
* */
fun appendSCEEGData(brainData: ByteArray)
/**
* 添加心率数据
* */
fun appendHeartRateData(heartRateData: Int)
/**
* 坐垫数据
* */
fun appendPEPRData(peprData: ByteArray)
fun addServiceConnectStatueListener(
connectionListener: () -> Unit,
disconnectListener: (String) -> Unit
)
fun removeServiceConnectStatueListener(
connectionListener: () -> Unit,
disconnectListener: (String) -> Unit
)
fun hasConnectAffectiveService(): Boolean
fun hasConnectAffectiveService(): Boolean
/**
* 断开
* */
fun closeAffectiveServiceConnection()
相应返回的 report 字段,具体字段的详细描述见报表数据字段详情。
/**
* 获取报表
* @param needFinishService 是否需要自动结束离线计算服务 true 自动结束
* */
fun getReport(listener: IGetReportListener, needFinishService: Boolean)
/**
* 获取报表接口
* */
interface IGetReportListener {
/**
* 获取报表出错
* */
fun onError(error: Error?)
/**
* 获取报表成功
* */
fun onSuccess(report: UploadReportEntity?)
/**
* 获取生物基础数据报表出错
* */
fun getBioReportError(error: Error?)
/**
* 获取生理状态分析数据报表出错
* */
fun getAffectiveReportError(error: Error?)
}
BioDataUtils.brainwave2Rate(
alpha: Double,
beta: Double,
gamma: Double,
delta: Double,
theta: Double,
brainwaveRate: (
Double,
Double,
Double,
Double,
Double
) -> Unit
)
参数 | 类型 | 说明 |
---|---|---|
alpha | Double | |
beta | Double | |
gamma | Double | |
delta | Double | |
theta | Double | |
brainwaveRate | ( Double, Double, Double, Double, Double ) -> Unit | 返回alpha,beta,gamma,delta,theta占比,小数 |
graph LR
设置连接情感云服务监听-->
连接情感云服务-->
启动情感云服务-->处理数据
处理数据-->获取报表
处理数据-->订阅数据解析
订阅数据解析-->取消订阅
取消订阅-->结束情感云服务
取消订阅-->获取报表
获取报表-->结束情感云服务-->
关闭情感服务连接
如果调试阶段需要打印日志调用如下方法:
AffectiveLogHelper.printer=object :ILogPrinter{
override fun d(tag: String, msg: String) {
}
override fun i(tag: String, msg: String) {
}
override fun e(tag: String, msg: String) {
}
}
内部默认使用DefaultLogPrinter
object DefaultLogPrinter:ILogPrinter {
override fun d(tag: String, msg: String) {
Log.d(tag, msg)
}
override fun i(tag: String, msg: String) {
Log.i(tag, msg)
}
override fun e(tag: String, msg: String) {
Log.e(tag, msg)
}
}
包头 | 包长度 | 脱落检测数据 | 第一个数据 | 第二个数据 | 第三个数据 | 第四个数据 | 第五个数据 | 校验位(单字节对比校验) | 包尾 |
---|---|---|---|---|---|---|---|---|---|
3字节 | 1字节 | 1字节 | 3个字节 | 3个字节 | 3个字节 | 3字节 | 3个字节 | 1字节 | 3字节 |
0xBB-0xBB-0xBB | 0x18 | 0x00(0为佩戴正常,非0为脱落) | 00-01-02 | 03-04-05 | 06-07-08 | 09-0A-0B | 0C-0D-0E | 0x77 | 0xEE-0xEE-0xEE |
SingleChannelEEGUtil.process(byteInt: Int, appendDataList: (List<Int>) -> Unit)
参数 | 类型 | 说明 |
---|---|---|
byteInt | Int | Byte 转成0-255的int型,可通过CharUtil.converUnchart方法进行转换 |
appendDataList | (List<Int>) -> Unit | 处理一个有效的单通道数据的方法 |
SingleChannelEEGUtil.process(byteInt,{sceegData->
affectiveService?.appendSCEEGData(sceegData)
})
使用adb命令查询目标设备或模拟器的架构
adb shell getprop ro.product.cpu.abi
在项目application类型的组件下的gradle 中的android/defaultConfig添加下面配置代码。abi指的是目标设备或模拟器的架构。
ndk {
abiFilters abi
}