
简介面向 Android 系统开发者与定位模块集成商这份和芯星通 UM220-III Android 支持包解决的是在 Android 平台上适配北斗/GPS 定位芯片的问题涵盖 framework 定制、HAL 接口实现、测试验证与协议参考等环节适合具备一定 Android 系统层开发经验、需要将 UM220-III 接入设备或应用的技术人员。压缩包共 29 个文件约 2.55MB以 10 个 Java 源码、4 个 XML 配置、3 个 C 与 2 个 C 源文件、2 个头文件及 2 个 mk 编译脚本为主体另含 aidl 接口定义、测试 apk 与两份 PDF 协议文档覆盖从框架层到硬件抽象层的完整链路。已有 857 人学习。读者可据此对照修改前后的 framework 与 HAL 代码理解定位服务的注册与数据获取流程借助测试应用验证定位速度、精度与信号强度并结合协议规范与移植协助文档降低集成难度快速排查适配中的常见问题。1. 从一块 UM220-III 模块说起Android 下拿到北斗数据没那么简单手里有一块和芯星通 UM220-III 模块想把它接到 Android 板子上跑出定位数据很多人第一反应是「串口能收到 NMEA 语句就算通了」。真上手才发现不是这么回事模块上电后串口确实在吐$GNRMC、$GNGGA可 Android 应用层拿不到LocationManager里空空如也日志里连个卫星数都看不见。问题不在模块而在 Android 的定位链路——从内核串口驱动、HAL 层、到 Framework 的 GNSS 服务中间任何一环没接上数据就卡在半路。这套 UM220-III 的 Android 支持包解决的就是把模块输出的原始 NMEA 数据接进 Android 定位框架这件事适合正在做车载终端、手持设备、工业平板这类带北斗定位需求的开发者。装不好会怎样轻则应用层拿不到位置重则 GNSS 服务反复重启、系统日志刷屏。下面按我实际部署的顺序把环境、编译、配置、验证和翻车后的救法一条条写清楚。2. 环境准备与版本对齐编译前先把这几样钉死2.1 确认模块型号与固件版本UM220-III 是支持包对应的硬件基础动手前先确认手上模块的固件版本。常见做法是通过串口工具发$PCAS06,0*XX查询版本或者直接看模块丝印批次。固件版本不同NMEA 输出语句的默认开关状态可能不一样比如有的批次默认不开$GNGSA后面 HAL 解析卫星仰角时就少数据。我一般会先把模块单独接到 USB 转串口上用串口助手确认三件事波特率UM220-III 常见默认 9600也有配置成 115200 的、输出语句集合、更新率。这三项记下来后面配 HAL 参数时直接对照省得来回试。2.2 Android 源码树与编译环境支持包要编进 Android 系统镜像所以你得有一份能完整编译的源码树。版本上这套包常见适配 Android 8.1 到 Android 11 的 GNSS HAL 接口Android 12 之后 HAL 接口有调整直接套用容易在android.hardware.gnss2.x的接口实现上编译报错。编译环境按 AOSP 官方要求来Ubuntu 18.04 或 20.04、JDK 对应版本、repo工具、以及至少 200GB 磁盘空间。下面是我习惯先跑一遍的环境自检# 检查基础工具链是否齐全 sudo apt-get install -y git-core gnupg flex bison build-essential zip curl \ zlib1g-dev gcc-multilib g-multilib libc6-dev-i386 lib32ncurses5-dev \ x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip # 确认 JDK 版本Android 10 及以下常用 OpenJDK 8 java -version # 确认 repo 可用 repo --version这段命令做的是补齐 AOSP 编译依赖。gcc-multilib和lib32ncurses5-dev这类 32 位库容易被漏装漏了会在编译 host 工具时报cannot find -lz之类的错。JDK 版本要对上源码树要求Android 10 用 OpenJDK 8Android 11 开始部分分支要求 JDK 11装错版本会在soong阶段直接失败。repo是拉源码用的版本太老会在 sync 时提示 manifest 解析失败。2.3 支持包目录结构与放置位置拿到支持包后先别急着往里拷解压看结构。典型内容包含 HAL 实现源码、Android.bp或Android.mk编译脚本、以及一份gnss.h配置头文件。放置位置有讲究HAL 实现一般放到hardware/interfaces/gnss/对应版本目录下或者作为独立 vendor 模块放到vendor/下。我一般会先建一个对照表把包里的文件和源码树里的目标路径一一对应避免拷错层级导致编译脚本找不到源文件支持包内文件目标路径作用gnss_hal.cpphardware/interfaces/gnss/2.0/default/HAL 接口实现Android.bp同上编译描述gnss_config.hdevice/vendor/board/串口与波特率配置init.gnss.rcdevice/vendor/board/服务启动脚本这张表不是让你照抄路径而是提醒你HAL 源码、编译脚本、板级配置、启动脚本分属不同目录少放一处就编不过或者跑不起来。板级配置里的串口设备节点比如/dev/ttyS1必须和实际硬件连接一致这个后面配置章节细说。3. 编译集成把 HAL 接进系统镜像3.1 修改板级配置文件挂载串口权限模块通过串口和主控通信Android 默认不给普通服务访问串口节点的权限得在ueventd或init配置里放开。常见做法是在板级的ueventd.board.rc里加一行把串口节点的属主和权限设好# 在 ueventd.board.rc 中追加ttyS1 换成实际串口 /dev/ttyS1 0660 system system这行的含义是设备节点/dev/ttyS1权限设为0660属主和属组都是system。GNSS HAL 服务一般以system身份运行这样它才有读写权限。如果串口节点属主是root而服务是system打开串口会返回Permission denied日志里表现为 HAL 初始化失败、GNSS 服务起不来。串口号别照抄得看你板子的实际接线接错串口的表现是服务起来了但一直收不到数据。3.2 配置 HAL 的串口参数与 NMEA 解析支持包里的gnss_config.h是核心配置点串口路径、波特率、NMEA 语句开关都在这里。下面是我改过的一个典型片段// gnss_config.h 关键配置项 #define GNSS_SERIAL_DEV /dev/ttyS1 // 与实际硬件接线一致 #define GNSS_SERIAL_BAUD 9600 // 与模块固件默认波特率一致 #define GNSS_NMEA_RMC 1 // 启用 RMC提供时间与经纬度 #define GNSS_NMEA_GGA 1 // 启用 GGA提供定位质量与海拔 #define GNSS_NMEA_GSA 1 // 启用 GSA提供卫星参与定位信息 #define GNSS_NMEA_GSV 1 // 启用 GSV提供可见卫星数GNSS_SERIAL_BAUD必须和模块实际波特率一致模块是 9600 你写 115200收到的全是乱码HAL 解析 NMEA 时校验和永远对不上表现就是「串口有数据但定位一直无效」。GNSS_NMEA_GSA和GSV这两个开关很多人图省事关掉结果应用层拿到的卫星数为 0做信号强度显示的界面直接空白。RMC 和 GGA 是定位必需别动。改完这些再确认Android.bp里把gnss_config.h的头文件路径加进了include_dirs否则编译时提示找不到宏定义。3.3 编译并打包进系统镜像配置改完就可以编了。先单独编 GNSS HAL 模块验证语法再整体打包这样出错时定位快# 初始化编译环境 source build/envsetup.sh lunch board-userdebug # 先单独编译 GNSS HAL 模块快速验证 m gnss2.0-service # 通过后整体打包 make -j$(nproc) snodlunch选的目标要和你的板子匹配选错目标编出来的镜像刷不进设备。m gnss2.0-service只编 HAL 服务几十秒就能出结果比整体编译快得多语法错误、头文件缺失在这一步就能暴露。make snod是只重新打包 system 镜像适合已经刷过底包、只改了 HAL 的场景比全量make省时间。如果m阶段报undefined reference多半是Android.bp里shared_libs少列了依赖库按报错里的符号去查对应库补上。4. 避坑排查这几处翻车我踩过不止一次4.1 串口有数据但应用层无定位现象串口助手能看到 NMEA 语句Android 应用里LocationManager一直返回 null。原因通常是 HAL 解析出的定位结果没通过GnssHal回调上报或者 NMEA 校验和解析失败被丢弃。解决先看logcat里 GNSS 相关 tag确认 HAL 是否收到数据再抓一段原始 NMEA 用校验和工具核对UM220-III 某些固件在语句末尾多一个回车解析器按严格格式匹配就会失败改解析逻辑容忍\r\n即可。4.2 GNSS 服务反复重启现象logcat里gnss2.0-service起来几秒就退出循环往复。原因多是串口打开失败或初始化超时。解决确认ueventd里串口权限已生效ls -l /dev/ttyS1看属主确认gnss_config.h里的串口路径和实际节点一致再确认模块已上电。还有一种情况是服务启动脚本里oneshot和disabled配错服务被 init 反复拉起检查init.gnss.rc的service段。4.3 编译报 HAL 接口版本不匹配现象m gnss2.0-service报接口方法未实现或签名不符。原因是支持包按某个 Android 版本的 HAL 接口写的你的源码树版本不同。解决对照源码树里hardware/interfaces/gnss/下的.hal接口文件看方法签名差异按你的版本调整实现版本跨度大时优先找支持包内是否有对应版本的适配分支别硬改。4.4 定位漂移严重或首次定位极慢现象能定位但坐标跳得厉害或者冷启动要几分钟。原因常见于天线放置和 AGPS 数据缺失。解决确认天线朝向和接地模块附近别放大电流器件首次定位慢可检查是否注入了星历辅助数据支持包里若有 AGPS 相关配置项确认其数据通路是否打通。这类问题不是装错了是环境没配到位别急着怀疑 HAL。5. 装完怎么验证从串口到应用层走一遍闭环验证不能只看「服务起来了」得从物理层一路验到应用层。我习惯按下面这个顺序走任何一环断了都能立刻定位# 第一层确认串口有原始数据 cat /dev/ttyS1 | head -20 # 第二层确认 HAL 服务在跑 ps -A | grep gnss # 第三层抓 GNSS 相关日志 logcat -s GnssHal GnssLocationProvider # 第四层应用层验证用系统自带的定位测试或自写 demo # 观察是否回调 onLocationChanged卫星数是否大于 0第一层cat串口能看到$GNRMC开头的语句说明硬件链路通看不到就回去查接线、波特率、权限。第二层确认服务进程存在不存在看 init 日志。第三层日志里应能看到 HAL 解析出的经纬度和卫星数如果只有「收到数据」没有「解析成功」回去查 NMEA 开关和校验和逻辑。第四层是最终验收应用能拿到Location对象且getSatellites()数量正常才算真正跑通。再补一个我常用的对照检查表把每层的预期结果列清楚排查时逐行打勾验证层检查命令正常表现异常时先查物理层cat /dev/ttyS1持续输出 NMEA 语句接线、波特率、权限服务层ps -A | grep gnss进程稳定存在init 脚本、串口打开HAL 层logcat -s GnssHal解析出经纬度与卫星数NMEA 开关、校验和应用层定位 demo回调位置、卫星数 0Framework 回调链路有个细节值得单独说验证时别在室内靠窗随便测UM220-III 在信号弱的环境下首次定位可能很久容易误判成装坏了。我一般会到室外开阔处冷启动等满两分钟再下结论。另外改完配置重新打包后记得make snod之后把镜像刷进去再测只编不刷等于没改这个低级错误我早期犯过对着旧镜像排查了半天。从那以后我每次集成这类定位模块都强制按「串口原始数据 → 服务进程 → HAL 日志 → 应用回调」四层走一遍任何一层不过就不往下走省得问题叠在一起分不清是谁的锅。这套 UM220-III 的 Android 支持包按上面的顺序装下来链路是能打通的配置项和排查点都在正文里了照着走一遍基本能复现。希望帮到你。本文还有配套的精品资源点击获取