AI
产品服务
解决方案
文档与支持
定价
更新时间: 2026/04/20 14:52
步骑行导航多实例
下载开发文档
步行导航功能实现
1. License功能授权

步骑行导航多实例功能为License授权高级服务,使用前需要联系PM或商务开通权限及配额

// License授权
// 创建BMKAuthorizeUserInfo前,通过BMKCommonInfo设置过公共互联设备ID信息
// options.authorizeOption会有默认值
// 授权方案1,全局配置deviceID
// [BMKCommonInfo setCommonShareDeviceID:@"123456789"];
BMKAuthorizeUserInfo *authorizeUserInfo = [[BMKAuthorizeUserInfo alloc] init];
/// 授权方案2,动态配置deviceID;AK(readonly)默认为SDK初始化鉴权时传入的,禁止动态修改
authorizeUserInfo.deviceID = @"123456789";
/// 授权请求,只请求和返回单个服务授权状态
/// serviceType 业务服务,BMKAuthorizeServiceTypeALL为所有服务,开发者根据业务需要设置对应的服务枚举值
/// userInfo 用户设备信息
/// needActive 是否需SDK端上激活,YES:端上主动激活操作并校验,消耗License配额 NO:端上仅拉取License信息做校验,不做激活操作
/// completion 授权完成回调,包含授权错误码和单个服务授权状态
[[BMKLicenseAuthorizeManager sharedManager] authorizeLicenseWithServiceType:BMKAuthorizeServiceTypeALL userInfo:authorizeUserInfo needActive:NO completion:^(BMKLicenseServiceErrorCode errorCode, BMKAuthorizeServiceResult * _Nullable result) {
    NSLog(@"授权请求状态码%ld", errorCode);
    if (BMK_LICENSE_SERVICE_NO_ERROR == errorCode) {
        NSLog(@"授权请求状态码为BMK_LICENSE_SERVICE_NO_ERROR时,授权文件正常返回,处理result中的authorizeServiceStatus授权状态列表,对应服务authorizeServiceType的authorizeStatus == 0 且 licenseVerification为YES时表明授权通过");
        for (BMKAuthorizeServiceStatus *status in result.authorizeServiceStatus) {
             /// 授权/校验进一步判断处理
            if (BMKAuthorizeServiceTypeNaviMulti == status.authorizeServiceType) {
                if (status.authorizeStatus == 0 && status.licenseVerification) {
                    NSLog(@"当前设备多实例功能获取License授权成功,可以正常创建和添加至父视图");
                } else {
                    NSLog(@"当前设备获取License授权失败,请联系PM或商务查看授权权限");
                }
            } else if (BMKAuthorizeServiceTypeNaviGuideInfo == status.authorizeServiceType){
                if (status.authorizeStatus == 0 && status.licenseVerification) {
                    NSLog(@"当前设备诱导信息回调功能获取License授权成功,相关配额已记录,如没有收到相关回调,请联系PM或商务开通【步骑行导航诱导信息高级权限】");
                } else {
                    NSLog(@"当前设备诱导信息回调获取License授权失败,请联系PM或商务查看授权权限,不影响诱导信息正常回调");
                }
            }
            /// 授权/校验错误分析
            for (BMKAuthorizeServiceError *error in result.authorizeServiceErrors) {
                if (BMKAuthorizeServiceTypeNaviMulti == error.authorizeServiceType) {
                    NSLog(@"多实例授权失败:%ld-%@", error.authorizeErrorCode, error.authorizeErrorMessage);
                } else if (BMKAuthorizeServiceTypeNaviGuideInfo == error.authorizeServiceType) {
                    NSLog(@"诱导信息授权失败:%ld-%@", error.authorizeErrorCode, error.authorizeErrorMessage);
                }
            }
        }
        
    } else {
        NSLog(@"授权请求状态码为非O时,请按错误码提示排查原因,必要时可以联系PM或商务查看授权权限及配额");
    }
}];
2. 初始化骑行导航引擎(以骑行导航为例)
BMKCycleNavigationManager*manager = [BMKCycleNavigationManager sharedManager];
manager.routeGuidanceDelegate= self;
manager.ttsPlayerDelegate= self;
manager.managerDelegate= self;
manager.locationAuthorizationDelegate = self;
// 启用后台位置指示器,进入后台时保留被授予的临时访问权限(精确位置)
[manager showsBackgroundLocationIndicator:YES];
BMKMultiNaviViewController*controller =[[BMKMultiNaviViewControlleralloc] init];
controller.navigationType=BMK_WALK_CYCLE_NAVIGATION_TYPE_NORMAL_CYCLE;
BOOL inited =[[BMKCycleNavigationManagersharedManager] initNaviEngine:controller options:options];
//发起算路
//引擎初始化成功之后,发起导航算路,其中BMKCycleNaviLaunchParam的参数naviType用于指定是普通骑行导航或是电动车骑行导航。
BMKCycleNaviLaunchParam *param = [[BMKCycleNaviLaunchParam alloc] init];
param.naviType = BMK_WALK_CYCLE_NAVIGATION_TYPE_NORMAL_CYCLE;
BMKCycleNaviRouteNodeInfo *startNode = [[BMKCycleNaviRouteNodeInfo alloc] init];
startNode.location = _startAnnotation.coordinate; // 设置起点
BMKCycleNaviRouteNodeInfo *endNode = [[BMKCycleNaviRouteNodeInfo alloc] init];
endNode.location = _endAnnotation.coordinate; // 设置终点
param.startNode = startNode;
param.endNode = endNode;
// 设置算路方式
param.startNode.type = BMKWalkNavigationRouteNodeLocation;
param.endNode.type = BMKWalkNavigationRouteNodeLocation;
[[BMKCycleNavigationManager sharedManager] routePlanWithParams:param];
3. 多实例导航
3.1多实例导航创建

注意:目前步骑行导航只支持创建绑定一个多实例,且需要在步骑行导航引擎初始化成功后、算路前创建绑定完成。

if (inited) {
    NSLog(@"SDK-初始化引擎成功");
    // 2.创建导航视图多实例
    BMKMultiNaviView *multiNaviView =[[BMKMultiNaviViewalloc] initWithFrame:CGRectMake(0,150,200,300)];
    // 3.根据导航视图多实例类型绑定导航数据源 注意:请在BMKWalkCycleAuthorizeDelegate授权代理回调中调用算路接口,否则多实例导航数据将绑定失败
    BOOL bindFlag =[multiNaviView bindNaviDataSourceWithNaviType:BMK_WALK_CYCLE_NAVIGATION_TYPE_NORMAL_CYCLE];
    if(bindFlag){
    NSLog(@"SDK-多实例导航数据绑定成功");
    }else{
    NSLog(@"SDK-多实例导航数据绑定失败");
    }
    /// 【重要】设置多实例回调代理
     multiNaviView.delegate = self;
/// 多实例展示在合适位置,demo是传给了BMKMultiNaviViewController同屏展示
    controller.multiNaviView = multiNaviView;
/// [self.view addSubview:multiNaviView]; 也可以按需求addSubview到任何父视图
}
3.2 多实例授权代理回调实现

通过addSubview将多实例View添加到任何父视图时触发多实例授权绑定状态回调,授权失败时会自动解绑导航数据,导航多实例功能将无法正常使用。

#pragma mark - BMKWalkCycleMultiNaviViewDelegate
- (void)multiNaviViewDidMoveToWindowOnBind {
    NSLog(@"多实例绑定成功");
}
- (void)multiNaviViewDidMoveToWindowUnBind {
    NSLog(@"多实例已解绑,请联系PM开通权限");
}
3.3 多实例生命周期
/// 恢复导航地图实例。
- (void)onResume;
/// 暂停导航地图实例。
- (void)onPause;
/// 销毁导航地图实例内部持有(并解除绑定多实例导航数据源)。
- (void)onDestroy;
3.4 多实例导航控制

通过以下接口可以实现多实例导航默认比例尺设置、导航地图旋转模式、导航地图俯仰视角模式、小车XY偏移量

/// 设置默认比例尺,默认:17,范围:4~22
@property (nonatomic, assign) float defaultNaviMapLevel;
/// 设置导航地图旋转模式,默认:BMKNaviMapRotateModeRoute 路线朝上
@property (nonatomic, assign) BMKNaviMapRotateMode naviMapRotateMode;
/// 设置导航地图俯仰视角模式,默认:BMKNaviMapOverlookingMode2D 2d视角
@property (nonatomic, assign) BMKNaviMapOverlookingMode naviMapOverlookingMode;
/// 小车XY偏移量,默认无效值(MAXFLOAT, MAXFLOAT),初始化引擎后设置,since 6.6.4
@property (nonatomic, assign) CGPoint carPositionOffset;
3.5 多实例导航元素控制

通过以下接口可以实现多实例导航元素显示/隐藏动态控制和自定义导航元素样式、图片动态设置

#pragma mark - 导航元素控制
/// 导航元素显示控制,包括:引导红线,红绿灯标签,红绿灯倒计时气泡,路名气泡,交通设施标签,交通设施气泡,里程碑标签等
/// - Parameters:
///   - show: YES:显示;NO:隐藏
///   - elements: 显示/隐藏的元素,可支持元素类型参考:BMKNaviDrawElementType
///   如:@[@(BMKNaviDrawElementTypeRedLine), @(BMKNaviDrawElementTypeTrafficLight), @(BMKNaviDrawElementTypeTrafficLightPop)]
- (void)setNaviDrawElementsShow:(BOOL)show elements:(NSArray *)elements;
/// 更新导航元素自定义样式
/// 包括罗盘、定位点(小车)、终点图片及图片尺寸缩放;路线未走过和已走过纹理、线宽;路名字体大小、颜色;路名气泡字体大小、颜色及背景色
/// - Parameters:
///   - dispalyOption: 自定义多实例导航实例元素自定义样式(这里自定义主实例的元素样式不会生效)
- (void)updateNaviDrawItemDisplayOption:(BMKWalkCycleNaviDrawItemDisplayOption *)dispalyOption;
3.6 多实例导航隐藏logo
/// 控制地图logo显示隐藏,默认显示,since 6.6.4
@property (nonatomic, assign) BOOL showLogo;
4.算路

步骑行导航支持两种算路方案

4.1 引擎算路

直接引擎算路,引擎算路成功直接进入导航

4.1.1 设置算路起终点数据
BMKCycleNaviLaunchParam *param = [[BMKCycleNaviLaunchParam alloc] init];
/// 起点
BMKCycleNaviRouteNodeInfo *startNode = [BMKCycleNaviRouteNodeInfo new];
startNode.location = CLLocationCoordinate2DMake(40.057038, 116.307899);
startNode.type = BMKWalkNavigationRouteNodeLocation;
param.startNode = startNode;
/// 终点
BMKCycleNaviRouteNodeInfo *endNode = [BMKCycleNaviRouteNodeInfo new];
endNode.location = CLLocationCoordinate2DMake(40.056534, 116.307378);
endNode.type = BMKWalkNavigationRouteNodeLocation;
param.endNode = endNode;
/// 途径点
// BMKCycleNaviRouteNodeInfo *wayPointNode = [BMKCycleNaviRouteNodeInfo new];
// wayPointNode.location = CLLocationCoordinate2DMake(39.972804, 116.328205);
// wayPointNode.poiId = @"a523992863e9afa5fadc8528";
// param.viaNodes = @[wayPointNode];
4.1.2 设置导航类型,设置引擎算路回调并开始算路
/// 设置为电动车骑行
param.naviType = BMK_WALK_CYCLE_NAVIGATION_TYPE_ELECTRIC_CYCLE;
/// 设置引擎算路代理回调,BMKWalkNaviCalcRouteDelegate
[BMKCycleNavigationManager sharedManager].routePlanDelegate = self;
/// 开始算路
[[BMKCycleNavigationManager sharedManager] routePlanWithParams:param];
4.1.3 开始导航
#pragma mark - <BMKWalkNaviCalcRouteDelegate>
/// 引擎算路结果回调
- (void)onNaviCalcRouteResult:(BMKWalkCycleRoutePlanErrorCode)errorCode naviType:(BMKWalkCycleNavigationType)naviType {
if (errorCode == BMK_WALK_CYCLE_ROUTEPLAN_RESULT_SUCCESS) {
if (naviType == BMK_WALK_CYCLE_NAVIGATION_TYPE_WALK) {
NSLog(@"startWalkNaviWithParentController");
/// 开始步行导航
[[BMKWalkNavigationManager sharedManager] startWalkNaviWithParentController:self isPush:YES];
} else {
NSLog(@"startCycleNaviWithParentController");
/// 开始骑行导航
[[BMKCycleNavigationManager sharedManager] startCycleNaviWithParentController:self isPush:YES];
}
} else {
NSLog(@"SDK-引擎算路失败 %zd", errorCode);
}
}
4.2 多路线规划

先规划多条路线,选择路线,传入路线索引进行引擎算路,算路成功后进入导航

4.2.1 配置支持多路线规划
/// 设置是否支持多路线规划选择,可在routePlanDelegate回调中处理多路线并进行绘制选择。默认NO
[BMKCycleNavigationManager sharedManager].enableMultiRoute = YES;
4.2.2 设置多路线规划结果代理回调和引擎算路结果回调
/// 设置多路线规划代理回调,BMKWalkCycleRoutePlanDelegate
[BMKCycleNavigationManager sharedManager].routePlanDelegate = self;
/// 设置引擎算路代理回调,BMKWalkNaviCalcRouteDelegate
[BMKCycleNavigationManager sharedManager].routePlanDelegate = self;
4.2.3 设置起终点、导航类型并开始算路
BMKCycleNaviRouteNodeInfo *startNode = [[BMKCycleNaviRouteNodeInfo alloc] init];
startNode.location = self.startAnnotation.coordinate;
startNode.keyword = self.startAnnotation.title;
startNode.type = BMKWalkNavigationRouteNodeKeyword;
BMKCycleNaviRouteNodeInfo *endNode = [[BMKCycleNaviRouteNodeInfo alloc] init];
endNode.location = self.endAnnotation.coordinate;
endNode.keyword = self.endAddressInput.text;
endNode.type = BMKWalkNavigationRouteNodeKeyword;
BMKCycleNaviLaunchParam *param = [[BMKCycleNaviLaunchParam alloc] init];
param.startNode = startNode;
param.endNode = endNode;
param.naviType = BMK_WALK_CYCLE_NAVIGATION_TYPE_ELECTRIC_CYCLE;
[[BMKCycleNavigationManager sharedManager] routePlanWithParams:param];
/// 设置为电动车骑行
param.naviType = BMK_WALK_CYCLE_NAVIGATION_TYPE_ELECTRIC_CYCLE;
/// 开始算路
[[BMKCycleNavigationManager sharedManager] routePlanWithParams:param];
4.2.4 回调方法实现

在回调方法中处理算路结果和绘制路线

#pragma mark - BMKWalkCycleRoutePlanDelegate
/**
开始算路
*/
- (void)onRoutePlanStart:(BMKWalkCycleNavigationType)naviType {
NSLog(@"SDK-开始算路");
}
- (void)onRoutePlanResult:(BMKWalkCycleRoutePlanErrorCode)errorCode naviType:(BMKWalkCycleNavigationType)naviType{
if (errorCode == BMK_WALK_CYCLE_ROUTEPLAN_RESULT_SUCCESS) {
NSLog(@"SDK-算路成功");
[self.mapView removeOverlays:self.mapView.overlays];
if (naviType == BMK_WALK_CYCLE_NAVIGATION_TYPE_WALK) {
[self.mapView removeOverlays:self.mapView.overlays];
_routePolylines = [[BMKWalkNavigationManager sharedManager] displayRoutePlanResult:_mapView];
if (_routePolylines.count == 1) {
[[BMKWalkNavigationManager sharedManager] naviCalcRoute:0];
}
} else {
_routePolylines = [[BMKCycleNavigationManager sharedManager] displayRoutePlanResult:_mapView];
if (_routePolylines.count == 1) {
[[BMKCycleNavigationManager sharedManager] naviCalcRoute:0];
}
}
} else {
NSLog(@"SDK-算路失败");
}
}
4.2.5 选择导航路线

示例中使用SDK的能力绘制多条路线,点击对应路线进行导航路线选择,通过naviCalcRoute方法传入对应路线的索引值

- (void)mapView:(BMKMapView *)mapView onClickedBMKOverlayView:(BMKOverlayView *)overlayView {
if ([overlayView isKindOfClass:[BMKPolylineView class]]) {
BMKOverlayView *polylineView = (BMKOverlayView *)overlayView;
NSInteger idx = [_routePolylines indexOfObject:polylineView.overlay];
if (idx >= 0 && idx < _routePolylines.count) {
if (self.navigationType == BMK_WALK_CYCLE_NAVIGATION_TYPE_WALK) {
[[BMKWalkNavigationManager sharedManager] naviCalcRoute:idx];
} else {
[[BMKCycleNavigationManager sharedManager] naviCalcRoute:idx];
}
for (int i = 0; i < _routePolylines.count; i++) {
BMKPolylineView *polylineView = _routePolylineViews[i];
if (idx == i) {
polylineView.strokeColor = [[UIColor alloc] initWithRed:0 green:0 blue:1 alpha:0.7];
} else {
polylineView.strokeColor = [[UIColor alloc] initWithRed:0 green:0 blue:1 alpha:0.4];
}
}
}
}
}
4.2.6 引擎算路结果回调

同样的,选路后需要监听引擎算路结果回调处理相关逻辑,示例中在该回调中调用startWalkNaviWithParentController进入并开始导航。

#pragma mark - <BMKWalkNaviCalcRouteDelegate>
/// 引擎算路结果回调
- (void)onNaviCalcRouteResult:(BMKWalkCycleRoutePlanErrorCode)errorCode naviType:(BMKWalkCycleNavigationType)naviType {
if (errorCode == BMK_WALK_CYCLE_ROUTEPLAN_RESULT_SUCCESS) {
if (naviType == BMK_WALK_CYCLE_NAVIGATION_TYPE_WALK) {
NSLog(@"startWalkNaviWithParentController");
[[BMKWalkNavigationManager sharedManager] startWalkNaviWithParentController:self isPush:YES];
} else {
NSLog(@"startCycleNaviWithParentController");
[[BMKCycleNavigationManager sharedManager] startCycleNaviWithParentController:self isPush:YES];
}
} else {
NSLog(@"SDK-引擎算路失败 %zd", errorCode);
}
}
5.主导航及多实例生命周期

以BMKMultiNaviViewController生命周期为参考

- (void)viewWillAppear:(BOOL)animated {
[superviewWillAppear:animated];
// 0.添加多实例View
[self.view addSubview:self.multiNaviView];
if(self.navigationType==BMK_WALK_CYCLE_NAVIGATION_TYPE_WALK){
// 1.步行导航恢复
[[BMKWalkNavigationManager sharedManager] resume];
}else{
//1. 骑行导航恢复
[[BMKCycleNavigationManager sharedManager] resume];
}
// 2.恢复多实例导航View
[self.multiNaviView onResume];
}
- (void)viewWillDisappear:(BOOL)animated {
[superviewWillDisappear:animated];
if(self.navigationType == BMK_WALK_CYCLE_NAVIGATION_TYPE_WALK){
// 3.步行导航暂停
[[BMKWalkNavigationManager sharedManager] pause];
}else{
// 3.骑行导航暂停
[[BMKCycleNavigationManager sharedManager] pause];
}
// 4.暂停多实例导航View
[self.multiNaviView onPause];
}
- (void)viewDidDisappear:(BOOL)animated {
// 5.移除多实例导航view
[self.multiNaviView removeFromSuperview];
// 6.销毁多实例导航view
[self.multiNaviView onDestroy];
if (self.navigationType == BMK_WALK_CYCLE_NAVIGATION_TYPE_WALK){
// 7.停止步行导航
[[BMKWalkNavigationManager sharedManager] stop];
// 8.销毁步行导航manager
[BMKWalkNavigationManager destroy];
} else {
// 7.停止骑行导航
[[BMKCycleNavigationManager sharedManager] stop];
// 8.销毁骑行导航manager
[BMKCycleNavigationManager destroy];
}
}
6.截屏
6.1多实例截屏
// 多实例截屏
[[self.multiNaviView getNaviMapView] takeSnapshot];
// 多实例截屏,裁剪
[[self.multiNaviView getNaviMapView] takeSnapshot:CGRectMake(10, 10, 100, 100)];
7.其他
7.1 眼镜场景隐藏地图logo
[self.multiNaviView setShowLogo:NO];

上一篇

导航路线及诱导信息

下一篇

步骑行导航后台投屏
本篇文章对您是否有帮助?