概述 最后更新时间: 2021年11月04日
重要:由于个人信息保护法的实施,从导航8.1.0版本起对旧版本SDK不兼容,请务必确保调用SDK任何接口前先调用更新隐私合规updatePrivacyShow、updatePrivacyAgree两个接口,否则可能导致功能不可用等异常情况。具体可参考开发指南-隐私合规说明传入相关参数。
iOS导航SDK是一款针对在线导航的产品,产品功能涵盖了路径规划、专业导航、UI界面定制、导航组件、货车导航等。并且,导航路径规划与实时交通信息相结合,力求为用户提供更加合理、准确、人性化的导航服务。应用场景包括但不限于O2O、网约车出行、货运物流快递等。
在您接入 SDK 的前中后整个过程中,我们都会提供全方位的支持,包括官网文档、官方Demo、商务合作、工单、大客户钉钉群、现场支持等。
面向的读者
iOS导航SDK是提供给具有一定iOS编程经验和了解面向对象概念的读者使用的。
- 模拟导航
- (void)viewDidLoad { [super viewDidLoad]; [self initDriveView]; [self initDriveManager]; [self calculateRoute]; } - (void)initDriveManager { //请在 dealloc 函数中或者页面pop时,执行 [AMapNaviDriveManager destroyInstance] 来销毁单例 [[AMapNaviDriveManager sharedInstance] setDelegate:self]; //将driveView添加为导航数据的Representative,使其可以接收到导航诱导数据 [[AMapNaviDriveManager sharedInstance] addDataRepresentative:self.driveView]; } - (void)initDriveView { if (self.driveView == nil) { self.driveView = [[AMapNaviDriveView alloc] initWithFrame:self.view.bounds]; self.driveView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; [self.driveView setDelegate:self]; [self.driveView setShowGreyAfterPass:YES]; [self.driveView setAutoZoomMapLevel:YES]; [self.driveView setMapViewModeType:AMapNaviViewMapModeTypeNight]; [self.driveView setTrackingMode:AMapNaviViewTrackingModeCarNorth]; [self.view addSubview:self.driveView]; } } - (void)calculateRoute { //进行路径规划 [[AMapNaviDriveManager sharedInstance] calculateDriveRouteWithStartPoints:@[self.startPoint] endPoints:@[self.endPoint] wayPoints:nil drivingStrategy:AMapNaviDrivingStrategySingleDefault]; } #pragma mark - AMapNaviDriveManager Delegate - (void)driveManagerOnCalculateRouteSuccess:(AMapNaviDriveManager *)driveManager { NSLog(@"onCalculateRouteSuccess"); //算路成功后进行模拟导航 [[AMapNaviDriveManager sharedInstance] startEmulatorNavi]; }
- 导航组件
@interface CompositeViewController () <AMapNaviCompositeManagerDelegate> @property (nonatomic, strong) AMapNaviCompositeManager *compositeManager; @end // init - (AMapNaviCompositeManager *)compositeManager { if (!_compositeManager) { _compositeManager = [[AMapNaviCompositeManager alloc] init]; // 初始化 _compositeManager.delegate = self; // 如果需要使用AMapNaviCompositeManagerDelegate的相关回调(如自定义语音、获取实时位置等),需要设置delegate } return _compositeManager; } - (void)routePlanAction { [self.compositeManager presentRoutePlanViewControllerWithOptions:nil]; // 通过present的方式显示路线规划页面 }
- 货车导航组件
@interface CompositeTrunkViewController () <AMapNaviCompositeManagerDelegate> @property (nonatomic, strong) AMapNaviCompositeManager *compositeManager; @end // init - (AMapNaviCompositeManager *)compositeManager { if (!_compositeManager) { _compositeManager = [[AMapNaviCompositeManager alloc] init]; // 初始化 _compositeManager.delegate = self; // 如果需要使用AMapNaviCompositeManagerDelegate的相关回调(如自定义语音、获取实时位置等),需要设置delegate } return _compositeManager; } - (void)trunkDemo { AMapNaviCompositeUserConfig *config = [[AMapNaviCompositeUserConfig alloc] init]; AMapNaviVehicleInfo *info = [[AMapNaviVehicleInfo alloc] init]; info.vehicleId = @"京N66Y66"; info.type = 1; // 设置车辆类型为货车 info.size = 4; info.height = 3.9; info.length = 15; info.weight = 45; info.load = 50; info.width = 3; info.axisNums = 6; [config setVehicleInfo:info]; [config setRoutePlanPOIType:AMapNaviRoutePlanPOITypeStart location:[AMapNaviPoint locationWithLatitude:39.902896 longitude:116.42792] name:@"北京站" POIId:nil]; [config setRoutePlanPOIType:AMapNaviRoutePlanPOITypeWay location:[AMapNaviPoint locationWithLatitude:39.975642 longitude:116.306332] name:@"苏州街(地铁站)" POIId:nil]; [config setRoutePlanPOIType:AMapNaviRoutePlanPOITypeEnd location:[AMapNaviPoint locationWithLatitude:39.894914 longitude:116.322062] name:@"北京西站" POIId:nil]; [self.compositeManager presentRoutePlanViewControllerWithOptions:config]; }
- AMapNaviDriveView完全自定义UI和图面
@interface CustomUIViewController () <AMapNaviDriveManagerDelegate, AMapNaviDriveDataRepresentable, AMapNaviDriveViewDelegate> @property (nonatomic, strong) AMapNaviPoint *startPoint; @property (nonatomic, strong) AMapNaviPoint *endPoint; @property (nonatomic, strong) AMapNaviDriveView *driveView; //xib views @property (nonatomic, weak) IBOutlet UIView *topInfoBgView; @property (nonatomic, weak) IBOutlet UIImageView *topTurnImageView; @property (nonatomic, weak) IBOutlet UILabel *topRemainLabel; @property (nonatomic, weak) IBOutlet UILabel *topRoadLabel; @property (nonatomic, weak) IBOutlet UIImageView *crossImageView; @property (nonatomic, weak) IBOutlet UIView *routeRemianInfoView; @property (nonatomic, weak) IBOutlet UILabel *routeRemainInfoLabel; @property (nonatomic, weak) IBOutlet UIButton *rightBrowserBtn; @property (nonatomic, weak) IBOutlet UIView *startEndPointInfoView; @property (nonatomic, weak) IBOutlet AMapNaviTrafficBarView *trafficBarView; @property (nonatomic, weak) IBOutlet UIButton *rightTrafficBtn; @property (nonatomic, weak) IBOutlet NSLayoutConstraint *topInfoViewTopSpace; @property (nonatomic, weak) IBOutlet NSLayoutConstraint *bottomInfoLabelBottomSpace; @property (nonatomic, weak) IBOutlet NSLayoutConstraint *topInfoViewLeftSpace; @property (nonatomic, weak) IBOutlet NSLayoutConstraint *crossImageViewHeight; @end @implementation CustomUIViewController #pragma mark - LifeCycle - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; //初始化xib界面上的元素 [self updateViewsWhenInit]; //为了方便展示,选择了固定的起终点 self.startPoint = [AMapNaviPoint locationWithLatitude:39.993135 longitude:116.474175]; self.endPoint = [AMapNaviPoint locationWithLatitude:39.908791 longitude:116.321257]; //driveView self.driveView = [[AMapNaviDriveView alloc] initWithFrame:self.view.bounds]; self.driveView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.driveView.delegate = self; self.driveView.showUIElements = NO; self.driveView.showGreyAfterPass = YES; self.driveView.autoZoomMapLevel = YES; self.driveView.mapViewModeType = AMapNaviViewMapModeTypeNight; self.driveView.autoSwitchShowModeToCarPositionLocked = YES; self.driveView.trackingMode = AMapNaviViewTrackingModeCarNorth; self.driveView.logoCenter = CGPointMake(self.driveView.logoCenter.x + 2, self.driveView.logoCenter.y + 60); [self.driveView setCarImage:[UIImage imageNamed:@"customCar"]]; [self.view addSubview:self.driveView]; [self.view sendSubviewToBack:self.driveView]; [self updateMapViewScreenAnchor]; // 设置锚点 //driveManager 请在 dealloc 函数中执行 [AMapNaviDriveManager destroyInstance] 来销毁单例 [[AMapNaviDriveManager sharedInstance] setDelegate:self]; [[AMapNaviDriveManager sharedInstance] setIsUseInternalTTS:YES]; [[AMapNaviDriveManager sharedInstance] setAllowsBackgroundLocationUpdates:YES]; [[AMapNaviDriveManager sharedInstance] setPausesLocationUpdatesAutomatically:NO]; //将self 、driveView、trafficBarView 添加为导航数据的Representative,使其可以接收到导航诱导数据 [[AMapNaviDriveManager sharedInstance] addDataRepresentative:self.driveView]; [[AMapNaviDriveManager sharedInstance] addDataRepresentative:self.trafficBarView]; [[AMapNaviDriveManager sharedInstance] addDataRepresentative:self]; //算路 [[AMapNaviDriveManager sharedInstance] calculateDriveRouteWithStartPoints:@[self.startPoint] endPoints:@[self.endPoint] wayPoints:nil drivingStrategy:AMapNaviDrivingStrategySingleDefault]; } - (void)dealloc { [[AMapNaviDriveManager sharedInstance] stopNavi]; [[AMapNaviDriveManager sharedInstance] removeDataRepresentative:self.driveView]; [[AMapNaviDriveManager sharedInstance] removeDataRepresentative:self.trafficBarView]; [[AMapNaviDriveManager sharedInstance] removeDataRepresentative:self]; [[AMapNaviDriveManager sharedInstance] setDelegate:nil]; BOOL success = [AMapNaviDriveManager destroyInstance]; NSLog(@"单例是否销毁成功 : %d",success); } #pragma mark - Setup - (void)updateViewsWhenInit { self.routeRemianInfoView.layer.cornerRadius = 5; self.startEndPointInfoView.layer.cornerRadius = 5; self.trafficBarView.borderWidth = 2.5; self.crossImageViewHeight.constant = MIN([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) * 16.0 / 25.0; //路口放大图宽高为25:16 if ([self isiPhoneX]) { self.topInfoViewTopSpace.constant = 30; self.bottomInfoLabelBottomSpace.constant = 12; self.topInfoViewLeftSpace.constant = 24; } //hide self.topInfoBgView.hidden = self.routeRemianInfoView.hidden = YES; self.crossImageView.hidden = YES; } //更新地图锚点 - (void)updateMapViewScreenAnchor { [self.view layoutIfNeeded]; CGFloat x = 0.5; CGFloat y = 0.75; if(self.driveView.isLandscape) { //横屏模式 CGFloat xStart = self.trafficBarView.frame.origin.x + self.trafficBarView.frame.size.width; CGFloat xEnd = self.driveView.bounds.size.width - 80; if (self.crossImageView.image) { xStart = self.trafficBarView.frame.origin.x - 10; xEnd = self.driveView.bounds.size.width; y = 0.7; } else { y = 0.55; } CGFloat xAreaMiddleInAll = (xEnd - xStart) / 2 + xStart; x = xAreaMiddleInAll / self.driveView.bounds.size.width; } if (x <= 0 || x >= 1 ) { x = 0.5; } if (self.driveView.screenAnchor.x != x || self.driveView.screenAnchor.y != y) { self.driveView.screenAnchor = CGPointMake(x, y); } } //处理路口放大图 - (void)handleWhenCrossImageShowAndHide:(UIImage *)crossImage { if (crossImage && self.driveView.showMode == AMapNaviDriveViewShowModeCarPositionLocked) { self.crossImageView.hidden = NO; self.crossImageView.image = crossImage; self.rightBrowserBtn.hidden = YES; self.rightTrafficBtn.hidden = YES; self.routeRemianInfoView.hidden = YES; self.trafficBarView.hidden = YES; self.startEndPointInfoView.hidden = YES; } else { self.crossImageView.hidden = YES; self.crossImageView.image = nil; self.rightBrowserBtn.hidden = NO; self.rightTrafficBtn.hidden = NO; self.routeRemianInfoView.hidden = NO; self.trafficBarView.hidden = NO; self.startEndPointInfoView.hidden = NO; } [self updateMapViewScreenAnchor]; } #pragma mark - AMapNaviDriveManager Delegate - (void)driveManagerOnCalculateRouteSuccess:(AMapNaviDriveManager *)driveManager { NSLog(@"onCalculateRouteSuccess"); //算路成功后开始导航 [[AMapNaviDriveManager sharedInstance] startEmulatorNavi]; } #pragma mark - AMapNaviDriveDataRepresentable //诱导信息 - (void)driveManager:(AMapNaviDriveManager *)driveManager updateNaviInfo:(AMapNaviInfo *)naviInfo { if (naviInfo) { if (self.topInfoBgView.hidden) { self.topInfoBgView.hidden = self.routeRemianInfoView.hidden = NO; } self.topRemainLabel.text = [NSString stringWithFormat:@"%@后",[self normalizedRemainDistance:naviInfo.segmentRemainDistance]]; self.topRoadLabel.text = naviInfo.nextRoadName; NSString *remainTime = [self normalizedRemainTime:naviInfo.routeRemainTime]; NSString *remainDis = [self normalizedRemainDistance:naviInfo.routeRemainDistance]; self.routeRemainInfoLabel.text = [NSString stringWithFormat:@"剩余 %@ %@",remainDis,remainTime]; } } //转向图标 - (void)driveManager:(AMapNaviDriveManager *)driveManager updateTurnIconImage:(UIImage *)turnIconImage turnIconType:(AMapNaviIconType)turnIconType { if (turnIconImage) { self.topTurnImageView.image = turnIconImage; } } //显示路口放大图 - (void)driveManager:(AMapNaviDriveManager *)driveManager showCrossImage:(UIImage *)crossImage { [self handleWhenCrossImageShowAndHide:crossImage]; } //隐藏路口放大图 - (void)driveManagerHideCrossImage:(AMapNaviDriveManager *)driveManager { [self handleWhenCrossImageShowAndHide:nil]; } #pragma mark - AMapNaviDriveViewDelegate - (void)driveView:(AMapNaviDriveView *)driveView didChangeOrientation:(BOOL)isLandscape { NSLog(@"didChangeOrientation:%ld", (long)isLandscape); [self updateMapViewScreenAnchor]; if (self.driveView.showMode == AMapNaviDriveViewShowModeOverview) { //如果是全览状态,重新适应一下全览路线,让其均可见 [self.driveView updateRoutePolylineInTheVisualRangeWhenTheShowModeIsOverview]; } } - (void)driveView:(AMapNaviDriveView *)driveView didChangeShowMode:(AMapNaviDriveViewShowMode)showMode { if (showMode == AMapNaviDriveViewShowModeOverview) { self.rightBrowserBtn.selected = YES; } else { self.rightBrowserBtn.selected = NO; } if (showMode != AMapNaviDriveViewShowModeCarPositionLocked) { //非锁车,隐藏路口放大图 [self handleWhenCrossImageShowAndHide:nil]; } } //返回边界Padding,来规定可见区域 - (UIEdgeInsets)driveViewEdgePadding:(AMapNaviDriveView *)driveView { //top left bottom right CGFloat offset = 20; CGFloat top = self.routeRemianInfoView.frame.origin.y + self.routeRemianInfoView.bounds.size.height + offset; CGFloat left = 40; CGFloat bottom = self.view.bounds.size.height - self.startEndPointInfoView.frame.origin.y + offset; CGFloat right = 80; if (self.driveView.isLandscape) { top = offset; left = self.trafficBarView.frame.origin.x + self.trafficBarView.frame.size.width + offset; bottom = self.view.bounds.size.height - self.startEndPointInfoView.frame.origin.y + offset; right = 80; } UIEdgeInsets insets = UIEdgeInsetsMake(top, left, bottom, right); return insets; } #pragma mark - Button Click - (IBAction)closeBtnClick:(id)sender { [self.navigationController popViewControllerAnimated:YES]; } - (IBAction)trafficBtnClick:(id)sender { UIButton *btn = (UIButton *)sender; self.driveView.mapShowTraffic = !self.driveView.mapShowTraffic; btn.selected = !self.driveView.mapShowTraffic; } - (IBAction)browserBtn:(id)sender { if (self.driveView.showMode == AMapNaviDriveViewShowModeOverview) { self.driveView.showMode = AMapNaviDriveViewShowModeCarPositionLocked; } else { self.driveView.showMode = AMapNaviDriveViewShowModeOverview; } } #pragma mark - Utility - (BOOL)isiPhoneX { return [UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO; } - (NSString *)normalizedRemainDistance:(NSInteger)remainDistance { if (remainDistance < 0) { return nil; } if (remainDistance >= 1000) { CGFloat kiloMeter = remainDistance / 1000.0; return [NSString stringWithFormat:@"%.1f公里", kiloMeter]; } else { return [NSString stringWithFormat:@"%ld米", (long)remainDistance]; } } - (NSString *)normalizedRemainTime:(NSInteger)remainTime { if (remainTime < 0) { return nil; } if (remainTime < 60) { return [NSString stringWithFormat:@"< 1分钟"]; } else if (remainTime >= 60 && remainTime < 60*60) { return [NSString stringWithFormat:@"%ld分钟", (long)remainTime/60]; } else { NSInteger hours = remainTime / 60 / 60; NSInteger minute = remainTime / 60 % 60; if (minute == 0) { return [NSString stringWithFormat:@"%ld小时", (long)hours]; } else { return [NSString stringWithFormat:@"%ld小时%ld分钟", (long)hours, (long)minute]; } } }
兼容性
v6.4.0及以上版本支持iOS 8.0及以上系统
开发者建议
对于高德开放平台提供的地图API/SDK,若您以非商业目的使用,则均可免费使用 。若您以商业目的使用,则您需事先从高德获取商用授权。您需要先申请Key,才能使用该服务。关于具体使用规则,请参阅《高德地图开放平台服务协议》获得详细信息。