RTOS SDK 接入与使用 最后更新时间: 2026年08月27日
一、概述
1.1 SDK 形态
SDK 以 C 语言静态库形式发布,对外仅暴露 C 头文件,作为静态库链入 RTOS 设备固件。
主要部署形态:
- 手表:RTOS 手表设备(如 SiFli、杰理、聚芯、拓步、小牛等芯片平台)
- 眼镜:RTOS 眼镜设备(rtosglass / Rokid 等)
两种形态均不依赖完整 libc / 文件系统 / 图形栈,全部通过 adapter 由厂商注入。
1.2 线程模型
单线程模型:SDK 的所有 API 必须在同一个线程("主流程线程")调用,不支持并发。
- awk_init 在哪个线程调用,后续 API 就必须在该线程调用
- 网络数据的接收可以在异步线程进行,但 awk_http_response_callback_t 的回调必须切回主流程线程
- SDK 内部会校验线程一致性,违反时返回 -3
1.3 坐标系
- 地理坐标:GCJ02 坐标系(高德/腾讯系)。如有 WGS84 数据,先调用 awk_map_wgs84_to_mgs 转换
- 屏幕坐标:以左上角为原点 (0, 0),单位像素,x 向右,y 向下
1.4 版本检查
库与头文件必须严格匹配,否则行为未定义。集成方需在初始化前自检:
if (!awk_check_version_compatibility()) {
// 头文件与库版本不一致,停止使用
}
const awk_version_info_t *v = awk_get_library_version();
printf("SDK version: %s build %s %s\n", v->version, v->build_date, v->build_time);
二、接入流程
2.1 调用链概览
awk_check_version_compatibility() ← 版本自检
│
▼
填充 awk_context_t ← 配置 + 注入 adapter
│
▼
awk_init(&ctx) ← 初始化
│
▼
awk_check_device_activated() ── 已激活 ──┐
│ 未激活 │
▼ ▼
awk_activate_device() awk_map_create_view()
│ │
▼ ▼
(回调成功后) 开始使用地图 API
│ │
└────────────►─────────────┘
│
▼
awk_uninit() ← 退出时反初始化
2.2 awk_context_t 字段
typedef struct _awk_context_t {
char *device_id; // 必填:设备唯一 id
char *key; // 必填:高德开放平台智能硬件 key
char *root_dir; // 必填:SDK 内部缓存/数据根目录
char *offline_map_dir; // 可选:离线地图根目录,不要位于 root_dir 下
char *language; // 可选:语言编码("zh"/"en"/...),NULL 默认 "zh"
// 瓦片相关
awk_map_tile_style_t tile_style; // 必填:瓦片样式(见 §2.4)
int32_t tile_load_mode; // 必填:AWK_MAP_TILE_LOAD_ONLINE / OFFLINE
awk_pixel_mode_t tile_pixel_mode; // 瓦片像素格式(如 ARGB_8888 / RGB_565)
uint32_t tile_disk_cache_max_size; // 瓦片磁盘缓存上限,单位 MB
uint32_t tile_mem_cache_max_size; // 瓦片内存缓存上限,单位 KB
uint32_t poi_tile_disk_cache_max_size; // POI 磁盘缓存上限,单位 MB
uint32_t poi_tile_mem_cache_max_size; // POI 内存缓存上限,单位 KB
uint32_t poi_tile_density; // POI 精细度 0/1/2,越大越细
uint32_t max_file_count_in_dir; // 单目录文件数上限,0 不限
uint32_t max_one_file_size; // 单文件大小上限 MB,0 不限
bool tile_zip; // 瓦片是否压缩
bool tile_clip_load; // 加载时是否裁剪(仅 tile_mem_cache_max_size=0 生效)
bool tile_background_custom_draw; // 瓦片背景是否外部自绘
bool tile_buff_mem_outer_free; // 瓦片绘制内存外部释放(仅 tile_clip_load=false)
bool tile_cache_decoded_bitmap; // 缓存解码后的位图
bool poi_labels_hidden; // 隐藏 POI 文字
bool road_labels_hidden; // 隐藏路名
bool disable_network_gzip_header; // 关闭网络 gzip 头
bool need_force_render; // 是否需要强制刷新
float limit_min_zoom; // 限制最小级别,最小 3
float limit_max_zoom; // 限制最大级别,最大 20
// Adapter(必填,见 §3)
awk_render_adapter_t render_adapter;
awk_file_adapter_t file_adapter;
awk_memory_adapter_t memory_adapter;
awk_fast_memory_adapter_t fast_memory_adapter; // 可选
awk_network_adapter_t network_adapter;
awk_thread_adapter_t thread_adapter;
awk_system_adapter_t system_adapter;
awk_map_tile_file_adapter_t tile_file_adapter; // 仅 POI 模式必填
awk_map_custom_adapter_t custom_adapter; // 可选,仅部分厂商
} awk_context_t;
2.3 初始化与反初始化
awk_context_t ctx;
memset(&ctx, 0, sizeof(ctx)); // 务必先 memset 清零
ctx.device_id = "abc-1234";
ctx.key = "your_amap_key";
ctx.root_dir = "/data/awksdk";
ctx.tile_style = AWK_MAP_TILE_STYLE_GRID_AND_POI;
ctx.tile_load_mode = AWK_MAP_TILE_LOAD_ONLINE;
ctx.tile_pixel_mode = AWK_PIXEL_MODE_ARGB_8888;
ctx.tile_disk_cache_max_size = 200; // 200 MB
ctx.tile_mem_cache_max_size = 512; // 512 KB
// ... 填充所有 adapter(见 §3)
int32_t ret = awk_init(&ctx);
if (ret != 0) {
// 错误码对照见 §7
}
// ... 业务结束时
awk_uninit(); // 必须在与 awk_init 相同线程调用
2.4 tile_style 选择
- 手表:常用 GRID_AND_POI 或 VECTOR
- 眼镜:常用 GRID_AND_POI 或 ROAD_AND_POI(SVG 默认关闭)
2.5 设备激活
设备首次使用需要联网激活:
awk_device_activate_param_t param = {
.area = "mainland", // mainland / overseas
.country = "cn",
.type = 0, // 0 新激活, 1 恢复出厂, 2 续约
.data_type = "raster" // raster / vector
};
awk_device_active_callback cb = {
.awk_device_active_on_success = on_active_success,
.awk_device_active_on_fail = on_active_fail
};
awk_activate_device(¶m, cb);
第二次启动时可先检查:
if (!awk_check_device_activated(¶m, &ctx)) {
awk_activate_device(¶m, cb);
}
2.6 创建地图
awk_map_view_param_t mp;
mp.port.width = 320;
mp.port.height = 320;
mp.map_view_rect = (awk_rect_area_t){ 0, 0, 320, 320 };
int32_t map_id = awk_map_create_view(mp); // > 0 即为成功
后续地图 API 使用 map_id 作为目标。
三、Adapter 实现指南
所有 adapter 函数都是必填字段(除特别标注外),不填会导致 awk_init 返回 -200 ~ -800 系列错误码。
3.1 render_adapter — 渲染
struct _awk_render_adapter_t {
void (*begin_drawing) (uint32_t map_id, awk_render_context_t status);
void (*commit_drawing) (uint32_t map_id);
void (*draw_point) (uint32_t map_id, awk_point_t *point, uint32_t n, const awk_paint_style_t *style);
void (*draw_polyline) (uint32_t map_id, awk_point_t *points, uint32_t n, const awk_paint_style_t *style);
void (*draw_polygon) (uint32_t map_id, awk_point_t *points, uint32_t n, const awk_paint_style_t *style);
void (*draw_bitmap) (uint32_t map_id, awk_rect_area_t area, awk_bitmap_t bitmap, const awk_paint_style_t *style);
void (*draw_image_buffer) (uint32_t map_id, awk_rect_area_t area, const awk_image_buf_info_t *info, const awk_paint_style_t *style);
void (*draw_text) (uint32_t map_id, awk_point_t center, const char *text, const awk_paint_style_t *style);
void (*draw_color) (uint32_t map_id, awk_rect_area_t area, const awk_paint_style_t *style);
bool (*measure_text) (uint32_t map_id, const char *text, const awk_paint_style_t *style,
int32_t *width, int32_t *ascender, int32_t *descender);
void (*draw_svg_bitmap) (uint32_t map_id, awk_rect_area_t area, awk_bitmap_t bitmap);
};
必填检查(awk_check_context 返回错误码):
位图像素格式:awk_bitmap_t::pixel_mode 由 awk_context_t.tile_pixel_mode 决定。常见组合:
- ARGB_8888 / RGBA_8888:彩屏 + 充足显存
- RGB_565 / BGR_565:紧显存设备常用(16 位减少带宽)
- GREY:单色屏
最小示例:
static void render_begin(uint32_t map_id, awk_render_context_t status) {
// 准备 Canvas/Context;status 含视口、地图姿态等
}
static void render_commit(uint32_t map_id) {
// 把累积的绘制提交到屏幕(SwapBuffer 或刷新 framebuffer)
}
static void render_bitmap(uint32_t map_id, awk_rect_area_t area,
awk_bitmap_t bm, const awk_paint_style_t *style) {
// 把 bm.buffer 按 bm.pixel_mode 拷到 area 区域
}
static void render_polyline(uint32_t map_id, awk_point_t *pts, uint32_t n,
const awk_paint_style_t *style) {
// 颜色 style->color 是 ARGB;宽度 style->width
}
// 其他类似
真机实现:直接操作 framebuffer,或对接厂商 GUI 库(LVGL / NemaGFX / 厂商自研栈),把 area 转成 GUI 库的 update region 即可。measure_text 通常用 freetype 或厂商字体引擎实现。 仓库自带的 iOS 参考工程(见 §6.1)用 CoreGraphics 演示了一套实现,仅供对照;其他 PC 宿主(Mac CLI / Linux)也可以按相同接口自建。
3.2 file_adapter — 文件系统
struct _awk_file_adapter_t {
void* (*file_open) (const char *filename, const char *mode);
int (*file_close) (void *handler);
size_t (*file_read) (void *ptr, size_t size, void *handler);
size_t (*file_write) (void *ptr, size_t size, void *handler);
long (*file_tell) (void *handler);
int (*file_seek) (void *handler, long offset, int where);
int (*file_flush) (void *handler);
bool (*file_exists) (const char *path);
int (*file_remove) (const char *path);
bool (*file_dir_exists) (const char *path);
int (*file_mkdir) (const char *path, uint16_t mode);
int (*file_rmdir) (const char *path);
void* (*file_opendir) (const char *path);
int (*file_closedir) (void *dir);
bool (*file_readdir) (void *dir, awk_readdir_result *result);
size_t (*file_get_size) (const char *path);
long (*file_get_last_access)(const char *path);
int (*file_rename) (const char *old_name, const char *new_name);
bool (*file_unzip) (const char *zip_file, const char *out_dir); // 可选
};
必填检查:上表中除 file_unzip 外全部必填(错误码 -300 ~ -316)。
POSIX 参考实现(适用于支持完整 POSIX 的 RTOS,或 PC 宿主上的 Demo):
static void *fa_open(const char *p, const char *m) { return fopen(p, m); }
static int fa_close(void *h) { return fclose((FILE*)h); }
static size_t fa_read (void *b, size_t s, void *h) { return fread (b, 1, s, (FILE*)h); }
static size_t fa_write(void *b, size_t s, void *h) { return fwrite(b, 1, s, (FILE*)h); }
static long fa_tell (void *h) { return ftell ((FILE*)h); }
static int fa_seek (void *h, long o, int w) { return fseek ((FILE*)h, o, w); }
static int fa_flush(void *h) { return fflush((FILE*)h); }
static bool fa_exists(const char *p) { return access(p, F_OK) == 0; }
static int fa_remove(const char *p) { return remove(p); }
static int fa_mkdir (const char *p, uint16_t m) { return mkdir(p, m); }
static int fa_rmdir (const char *p) { return rmdir(p); }
static bool fa_dir_exists(const char *p) {
struct stat st;
return stat(p, &st) == 0 && S_ISDIR(st.st_mode);
}
static void *fa_opendir (const char *p) { return opendir(p); }
static int fa_closedir(void *d) { return closedir((DIR*)d); }
static bool fa_readdir(void *dir, awk_readdir_result *out) {
// 把目录下所有条目填入 out->nodes(数组由外部分配并管理)
// 实现示例略;注意越界检查
return true;
}
static size_t fa_get_size(const char *p) {
struct stat st; return stat(p, &st) == 0 ? (size_t)st.st_size : 0;
}
static long fa_get_last_access(const char *p) {
struct stat st; return stat(p, &st) == 0 ? (long)st.st_atime : 0;
}
static int fa_rename(const char *a, const char *b) { return rename(a, b); }
RTOS 适配:很多 RTOS 仅支持 POSIX 子集,opendir/readdir 等需要替换为厂商等价接口。若设备不支持目录遍历,可考虑维护一个文件清单文件作为 readdir 的模拟。多进程共享 root_dir:SDK 内部没有文件锁,若两个进程共用同一 root_dir 可能损坏 tile_cache.index。多进程场景建议各自使用独立 root_dir;offline_map_dir 因下载后只读可安全共享。
3.3 memory_adapter — 内存
struct _awk_memory_adapter_t {
void (*mem_free) (void *ptr);
void* (*mem_malloc) (size_t size);
void* (*mem_calloc) (size_t count, size_t size);
void* (*mem_realloc)(void *ptr, size_t size);
};
全部必填(错误码 -400 ~ -403)。最简单的实现:
static void *ma_malloc (size_t s) { return malloc(s); }
static void ma_free (void *p) { free(p); }
static void *ma_calloc (size_t n, size_t s) { return calloc(n, s); }
static void *ma_realloc(void *p, size_t s) { return realloc(p, s); }
3.4 fast_memory_adapter — 大内存优化(可选)
struct _awk_fast_memory_adapter_t {
void (*mem_free) (void *ptr);
void* (*mem_malloc)(size_t size, int type); // type=0 瓦片缓存 / type=1 瓦片绘制
};
适用于宿主有专用大内存池(如 PSRAM)的眼镜平台。若不需要,留 NULL,SDK 会回退到普通 memory_adapter。
3.5 network_adapter — 网络
struct _awk_network_adapter_t {
uint64_t (*send) (awk_http_request_t *request, awk_http_response_callback_t *callback);
void (*cancel) (uint64_t request_id);
};
必填(错误码 -600 / -601)。
关键约定:
- send 必须返回唯一 request_id(自增即可),用于 cancel
- HTTP 请求体可以在异步线程发起,但 callback 必须切回主流程线程调用
- request 由 SDK 维护生命周期,adapter 不要释放
响应回调:
struct _awk_http_response_callback_t {
void (*on_receive_header)(awk_http_response_callback_t*, const awk_http_response_t*);
void (*on_receive_body) (awk_http_response_callback_t*, const awk_http_response_t*);
void (*on_fail) (awk_http_response_callback_t*, const awk_http_response_t*, int32_t error);
void (*on_success) (awk_http_response_callback_t*, const awk_http_response_t*);
void (*on_canceled) (awk_http_response_callback_t*, const awk_http_response_t*);
};
- on_receive_header 最多回调 1 次
- on_receive_body 可分多次回调(流式)
- 终态三选一:on_success / on_fail / on_canceled
最小示例骨架:
static uint64_t s_req_seq = 0;
static uint64_t net_send(awk_http_request_t *req, awk_http_response_callback_t *cb) {
uint64_t id = ++s_req_seq;
// 投递到工作队列,异步执行 HTTP
enqueue_http_task(id, req, cb);
return id;
}
static void net_cancel(uint64_t id) {
cancel_http_task(id);
}
3.6 system_adapter — 系统
struct _awk_system_adapter_t {
uint64_t (*get_system_time)(void); // 单位 ms
int (*log_printf) (const char *fmt, ...);
};
必填(错误码 -500 / -501)。
static uint64_t sa_time(void) {
struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts);
return (uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
}
static int sa_log(const char *fmt, ...) {
va_list ap; va_start(ap, fmt);
int r = vprintf(fmt, ap);
va_end(ap);
return r;
}
注意:get_system_time 必须返回真实墙钟时间(用于 license 校验、tile 时效)。如果 RTOS 没有硬件 RTC,需要在联网后用 NTP 同步。
3.7 thread_adapter — 线程
typedef struct _awk_thread_adapter_t {
uint64_t (*get_thread_id)(void);
} awk_thread_adapter_t;
必填(错误码 -701)。仅用于校验调用线程是否与 awk_init 时一致。
static uint64_t ta_tid(void) { return (uint64_t)pthread_self(); }
3.8 tile_file_adapter — 离线瓦片文件
typedef struct _awk_map_tile_file_adapter_t {
bool (*on_tile_file)(const char *tile_file_key,
char *file_path, size_t *file_offset, size_t *file_size);
} awk_map_tile_file_adapter_t;
仅当 tile_style = GRID_AND_POI 或 ROAD_AND_POI 时必填(错误码 -800)。SDK 给一个瓦片 key,宿主返回对应的文件路径、偏移、长度。
3.9 custom_adapter — 定制接口(可选)
typedef struct _awk_map_custom_adapter_t {
int (*custom_sscanf)(const char *s, const char *format, ...);
void (*custom_assert)(int expression);
} awk_map_custom_adapter_t;
某些不带 libc 的 RTOS 厂商需要外部实现 sscanf 和 assert。普通平台留 NULL。
四、地图 API 参考
4.1 生命周期与渲染
渲染回调结构(awk_map_render_callback_t)部分关键回调:
bool (*on_tile_begin_draw) (uint32_t map_id, uint32_t tx, uint32_t ty, uint32_t zoom);
void (*on_tile_end_draw) (uint32_t map_id, uint32_t tx, uint32_t ty, uint32_t zoom, int32_t status);
bool (*on_tile_begin_download) (int32_t type, uint32_t tx, uint32_t ty, uint32_t zoom);
void (*on_tile_end_download) (int32_t type, uint32_t tx, uint32_t ty, uint32_t zoom, awk_map_tile_response_status_t status);
bool (*on_poi_begin_draw) (uint32_t map_id, uint32_t tx, uint32_t ty, uint32_t zoom);
void (*on_poi_end_draw) (uint32_t map_id, uint32_t tx, uint32_t ty, uint32_t zoom, int32_t status);
bool (*on_point_begin_draw) (uint32_t map_id, int32_t guid);
void (*on_point_end_draw) (uint32_t map_id, int32_t guid, int32_t status);
// 还有 line / polygon / img_bin 等系列
on_*_begin_* 返回 false 表示放弃绘制/下载该项。
4.2 视图与坐标
4.3 交互(手势)
4.4 覆盖物
纹理(点 icon):
int32_t awk_map_add_texture (const awk_map_texture_data_t *data); // 返回 texture_id
int32_t awk_map_update_texture(uint32_t texture_id, const awk_map_texture_data_t *data);
int32_t awk_map_remove_texture(uint32_t texture_id);
点/线/面/轨迹(共用接口):
int32_t awk_map_init_point_overlay (awk_map_point_overlay_t *o);
int32_t awk_map_init_line_overlay (awk_map_polyline_overlay_t *o);
int32_t awk_map_init_polygon_overlay(awk_map_polygon_overlay_t *o);
int32_t awk_map_add_overlay (uint32_t map_id, awk_map_base_overlay_t *o);
int32_t awk_map_update_overlay(uint32_t map_id, awk_map_base_overlay_t *o);
int32_t awk_map_remove_overlay(uint32_t map_id, uint32_t overlay_id);
const awk_map_base_overlay_t* awk_map_find_overlay(uint32_t map_id, uint32_t overlay_id);
const awk_map_base_overlay_t* awk_map_get_overlay (uint32_t map_id, uint32_t index);
uint32_t awk_map_get_overlay_count(uint32_t map_id);
核心结构:
typedef struct _awk_map_base_overlay_t {
awk_map_overlay_type geometry_type; // POINT / LINE / POLYGON / TRACK_NAVI
int32_t group_id;
int32_t map_id;
int32_t priority;
bool visible;
bool is_focus;
float min_level; // 可显示的最小级别
float max_level; // 可显示的最大级别
int32_t guid; // 由调用方分配
} awk_map_base_overlay_t;
点覆盖物有 normal_marker / focus_marker,每个包含 icon_texture / name_texture / bubble_texture。 线覆盖物支持虚线、鱼骨箭头、走过路线 (pre_index) 等。
4.5 瓦片预加载与缓存
4.6 离线数据下载(仅手表,需 OFFLINE feature)
int32_t awk_map_start_download_offline_data(const char *adcode, uint32_t level, awk_map_download_callback_t *cb);
int32_t awk_map_stop_download_offline_data(void);
int32_t awk_map_start_download_region_range(awk_map_coord2d_t center, awk_map_range_t range,
uint8_t expect_level, awk_map_download_callback_t *cb);
int32_t awk_map_stop_download_region_range(void);
int32_t awk_map_list_download_offline_regions(const char *adcode, uint32_t level,
awk_map_offline_gdb_query_result_t *out);
int32_t awk_map_delete_download_offline_region(const char *adcode, uint32_t level);
int32_t awk_map_list_download_region_range(awk_map_coord2d_t loc, awk_map_range_t range,
uint8_t expect_level, awk_map_offline_gdb_query_result_t *out);
int32_t awk_map_delete_download_region_range(awk_map_coord2d_t loc, awk_map_range_t range, uint8_t expect_level);
int32_t awk_map_sync_download_offline_region(void);
int32_t awk_map_list_region_levels(awk_map_coord2d_t loc, uint8_t *expect_levels, int32_t n,
awk_map_offline_gdb_query_result_t *out);
// 沿路下载
int32_t awk_map_download_polyline_region(const char *key, awk_map_coord2d_t *pts, uint32_t n,
uint8_t *expand_levels, uint8_t expand_levels_n,
awk_map_tile_download_callback_t *cb);
// 获取瓦片请求(高级用法,外部自管下载)
awk_http_request_t* awk_map_download_get_request(const char *tile_file_key);
int32_t awk_map_sync_tile_file(char **keys, uint32_t n);
下载回调:
struct _awk_map_download_callback_t {
void (*on_started) (awk_map_download_callback_t *cb);
void (*on_progress)(awk_map_download_callback_t *cb, float progress);
void (*on_finish) (awk_map_download_callback_t *cb);
void (*on_stop) (awk_map_download_callback_t *cb);
void (*on_error) (awk_map_download_callback_t *cb, int32_t code, const char *msg);
};
下载不支持并发,需顺序执行。
4.7 轨迹导航 / 循迹(仅手表,需 TRACK_NAVI feature)
awk_map_track_info_t* awk_map_track_navi_parse_gpx(const char *gpx, size_t len);
void awk_map_track_navi_parse_track_info_free(awk_map_track_info_t *info);
int32_t awk_map_init_track_navi_overlay (awk_map_track_navi_overlay_t *o);
int32_t awk_map_track_navi_add_overlay (uint32_t map_id, awk_map_track_navi_overlay_t *o);
int32_t awk_map_track_navi_remove_overlay(uint32_t map_id, uint32_t overlay_id);
void awk_map_track_navi_update_real_point(uint32_t map_id, awk_map_coord2d_t pt, float bear,
awk_map_track_navi_overlay_t *o);
double awk_map_track_navi_get_distance (uint32_t map_id, awk_map_coord2d_t pt,
awk_map_track_point_type ptype,
awk_map_track_navi_overlay_t *o);
轨迹覆盖物 awk_map_track_navi_overlay_t 包含规划线、实走线、偏航线、转向点图标和事件监听 (on_track_pass_point / on_trajector_yaw / on_navi_event)。
五、导航 API 参考
导航功能依赖 NAVI feature。手表和眼镜默认都启用。
导航构建在地图层之上:必须先 awk_init 并 awk_map_create_view 拿到 map_id,再 awk_init_navi 启动导航服务。
5.1 生命周期
int32_t awk_init_navi (awk_navi_config_t *config); // 启动导航数据通路
int32_t awk_uninit_navi (void);
int32_t awk_init_navi_view (uint32_t map_id, awk_navi_view_config_t *vc); // 启动导航 UI
int32_t awk_uninit_navi_view(void);
- 调用 awk_init_navi 后,仅有数据回调;若需要 SDK 内部画导航 UI(车标、路线高亮等),再调 awk_init_navi_view
- 导航期间外部不要直接操作地图(如旋转、缩放),与内部冲突
- awk_navi_get_map_id() 返回当前导航绑定的 map_id
5.2 数据输入
导航数据由宿主以 protobuf 格式喂入:
int32_t awk_navi_data(const uint8_t *data, size_t len);
// 返回 0 成功;负值为数据类型相关错误(详见头文件)
// -10000 外层包装异常;-10001 反初始化后调用
5.3 视图控制
5.4 回调监听
int32_t awk_navi_add_data_callback (awk_navi_data_callback_t *cb);
int32_t awk_navi_remove_data_callback(awk_navi_data_callback_t *cb);
int32_t awk_navi_add_event_callback (awk_navi_event_callback_t *cb);
int32_t awk_navi_remove_event_callback(awk_navi_event_callback_t *cb);
数据回调(awk_navi_data_callback_t) 关键字段:
void (*update_navi_route_group)(...); // 路线更新
void (*update_navi_info) (...); // 行中导航信息(剩余距离/时间/下一动作)
void (*update_navi_location) (...); // 自车位置
void (*update_turn_info) (...); // 当前路口转向图标
void (*update_next_turn_info) (...); // 下下路口转向
void (*show_rear_appr_vehicle) (...); // 后方来车提醒(显示)
void (*hide_rear_appr_vehicle) (...); // 后方来车提醒(隐藏)
void (*show_traffic_signal) (...); // 红绿灯倒计时(显示)
void (*hide_traffic_signal) (...);
void (*show_lane_info) (...); // 车道线
void (*hide_lane_info) (...);
void (*show_traffic_light_num) (..., int32_t num, ...);
事件回调(awk_navi_event_callback_t) 关键字段:
void (*update_navi_calc_success)(...); // 算路成功
void (*update_navi_calc_failed) (...); // 算路失败
void (*did_start_navi) (...); // 开始导航
void (*play_navi_sound_string) (...); // 播报
void (*arrived_way_point) (...); // 到达途经点
void (*update_tracking_mode) (...); // 跟随模式变更
void (*update_show_mode) (...); // 显示模式变更
void (*update_is_navigation) (...); // 是否在导航
void (*on_reset) (...);
void (*update_highlight_route) (...); // 高亮路线变更
void (*stop_navi) (...); // 停止导航
void (*on_arrived_destination) (...); // 到达终点
void (*show_map) (..., uint32_t map_id, bool show); // 显隐地图
5.5 枚举与类型
typedef enum {
AWK_NAVI_TRACKING_MODE_MAP_NORTH, // 0 正北朝上
AWK_NAVI_TRACKING_MODE_CAR_NORTH, // 1 车头朝上
AWK_NAVI_TRACKING_MODE_ROUTE_NORTH // 2 路线朝上
} awk_navi_tracking_mode_type;
typedef enum {
AWK_NAVI_SHOW_MODE_NONE,
AWK_NAVI_SHOW_MODE_CAR_POSITION_LOCKED,
AWK_NAVI_SHOW_MODE_OVERVIEW,
} awk_navi_show_mode_type;
typedef enum {
AWK_NAVI_LOCKED_OVERLAY_NONE,
AWK_NAVI_LOCKED_OVERLAY_MAP,
AWK_NAVI_LOCKED_OVERLAY_SPEED
} awk_navi_locked_overlay_type;
更详细的导航事件/回调字段(awk_navi_route_group_t / awk_navi_info_t / awk_navi_location_t 等结构),见 include/navi/awk_navi_defines.h。
六、Demo / Harness 验证
SDK 本体是 C 语言静态库,最终部署在 RTOS 设备上。真机调试链路慢、可观测性弱,因此推荐的工作流是:先在 PC 端宿主上用同一份 SDK 把流程跑通,再换 adapter 部署到 RTOS 真机。
仓库提供两类验证手段:
- 上层 Demo:用任意一种能跑 C 的宿主(iOS App / Mac CLI / Linux / Android 等)实现一套 adapter,把 SDK 静态库链入,跑通主流程
- 事件流 Harness:基于日志关键字做断言,可在 Demo 宿主或 RTOS 真机上跑,用于自动化回归
两者都不是最终交付形态,但能在厂商对接真机前把 SDK 行为收敛。
6.1 上层 Demo(以 iOS 工程为参考)
定位:宿主仅作为验证容器,目的不是发布 iOS 应用。SDK 是同一份 C 库,宿主可以是任意能跑 C 的环境(iOS / Mac / Linux / Android / 厂商 PC 工具),各家按需自建即可。
仓库自带的 iOS 参考工程(test/WatchSDKDemo/WatchSDKDemo.xcodeproj)用 CoreGraphics / NSURLSession / POSIX 文件接口实现了一套完整 adapter,可直接在 iOS 模拟器上看到地图绘制结果,便于快速对照。
运行 iOS 参考工程:
# 用 Xcode 打开
open test/WatchSDKDemo/WatchSDKDemo.xcodeproj
# 或命令行编译
xcodebuild build \
-project test/WatchSDKDemo/WatchSDKDemo.xcodeproj \
-scheme WatchSDKDemo \
-configuration Debug \
-destination 'generic/platform=iOS Simulator'
判断成功的关键信号(任何宿主都通用):
- awk_init 返回 0
- awk_map_create_view 返回 > 0 的 map_id
- render_adapter.begin_drawing 持续被调用
- on_tile_begin_download → on_tile_end_download 链路成功(在线模式)
- 屏幕(或 framebuffer 抓帧)显示出地图瓦片
厂商对接建议:先用熟悉的 PC 宿主实现一遍 adapter(甚至 Mac 上写个命令行程序也行),把上面 5 个信号跑通;然后再把 adapter 移植到 RTOS 真机,只需替换平台相关的实现,业务逻辑无需变动。
6.2 Harness 事件流验证
位置:script/harness/run_requirement_harness.sh
适用于 RTOS 真机或 iOS 参考工程上的自动化回归。Harness 基于事件流(日志关键字)做断言,能验证:
- SDK 初始化是否成功
- 网络请求路径与 payload
- 缓存文件生成情况
- DAU 上报链路是否打通
基本用法:
# 默认用例
./script/harness/run_requirement_harness.sh
# 指定 case
./script/harness/run_requirement_harness.sh <case_name>
需要在环境中预设:
export WATCH_SDK_DEMO_DIR=/path/to/WatchSDKDemo
export DEMO_PROJECT_DIR=$WATCH_SDK_DEMO_DIR/AMapWatch
export SIMULATOR_UDID=<your-booted-ios-simulator-udid>
export LOG_PREFIX="[RTOS_DAU]" # 或对应业务前缀
关键事件日志前缀:
详细原理参见 doc/requirement_development_harness.md。
七、错误码速查
7.1 awk_init 返回码
具体到字段,参考 src/awk.c::awk_check_context() / awk_check_feature()。
7.2 通用错误码
7.3 地图常见错误码
7.4 设备激活错误码
八、常见问题
Q1:awk_init 返回 -900 / -901 / -902 怎么办?
tile_style 与编译时启用的 feature 不匹配。例如眼镜默认未启用 SVG,但 tile_style 设成 AWK_MAP_TILE_STYLE_VECTOR 就会返回 -901。改用支持的 tile_style,或与 SDK 提供方确认平台 feature 集合。
Q2:awk_init 返回 -200 系列怎么办?
render_adapter 中某个函数指针为 NULL。对照 §7.1 表格定位具体哪一个,补上实现即可。
Q3:调用任意 API 返回 -3?
调用线程与 awk_init 时不一致。SDK 是单线程模型,所有 API(包括网络回调注入数据)必须切回主流程线程。
Q4:多实例(多张地图同屏)注意事项?
- 每个 awk_map_create_view 返回独立 map_id,可同时存在多个
- 退出页面/不再使用时必须调用 awk_map_destroy_view 释放
- 渲染回调 awk_map_render_callback_t 是全局的,需在回调内部通过 map_id 区分实例
Q5:内存/磁盘缓存大小如何选?
RTOS 设备普遍紧内存,建议根据可用 PSRAM / 闪存按需调整:
- 内存缓存:受 PSRAM 大小约束;开 tile_clip_load=true 可显著降低瓦片缓冲占用
- 磁盘缓存:受闪存大小约束;默认 200 MB 通常需要按设备闪存余量下调
- 像素格式:彩屏选 ARGB_8888;紧显存选 RGB_565 / BGR_565;单色屏选 GREY
Q6:多进程共用 root_dir 会有问题吗?
会。SDK 内部没有跨进程文件锁,多个进程同时写 tile_cache.index 会损坏索引。 多进程场景下,请每个进程使用独立的 root_dir。 offline_map_dir 因为下载完成后只读,可以安全共享。
Q7:网络请求回调能在异步线程吗?
send 可以在异步线程内部发起 HTTP,但 awk_http_response_callback_t 的回调必须切回主流程线程,否则 SDK 内部线程检查会失败。
Q8:导航开了,但 SDK 不画 UI 怎么办?
只调用 awk_init_navi 不会画 UI,只回调数据。需要 SDK 内部绘制时必须再调用 awk_init_navi_view(map_id, vc)。 同时检查 awk_navi_show_ui_elements(true) 是否打开。
九、延伸阅读
权威头文件(凡本文档与头文件冲突,以头文件为准):
- include/awk.h
- include/awk_adapter.h
- include/awk_version.h
- include/map/awk_map.h
- include/map/awk_map_defines.h
- include/navi/awk_navi.h
- include/navi/awk_navi_defines.h
