开发 AIoT 智能眼镜SDK 开发指南 与高德地图App建联 iOS AMap IPC Link Kit

iOS AMap IPC Link Kit 最后更新时间: 2026年08月27日

一、概述

AMap IPC Link Kit 提供了与高德地图应用进行进程间通信的能力,主要包含两个核心组件: - AMapAuthorizationManager: 负责高德应用认证 - AMapLinkManager: 负责IPC连接管理和数据传输

二、基础配置

2.1 导入头文件

#import "AMapLinkManager.h"
#import "AMapAuthorizationManager.h"

2.2 配置URL Scheme

在合作方工程的 Info.plist 中配置回调URL Scheme:

授权后高德APP返回合作方APP,否则无法返回获取授权结果

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLName</key>
        <string>AMapAuth</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>amapuri2f3df76603c218a5f2198c77f956</string>
        </array>
    </dict>
</array>

判断是否安装高德APP,否则判断始终返回NO

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>amapuri</string>
</array>

三、认证管理 (AMapAuthorizationManager)

3.1 初始化配置

授权时依赖APIKey进行认证,需在更早时机调用基础库设置APIKey,举例如下

- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
    self.window = [[UIWindow alloc] initWithWindowScene:(UIWindowScene *)scene];
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
    self.window.rootViewController  = nav;
    self.window.backgroundColor     = [UIColor whiteColor];
    
    [self.window makeKeyAndVisible];
    
    [[[NSBundle mainBundle] infoDictionary] setValue:@"com.autonavi.DevDemoNavi" forKey:@"CFBundleIdentifier"];
    [[AMapServices sharedServices] setEnableHTTPS:NO];
    [[AMapServices sharedServices] setApiKey:(NSString *)APIKey];
    
    [AMapPrivacyUtility handlePrivacyAgreeStatusWithWindow:self.window];
}

3.2 安装状态检查

// 检查是否安装高德APP
BOOL isInstalled = [[AMapAuthorizationManager sharedInstance] isInstallAMapApp];

// 跳转应用商店下载高德APP
[[AMapAuthorizationManager sharedInstance] turnToAppStore];

3.3 启动认证流程

- (void)startAuthentication {
    __weak typeof(self) weakSelf = self;
    [[AMapAuthorizationManager sharedInstance] startAuthenticationWithCallback:^(BOOL success, NSError * _Nonnull error) {
    }];
}

3.4 处理认证回调

AppDelegate 方式

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
    return [[业务Manager sharedInstance] handleURL:url];
}

SceneDelegate 方式

- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
    UIOpenURLContext *urlContext = URLContexts.allObjects.firstObject;
    if (urlContext) {
        [[业务Manager sharedInstance] handleURL:urlContext.URL];
    }
}

业务Manager处理URL

- (BOOL)handleUrl:(NSURL *)url
{
    BOOL authResult = [[AMapAuthorizationManager sharedInstance] handleURL:url];
    if (authResult) {
        [[NSUserDefaults standardUserDefaults] setBool:authResult forKey:@"AMapAuthorization_Authored"];
        [self createConnect];
    }
    return YES;
}

四、连接管理 (AMapLinkManager)

4.1 初始化linkSDK&建联

connect之前务必先授权成功、再调用initWithConnectConfig,否则linkClient不会初始化,示例如下

- (void)createConnect
{
    BOOL isAuthed = [[NSUserDefaults standardUserDefaults] boolForKey:@"AMapAuthorization_Authored"];
    if (!isAuthed) {
        // 需在业务场景内调用startAuthenticationWithCallback处理授权
        return;
    }
    
    if ([[AMapLinkManager sharedInstance] isConnected]) {
        return;
    }
    AMapLinkConnectConfig *config = [AMapLinkConnectConfig new];
    config.autoReconnect = YES;
    config.maxReconnectAttempts = 50;
    config.reconnectDelay = 2;
    [[AMapLinkManager sharedInstance] initWithConnectConfig:config];
    [[AMapLinkManager sharedInstance] connect];
}

4.2 监听连接状态

@property (nonatomic, strong) NSString *reachabilityObserverID;

- (void)setupConnectionObserver {
    __weak typeof(self) weakSelf = self;
    self.reachabilityObserverID = [[AMapLinkManager sharedInstance] addReachablityChanged:^(BOOL isReachablity) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (isReachablity) {
                NSLog(@"连接已建立");
                [weakSelf onConnectionEstablished];
            } else {
                NSLog(@"连接已断开");
                [weakSelf onConnectionLost];
            }
        });
    }];
}

- (void)removeConnectionObserver {
    if (self.reachabilityObserverID) {
        [[AMapLinkManager sharedInstance] removeReachablityObserver:self.reachabilityObserverID];
        self.reachabilityObserverID = nil;
    }
}

4.3 监听错误

IPC Link ErrorCode

@property (nonatomic, strong) NSString *errorObserverID;

- (void)setupErrorObserver {
    self.errorObserverID = [[AMapLinkManager sharedInstance] addErrorOccurred:^(NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"连接错误: %@", error.localizedDescription);
        });
    }];
}

- (void)removeErrorObserver {
    if (self.errorObserverID) {
        [[AMapLinkManager sharedInstance] removeErrorObserver:self.errorObserverID];
        self.errorObserverID = nil;
    }
}

4.4 监听打车数据变化

高德测试安装包,登录后进入打车页面,起终点定位在北京,比如 起点在高德总部,终点也改成高德附近,立即打车。

可测打车发起订单、进入行程、结束等链路。(测试环境订单到打车测试平台,有测试人员在测时可能会被接单,无人接单时 可重新打车试试)

[[AMapLinkManager sharedInstance] addTaxiInfoChanged:^(AMapTaxiInfo * _Nonnull taxiInfo) {
        NSString *msg = [NSString stringWithFormat:@"addTaxiInfoChanged:%@", taxiInfo];
        callBack(msg);
}];

4.5 检查连接状态

BOOL isConnected = [[AMapLinkManager sharedInstance] isConnected];

4.6 断开连接

- (void)disconnect {
    [[AMapLinkManager sharedInstance] disconnect];
}

五、数据传输

5.1 发送数据

- (void)sendDataToClient:(NSDictionary *)data {
    if (!data || ![NSJSONSerialization isValidJSONObject:data]) {
        return;
    }

    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:data
                                                       options:NSJSONWritingSortedKeys
                                                         error:&error];

    if (error) {
        NSLog(@"JSON序列化失败: %@", error.localizedDescription);
        return;
    }

    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    if (jsonString) {
        [[AMapLinkManager sharedInstance] sendDataToClient:jsonString];
    }
}

5.2 常用命令示例

// 开始导航
- (void)startNavigation {
    NSDictionary *command = @{
        @"cmd": @(5),
        @"requestId": @(12345)
    };
    [self sendDataToClient:command];
}

// 添加途经点
- (void)addViaPoint {
    NSDictionary *command = @{
        @"cmd": @(3),
        @"data": @{
            @"lon": @116.397455,
            @"lat": @39.909187,
            @"name": @"天安门",
            @"poiid": @"B000A60DA1",
            @"entranceList": @[
                @{
                    @"lon": @116.397604,
                    @"lat": @39.907697
                }
            ]
        },
        @"requestId": @(12346)
    };
    [self sendDataToClient:command];
}

// 更改目的地
- (void)changeDestination {
    NSDictionary *command = @{
        @"cmd": @(4),
        @"data": @{
            @"lon": @116.397455,
            @"lat": @39.909187,
            @"name": @"天安门",
            @"poiid": @"B000A60DA1",
            @"entranceList": @[
                @{
                    @"lon": @116.397604,
                    @"lat": @39.907697
                }
            ]
        },
        @"requestId": @(12347)
    };
    [self sendDataToClient:command];
}

// 更改播报设置
- (void)changeBroadcastSettings {
    NSDictionary *command = @{
        @"cmd": @(6),
        @"data": @{
            @"value": @(1) // 0:静音, 1:简洁, 2:详细, 6:极简, 7:智能
        },
        @"requestId": @(12348)
    };
    [self sendDataToClient:command];
}

5.3 获取出行方式

在 AMapLinkManager.h内,如下接口

// 当前Link投屏的导航类型 0、-1为-无效值 1-驾车 2-骑行(自行车) 3-步行 4-骑行(电动车)
- (int)getCurrentTravelTool;

5.4 获取终点目的地

高德app投屏获取目的地poi,需要调用如下监听

    self.naviTypeDataCallback = ^(AMapNaviTypeData * _Nonnull naviTypeData) {
        NSString *msg = [NSString stringWithFormat:@"😊AMapLinkManagerDemo addNaviTypeDataListener:%@", naviTypeData];
        [AMapIPCLinkLogger logFormat:@"addNaviTypeDataListener: %ld, %@", naviTypeData.type, naviTypeData];
        if (callBack) {
            callBack(msg);
        }
    };
    [[AMapNaviClientManager shareInstance] addNaviTypeDataListener:self.naviTypeDataCallback];

在监听到type==2时,取resultObj字段,获取到的数据为AMapNaviRouteGroup对象,对象内有endPoi对象  可以拿到后进行缓存

@interface AMapNaviTypeData : NSObject

/**
 * 导航数据对象
 * 如果路线类型,路线信息数据结构  AMapNaviRouteGroup
 * id类型用于后续扩展
 */
@property (nonatomic, strong) id _Nullable resultObj;

/**
 * 数据类型
 */
@property (nonatomic, assign) AMapNaviDataType type;

/**
 * 数据来源
 */
@property (nonatomic, assign) AMapNaviDataSource source;

@end

六、完整集成示例

//
//  AMapLinkClientViewController.m
//  AMapNaviKit
//
//  Created by lihui.qlh on 2025/3/25.
//  Copyright © 2025 Amap. All rights reserved.
//

#import "AMapLinkClientViewController.h"
#import "NavBarView.h"
#import "EventActionView.h"
#import <MALLMKit/AMapLinkManager.h>
#import <MALLMKit/AMapAuthorizationManager.h>
#import <MALLMKit/AMapLinkConnectConfig.h>
#import "AMapLinkClientObserverManager.h"

@interface AMapLinkClientViewController ()

@property(nonatomic, assign) BOOL isAuthored;

@property(nonatomic, strong) UITextView *receivedTextView;
@property(nonatomic, strong) NavBarView *navBarView;
@property(nonatomic, strong) EventActionView *eventActionView;

@property(nonatomic, strong) AMapLinkConnectConfig *connectConfig;

@end

@implementation AMapLinkClientViewController

- (void)viewDidLoad 
{
    [super viewDidLoad];
    [self.view setBackgroundColor:[UIColor whiteColor]];
    [self initUI];
    [self tryLink];
    __weak typeof(self) weakSelf = self;
    [[AMapLinkClientObserverManager sharedInstance] addObserver:^(NSString * _Nonnull msg) {
        [weakSelf apptendMessage:msg];
        [weakSelf updateInfo];
    }];
}

- (void)handleBackButtonClick
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)tryLink
{
    [self createConnect];
}

- (BOOL)handleUrl:(NSURL *)url
{
    BOOL authResult = [[AMapAuthorizationManager sharedInstance] handleURL:url];
    if (authResult) {
        [[NSUserDefaults standardUserDefaults] setBool:authResult forKey:@"AMapAuthorization_Authored"];
        [self createConnect];
    }
    return YES;
}

#pragma EventActionViewDelegate

- (void)createConnect
{
    BOOL isAuthed = [[NSUserDefaults standardUserDefaults] boolForKey:@"AMapAuthorization_Authored"];
    if (!isAuthed) {
        // 需在业务场景内调用startAuthenticationWithCallback处理授权
        return;
    }
    
    if ([[AMapLinkManager sharedInstance] isConnected]) {
        return;
    }
    AMapLinkConnectConfig *config = [AMapLinkConnectConfig new];
    config.autoReconnect = YES;
    config.maxReconnectAttempts = 50;
    config.reconnectDelay = 2;
    self.connectConfig = config;
    [[AMapLinkManager sharedInstance] initWithConnectConfig:config];
    [[AMapLinkManager sharedInstance] connect];
}

- (void)disconnect
{
    [[AMapLinkManager sharedInstance] disconnect];
}

- (void)sendData:(NSDictionary *)data {
    if (!data || ![NSJSONSerialization isValidJSONObject:data]) {
        return;
    }
    
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:data
                                                       options:NSJSONWritingSortedKeys
                                                         error:&error];
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

    if (jsonString) {
        [self apptendMessage:[NSString stringWithFormat:@"writeData: %@",jsonString]];
        [[AMapLinkManager sharedInstance] sendDataToClient:jsonString]; // 使用tag 200标识二进制数据
    }
}

- (void)openAmap 
{
    __weak typeof(self) weakSelf = self;
    [[AMapAuthorizationManager sharedInstance] startAuthenticationWithCallback:^(BOOL success, NSError * _Nonnull error) {
        [weakSelf updateInfo];
    }];
}

#pragma UIView
- (void)apptendMessage:(id)message
{
    if ([message isKindOfClass:[NSObject class]]) {
        self.receivedTextView.text = [NSString stringWithFormat:@"%@\n----------------------------\n%@",self.receivedTextView.text,message];
    }
}

- (void)updateInfo
{
    BOOL isConnected = [[AMapLinkManager sharedInstance] isConnected];
    BOOL isAuthed = self.isAuthored || [[NSUserDefaults standardUserDefaults] boolForKey:@"AMapAuthorization_Authored"];
    [self.eventActionView updateInfo:@{
        @"isConnected": @(isConnected),
        @"isAuthored": @(isAuthed)
    }];
}

- (void)sendData
{
    [self sendData:@{
        @"text": @"你好呀"
    }];
}
- (void)startNavi
{
    NSDictionary *dict = @{
        @"cmd": @(5),
        @"requestId": @2222225
    };
    [self sendData:dict];
}
- (void)changeRideBroadcast
{
    NSArray *rideValues = @[@"0", @"1"];
    NSUInteger randomIndex = arc4random_uniform((uint32_t)rideValues.count);
    NSString *randomValue = rideValues[randomIndex];
    [self sendData:@{
        @"cmd": @(6),
        @"data": @{
            @"value": randomValue, // 骑行 @"0", @"1"
        },
        @"requestId": @2222226
    }];
}

- (void)changeCarBroadcast
{
    NSArray *carValues = @[@(0), @(1), @(2), @(6), @(7)];
    NSUInteger randomIndex = arc4random_uniform((uint32_t)carValues.count);
    NSNumber *randomValue = carValues[randomIndex];
    [self sendData:@{
        @"cmd": @(6),
        @"data": @{
            @"value": randomValue, // 驾车 @(0),@(1),@(2),@(6),@(7) 静音、简洁、详细、极简、智能
        },
        @"requestId": @2222227
    }];
}

- (void)changeDestination
{
    NSDictionary *dict = @{
        @"cmd": @(4),
        @"data": @{
            @"lon": @116.397455,
            @"lat": @39.909187,
            @"name": @"天安门",
            @"poiid": @"B000A60DA1",
            @"entranceList": @[
                @{
                    @"lon": @116.397604,
                    @"lat": @39.907697
                }
            ]
        },
        @"requestId": @2222224
    };
    [self sendData:dict];
}

- (void)addViaPoint
{
    NSDictionary *dict = @{
        @"cmd": @(3),
        @"data": @{
            @"lon": @116.397455,
            @"lat": @39.909187,
            @"name": @"天安门",
            @"poiid": @"B000A60DA1",
            @"entranceList": @[
                @{
                    @"lon": @116.397604,
                    @"lat": @39.907697
                }
            ]
        },
        @"requestId": @2222223
    };
    
    [self sendData:dict];
}

- (void)clearLog
{
    self.receivedTextView.text = [NSString stringWithFormat:@"日志已清除"];
}

- (void)copyLog
{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"复制日志"
                                                                             message:@"确认要复制日志内容到剪贴板吗?"
                                                                      preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消"
                                                           style:UIAlertActionStyleCancel
                                                         handler:nil];

    UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"确认"
                                                            style:UIAlertActionStyleDefault
                                                          handler:^(UIAlertAction * _Nonnull action) {
        [UIPasteboard generalPasteboard].string = self.receivedTextView.text;
        [self apptendMessage:@"日志内容已复制到剪贴板"];
    }];

    [alertController addAction:cancelAction];
    [alertController addAction:confirmAction];
    [self presentViewController:alertController animated:YES completion:nil];
}

#pragma UIView
// 初始化UI
- (void)initUI {
    NSInteger screenWidth = self.view.bounds.size.width;
    NSInteger screenHeight = self.view.bounds.size.height;
    
    CGFloat statusBarHeight = 20;
    if (@available(iOS 11.0, *)) {
        UIWindow *window = UIApplication.sharedApplication.windows.firstObject;
        statusBarHeight = window.safeAreaInsets.top;
    }
    CGFloat navBarHeight = statusBarHeight + 44;
    NavBarView *navBarView = [[NavBarView alloc] initWithFrame:CGRectMake(0, 0, screenWidth, navBarHeight)];
    [navBarView setTitle:@"AMap IPC Link Demo"];
    [self.view addSubview:navBarView];
    
    EventActionView *eventActionView = [[EventActionView alloc] initWithOriginX:0 originY:navBarView.bounds.size.height width:screenWidth];
    eventActionView.delegate = self;
    [self.view addSubview:eventActionView];
    self.eventActionView = eventActionView;
    
    // 创建"接收数据"的容器UITextView(放在Label下方)
    NSInteger eventActionViewBottom = eventActionView.bounds.size.height + navBarView.bounds.size.height + 10;
    UITextView *receivedTextView = [[UITextView alloc] initWithFrame:CGRectMake(20, eventActionViewBottom, screenWidth-40, screenHeight- eventActionViewBottom-48)];
    receivedTextView.text = @"日志回显..."; // 初始文本
    receivedTextView.textColor = [UIColor blackColor];
    receivedTextView.font = [UIFont systemFontOfSize:14];
    receivedTextView.backgroundColor = [UIColor whiteColor];
    receivedTextView.textAlignment = NSTextAlignmentLeft;
    receivedTextView.editable = NO; // 设置为不可编辑
    receivedTextView.scrollEnabled = YES; // 允许滚动(内容过长时)
    receivedTextView.translatesAutoresizingMaskIntoConstraints = NO;
    receivedTextView.layer.borderColor = [UIColor lightGrayColor].CGColor;
    receivedTextView.layer.borderWidth = 0.5;
    [self.view addSubview:receivedTextView];
    self.receivedTextView = receivedTextView;
}
@end

七、注意事项

  1. API Key配置: 必须在应用启动时尽早配置API Key
  2. URL Scheme: 确保正确配置回调URL Scheme
  3. 认证流程: 首次使用需要完成认证流程
  4. 连接管理: 建议在适当的时机建立和断开连接
  5. 观察者管理: 记得在适当时机移除观察者,避免内存泄漏
  6. 线程安全: 回调可能在子线程,UI更新需要切换到主线程
  7. 错误处理: 做好网络异常和连接失败的处理,参考 IPC Link ErrorCode

八、常见问题

Q: 认证失败怎么办?

A: 检查API Key是否正确,URL Scheme是否配置正确,确保已安装高德地图APP

Q: 连接失败怎么办?

A: 可以开启自动服务器探测功能,或者检查网络连接状态

Q: 如何处理数据接收?

A: 需要额外实现数据接收的观察者模式,具体实现可参考AMapNaviClientManager

返回顶部 示例中心 常见问题 智能客服 公众号
二维码