这是一份AI技术方案,将我现有的Qt应用转为Android应用。
一、项目概述
| 项目要素 | 说明 |
|---|---|
| 目标 | 将现有Qt上位机软件转为原生Android应用 |
| 开发语言 | Kotlin(Java开发者可无缝上手) |
| 最低SDK | API 28 (Android 9.0) —— 经重新评估后的正式起点 |
| 目标SDK | API 36 (Android 16) |
| 适配要求 | 手机和平板自适应,支持横屏/竖屏切换 |
| 网络通信 | 局域网WiFi通信(Socket/NSD) |
| 核心数据 | SQLite持久化 + 内存缓存(多雷达阵面管理) |
| 核心约束 | 低成本、高稳定、易维护 |
二、Android版本支持策略(关键决策)
2.1 最终确定的最低支持版本
经过全面评估,最低正式支持版本定为 Android 9.0 (API 28),不再支持Android 8及以下版本。
| Android 版本 | API Level | 支持策略 | 决策理由 |
|---|---|---|---|
| Android 5.0 | API 21 | ❌ 不支持 | 市场份额已极低(<1%),维护成本高 |
| Android 6.0 | API 23 | ❌ 不支持 | 运行时权限模型老旧,兼容性投入产出比低 |
| Android 7.0 | API 24 | ❌ 不作为正式目标 | 2026年7月起Google Play服务最低要求已升至API 24,继续支持存在底层服务风险 |
| Android 8.0 | API 26 | ⚠️ 不建议 | 开发框架趋势明确向上,维护成本高 |
| Android 9.0 | API 28 | ✅ 最低正式支持 | 稳定存量设备,避开API 21-26的维护泥潭 |
| Android 10~12 | API 29~31 | ✅ 重点兼容 | 用户基数庞大,测试性价比最高 |
| Android 13~15 | API 33~35 | ✅ 重点兼容 | 当前及未来的主流版本 |
| Android 16 | API 36 | ✅ 当前目标 | 2026年最新版本,需关注大屏强制适配 |
| Android 17 | API 37 | ✅ 前瞻适配 | 长期迭代目标,确保新设备兼容 |
2.2 版本策略的核心理由
- 生态系统的自然淘汰:2026年7月,Google Play服务最低要求已提升至Android 7.0 (API 24)。继续支持更老版本,设备可能因缺少底层服务更新而无法正常运行应用。
- 开发框架的跟进趋势:主流开发框架正加速放弃对Android 8及更早版本的支持。选择API 28作为起点,能在未来更长时间内使用最新的稳定版开发库。
- "低成本稳定"的真实含义:支持Android 5-8意味着投入额外时间处理老旧系统特有的Bug和兼容性问题。放弃市场份额已极低的旧系统,将精力集中在主流版本上,反而是更经济、更稳健的策略。
2.3 如确有特殊需求需覆盖极老设备
若因特殊场景(如军工、特定工业现场)必须支持Android 5-8设备,建议采取以下策略:
- 从Google Play的兼容设备列表中移除这些设备
- 单独维护一个功能精简的旧版本分支(不推荐长期并行维护)
三、核心决策对比:Qt移植 vs. Kotlin原生重写
| 对比维度 | Qt 5.12 移植 | Kotlin 原生重写 |
|---|---|---|
| 环境配置 | 复杂,5.12版本存在已知Bug和SSL兼容问题 | Android Studio一键配置 |
| UI适配 | Qt Widgets灵活性差,平板/手机适配极难 | ConstraintLayout成熟方案 |
| 技术门槛 | 需同时熟悉C++/Qt/Android | 纯Android生态,你已有Java+原生安卓基础 |
| 维护成本 | 高,找问题和修复都困难 | 低,社区支持强大 |
| 预估工时 | 不可控(环境问题可能耗时数周) | 约10-14天 |
✅ 结论:采用Kotlin原生重写方案
四、技术选型
| 组件 | 选型方案 | 理由 |
|---|---|---|
| 开发语言 | Kotlin | 官方推荐,与Java完全互通,代码更简洁 |
| UI框架 | 传统View系统 + ConstraintLayout | 兼容性最好(支持API 7+),适配灵活 |
| 网络通信 | java.net.Socket + NsdManager | 你已精通Java Socket,零学习成本 |
| 数据库 | Room (SQLite) | 官方ORM库,编译期SQL校验,与Kotlin协程完美配合 |
| 内存缓存 | StateFlow / MutableStateFlow | 响应式数据流,UI自动感应数据变化 |
| 异步处理 | Kotlin Coroutines(协程) | 轻量级并发,替代AsyncTask和Thread |
| 位置服务 | FusedLocationProviderClient + SensorManager | 获取设备经纬度与航向,官方推荐API |
| 依赖注入 | 暂不引入 | 中小项目手动管理更简单可控 |
| 最低SDK | API 28 (Android 9.0) | 经评估后的稳定起点 |
| 目标SDK | API 36 (Android 16) | 2026年最新版本 |
五、开发路线图(预计10-14天)
| 阶段 | 任务内容 | 预估工时 | 关键要点 |
|---|---|---|---|
| 阶段一:环境搭建 | 安装Android Studio,配置JDK 17+,创建项目 | 0.5天 | 设置minSdk=28,targetSdk=36 |
| 阶段二:语言过渡 | 用Kotlin写Java风格代码,熟悉基本语法差异 | 1天 | 重点:val/var、空安全?、when表达式、类声明: |
| 阶段三:UI布局开发 | 使用ConstraintLayout构建主界面,适配手机和平板 | 3-4天 | 使用约束比例、屏障(Barrier)、组(Group),一套布局适配所有屏幕 |
| 阶段四:数据库与缓存 | 集成Room,设计RadarSite实体和DAO,实现Repository缓存层 | 2天 | 内存缓存(StateFlow) + SQLite持久化,启动时加载到内存 |
| 阶段五:雷达态势图 | 自定义View + Canvas绘制PPI雷达图,支持目标实时更新 | 2-3天 | 坐标系转换,性能优化,硬件加速适配 |
| 阶段六:网络通信 | 移植Java Socket逻辑,集成NsdManager设备发现 | 2-3天 | 纯Java网络代码可直接复用 |
| 阶段七:位置与传感器 | 集成FusedLocationProviderClient获取经纬度,SensorManager获取航向 | 1-2天 | 运行时权限申请,前台服务类型声明 |
| 阶段八:Android特性适配 | 运行时权限(API 23+)、前台服务(API 26+) | 已包含 | minSdk=28后,需处理的兼容性问题大幅减少 |
| 阶段九:横屏适配 | 声明resizeableActivity,测试横竖屏切换UI | 1天 | Android 16+大屏强制适配需提前准备 |
| 阶段十:测试与发布 | 多分辨率/安卓版本模拟器及真机测试 | 2-3天 | 重点测试API 28~36各版本,覆盖手机和平板 |
六、硬件配置要求
6.1 最低与推荐配置
| 配置项 | 最低要求 | 推荐配置 | 说明 |
|---|---|---|---|
| 操作系统 | Android 9.0 (API 28) | 最新稳定版 | 已确定的minSdk,所有新API和性能优化的基础 |
| 处理器(CPU) | 1GHz 双核 | 八核 2.0GHz 以上 | 更高的主频和核心数确保态势图动画平滑 |
| 运行内存(RAM) | 1GB | 4GB 或以上 | 多阵面配置 + 态势图缓存 + 系统开销,需充足余量 |
| 存储空间 | 100MB 可用空间 | 256GB 或以上 | 应用本体及本地SQLite数据库占用不大 |
| 屏幕分辨率 | 800x480 | 1920x1080 或更高 | 自适应布局可兼容各类分辨率 |
| 传感器 | 陀螺仪 + 加速度计 + 磁力计 | 支持 | 用于获取设备航向信息(获取经纬度无需特定传感器) |
| 定位模块 | GPS / 网络定位 | GPS + GLONASS + 北斗 | 用于获取设备经纬度 |
6.2 内存详细分析
应用内存占用估算(正常运行状态):
| 内存占用项 | 估算大小 | 说明 |
|---|---|---|
| Android 9 系统基础占用 | ~600-800MB | 不同设备定制系统差异较大 |
| 应用本身 (APK + 运行时代码) | ~30-50MB | 未混淆前 |
| 雷达态势图 (Canvas绘制缓冲区) | ~10-20MB | 取决于屏幕分辨率 |
| 多阵面缓存数据 (假设20个阵面) | ~1-2MB | 每个阵面配置约几十KB |
| 网络数据缓冲 | ~5-10MB | Socket收发缓冲区 |
| 传感器数据流 | ~1-2MB | 持续更新的传感器数据 |
| 其他 (UI缓存、临时对象等) | ~20-50MB | GC可回收 |
| 总计(最低) | ~700-900MB | 1GB内存设备处于临界状态 |
| 总计(推荐) | ~150-250MB(应用自身) | 4GB内存设备游刃有余 |
内存优化策略:
- 态势图绘制优化:使用对象池复用
Paint和Path,减少onDraw()中临时对象分配 - 数据缓存策略:仅缓存当前可见阵面的数据,不可见阵面数据从SQLite延迟加载
- 图片资源:使用
WebP格式压缩图片资源,减少APK体积和运行时内存占用 - 内存抖动控制:高频网络数据更新时,避免频繁创建新对象触发GC
6.3 设备传感器与定位要求
方案一:获取设备经纬度(FusedLocationProviderClient)
使用Google Play服务的FusedLocationProviderClient,自动选择最优定位方式。
// 依赖:implementation 'com.google.android.gms:play-services-location:21.0.1'
// AndroidManifest.xml 权限声明
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 如需后台获取位置 -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
// 运行时权限动态申请(Android 6.0+)
// 获取最后已知位置
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
val latitude = location?.latitude ?: 0.0
val longitude = location?.longitude ?: 0.0
// 使用经纬度
}
// 如需实时位置更新
fusedLocationClient.requestLocationUpdates(
LocationRequest.create().apply {
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
interval = 1000 // 更新间隔(毫秒)
},
locationCallback,
Looper.getMainLooper()
)
方案二:获取设备航向(SensorManager)
使用SensorManager获取设备朝向(方位角/航向角)。
// 注册旋转矢量传感器(融合陀螺仪+磁力计,输出平滑稳定)
sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)?.let {
sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_UI)
}
// 在 onSensorChanged 中计算航向
override fun onSensorChanged(event: SensorEvent?) {
event?.let {
if (it.sensor.type == Sensor.TYPE_ROTATION_VECTOR) {
SensorManager.getRotationMatrixFromVector(rotationMatrix, it.values)
SensorManager.remapCoordinateSystem(rotationMatrix,
SensorManager.AXIS_X, SensorManager.AXIS_Z, rotationMatrix)
SensorManager.getOrientation(rotationMatrix, orientationValues)
val azimuth = Math.toDegrees(orientationValues[0].toDouble()).toFloat()
// azimuth 范围 -180° ~ 180°,可归一化为 0° ~ 359°
val heading = (azimuth + 360) % 360
// 下发航向给设备
}
}
}
传感器硬件要求:
| 传感器类型 | 用途 | 是否必需 | 替代方案 |
|---|---|---|---|
| GPS/定位模块 | 获取经纬度 | ✅ 必需 | 无替代,必须硬件支持 |
| 陀螺仪 (Gyroscope) | 航向计算(融合算法) | ⚠️ 强烈建议 | 仅磁力计航向易受干扰,精度较差 |
| 磁力计 (Magnetometer) | 航向计算(地磁方向) | ⚠️ 强烈建议 | 与陀螺仪配合使用效果最佳 |
| 加速度计 (Accelerometer) | 设备姿态检测 | ⚠️ 建议 | 提升航向计算稳定性 |
注意事项:
- 缺少陀螺仪/磁力计的设备仍可获取航向,但精度会显著下降(仅靠GPS速度方向推算)
- Android 10 (API 29) 及以上要求前台服务声明
foregroundServiceType="location"才能在后台持续获取位置 - Android 12 (API 31) 及以上要求动态申请
ACCESS_BACKGROUND_LOCATION权限时,需引导用户到设置页面手动开启 - 位置信息是敏感隐私数据,需遵守GDPR等数据保护法规要求
6.4 设备选购建议(针对硬件采购场景)
| 场景 | 推荐配置 | 典型设备示例 |
|---|---|---|
| 最低成本测试 | Android 9, 2GB RAM, 有GPS | 二手小米/红米低端机 |
| 稳定运行 | Android 10-12, 4GB RAM, GPS+陀螺仪+磁力计 | 荣耀/OPPO/vivo 中端机 |
| 主控平板(大屏展示) | Android 11+, 6GB RAM, 10寸以上屏幕 | 华为MatePad、联想小新Pad |
| 高性能工业终端 | Android 13+, 8GB RAM, 三防+高精度定位 | 亿道/研华工业平板 |
七、核心技术实现详解
7.1 屏幕自适应(手机/平板)
使用ConstraintLayout实现一套布局适配所有屏幕:
<!-- 示例:按钮宽度占屏幕30%,图片保持16:9比例 -->
<Button
android:layout_width="0dp"
app:layout_constraintWidth_percent="0.3"
android:layout_height="wrap_content" />
<ImageView
android:layout_width="0dp"
app:layout_constraintDimensionRatio="H,16:9"
android:layout_height="0dp" />
核心原则:
- 优先调整
ConstraintLayout的约束关系,而非创建多套布局文件 - 使用屏障(Barrier)和组(Group)处理动态内容变化
- 使用Android Studio可调整大小模拟器实时预览
7.2 横屏/竖屏支持
<!-- AndroidManifest.xml -->
<activity
android:name=".MainActivity"
android:resizeableActivity="true"
android:screenOrientation="fullSensor" />
⚠️ 重要提醒:
- Android 16起,大屏设备(最小宽度≥600dp)将忽略
screenOrientation锁定 - Android 16提供"选择退出"选项作为临时过渡
- Android 17将彻底移除该选项,所有应用必须自适应
7.3 雷达态势图(PPI显示)
这是Qt上位机中最核心的视觉组件,可完整迁移到Android自定义View。
实现方案选择:
| 方案 | 实现方式 | 适用场景 | 性能 | 开发成本 |
|---|---|---|---|---|
| 自定义View + Canvas | 重写onDraw()绘制 | 目标点<500个,刷新率25-50fps | 优(CPU绘制) | 中 |
| OpenGL ES | GLSurfaceView + GPU渲染 | 目标点>1000个,高性能需求 | 卓越 | 高 |
| WebView + JS图表 | ECharts/Canvas绘制 | 对移植成本敏感 | 一般 | 低 |
推荐采用方案一:自定义View + Canvas,与你的"低成本稳定"目标最匹配。
核心绘制逻辑参考:
class RadarPPIView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null
) : View(context, attrs) {
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
private val targetPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
style = Paint.Style.FILL
}
private var targets = listOf<RadarTarget>()
private var centerX = 0f
private var centerY = 0f
private var radius = 0f
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
centerX = w / 2f
centerY = h / 2f
radius = min(w, h) / 2f - 20f
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
drawRangeRings(canvas) // 距离环
drawRadialLines(canvas) // 方位刻度线
drawTargets(canvas) // 目标点
drawCrosshair(canvas) // 中心十字
}
private fun drawTargets(canvas: Canvas) {
targets.forEach { target ->
// 极坐标转屏幕坐标(注意Y轴方向取反)
val angleRad = Math.toRadians(target.azimuth.toDouble())
val x = centerX + target.distance / maxRange * radius * sin(angleRad).toFloat()
val y = centerY - target.distance / maxRange * radius * cos(angleRad).toFloat()
targetPaint.color = when(target.category) {
"UAV" -> Color.YELLOW
else -> Color.RED
}
canvas.drawCircle(x, y, 8f, targetPaint)
}
}
fun updateTargets(newTargets: List<RadarTarget>) {
targets = newTargets
postInvalidate() // 请求重绘
}
}
Qt绘制与Android Canvas对照表:
| Qt绘制概念 | Android Canvas等效 |
|---|---|
QPainter | Canvas |
QPen | Paint (stroke) |
QBrush | Paint (fill) |
drawEllipse() | canvas.drawCircle() |
drawLine() | canvas.drawLine() |
drawText() | canvas.drawText() |
7.4 多雷达阵面管理(SQLite + 内存缓存)
每个IP地址对应一个雷达阵面,需要同时支持持久化存储和高效内存访问。
数据模型:
@Entity(tableName = "radar_sites")
data class RadarSite(
@PrimaryKey(autoGenerate = true)
val id: Long = 0,
val name: String, // 阵面名称
val ipAddress: String, // IP地址(业务唯一标识)
val port: Int, // 通信端口
val latitude: Double = 0.0, // 阵面部署纬度
val longitude: Double = 0.0, // 阵面部署经度
val heading: Float = 0f, // 阵面航向
val isEnabled: Boolean = true,
val lastOnlineTime: Long = 0,
val customParams: String? = null
)
内存缓存层(Repository):
class RadarSiteRepository(private val dao: RadarSiteDao) {
// 内存缓存:StateFlow作为可观察数据源
private val _sitesFlow = MutableStateFlow<List<RadarSite>>(emptyList())
val sitesFlow: StateFlow<List<RadarSite>> = _sitesFlow.asStateFlow()
// 应用启动时加载数据库数据到内存
suspend fun refreshCache() {
_sitesFlow.value = dao.getAllSites()
}
// 增删改:先更新内存再持久化
suspend fun addSite(site: RadarSite) {
dao.insertSite(site)
refreshCache()
}
suspend fun updateSite(site: RadarSite) {
dao.updateSite(site)
refreshCache()
}
suspend fun deleteSite(siteId: Long) {
dao.deleteSiteById(siteId)
refreshCache()
}
}
7.5 位置与传感器集成
获取设备经纬度:
// AndroidManifest.xml 权限声明
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
// 运行时权限申请(Android 6.0+)
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), REQ_CODE)
}
// 获取位置(FusedLocationProviderClient)
val fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
val latitude = location?.latitude ?: 0.0
val longitude = location?.longitude ?: 0.0
// 下发至设备或显示在UI
}
获取设备航向:
// 使用旋转矢量传感器
sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)?.let {
sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_UI)
}
override fun onSensorChanged(event: SensorEvent?) {
event?.let {
if (it.sensor.type == Sensor.TYPE_ROTATION_VECTOR) {
SensorManager.getRotationMatrixFromVector(rotationMatrix, it.values)
SensorManager.remapCoordinateSystem(rotationMatrix,
SensorManager.AXIS_X, SensorManager.AXIS_Z, rotationMatrix)
SensorManager.getOrientation(rotationMatrix, orientationValues)
val heading = (Math.toDegrees(orientationValues[0].toDouble()) + 360) % 360
// 下发给设备
}
}
}
下发经纬度/航向给设备:
class RadarCommunicationManager {
fun sendPoseToDevice(ip: String, port: Int,
latitude: Double, longitude: Double, heading: Float) {
val message = buildPoseMessage(latitude, longitude, heading)
sendData(ip, port, message)
}
}
7.6 网络通信
// Java Socket代码可直接复用,Kotlin无缝调用
// 局域网设备发现使用NsdManager (Android 4.1+)
val nsdManager = getSystemService(Context.NSD_SERVICE) as NsdManager
注意事项:
- Android 9+默认禁止明文HTTP流量,需配置
network_security_config.xml - 如需后台持续网络通信,使用前台服务(Foreground Service)
7.7 发热控制(ADPF自适应性能框架)
// 获取设备热状态,动态调整应用负载
val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
val thermalHeadroom = powerManager.getThermalHeadroom(1000) // 未来1秒的热余量
// 根据thermalHeadroom值动态调整网络请求频率/UI刷新率
效果参考:知名游戏开发商Netmarble利用ADPF改善设备热余量11%,帧率更稳定。
八、Android 16 (2026) 及未来版本注意事项
| 变化点 | 影响 | 应对措施 |
|---|---|---|
| 大屏强制全屏 | 应用在大屏设备上无法锁定方向 | 提前声明resizeableActivity="true",UI自适应 |
| 16KB内存页支持 | API 35+设备强制要求 | 确保应用兼容16KB页面大小(Google Play上架要求) |
| 后台任务限制 | 后台执行配额管理更严格 | 优化后台网络任务,使用前台服务 |
| 私有API限制 | 非公开SDK接口访问受限 | 替换为官方公开API |
九、老机型兼容策略(API 28+)
| 兼容点 | 策略 |
|---|---|
| 最低API版本 | 28 (Android 9.0) |
| UI兼容 | ConstraintLayout支持API 7+,无兼容性问题 |
| 网络兼容 | java.net.Socket标准库全版本支持 |
| 权限兼容 | 统一使用Android 6.0+运行时权限模型 |
| Room数据库 | 支持API 14+,API 28无额外兼容负担 |
| 传感器兼容 | SensorManager API 1+全版本支持,旋转矢量传感器API 9+支持 |
| 位置服务 | FusedLocationProviderClient需Google Play服务,API 28+均支持 |
| 测试覆盖 | 使用API 28~36各版本模拟器验证 |
十、维护与迭代建议
- 业务逻辑复用:Java网络协议解析、数据处理代码直接复制到新项目,零风险迁移
- 模块化设计:网络模块、数据模块(Repository+DAO)、UI模块、传感器模块分离
- 版本控制:建议使用Git,标记稳定版本便于回滚
- 监控埋点:关键网络请求、数据库操作、位置获取加入日志
- 版本升级策略:每年评估一次minSdk,若API 28设备市场份额降至阈值以下,可考虑提升
十一、工时与成本估算
| 项目 | 估算 |
|---|---|
| 开发周期 | 10-14天(单人从容开发) |
| 测试周期 | 3-5天(覆盖API 28~36各主要版本,手机+平板) |
| 学习成本 | Kotlin语法1-2天过渡,其余技能已具备 |
| 维护成本 | 低,纯Android生态,社区资源丰富 |
| 硬件成本 | 无额外硬件投入,使用现有Android设备测试 |
| 数据库设计 | 已包含在开发周期内,无额外成本 |
| 传感器集成 | 已包含在开发周期内,无需额外硬件 |
十二、结论与建议
本方案充分利用多年Java功底和原生安卓经验,在不引入额外技术栈(Qt/C++)的前提下,以最低成本和风险交付高质量、易长期维护的原生Android应用。
关键成功因素:
- ✅ Android版本策略务实:以API 28为起点,避开旧版本维护泥潭,专注主流设备
- ✅ 硬件要求明确:最低1GB RAM + GPS定位,推荐4GB RAM + 陀螺仪+磁力计
- ✅ 位置与传感器方案成熟:FusedLocationProviderClient获取经纬度,SensorManager获取航向,均为Android官方推荐API
- ✅ Kotlin不必专门学习:从Java风格写起,边写边熟悉
- ✅ 网络代码完全复用:核心业务逻辑零风险迁移
- ✅ UI适配有成熟方案:ConstraintLayout解决手机平板横竖屏所有问题
- ✅ 雷达态势图完美迁移:自定义View + Canvas绘制,性能可控,与Qt绘制逻辑一一对应
- ✅ 数据管理清晰高效:SQLite持久化 + StateFlow内存缓存,多阵面管理游刃有余
- ✅ 发热问题可主动控制:ADPF框架提供官方解决方案
- ✅ Android 16变化提前知晓:有充足时间应对过渡
预期交付质量:一个稳定运行在Android 9.0至Android 16全系列设备上、支持手机和平板自适应横竖屏切换、局域网WiFi通信、多雷达阵面本地化管理(SQLite持久化+内存缓存)、雷达态势图PPI显示、设备经纬度/航向获取与下发的原生Android应用。