因酷西安网站建设公司怎么样哪个软件可以制作游戏
因酷西安网站建设公司怎么样,哪个软件可以制作游戏,wordpress 上传图片,做华为网站的还有哪些功能吗从社死边缘拯救我#xff1a;用 AR 眼镜打造亲戚称呼助手
一个真实的新年灾难
大年初二#xff0c;我跟着新婚妻子回娘家。 刚进门#xff0c;七大姑八大姨就围了上来。一位头发花白的阿姨笑盈盈地递过来一个红包#xff0c;我脑子里嗡的一声——这到底是妻子的哪位…从社死边缘拯救我用 AR 眼镜打造亲戚称呼助手一个真实的新年灾难大年初二我跟着新婚妻子回娘家。刚进门七大姑八大姨就围了上来。一位头发花白的阿姨笑盈盈地递过来一个红包我脑子里嗡的一声——这到底是妻子的哪位亲戚大姨小姨还是什么远房表姑“小张啊还认识我不”我支支吾吾半天最后还是妻子打了圆场“这是大姨小时候还抱过你呢”那一刻我看到了大姨眼里的失望。这种社死现场相信很多人都经历过春节期间走亲访友是必修课但那些一年见一次的亲戚名字和称呼根本记不住。尤其是刚结婚的新人、不常回家的打工人简直是称呼灾难高发人群。回家后我下定决心明年春节我绝不能再叫错人。思路为什么是 AR 眼镜解决方案无非几种● 记在手机备忘录掏手机、解锁、搜索太慢而且当着亲戚面查手机很不礼貌● 记在小本本上更尴尬像是在做作弊小抄● 让家人提醒每次都要麻烦别人不靠谱想了很久我注意到桌上的 Rokid AR 眼镜。眼镜有几个天然优势对比维度手机AR 眼镜使用隐蔽性众人可见你在查手机只有自己能看到屏幕内容操作便捷度掏出→解锁→搜索→查看抬眼即见无需动手社交压力明显在看手机不礼貌自然地瞟一眼谁也发现不了响应速度打开APP需要几秒信息即时显示项目搭建从零开始集成 SDK1. 创建项目并配置 Maven 仓库首先是一个标准的 Android 项目Kotlin 语言minSdk 设为 28SDK 硬性要求。在 settings.gradle.kts 中添加 Rokid 的 Maven 仓库// settings.gradle.kts dependencyResolutionManagement{repositories{maven{urluri(https://maven.rokid.com/repository/maven-public/)}google()mavenCentral()}}2. 添加依赖项在 app/build.gradle.kts 中引入 CXR-M SDK 和必要的 Android 组件// app/build.gradle.kts android{namespacecom.rokid.relativehelpercompileSdk34defaultConfig{minSdk28targetSdk34}}dependencies{// Rokid CXR-M SDK implementation(com.rokid.cxr:client-m:1.0.1-20250812.080117-2)// Android 组件 implementation(androidx.core:core-ktx:1.12.0)implementation(com.google.android.material:material:1.11.0)implementation(androidx.recyclerview:recyclerview:1.3.2)implementation(androidx.lifecycle:lifecycle-livedata-ktx:2.7.0)}3. 权限声明眼镜与手机通过蓝牙通信需要声明相关权限。Android 12 对蓝牙权限做了拆分需要特别注意!-- AndroidManifest.xml --!-- 蓝牙基础权限 --uses-permission android:nameandroid.permission.BLUETOOTH/uses-permission android:nameandroid.permission.BLUETOOTH_ADMIN/!-- Android12 蓝牙扫描/连接权限 --uses-permission android:nameandroid.permission.BLUETOOTH_SCANandroid:usesPermissionFlagsneverForLocation/uses-permission android:nameandroid.permission.BLUETOOTH_CONNECT/!-- 定位权限部分设备蓝牙扫描需要 --uses-permission android:nameandroid.permission.ACCESS_FINE_LOCATION/关键提示Android 12 以上BLUETOOTH_SCAN 和 BLUETOOTH_CONNECT 必须在运行时动态申请仅 Manifest 声明会导致崩溃。数据模型如何存储亲戚信息先定义一个简洁的数据结构。每个亲戚条目需要名字、称呼、关系描述、拜年话术以及可选的拼音和备注// model/Relative.kt data class Relative(var id: Long0, val name: String, // 亲戚名字如王芳val title: String, // 称呼如大姨、叔叔val relation: String, // 关系描述如妈妈的姐姐val greetingTemplate: String, // 拜年话术模板 val phonetic: String?null, // 名字拼音可选防止读错 val notes: String?null // 备注可选){/** * 生成眼镜端显示的格式化文本 */ fun toGlassDisplayText(): StringbuildString{appendLine($name)appendLine()appendLine(称呼$title)appendLine(关系$relation)appendLine()appendLine(────── 拜年话术 ──────)appendLine(greetingTemplate)}}这个 toGlassDisplayText() 方法很关键——它决定了信息在眼镜上的呈现方式。我选择了简洁清晰的格式 王芳 称呼大姨 关系妈妈的姐姐 ────── 拜年话术 ────── 大姨新年好祝您身体健康万事如意这样在眼镜上一眼就能看到关键信息。数据持久化亲戚数据需要持久化存储。考虑到数据量不大通常几十条我选择了最简单的 SharedPreferences JSON 序列化方案// data/RelativeRepository.kt object RelativeRepository{private const val PREFS_NAMErelative_helper_prefsprivate const val KEY_RELATIVESrelativesprivate val relativesmutableListOfRelative()fun init(context: Context){loadFromPrefs(context)if(relatives.isEmpty()){loadPresetData()// 首次运行加载预设数据}}fun searchRelatives(keyword: String): ListRelative{if(keyword.isBlank())returnrelatives.toList()val lowerKeywordkeyword.lowercase()returnrelatives.filter{it.name.contains(keyword, ignoreCasetrue)||it.title.contains(keyword, ignoreCasetrue)||it.relation.contains(keyword, ignoreCasetrue)}}private funloadPresetData(){// 内置20条常见亲戚数据涵盖祖辈、父辈、同辈 relatives.addAll(listOf(Relative(1,王芳,大姨,妈妈的姐姐,大姨新年好祝您身体健康万事如意), Relative(2,李明,叔叔,爸爸的弟弟,叔叔过年好祝您事业顺利财源广进), //... 更多预设))}}此外我还实现了一个贴心的小功能根据称呼自动生成拜年话术。比如输入爷爷自动填充爷爷新年好祝您身体健康长命百岁fun generateDefaultGreeting(title: String): Stringwhen(title){爷爷,外公-${title}新年好祝您身体健康长命百岁奶奶,外婆-${title}新年好祝您福如东海寿比南山姑姑,婶婶,舅妈,大姨,小姨-${title}新年好祝您青春永驻越来越年轻表哥,堂哥-${title}新年好祝今年发大财else-${title}新年好祝您新年快乐万事如意}核心眼镜通信模块这是整个项目最核心的部分——如何让手机和眼镜对话SDK 封装思路CXR-M SDK 提供了 CxrApi 类作为通信入口包含蓝牙连接、场景控制、数据发送等功能。为了方便使用我将其封装成单例对象 RokidGlassesManager// sdk/RokidGlassesManager.kt object RokidGlassesManager{private val cxrApi: CxrApi by lazy{CxrApi.getInstance()}private var connectionCallback: ConnectionCallback?null // 连接状态回调接口 interface ConnectionCallback{fun onConnecting()fun onConnected()fun onDisconnected()fun onFailed(errorMsg: String)}// 检查蓝牙是否已连接 val isBluetoothConnected: Boolean get()cxrApi.isBluetoothConnected}蓝牙连接流程连接眼镜分为两步先调用 initBluetooth 获取连接信息再调用 connectBluetooth 建立实际连接fun initBluetoothConnection(context: Context, device: BluetoothDevice){connectionCallback?.onConnecting()// 第一步初始化蓝牙获取 UUID 和 MAC 地址 cxrApi.initBluetooth(contextcontext, devicedevice, callbackobject:BluetoothStatusCallback(){override fun onConnectionInfo(socketUuid: String?, macAddress: String?, rokidAccount: String?, glassesType: Int){if(!socketUuid.isNullOrEmpty()!macAddress.isNullOrEmpty()){// 第二步使用获取的信息建立连接 connectBluetooth(context, socketUuid, macAddress)}else{connectionCallback?.onFailed(获取连接信息失败)}}override funonConnected(){connectionCallback?.onConnected()}override funonDisconnected(){connectionCallback?.onDisconnected()}override fun onFailed(errorCode: ValueUtil.CxrBluetoothErrorCode?){connectionCallback?.onFailed(getBluetoothErrorMessage(errorCode))}})}踩坑提醒SDK 的蓝牙连接是异步的所有结果都通过回调返回。不要试图同步等待连接结果会导致死锁。发送数据到眼镜数据发送是整个应用的关键功能。这里有一个必须注意的顺序先打开提词器场景再发送文本数据fun sendTextToGlasses(text: String, callback: SendCallback?null): Boolean{if(!isBluetoothConnected){callback?.onFailed(眼镜未连接)returnfalse}// 关键必须先打开提词器场景 openWordTipsScene()val statuscxrApi.sendStream(typeValueUtil.CxrStreamType.WORD_TIPS, streamtext.toByteArray(Charsets.UTF_8), // 注意编码 fileNamerelative_info.txt, cbobject:SendStatusCallback(){override funonSendSucceed(){callback?.onSuccess()}override fun onSendFailed(errorCode: ValueUtil.CxrSendErrorCode?){callback?.onFailed(getSendErrorMessage(errorCode))}})returnstatusValueUtil.CxrStatus.REQUEST_SUCCEED}private fun openWordTipsScene(): Boolean{val statuscxrApi.controlScene(sceneTypeValueUtil.CxrSceneType.WORD_TIPS, openOrClosetrue, otherParamsnull)returnstatusValueUtil.CxrStatus.REQUEST_SUCCEED}我第一次调试时sendStream 返回成功但眼镜端什么都没显示。排查了半天才发现是场景没打开——这个坑踩得很痛。TTS 语音播报除了文字显示SDK 还支持 TTS文字转语音功能可以在同步信息后播放语音提示fun sendTtsFeedback(text: String): Boolean{if(!isBluetoothConnected)returnfalseval statuscxrApi.sendTtsContent(text)if(statusValueUtil.CxrStatus.REQUEST_SUCCEED){// 关键必须通知 TTS 播放完成 cxrApi.notifyTtsAudioFinished()}returnstatusValueUtil.CxrStatus.REQUEST_SUCCEED}注意调用 sendTtsContent 后必须再调用 notifyTtsAudioFinished()否则 TTS 可能播放不完整。UI 界面简洁实用优先主界面采用经典的列表式布局● 顶部眼镜连接状态指示器 连接按钮● 中间搜索框 亲戚卡片列表● 右下角浮动添加按钮布局结构!-- layout/activity_main.xml --androidx.coordinatorlayout.widget.CoordinatorLayout!-- 顶部 Toolbar --com.google.android.material.appbar.AppBarLayoutandroidx.appcompat.widget.Toolbar app:title亲戚称呼助手//com.google.android.material.appbar.AppBarLayoutLinearLayout!-- 眼镜连接状态卡片 --androidx.cardview.widget.CardViewLinearLayoutView android:idid/connection_indicator/!-- 状态指示灯 --TextView android:idid/tv_connection_status/MaterialButton android:idid/btn_connect//LinearLayout/androidx.cardview.widget.CardView!-- 搜索框 --TextInputLayout app:startIconDrawabledrawable/ic_searchTextInputEditText android:idid/et_search//TextInputLayout!-- 亲戚列表 --RecyclerView android:idid/recycler_view//LinearLayout!-- 添加按钮 --FloatingActionButton android:idid/fab_add//androidx.coordinatorlayout.widget.CoordinatorLayout列表项卡片每张卡片展示一个亲戚的关键信息并提供同步到眼镜按钮!-- layout/item_relative.xml --androidx.cardview.widget.CardViewLinearLayout android:orientationvertical!-- 名字大字加粗 --TextView android:idid/tv_nameandroid:textSize18spandroid:textStylebold/!-- 称呼标签 关系描述 --LinearLayout android:orientationhorizontalTextView android:idid/tv_titleandroid:backgrounddrawable/bg_tag/TextView android:idid/tv_relation//LinearLayout!-- 拜年话术预览最多两行 --TextView android:idid/tv_greetingandroid:maxLines2android:ellipsizeend/!-- 同步按钮 --Button android:idid/btn_syncandroid:text同步到眼镜//LinearLayout/androidx.cardview.widget.CardViewActivity 核心逻辑// MainActivity.kt class MainActivity:AppCompatActivity(){private val glassesManagerRokidGlassesManager override fun onCreate(savedInstanceState: Bundle?){// 初始化数据 RelativeRepository.init(this)// 设置眼镜连接回调 glassesManager.setConnectionCallback(object:ConnectionCallback{override funonConnected(){updateConnectionStatus(true)Snackbar.make(binding.root,眼镜连接成功, Snackbar.LENGTH_SHORT).show()}override funonDisconnected(){updateConnectionStatus(false)}//...})// 搜索功能 binding.etSearch.addTextChangedListener{text -filterRelatives(text?.toString()?:)}}private fun syncToGlasses(relative: Relative){if(!glassesManager.isBluetoothConnected){Snackbar.make(binding.root,请先连接眼镜, Snackbar.LENGTH_SHORT).show()return}val textrelative.toGlassDisplayText()glassesManager.sendTextToGlasses(text, object:SendCallback{override funonSuccess(){Snackbar.make(binding.root,已同步到眼镜, Snackbar.LENGTH_SHORT).show()// 语音提示 glassesManager.sendTtsFeedback(${relative.title}的信息)}override fun onFailed(errorMsg: String){Snackbar.make(binding.root,同步失败:$errorMsg, Snackbar.LENGTH_LONG).show()}})}}踩坑实录那些文档没告诉你的事坑一蓝牙权限动态申请Android 12API 31对蓝牙权限做了重大调整将原来的 BLUETOOTH 和 BLUETOOTH_ADMIN 拆分为更细粒度的 BLUETOOTH_SCAN 和 BLUETOOTH_CONNECT。关键点这些新权限必须运行时动态申请。仅 Manifest 声明在 Release 版本中会直接崩溃。private fun checkAndRequestPermissions(): Boolean{val permissionsif(Build.VERSION.SDK_INTBuild.VERSION_CODES.S){arrayOf(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.ACCESS_FINE_LOCATION)}else{arrayOf(Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.ACCESS_FINE_LOCATION)}val notGrantedpermissions.filter{ActivityCompat.checkSelfPermission(this, it)!PackageManager.PERMISSION_GRANTED}if(notGranted.isEmpty())returntrueActivityCompat.requestPermissions(this, notGranted.toTypedArray(), REQUEST_PERMISSIONS)returnfalse}坑二提词器场景必须先打开这个问题让我调试了整整一下午。sendStream 调用返回成功但眼镜端什么都没显示。最后发现必须先调用 controlScene 打开提词器场景才能发送数据。// 正确顺序 cxrApi.controlScene(WORD_TIPS, true, null)// 先打开场景 cxrApi.sendStream(WORD_TIPS, data,...)// 再发送数据坑三中文编码第一次发送中文内容眼镜上显示一堆乱码。原因是 toByteArray() 默认使用系统编码在某些设备上可能不是 UTF-8。// 错误 streamtext.toByteArray()// 正确 streamtext.toByteArray(Charsets.UTF_8)最终效果功能清单功能状态说明亲戚列表✅支持按名字/称呼/关系搜索添加/编辑/删除✅表单输入自动生成话术眼镜连接✅自动发现已配对设备眼镜同步✅一键发送称呼话术TTS 播报✅语音反馈同步成功预设数据✅内置 20 条常见亲戚眼镜端显示效果当你在手机上点击同步到眼镜后眼镜屏幕上会立即显示┌─────────────────────────────┐ │ │ │ 王芳 │ │ │ │ 称呼大姨 │ │ 关系妈妈的姐姐 │ │ │ │ ────── 拜年话术 ────── │ │ │ │ 大姨新年好 │ │ 祝您身体健康万事如意 │ │ │ └─────────────────────────────┘春节拜年时当亲戚走过来你只需要悄悄瞟一眼眼镜称呼和话术尽收眼底从容应对再也不会叫错人了。总结与展望这个项目从想法到完成只用了两天时间代码量不大约 800 行但确实解决了一个真实痛点。技术亮点● CXR-M SDK 的正确使用方式场景控制 数据发送的顺序问题● Android 12 蓝牙权限的正确处理● 简洁实用的数据模型设计未来改进方向● 加入语音识别说这个是谁自动识别并显示● 支持拍照识别亲戚需要人脸识别技术● 关系图谱可视化直观展示家族关系● 云端数据同步换手机不丢数据项目源码RelativeTitleHelper/相关资源● CXR-M SDK 官方文档● Rokid 开发者论坛