最近做到这个需求要求应用内用户导航时根据手机手机内安装的地图来选择什么地图进行跳转到第三方地图导航功能。这个功能实现并不复杂,网上也有很多相关的文章,这里我自己做的总结,还有自己做这个功能是遇到的一些问题。
1、第一步要做的事,给常用的地图在APP infoplist文件里添加白名单
这这个字段下添加以下白名单
这些是我添加的高德,百度,谷歌,腾讯地图,主流的导航APP,如果你有其他的APP需要也可以在这里添加。
2、开始代码
我们的需求是用户手机安装了这些第三方导航,用户选择导航的时候才显示对应的名称。没有安装就不显示。这里需要用:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];来判断用户是否安装了某个导航APP。
- (void)checkMapsUseful
{
//苹果地图
NSMutableDictionary *iosMapDic = [NSMutableDictionary dictionary];
iosMapDic[@"title"] = @"苹果地图";
[self.mapsArray addObject:iosMapDic];
//百度地图
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"baidumap://"]]) {
NSMutableDictionary *baiduMapDic = [NSMutableDictionary dictionary];
baiduMapDic[@"title"] = @"百度地图";
NSString *urlString = [[NSString stringWithFormat:@"baidumap://map/direction?origin={{我的位置}}&destination=latlng:%f,%f|name=目的地&mode=driving&coord_type=gcj02",self.gcj02Location.latitude,self.gcj02Location.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
baiduMapDic[@"url"] = urlString;
[self.mapsArray addObject:baiduMapDic];
}
//高德地图
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"iosamap://"]]) {
NSMutableDictionary *gaodeMapDic = [NSMutableDictionary dictionary];
gaodeMapDic[@"title"] = @"高德地图";
NSString *urlString = [[NSString stringWithFormat:@"iosamap://navi?sourceApplication=%@&backScheme=%@&lat=%f&lon=%f&dev=0&style=2",@"导航功能",@"nav123456",self.gcj02Location.latitude,self.gcj02Location.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
gaodeMapDic[@"url"] = urlString;
[self.mapsArray addObject:gaodeMapDic];
}
//腾讯地图
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"qqmap://"]]) {
NSMutableDictionary *qqMapDic = [NSMutableDictionary dictionary];
qqMapDic[@"title"] = @"腾讯地图";
NSString *urlString = [[NSString stringWithFormat:@"qqmap://map/routeplan?from=我的位置&type=drive&tocoord=%f,%f&to=终点&coord_type=1&policy=0",self.gcj02Location.latitude, self.gcj02Location.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
qqMapDic[@"url"] = urlString;
[self.mapsArray addObject:qqMapDic];
}
//谷歌地图
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"comgooglemaps://"]]) {
NSMutableDictionary *googleMapDic = [NSMutableDictionary dictionary];
googleMapDic[@"title"] = @"谷歌地图";
NSString *urlString = [[NSString stringWithFormat:@"comgooglemaps://?x-source=%@&x-success=%@&saddr=&daddr=%f,%f&directionsmode=driving",@"导航",@"nav123456",self.gcj02Location.latitude, self.gcj02Location.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
googleMapDic[@"url"] = urlString;
[self.mapsArray addObject:googleMapDic];
}
}
这个方法是将你需要的地图软件先预存在一个字典里。然后根据这个字段来创建弹出框,弹出我为了方便就用的系统的actionSheet
- (void)startThirdAppNavigationWithStartPoint:(CLLocationCoordinate2D)startPoint endPoint:(CLLocationCoordinate2D)endPoint inView:(UIViewController*)vc
{
[self.mapsArray removeAllObjects];
self.gcj02Location = [JZLocationConverter bd09ToGcj02:endPoint];
self.originLocaion = endPoint;
[self checkMapsUseful];
UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"导航" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
for (int i = 0; i < self.mapsArray.count; i++) {
if (i == 0) {
[alertVC addAction:[UIAlertAction actionWithTitle:self.mapsArray[i][@"title"] style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self appleMapNavi];
}]];
}else{
[alertVC addAction:[UIAlertAction actionWithTitle:self.mapsArray[i][@"title"] style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self otherMap:i];
}]];
}
}
[alertVC addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
[vc presentViewController:alertVC animated:YES completion:nil];
}
这里就基本快完成了,如果是第三方导航就调用下面这个方法:
/// 第三方地图
- (void)otherMap:(NSInteger)index
{
NSDictionary *dic = self.mapsArray[index];
NSString *urlString = dic[@"url"];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}
如果用户没有安装任何第三方地图软件,没关系,我们iOS还有系统自带的苹果地图,头文件导入#import <MapKit/MapKit.h>
- (void)appleMapNavi
{
CLLocationCoordinate2D gps = [JZLocationConverter bd09ToWgs84:self.originLocaion];
MKMapItem *currentLoc = [MKMapItem mapItemForCurrentLocation];
MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:gps addressDictionary:nil]];
NSArray *items = @[currentLoc,toLocation];
NSDictionary *dic = @{
MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving,
MKLaunchOptionsMapTypeKey : @(MKMapTypeStandard),
MKLaunchOptionsShowsTrafficKey : @(YES)
};
[MKMapItem openMapsWithItems:items launchOptions:dic];
}
然后就基本大功告成了,只要在用户需要的地方调用我们写好的方法就可以了:
[[NavigationManager sharedInstance] startThirdAppNavigationWithStartPoint:self.userLocation.location.coordinate endPoint:self.housePointAnnotation.coordinate inView:self];
这里我当初是传了起点的经纬度坐标的,后来发现起点坐标不需要,偷懒就没改了。
tips:需要注意的地方
因为我们后天用的是百度地图的坐标,所以在导航的时候如果你直接传入后台的坐标可能跳转过去的时候会有误差。所以需要对经纬度进行转换。
这里我用的是JZLocationConverter,这个也很好用,Mark一下!
self.gcj02Location = [JZLocationConverter bd09ToGcj02:endPoint];
self.originLocaion = endPoint;
这里用了2个坐标是为了对应系统苹果地图的坐标即CLLocationCoordinate2D gps = [JZLocationConverter bd09ToWgs84:self.originLocaion];,需用的是世界地理坐标系。
其他第三方的地图坐标用的是self.gcj02Location,即火星坐标系。
这样一般就没有问题了。如果你传入的坐标跟实际位置仍然有偏差,可以试试不同的转换方式。我也是试了好几次的,或者跟后台的同学看看,可能他们已经做过位置转换了。