Android AmapLinkClient API 最后更新时间: 2026年08月27日
一、概述
AmapLinkClient 是高德地图链接服务的客户端实现,提供与高德地图服务通信的接口。通过此SDK,第三方应用可以与高德地图进行安全、高效的通信。
二、主要接口
2.1 初始化
URL Scheme配置
在AndroidManifest.xml中配置
<activity
android:name=".YourTargetActivity"
android:exported="true" <!-- 必须为 true,以接收来自其他应用的 Intent -->
>
<!-- ... 其他可能存在的 intent-filter ... -->
<intent-filter>
<!-- Action 和 Category 是标准配置 -->
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Data 部分是关键 -->
<data
android:scheme="amapuri"
android:host="<API KEY>"
/>
</intent-filter>
</activity>可使用如下adb命令校验
adb shell am start -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -c android.intent.category.DEFAULT -f 0x10000000 -d "amapuri://<apiKey>" <packageName>构造函数
public AmapLinkClient(Context context, String apiKey)- 描述:创建AmapLinkClient实例
- 参数:
- context: 应用上下文
- apiKey: 高德开放平台申请的API Key
- 注意事项:
- API Key必须在高德开放平台注册并通过审核
- 建议使用ApplicationContext避免内存泄漏
2.2 核心方法
startAuth()
public void startAuth()- 描述:授权接口
connect()
public boolean connect()- 描述:连接到高德地图服务
- 返回值:boolean - 初始连接尝试是否成功发出
- 注意事项:
- 如果配置了重连间隔,会启动自动重连机制
- 需要提前设置ConnectionListener
- 连接成功会通过ConnectionListener.onConnected()回调通知
disconnect()
public void disconnect()- 描述:断开连接
- 注意事项:
- 会停止自动重连机制
- 会触发ConnectionListener.onDisconnected()
- 会清理所有注册的监听器
execute(String param)
public String execute(String param)- 描述:执行命令
- 参数:
- param: 命令参数,JSON格式字符串
- 返回值:String - 执行结果,JSON格式
- 成功时:返回服务端的原始响应
- 失败时:返回包含 、 和 字段的JSON字符串
- 错误码:
- SERVICE_NOT_CONNECTED (101): 服务未连接
- INVALID_PARAMETER (300): 参数格式错误
- SERVICE_UNAVAILABLE (102): 服务不可用
- 注意事项:
- 会自动处理token验证和刷新
- 返回的JSON中status="error"时表示出错,包含errorCode和message字段
isConnected()
public boolean isConnected()- 描述:检查当前连接状态
- 返回值:boolean - 服务是否已连接且可用
- 注意事项:
- 会进行实际的ping测试,确保服务可用
2.3 监听器管理
setConnectionListener(ConnectionListener listener)
public void setConnectionListener(ConnectionListener listener)- 描述:设置连接状态监听器
- 参数:
- listener: 连接状态监听器
- 注意事项:
- 必须在connect()之前设置
registerDataListener(AmapLinkDataListener listener)
public boolean registerDataListener(AmapLinkDataListener listener)- 描述:注册数据监听器
- 参数:
- listener: 数据监听器
- 返回值:boolean - 注册是否成功
- 注意事项:
- 如果服务已连接,会自动注册到服务端
- 需要处理AmapLinkDataListener.onError()回调
- 可以注册多个不同类型的监听器
2.4 配置方法
setReconnectConfig(boolean enabled, int maxAttempts, int delaySeconds)
public void setReconnectConfig(boolean enabled, int maxAttempts, int delaySeconds)- 描述:设置自动重连策略
- 参数:
- enabled: 是否开启自动重连
- maxAttempts: 最大重连次数(enabled为true时,必须大于0)
- delaySeconds: 重连间隔时间(enabled为true时,必须大于0)
- 注意事项:
- 建议在初始化时配置
- 如果参数无效,会强制设为有效值
三、监听器接口
ConnectionListener
public interface ConnectionListener { void onConnected(); void onConnectionFailed(int errorCode, String message); void onDisconnected();}- onConnected: 连接成功时回调
- onConnectionFailed: 连接失败时回调,提供错误码和错误信息
- onDisconnected: 连接断开时回调
AmapLinkDataListener
public interface AmapLinkDataListener { int TRANSPORT_DIRECT = 1; // 直接传输 int TRANSPORT_SHARED_MEMORY = 2; // 共享内存传输 int TRANSPORT_CHUNKED = 3; // 分块传输 void onDataReceived(JSONObject data, int transportType); void onError(int errorCode, String errorMessage);}- onDataReceived: 接收数据回调,提供数据内容和传输方式
- onError: 数据处理错误回调,提供错误码和错误信息
- 传输方式:
- TRANSPORT_DIRECT: 小数据直接传输
- TRANSPORT_SHARED_MEMORY: 大数据通过共享内存传输
- TRANSPORT_CHUNKED: 大数据通过分块方式传输
四、使用示例
// 1. 创建AmapLinkClient实例
AmapLinkClient client = new AmapLinkClient(context, "YOUR_API_KEY");
// 2. 设置自动重连策略
client.setReconnectConfig(true, 5, 2);
// 3. 设置连接监听器
client.setConnectionListener(new ConnectionListener() {
@Override
public void onConnected() {
// 连接成功
Log.d(TAG, "服务连接成功");
}
@Override
public void onConnectionFailed(int errorCode, String message) {
// 连接失败
Log.e(TAG, "连接失败: " + errorCode + ", " + message);
}
@Override
public void onDisconnected() {
// 连接断开
Log.d(TAG, "服务连接断开");
}
});
// 4. 注册数据监听器
client.registerDataListener(new AmapLinkDataListener() {
@Override
public void onDataReceived(JSONObject data, int transportType) {
// 收到数据
String transportMethod;
switch (transportType) {
case AmapLinkDataListener.TRANSPORT_DIRECT:
transportMethod = "直接传输";
break;
case AmapLinkDataListener.TRANSPORT_SHARED_MEMORY:
transportMethod = "共享内存传输";
break;
case AmapLinkDataListener.TRANSPORT_CHUNKED:
transportMethod = "分块传输";
break;
default:
transportMethod = "未知传输方式";
}
Log.d(TAG, "收到数据,传输方式: " + transportMethod);
}
@Override
public void onError(int errorCode, String errorMessage) {
// 处理错误
Log.e(TAG, "数据处理错误: " + errorCode + ", " + errorMessage);
}
});
// 5. 连接到服务
client.connect();
// 6. 执行命令
changeDesButton.setOnClickListener(v -> {
try {
/**
* {
* "cmd": 4,
* "data": {
* "lon": 116.397455,
* "lat": 39.909187,
* "name": "天安门",
* "poiid": "B000A60DA1",
* "entranceList": [
* {
* "lon": 116.397604,
* "lat": 39.907697
* }
* ]
* },
* "requestId": 2222224
* }
*/
JSONObject commandJson = new JSONObject();
commandJson.put("cmd", 4);
commandJson.put("requestId", 2222224);
JSONObject dataJson = new JSONObject();
dataJson.put("lon", 116.397455);
dataJson.put("lat", 39.909187);
dataJson.put("name", "天安门");
dataJson.put("poiid", "B000A60DA1");
JSONArray entranceListJson = new JSONArray();
JSONObject entranceJson = new JSONObject();
entranceJson.put("lon", 116.397604);
entranceJson.put("lat", 39.907697);
entranceListJson.put(entranceJson);
dataJson.put("entranceList", entranceListJson);
commandJson.put("data", dataJson);
String result = client.execute(commandJson.toString());
boolean success = result != null && result.contains("success");
if (success) {
Toast.makeText(this, "更改目的地数据请求", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "更改目的地请求失败", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
Log.e(TAG, "更改目的地指令异常", e);
Toast.makeText(this, "更改目的地指令异常: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
// 7. 断开连接
client.disconnect();五、错误码
5.1 连接相关错误码
- SERVICE_NOT_INSTALLED (100): 服务未安装
- SERVICE_NOT_CONNECTED (101): 服务未连接
- SERVICE_UNAVAILABLE (102): 服务不可用
- CONNECTION_RETRIES_EXCEEDED (103): 重连次数超限
5.2 认证相关错误码
- TOKEN_INVALID (200): Token无效
- SIGNATURE_VERIFY_FAILED (201): 签名验证失败
- ENCRYPTION_FAILED (202): 请求加密失败
- DECRYPTION_FAILED (203): 响应解密失败
- API_KEY_INVALID (204): API Key无效
- PERMISSION_DENIED (205): 权限不足
- AUTHENTICATION_FAILED (206): 认证失败
5.3 参数相关错误码
- INVALID_PARAMETER (300): 参数非法
- LISTENER_IS_NULL (301): 监听器为空
- REQUEST_DATA_PARSE_ERROR (302): 请求参数解析错误
5.4 数据处理相关错误码
- RESPONSE_DATA_PARSE_ERROR (400): 客户端解析响应失败
- DATA_TRANSFER_ERROR (401): 分块传输失败
- SHARED_MEMORY_ERROR (402): 共享内存错误
- DATA_TOO_LARGE (403): 数据过大
- DATA_PARSE_ERROR (404): 数据解析异常
5.5 服务端业务错误码
- SERVER_AUTH_FAILED (500): 服务器端认证失败
- SERVER_COMMAND_EXEC_FAILED (501): 命令执行失败
- SERVER_ROUTE_PLAN_FAILED (502): 路线规划失败
- SERVER_COMMAND_NOT_SUPPORTED (503): 不支持的命令
- COMMAND_NOT_FOUND (504): 未找到命令
5.6 服务端内部错误码
- SERVER_INTERNAL_ERROR (600): 服务端内部错误
5.7 通用错误码
- REMOTE_EXCEPTION (900): 远程调用异常
- CREATE_ERROR_RESPONSE_FAILED (901): 创建错误响应失败
- UNKNOWN_ERROR (999): 未知错误
六、错误码获取入口
七、注意事项
- 线程安全性:
- 所有操作都建议在主线程中进行
- SDK内部已处理线程同步,确保回调在主线程执行
- 错误处理建议:
- ConnectionListener.onConnectionFailed() 处理连接相关错误
- AmapLinkDataListener.onError() 处理数据传输和解析相关错误
- execute() 的返回值处理同步命令执行错误
- 最佳实践:
- 建议在Application初始化时配置自动重连策略
- 断开连接时会自动清理所有资源
- 处理大数据时,注意区分不同的传输方式
- 保持API Key的安全性,不要硬编码在代码中
- 性能考虑:
- 对于大数据传输,SDK会自动选择最优传输方式
- 共享内存传输效率最高,但需要特殊处理
- 分块传输适合网络不稳定的情况
- 安全性:
- SDK内部实现了token验证和自动刷新机制
- 敏感数据传输采用加密保护
- 确保API Key和包名在高德开放平台正确配置
八、AmapLinkClient.execute 指令与协议
本文档基于当前仓库源码整理 mAmapLinkClient.execute(String param) 的调用链、请求协议、已封装指令和回调协议。
8.1 基础请求协议
业务侧传入的基础 JSON:
{
"cmd": 1,
"requestId": 123456,
"data": {}
}
字段说明:
AmapLinkClient.execute 会在调用 AIDL 前补充认证字段:
{
"cmd": 1,
"requestId": 123456,
"data": {},
"token": "...",
"sessionId": "..."
}
AIDL 接口:
String execute(String param);
8.2 本地错误响应
如果客户端本地检查失败,execute 返回 JSON 字符串:
{
"status": "error",
"errorCode": 101,
"message": "服务未连接"
}
常见客户端错误码:
cmd=1 切换路线
{
"cmd": 1,
"requestId": 1760000000000,
"data": {
"pathID": "123"
}
}
说明:
- pathID 是路线 ID,通常来自导航路线数据中的备选路线。
- 当前实现中 requestId 使用 System.currentTimeMillis()。
cmd=2 停止导航
{
"cmd": 2,
"requestId": 123456
}
说明:
- 无 data。
- 当前实现中 requestId 是 100000~999999 的随机数。
cmd=3 添加途经点
{
"cmd": 3,
"requestId": 123456,
"data": {
"lon": 116.397,
"lat": 39.908,
"name": "故宫博物院",
"poiid": "B000A8UIN8",
"entranceList": [
{
"lon": 116.3971,
"lat": 39.9081
}
]
}
}
说明:
- requestId 来自 Agent taskId,代码里会 Integer.parseInt(taskId)。
- entranceList 可选,仅当 POI 有入口点时附加。
cmd=4 设置/变更终点
{
"cmd": 4,
"requestId": 123456,
"data": {
"lon": 116.397,
"lat": 39.908,
"name": "故宫博物院",
"poiid": "B000A8UIN8"
}
}
说明:
- 参数结构与 cmd=3 一致。
- cmd=3 和 cmd=4 的区别是语义:3 为途经点,4 为终点。
cmd=5 查询导航行中结构体
{
"cmd": 5,
"requestId": 123456
}
说明:
- 无 data。
- Agent 侧会等待 onStructuredInfo(requestId, jsonData) 回调。
- 回调 JSON 中期望存在 navi_structured_info 字段,其值是 JSON 数组字符串。
cmd=6 切换播报方式
驾车协议:
{
"cmd": 6,
"requestId": 123456,
"data": {
"mode": 2
}
}
驾车 mode 含义:
骑行/步行协议:
{
"cmd": 6,
"requestId": 123456,
"data": {
"value": "1"
}
}
骑行/步行 value 含义:
cmd=7 触发导航关键信息刷新
{
"cmd": 7,
"requestId": 123456
}
说明:
- 无 data。
- 当前上层方法名是 sendKeyNaviInfo,注释为“触发一次导航关键信息刷新传递”。
8.3 回调协议
客户端通过 AIDL 注册监听:
boolean registerListener(ILinkSdkCallback callback);
回调接口:
void onAmapCallback(String data);
void onAmapCallbackWithFd(String metadata, in ParcelFileDescriptor fd);
SDK 最终回调业务:
void onDataReceived(JSONObject data, int transportType);
void onError(int errorCode, String errorMessage);
transportType:
普通导航数据在 AMapLinkManager 中按如下格式解析:
{
"datas": "[{\"type\":1,\"data\":\"...\"}]"
}
注意:
- datas 是字符串形式的 JSON 数组。
- 数组每项包含 type 和 data。
- type 对应 AMapNaviDataType。
- data 是具体导航数据字符串,随后交给 AMapInteractiveDataManager.handleAMapInteractiveData(...) 处理。
出租车业务数据是另一套结构,示例注释中出现过:
{
"biz_type": 201,
"biz_version": 1,
"message": {
"active": 1,
"data": {
"gdServiceId": "1",
"state": 103,
"title": "京J232301 红色",
"subTitle": "司机正在赶来 距你1.1公里,3分钟"
}
},
"bizType": 201
}
