2. Wear OS应用架构与项目结构
Wear OS 应用并不是把手机应用“缩小”后直接搬到手表上。它运行在屏幕尺寸、交互方式、传感器能力、功耗预算和系统调度策略都截然不同的设备上,因此从工程结构开始就与手机应用存在系统性差异。理解这些差异,是后续开发、调试和上架的基础。
一、Wear OS 与手机应用的核心差异
最直观的差异来自交互模型。手机以触摸为主,手表则以“抬腕即看”的短时交互为核心,辅以旋转表冠、物理按键、语音和手势。这决定了 Wear OS 界面必须支持 环境模式(Ambient Mode):当用户放下手腕或系统进入低功耗状态时,界面会切换到简化、低刷新率的显示形态。手机应用通常没有这一状态,因此 Wear OS 的界面组件需要显式处理“交互态”和“环境态”两套渲染逻辑。
其次是进程与生命周期。Wear OS 对后台任务限制更严格,长时间运行的服务容易被系统回收。应用需要把耗时操作交给 WorkManager 或前台服务,并尽量让界面层保持轻量。此外,手表常作为手机的“伴随设备”存在,数据同步、通知转发、能力协商都依赖 Wearable Data Layer API,而不是简单的本地数据库共享。
第三是模块划分。现代 Wear OS 项目通常采用多模块结构,把“可复用逻辑”“手表界面”“手机端伴随应用”“数据层协议”拆开,避免把手机代码直接塞进手表模块。下面这张结构图展示了典型的分层与依赖方向。
二、Manifest 配置的关键差异
Wear OS 的 AndroidManifest.xml 与手机应用有三处必须注意的差异。第一,手表应用需要声明 <uses-feature android:name="android.hardware.type.watch" />,让 Play 商店正确识别设备类型。第二,如果应用需要独立运行(不依赖手机),应在 <application> 中设置 android:standalone="true";若必须与手机配对,则用 android:companion="true" 并配合手机端模块。第三,环境模式需要声明 WAKE_LOCK 权限,并在 Activity 中实现 AmbientModeSupport.AmbientCallbackProvider。
一个典型的手表模块 Manifest 片段如下:
<uses-feature android:name="android.hardware.type.watch" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:label="@string/app_name"
android:standalone="true">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
注意 standalone 与 companion 的选择会直接影响安装逻辑:独立应用可单独安装到手表,伴随应用则要求手机端先安装。若两者都声明,系统会按独立应用处理,但数据同步仍需自行实现。
三、资源目录的组织方式
Wear OS 的资源目录与手机类似,但需要额外考虑圆形屏幕和不同屏幕密度。常用限定符包括 values-round(圆形表盘专用尺寸)、drawable-hdpi 到 drawable-xxhdpi(手表常见 1.0x~2.0x 密度)。对于表盘或 Tiles,还需要在 res/xml 下放置 watch_face.xml 或 tile_service.xml 等描述文件。
一个推荐的做法是:把通用颜色、字符串放在 values/,把圆形屏幕专用的边距、字号放在 values-round/,把方形屏幕的对应值放在 values-square/。这样同一套布局代码可以在两种表盘形态下自动适配,而不需要写两套 XML。
build.gradle 中为手表模块单独设置 minSdk(建议 26 以上)和 targetSdk,并启用 composeOptions 以使用 Compose for Wear OS。手机模块与手表模块的版本号可以独立管理,但共享模块的版本必须保持一致,避免 Data Layer 序列化协议不匹配。
四、从项目结构到运行时的映射
理解模块划分后,还需要知道代码在运行时如何落到具体进程。手表模块编译为独立的 APK,安装后拥有自己的进程和 applicationId;手机模块同理。两者通过 MessageClient 发送消息时,系统会根据节点 ID 和路径路由,而不是直接调用对方的方法。因此,共享模块只共享编译期代码,不共享运行时内存。这一点在调试时尤其重要:手表端日志和手机端日志需要分别查看,不能假设变量在两端同步。
最后,资源目录中的 res/values/wear.xml 可用于声明应用支持的能力(如 com.example.watchface),手机端通过 CapabilityClient 查询这些能力来决定是否显示“发送到手表”按钮。这种“能力协商”机制是 Wear OS 应用架构中区别于手机应用的重要设计,也是多设备协同的基础。
:wear、:phone、:shared、:datalayer 四个模块,依赖方向自上而下,跨设备通信走 Data Layer 而非直接依赖。Manifest 中必须声明手表特性,并根据独立/伴随模式设置 standalone 或 companion。资源目录需用 values-round 等限定符适配圆形屏幕。