# 蓝小飞智屏二次开发指引

# 说明

蓝小飞智屏是 iFLYOS 团队推出的有屏音箱公版,集合了科大讯飞强大的语音交互能力、iFLYOS丰富的合作内容服务和基于EVS协议开发的 Android 语音交互应用 ShowCore 。是一款场景广泛,能力多样的智能音箱。由于 iFLYOS 的开放性,开发者可以在蓝小飞智屏的基础上定制出更个性化的面向市场的智能硬件。

为了使开发者可以在音箱上运行自己开发的技能或应用,完成更高级的音箱定制功能,iFLYOS 为开发者提供了蓝小飞智屏的二次开发文档。

如按照此指引操作,且查看了相关文档后,在开发过程中仍遇到接入问题,可以通过 iFLYOS 工单或论坛咨询,我们会在 12 小时内响应回复。

iFLYOS 工单: 点击此处 (opens new window)

iFLYOS 论坛:点击此处 (opens new window)

如需更高效的技术支持,可选择购买为期 2 个月的 iFLYOS 技术支持包 (opens new window),购买了技术支持包的用户,可享受以下服务:

  1. 开通工单绿色通道;
  2. 问题咨询 2 小时内回复响应;
  3. VIP 技术支持,优先回复解决开发中遇到的接入问题;
  4. 开通新需求评估通道,2 个工作日内回复评估结论;

# 前期准备

# 了解 iFLYOS 设备接入

在进行二次开发之前,建议你先了解一下 iFLYOS 设备接入,避免因不了解系统造成设备不可用。

iFLYOS 官网地址:点击此处 (opens new window)

iFLYOS 设备接入参考文档:点击此处 (opens new window)

# 在设备接入控制台创建一个设备

步骤参考: 点击此处 (opens new window)

注意

为了保证你的设备在小飞在线 App (opens new window)中可正常添加和配网,请确保:

  1. 新建设备时,在【是否有屏】的选项中选择【有屏】。
  2. 在【设备控制台-设备能力】的【网络配置】中开启【屏幕配网】。
  3. 在【设备控制台-真机测试】中配置手机号白名单。

# 在技能工作室新建属于自己的技能

iFLYOS技能工作室参考文档:点击此处 (opens new window)

步骤参考:点击此处 (opens new window)

# 温馨提示

在二次开发前,请确认已知晓以下事项:

  1. 进入过开发者模式并更改了 client_id 的设备,除了硬件问题将不享受其他保修服务。

  2. 由于音乐服务与设备的 client_iddevice_id 挂钩,修改 client_id 后的音箱将无法使用该音箱自带的一年免费音乐服务。

  3. 请勿擅自用开源 ShowCore 直接替换蓝小飞智屏自带 ShowCore ,出现问题将不享受保修服务。

    注意

    更改 client_id 可能导致音箱无法正常启动,请谨慎修改。

# 重要概念说明

# 开源 ShowCore

ShowCore 是基于 EVS协议 (opens new window) 开发、运行在 Android 平台的通用语音交互 Launcher App。通过接入 ShowCore,开发者可以降低将 EVS 接入硬件的开发成本,快速开发一款使用 iFLYOS 的智能带屏音箱。开发者可根据自身需求,对开源 ShowCore 进行二次开发。作为一款Android App, ShowCore 能够运用在手机,智能设备,有屏智能家居等多个场景,让设备快速具备可视化语音交互能力。点击查看 ShowCore 介绍 (opens new window) ShowCore 源码 (opens new window)

注意

开源 ShowCore 作为 iFLYOS 针对带屏设备的通用解决方案,并未针对蓝小飞智屏做适配与优化。请勿直接将开源 ShowCore 直接安装至蓝小飞智屏中,以免造成未知问题。

# 开源 ShowCore 与蓝小飞智屏版 ShowCore 的区别

蓝小飞智屏中的 ShowCore 虽然是在开源的基础上进行开发,但由于在开发过程中,蓝小飞智屏版本 ShowCore 针对设备体验和固件逻辑做了较多修改,所以两者有较大不同。具体如下:

1.蓝小飞智屏版 ShowCore 拥有系统签名

蓝小飞智屏版的 ShowCore 是系统级桌面应用,拥有系统诸多权限(包括位置,存储,相机,麦克风等)。使用蓝小飞智屏的过程中,用户无需进行各项授权。

开源 ShowCore 并非系统级应用,若直接将开源版直接集成至设备端,用户在使用时会进行多项授权,部分功能可能因为权限问题无法使用。

2.录音调用方式不同

开源 ShowCore 无CAE,而在蓝小飞智屏固件中内嵌了CAE,若将开源的 ShowCore 直接集成至蓝小飞智屏中,可能会造成麦克风通道冲突等多项问题。

3.OTA功能不同

开源 ShowCore 的OTA主要是提供 ShowCore APK的更新。而蓝小飞智屏版的 ShowCore 的OTA更新的是固件。两者功能并不一致。

TIP

蓝小飞智屏的固件包括 ShowCore 以及前端声学相关。固件格式为zip,更新方式为全量更新,固件大小在500MB左右

# Launcher

ShowCore 由 evs 语音助手以及 Launcher 页面构成。Launcher 页面包括用户在音箱上所有非第三方应用页面,包括桌面,设置页,闹钟,技能商店,内容发现页以及部分模板应用。

# 蓝小飞智屏开发者模式

如果你希望在蓝小飞智屏上快速体验自定义技能,在音箱上安装第三方apk进行体验,开发者选项能够满足你的需求。开发者选项提供了可视化的二次开发入口,通过开发者模式,你可以开启 Wi-Fi adb,使用 adb 执行命令去更换配置与深定制唤醒词。

# 如何进入开发者模式

开启蓝小飞智屏,进入【设置-关于】页面,连续点击【系统版本】7 次,会出现【开发者选项】入口,点击后即进入开发者模式。

# 可以做什么

开发者模式的主要功能包括开/关 Wi-Fi adb 、更换 client_id 、更换深定制唤醒词。

Wi-Fi adb 功能出厂时默认关闭,进入开发者选项后,可点击下图区域打开。打开 Wi-Fi adb 后,你可以在【设置-关于】页面查看设备的 ip 地址,然后通过 adb connect {ip} 的方式连接音箱。

连接音箱后,你可以通过 adb 来安装第三方 APK ,

配置文件包括设备的 client_iddevice_id,在开发者模式中,您可以更换 client_id 以及快速获取设备的 device_id

你可以将智屏的 client_id修改为你在 iFLYOS 设备接入平台创建的设备 client_id,并在设备接入平台的前/后拦截器配置自己开发的自定义技能,这样就可以在带屏上快速体验自己的技能。

蓝小飞智屏提供了自定义浅定制唤醒词的功能;若你的音箱希望使用深度唤醒词,可联系商务,讯飞将会为你训练效果更好的深定制唤醒词。拿到唤醒词资源后,将文件命名为 **wake_up.bin **; 通过 adb push wake_up.bin /sdcard/ 发送到 sdcard 目录。从开发者模式的【更换深定制唤醒词】入口进入 sdcard 目录,找到 **wake_up.bin ** 并替换即可。

注意

  1. Wi-Fi adb 状态的变更需要 重启设备 才能生效,所以在点击【打开/关闭 Wi-Fi adb】后,会弹出弹窗确认是否重启设备。
  2. 更换 client_id 后,尽管音箱通过配置文件中的相关参数来连接到 EVS ,但是 OTA 检查更新服务不会去检查你自定义的 client_id 对应的 OTA 后台中的包更新。
  3. 更换 client_id 完成后,需要重新对设备进行授权绑定。使用小飞在线 App 扫描设备上的二维码,按照 APP 流程进入相应产品页面中为设备授权绑定。授权完成即可通过蓝小飞智屏体验你为产品开发的相关能力。
  4. 由于更改 device_id 将导致 iFLYOS 与 CAE 鉴权失败,造成设备无法正常使用的情况,所以目前不支持更改 device_id

# 二次开发指引

根据开发者的需求,我们提供了不同的开发指引。具体如下:

# 一、无定制需求,在蓝小飞智屏的基础上做轻量二次开发

以下场景,可以参考此流程

  • 使用蓝小飞智屏的 Launcher 页面,无定制需求,希望在此基础上增加自己的自定义技能。
  • 使用蓝小飞智屏的 Launcher 页面,无定制需求,希望在此基础上运行第三方 APP,并能够通过语音与第三方 APP 完成语音交互,例如打开,退出,以及其他进阶操作。
  • 使用蓝小飞智屏的 Launcher 页面,无定制需求,希望在此基础上更换唤醒词。

针对满足以上一种或多种条件的开发者,无需使用开源 ShowCore ,蓝小飞智屏自带的开发者模式便能够满足需求,具体步骤如下:

1.进入开发者模式,将智屏的 client_id修改为你在 iFLYOS设备接入平台创建的设备 client_id,若需更换唤醒词,可点击【更换深定制唤醒词】进行替换。

2.若希望安装第三方 apk,在开发者模式中打开 Wi-Fi adb,执行adb install -r xxx.apk(xxx是 APK 文件名称,r 后面有空格)。安装完成后,会自动展示在智屏的应用中心。

3.前往技能工作室编写自定义技能及后处理,并将写好的技能配在设备接入平台的拦截器上。具体流程可参考 技能开发指引 (opens new window)

4.在智屏上体验自定义技能、第三方 APP 、唤醒词效果。确认无误后,联系讯飞商务人员,沟通相关费用,若达成一致,开发者需将 client_id (若更换唤醒词还需提供唤醒词资源)提供给讯飞,由讯飞打包固件输出给开发者。

若开发者后续有更新迭代的要求,讯飞可提供打包固件以及 OTA 升级服务。

# 二、有定制需求,根据自身需求二次开发界面

若开发者不使用或不完全使用蓝小飞智屏自带的 Launcher 页面,希望定制前端页面交互,那么可参考以下步骤:

1.联系商务,申请带系统签名的蓝小飞智屏固件,并按照刷机教程 (opens new window)将固件安装至蓝小飞智屏中。

2.从 github 下载开源 ShwoCore (opens new window),将 ShowCore 安装至蓝小飞智屏中。

3.安装开源 ShowCore 后,需要做如下准备工作:

# 将 ShowCore 作为系统应用运行

app/src/main/AndroidManifest.xml 中的

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.iflytek.cyber.iot.show.core">

    <!-- others ... -->

</manifest>

修改为

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.iflytek.cyber.iot.show.core"
    android:sharedUserId="android.uid.system">

    <!-- others ... -->

</manifest>

将 ShowCore 签名更换为固件相同的系统签名platform.keystore**(联系商务获取)**。

# 使用 CAE 获取录音

为了避免第三方应用中使用录音和语音助手发生冲突的情况,我们推荐在音箱中的语音助手应用使用封装后直接调用声卡捕获录音的方式来进行录音获取。因此,我们提供一个可用于蓝小飞智屏音箱固件的 CAE 录音调用方式,并封装为 aar 提供调用。

将 caeservice.aar**(联系商务获取)**复制到 app/libs 目录下,app/build.gradle 中增加依赖

dependencies {
    // ...
    implementation(name: 'caeservice', ext: 'aar')
    // ...
}

录音关键代码位于 app/src/main/java/com/iflytek/cyber/iot/show/core/record/GlobalRecorder.kt ,将其替换为如下内容。

package com.iflytek.cyber.iot.show.core.record

import com.iflytek.iflyos.cae.CAEService
import com.iflytek.iflyos.cae.IListener

object GlobalRecorder {
    @Suppress("unused")
    private const val TAG = "GlobalRecorder"

    var isRecording = false
        private set
    private val observerSet = HashSet<Observer>()

    private val ivwListener = object : IListener {
        override fun onAudio(audioData: ByteArray?, length: Int) {
            if (isRecording)
                publishAudioData(audioData ?: ByteArray(0), 0, length)
        }

        override fun onWakeUp(angle: Int, beam: Int, params: String?) {
            publishWakeUp(angle, beam, params)
        }

    }

    fun init() {
        CAEService.init(ivwListener)
    }

    fun startRecording() {
        isRecording = true
    }

    fun stopRecording() {
        isRecording = false
    }

    fun registerObserver(observer: Observer) {
        observerSet.add(observer)
    }

    fun unregisterObserver(observer: Observer) {
        observerSet.remove(observer)
    }

    private fun publishAudioData(
        array: ByteArray, @Suppress("SameParameterValue") offset: Int,
        length: Int
    ) {
        try {
            for (observer in observerSet) {
                try {
                    observer.onAudioData(array, offset, length)
                } catch (e: Exception) {
                    e.printStackTrace()
                }

            }
        } catch (e: ConcurrentModificationException) {
            // ignore possible ConcurrentModificationException
        }
    }

    private fun publishWakeUp(angle: Int, beam: Int, params: String?) {
        try {
            for (observer in observerSet) {
                try {
                    observer.onWakeUp(angle, beam, params)
                } catch (e: Exception) {
                    e.printStackTrace()
                }

            }
        } catch (e: ConcurrentModificationException) {
            // ignore possible ConcurrentModificationException
        }
    }

    interface Observer {
        fun onAudioData(array: ByteArray, offset: Int, length: Int)
        fun onWakeUp(angle: Int, beam: Int, params: String?)
    }
}

# OTA 功能修改

在 GitHub 中开源的 ShowCore 中,OTA 功能主要是提供更新 APK 的实现,而集成到音箱中时我们通常期望 OTA 更新的是固件。如果觉得没有更新固件的需求,那么可以忽略本步骤。

检查更新页面的类 CheckUpdateFragment 位于 com.iflytek.cyber.iot.show.core.fragment ,其中负责执行升级操作的代码为 onViewCreated 中为 updateButton 添加的点击监听中。

开源于 GitHub 中的用于 更新 APK 的升级逻辑如下

updateButton?.setOnClickListener {
    // ...
    downloadedPath?.let { path ->
        // ...

        PackageUtils.notifyInstallApk(it.context, path)

        // ...
    }
}

我们需要将这段逻辑修改为更新固件

updateButton?.setOnClickListener {
    // ...
    downloadedPath?.let { path ->
        // ...

        // PackageUtils.notifyInstallApk(it.context, path)
        Thread {
            TerminalUtils.execute("cp $path /sdcard/ota_update.zip")

            RecoverySystem.installPackage(
                it.context,
                File("/data/media/0/ota_update.zip")
            )

            progress.dismiss()
        }.start()

        // ...
    }
}

这段代码中表示将下载缓存中的固件包复制到 /sdcard/ 目录下,然后将固件包路径传到 RecoverySystem.installPackage (opens new window) 进行更新(该接口为 Android API 标准接口,需要在子线程中执行)。

4.做完上述准备工作后,便可根据 ShowCore介绍文档 (opens new window)做二次开发。智屏配套的移动端应用开发,可参照 APP SDK 文档 (opens new window)

# 三、有定制需求,希望讯飞提供二次开发服务

若你希望讯飞帮你在蓝小飞智屏的基础上做定制需求,可联系讯飞商务(联系方式xxxx)。整个流程包括:需求评估->合同签署->需求沟通->开发排期->测试验收->固件发布->硬件交货

若你的设备后续有迭代更新的需求我们也可以提供迭代开发以及固件 OTA 的服务。

# 四、希望使用 ShowCore 的界面 但不使用蓝小飞智屏硬件

可从 GitHub 上下载开源 ShowCore ,参照 GitHub 上的开发说明,以及 ShowCore 介绍文档 (opens new window)进行开发。智屏配套的移动端应用开发,可参照 APP SDK 文档 (opens new window)

# 五、只希望使用讯飞的语音交互能力,不用 ShowCore 界面和蓝小飞智屏硬件

讯飞将提供 EVS SDK (opens new window) 以及 API 文档 (opens new window) ,你可以将 SDK 集成至智能设备中,让你的设备具有语音交互能力。

#

# 常见问题

# 1.如何拆机,连接 usb?

我们提供两种方式帮助开发者连接音箱。

1.可以通过刷机教程 (opens new window),获取音箱 usb 口,将电脑与音箱通过数据线连接;

2.在开发者模式中,我们提供了 Wi-Fi adb 功能,你可以进入开发者模式打开 Wi-Fi adb 功能,通过 adb connect {ip} 连接设备。

# 2.如何在调试阶段进入 root 模式?

原则上,我们不希望开发者进入 root 模式,蓝小飞智屏无需 root 便可满足开发者的二次开发需求,若开发者有 root 需求,可联系讯飞技术支持人员。

# 3.如何将智屏开源 ShowCore 项目运行到设备上,替换掉智屏原有showCore

解决方案:

如果开发者希望基于蓝小飞智屏做二次开发,请勿将开源 ShowCore 直接替换掉智屏原有 ShowCore 。先联系讯飞工作人员,讯飞将提供带系统签名的固件。把固件安装刷在智屏上后,在音箱上运行开源 ShowCore ,并参照开发指引中的步骤进行操作后,再开始二次开发。

# 4.更换设备 client_id 后,扫码绑定页面提示授权失败。

解决方法: 请确定以下事项:

  1. 请在设备接入控制台-【设备能力】处,打开【屏幕配网】;
  2. 请在设备接入控制台-【产品测试】处,在白名单中输入用于登录小飞在线的手机号;
  3. 请在设备接入控制台-【设备ID】处,将您的设备 device_id 加到设备白名单中;

# 5.如何进行二次开发,例如实现打开第三方应用、打电话等自定义技能实现。

解决方法:

我们提供了技能开发指引 (opens new window),开发者可根据指引实现自定义技能,若开发过程中遇到问题,可以通过 iFLYOS 工单或论坛咨询。

# 6.通过 adb 更换唤醒词开机后提示应用无响应

解决方法:

代表替换的唤醒词资源格式错误或版本错误,无响应的提示框可以暂时不理会,等待一段时间后设备就会显示主界面,出现主界面后点击无响应提示框的 等待 按钮,即可对应用继续操作。但此时设备已无法正常进行语音交互,请进入开发者选项中的替换唤醒词指引页面,点击右上角恢复唤醒词。资源问题则请联系技术支持分析具体原因。

# 7.音箱刷了讯飞提供的固件后,交互效果差且音量变小。

解决方法:

可能是固件唤醒词与上层唤醒词冲突导致;若你的音箱有自己的唤醒词与唤醒引擎,请提前告知讯飞并提供唤醒词文件(70版本),讯飞将在打包固件时把你的唤醒词加载固件中。讯飞提供的固件中,默认唤醒词是小飞小飞。若固件本身的唤醒词与上层唤醒词不一致,将无法获取 CAE 音频,只能获得原始数字埋音频。原始音频未经回声消除和音频增益处理,交互效果与音量会受到较大程度的影响。

# 8.二次开发后的音箱,后续如何进行升级维护?

解决方法:

如果你的设备后续有更新固件的需求,可将最新版本的 ShowCore APK 文件(或第三方预装 APP)提供给讯飞。讯飞打包固件,你可在 iFLYOS 设备接入平台的【自动更新】中上传固件。正式发布后,设备端将收到更新提示。

# 9.开发者集成在音箱中的 APP,如何升级维护 ?

解决方法:

由于第三方 APP 在音箱的升级过程不受讯飞控制,为避免音箱在apk升级过程中崩溃或apk升级后包含违法敏感内容而遭到投诉,可将需要升级的 APP 提交给讯飞,讯飞审核通过后,将 APK 文件集成至新版固件中。你可将新版固件上传至企业平台并发布,通过固件升级来完成 APP 的升级。

#

#