feat: 初始化 SDK
This commit is contained in:
parent
41726d5006
commit
22ff4384ca
Binary file not shown.
|
|
@ -3,7 +3,7 @@
|
|||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<application
|
||||
android:name=".app.RokidApplication"
|
||||
android:name=".RokidApplication"
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
package com.yuanxuan.rokid
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.addCallback
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.yuanxuan.rokid.dependencies.AppDependencies
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
|
@ -16,5 +21,9 @@ class MainActivity : AppCompatActivity() {
|
|||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
|
||||
insets
|
||||
}
|
||||
AppDependencies.deviceServiceManager.playTTS("测试一下")
|
||||
|
||||
onBackPressedDispatcher.addCallback {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package com.yuanxuan.rokid
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Intent
|
||||
import com.yuanxuan.rokid.dependencies.AppDependencies
|
||||
import com.yuanxuan.rokid.dependencies.ApplicationDependencyProvider
|
||||
import com.yuanxuan.rokid.keeplive.KeepLiveService
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
class RokidApplication : Application() {
|
||||
|
||||
private val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
Timber.plant(Timber.DebugTree())
|
||||
AppDependencies.init(this, ApplicationDependencyProvider(this))
|
||||
/**
|
||||
* 启动APP必须先获取到SN 后面网络依赖
|
||||
*/
|
||||
applicationScope.launch {
|
||||
val sn = AppDependencies.deviceServiceManager.getSn()
|
||||
Timber.d("sn = $sn")
|
||||
}
|
||||
/**
|
||||
* 这个服务保证心跳包准时发
|
||||
*/
|
||||
val serviceIntent = Intent(this, KeepLiveService::class.java)
|
||||
startForegroundService(serviceIntent)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
package com.yuanxuan.rokid.app
|
||||
|
||||
import android.app.Application
|
||||
|
||||
class RokidApplication : Application() {
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package com.yuanxuan.rokid.dependencies
|
||||
|
||||
import android.app.Application
|
||||
import com.yuanxuan.rokid.device.DeviceServiceManager
|
||||
|
||||
/**
|
||||
* 项目的服务管理器,所有依赖集中管理
|
||||
*/
|
||||
object AppDependencies {
|
||||
|
||||
private lateinit var _application: Application
|
||||
private lateinit var provider: Provider
|
||||
|
||||
fun init(application: Application, provider: Provider) {
|
||||
if (this::_application.isInitialized || this::provider.isInitialized) {
|
||||
return
|
||||
}
|
||||
|
||||
_application = application
|
||||
AppDependencies.provider = provider
|
||||
}
|
||||
|
||||
val deviceServiceManager by lazy {
|
||||
provider.provideDeviceServiceManager()
|
||||
}
|
||||
|
||||
interface Provider {
|
||||
fun provideDeviceServiceManager(): DeviceServiceManager
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.yuanxuan.rokid.dependencies
|
||||
|
||||
import android.app.Application
|
||||
import com.yuanxuan.rokid.device.DeviceServiceManager
|
||||
|
||||
class ApplicationDependencyProvider(val context: Application) : AppDependencies.Provider {
|
||||
override fun provideDeviceServiceManager(): DeviceServiceManager {
|
||||
return DeviceServiceManager(context)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
package com.yuanxuan.rokid.device
|
||||
|
||||
import android.app.Application
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import com.rokid.dcg.sprite.service.IInstructListener
|
||||
import com.rokid.dcg.sprite.service.IInstructService
|
||||
import com.rokid.dcg.sprite.service.ISpriteMediaService
|
||||
import com.rokid.dcg.sprite.service.ISystemFuncService
|
||||
import com.rokid.dcg.sprite.service.ITTSService
|
||||
import com.rokid.dcg.sprite.service.ServiceManager
|
||||
import com.rokid.dcg.sprite.syskey.SysKeyAction
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import timber.log.Timber
|
||||
import kotlin.coroutines.resume
|
||||
|
||||
|
||||
class DeviceServiceManager(val context: Application) {
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* 语音指令等待超时
|
||||
*/
|
||||
private const val INSTRUCT_WAITE_TIME = 15000L
|
||||
}
|
||||
|
||||
private var instructService: IInstructService? = null
|
||||
private var ttsService: ITTSService? = null
|
||||
private var systemFuncService: ISystemFuncService? = null
|
||||
private var spriteMediaService: ISpriteMediaService? = null
|
||||
|
||||
private val _instructState = MutableStateFlow<InstructState>(InstructState.None)
|
||||
val instructState = _instructState.asStateFlow()
|
||||
|
||||
lateinit var sn: String
|
||||
private set
|
||||
|
||||
val coroutineExceptionHandler = CoroutineExceptionHandler { _, exception ->
|
||||
Timber.e(exception, "全局捕获协程异常:${exception.message}")
|
||||
}
|
||||
private val scope =
|
||||
CoroutineScope(SupervisorJob() + Dispatchers.Main + coroutineExceptionHandler)
|
||||
private var wakeTimeoutJob: Job? = null
|
||||
|
||||
init {
|
||||
val filter = IntentFilter()
|
||||
filter.addAction(SysKeyAction.SPRITE_BUTTON_DOWN)
|
||||
filter.addAction(SysKeyAction.SPRITE_BUTTON_UP)
|
||||
filter.addAction(SysKeyAction.SPRITE_BUTTON_CLICK)
|
||||
filter.addAction(SysKeyAction.SPRITE_BUTTON_LONG_PRESS)
|
||||
filter.addAction(SysKeyAction.SPRITE_BUTTON_VERY_VERY_LONG_PRESS)
|
||||
filter.addAction(SysKeyAction.TOUCH_BAR_LONG_PRESS)
|
||||
context.registerReceiver(SysKeyReceiver(), filter)
|
||||
|
||||
scope.launch {
|
||||
instructState.collect {
|
||||
Timber.d("语音指令状态 $it")
|
||||
when (it) {
|
||||
InstructState.None -> instructService?.unregisterListener(instructListener)
|
||||
InstructState.WaitingInstructState -> {
|
||||
instructService?.registerListener(instructListener)
|
||||
startWakeTimeoutCountdown()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val instructListener = object : IInstructListener.Stub() {
|
||||
override fun onInstructReceived(p0: Int) {
|
||||
Timber.d("接受到语音指令$p0")
|
||||
if (p0 != IInstructService.INSTRUCT_QUIT) {
|
||||
startWakeTimeoutCountdown()
|
||||
}
|
||||
when (p0) {
|
||||
IInstructService.INSTRUCT_WAKEUP -> {
|
||||
}
|
||||
|
||||
IInstructService.INSTRUCT_VOLUME_UP -> {
|
||||
systemFuncServiceTodo { service ->
|
||||
setVolumeSpecified(service.volumeSpecified + 1)
|
||||
}
|
||||
}
|
||||
|
||||
IInstructService.INSTRUCT_VOLUME_DOWN -> {
|
||||
systemFuncServiceTodo { service ->
|
||||
setVolumeSpecified(service.volumeSpecified - 1)
|
||||
}
|
||||
}
|
||||
|
||||
IInstructService.INSTRUCT_LIGHT_UP -> {
|
||||
systemFuncServiceTodo { service ->
|
||||
setBrightnessSpecified(service.brightnessSpecified + 1)
|
||||
}
|
||||
}
|
||||
|
||||
IInstructService.INSTRUCT_LIGHT_DOWN -> {
|
||||
systemFuncServiceTodo { service ->
|
||||
setBrightnessSpecified(service.brightnessSpecified - 1)
|
||||
}
|
||||
}
|
||||
|
||||
IInstructService.INSTRUCT_TAKE_PHOTO -> {
|
||||
|
||||
}
|
||||
|
||||
IInstructService.INSTRUCT_START_AUDIO_RECORD -> {
|
||||
|
||||
}
|
||||
|
||||
IInstructService.INSTRUCT_STOP_AUDIO_RECORD -> {
|
||||
|
||||
}
|
||||
|
||||
IInstructService.INSTRUCT_START_VIDEO_RECORD -> {
|
||||
|
||||
}
|
||||
|
||||
IInstructService.INSTRUCT_STOP_VIDEO_RECORD -> {
|
||||
|
||||
}
|
||||
|
||||
IInstructService.INSTRUCT_QUIT -> {
|
||||
_instructState.update { InstructState.None }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [INSTRUCT_WAITE_TIME] 一段时间无新指令 退出等待状态
|
||||
*/
|
||||
private fun startWakeTimeoutCountdown() {
|
||||
wakeTimeoutJob?.cancel()
|
||||
wakeTimeoutJob = scope.launch {
|
||||
delay(INSTRUCT_WAITE_TIME)
|
||||
_instructState.update { InstructState.None }
|
||||
}
|
||||
}
|
||||
|
||||
fun playTTS(msg: String) {
|
||||
ttsServiceTodo {
|
||||
ttsService?.playTtsMsg(msg)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getSn() = suspendCancellableCoroutine { continuation ->
|
||||
systemFuncServiceTodo { service ->
|
||||
sn = service.sn
|
||||
continuation.resume(sn)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun ttsServiceTodo(crossinline todo: (ITTSService) -> Unit) {
|
||||
if (ttsService == null) {
|
||||
ServiceManager.getTTSService(context) { service ->
|
||||
if (service == null) {
|
||||
Timber.d("设备初始化TTS服务失败")
|
||||
return@getTTSService
|
||||
}
|
||||
ttsService = service
|
||||
todo.invoke(service)
|
||||
}
|
||||
} else {
|
||||
todo.invoke(ttsService!!)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun systemFuncServiceTodo(crossinline todo: (ISystemFuncService) -> Unit) {
|
||||
if (systemFuncService == null) {
|
||||
ServiceManager.getSystemFuncService(context) { service ->
|
||||
if (service == null) {
|
||||
Timber.d("设备初始化系统功能服务失败")
|
||||
return@getSystemFuncService
|
||||
}
|
||||
systemFuncService = service
|
||||
todo.invoke(service)
|
||||
Timber.d(" ${service.sn}")
|
||||
}
|
||||
} else {
|
||||
todo.invoke(systemFuncService!!)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun instructServiceTodo(crossinline todo: (IInstructService) -> Unit) {
|
||||
if (instructService == null) {
|
||||
ServiceManager.getInstructService(context) { service ->
|
||||
if (service == null) {
|
||||
Timber.d("设备初始化语音指令服务失败")
|
||||
return@getInstructService
|
||||
}
|
||||
instructService = service
|
||||
todo.invoke(service)
|
||||
}
|
||||
} else {
|
||||
todo.invoke(instructService!!)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setVolumeSpecified(volume: Int) {
|
||||
systemFuncService?.volumeSpecified = volume.coerceIn(0, 15)
|
||||
}
|
||||
|
||||
private fun setBrightnessSpecified(brightness: Int) {
|
||||
systemFuncService?.brightnessSpecified = brightness.coerceIn(0, 15)
|
||||
}
|
||||
|
||||
inner class SysKeyReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
val action = intent?.action ?: return
|
||||
when (action) {
|
||||
SysKeyAction.SPRITE_BUTTON_DOWN -> {
|
||||
Timber.d("按下拍照键 SPRITE_BUTTON_DOWN")
|
||||
}
|
||||
|
||||
SysKeyAction.SPRITE_BUTTON_UP -> {
|
||||
Timber.d("抬起拍照键 SPRITE_BUTTON_UP")
|
||||
}
|
||||
|
||||
SysKeyAction.SPRITE_BUTTON_CLICK -> {
|
||||
Timber.d("点击拍照键 SPRITE_BUTTON_CLICK")
|
||||
}
|
||||
|
||||
SysKeyAction.SPRITE_BUTTON_LONG_PRESS -> {
|
||||
Timber.d("长按拍照键 SPRITE_BUTTON_LONG_PRESS")
|
||||
}
|
||||
|
||||
SysKeyAction.SPRITE_BUTTON_VERY_VERY_LONG_PRESS -> {
|
||||
Timber.d("超级长的长按拍照键 SPRITE_BUTTON_VERY_VERY_LONG_PRESS")
|
||||
}
|
||||
|
||||
SysKeyAction.TOUCH_BAR_LONG_PRESS -> {
|
||||
Timber.d("长按触摸板 TOUCH_BAR_LONG_PRESS")
|
||||
instructServiceTodo {
|
||||
_instructState.update { InstructState.WaitingInstructState }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface InstructState {
|
||||
data object None : InstructState
|
||||
data object WaitingInstructState : InstructState
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ class KeepLiveService : Service() {
|
|||
companion object {
|
||||
const val NOTIFICATION_CHANNEL_ID = "KeepLiveServiceChannel"
|
||||
const val NOTIFICATION_CHANNEL_NAME = NOTIFICATION_CHANNEL_ID
|
||||
const val NOTIFICATION_ID = 101 // 使用一个唯一的ID
|
||||
const val NOTIFICATION_ID = 101
|
||||
const val WAKE_LOCK_TAG = "KeepLiveService:WakeLock"
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue