项目里面要求点击发送的位置, 需要导航, 导航两种实现方式 (集成第三方SDK、URL跳转第三方应用) 项目要求实现直接跳转 所以接下来做的是实现URL跳转第三方地图来导航了
项目实现如下的效果:
思路:传入的目的地经纬度,再调用第三方的导航
第三方导航是指以URL跳转的方式(在iOS中就是以URL Scheme的方式),直接跳到对应的地图APP中,直接利用对方的功能来导航。这样的优点,一是接入方便,二是不增加自己APP的开销。缺点就是如果用户没有装这个地图,应用就没办法使用这个地图的服务。但是苹果有个自带的高德地图,像流氓软件一样,删也删不掉,所以说这个跳转是能实现的。
接下来说一下我的实现
实现跳转首先想到的肯定是配置URL Scheme 和白名单了
常用的4个地图的 URL Scheme:
1.苹果自带地图(不需要检测,所以不需要URL Scheme)
2.百度地图 :baidumap://
3.高德地图 :iosamap://
4.谷歌地图 :comgooglemaps://
注意:在 iOS 9 之后我们做跳转是需要有个白名单的,添加白名单的方法就是在 info.plist 文件里面,添加一个字段LSApplicationQueriesSchemes 类型为数组,然后在这个数组里面再添加我们所需要的地图 URL Scheme :
配置好白名单之后就要敲代码了 如果没有安装某个地图App 那么对应的选项就不应该出现
想要检测手机是否安装了某个地图APP,只要调用下面这个方法就可以了:
[[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"XXX://"]];
下面开始撸代码:
第一:苹果自带地图
苹果提供了一种方式:MKMapItem(要使用记得导入#import <MapKit/MapKit.h>
头文件)
编程代码:
//苹果地图
- (void)navAppleMap
{
CLLocationCoordinate2D gps = _currentLocationCoordinate;
MKMapItem *currentLoc = [MKMapItem mapItemForCurrentLocation];
MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:gps addressDictionary:nil]];
NSArray *items = @[currentLoc,toLocation];
NSDictionary *dic = @{
MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeWalking,
MKLaunchOptionsMapTypeKey : @(MKMapTypeStandard),
MKLaunchOptionsShowsTrafficKey : @(YES)
};
[MKMapItem openMapsWithItems:items launchOptions:dic];
}
其他第三方地图,需要传入经纬度:
Demo如下:
#pragma mark ----导航方法-----------
- (NSArray *)getInstalledMapAppWithEndLocation:(CLLocationCoordinate2D)endLocation
{
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSString *appName = [infoDictionary objectForKey:(NSString *)kCFBundleExecutableKey]; //获取项目名称
NSMutableArray *maps = [NSMutableArray array];
//苹果地图
NSMutableDictionary *iosMapDic = [NSMutableDictionary dictionary];
iosMapDic[@"title"] = @"苹果地图";
[maps 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=walking&coord_type=gcj02",endLocation.latitude,endLocation.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
baiduMapDic[@"url"] = urlString;
[maps 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",appName,APP_SCHEMES,endLocation.latitude,endLocation.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
gaodeMapDic[@"url"] = urlString;
[maps addObject:gaodeMapDic];
}
//谷歌地图
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=walking",appName,@"nav123456",endLocation.latitude, endLocation.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
googleMapDic[@"url"] = urlString;
[maps addObject:googleMapDic];
}
//腾讯地图
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"qqmap://"]]) {
NSMutableDictionary *qqMapDic = [NSMutableDictionary dictionary];
qqMapDic[@"title"] = @"腾讯地图";
NSString *urlString = [[NSString stringWithFormat:@"qqmap://map/routeplan?from=我的位置&type=walk&tocoord=%f,%f&to=终点&coord_type=1&policy=0",endLocation.latitude, endLocation.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
qqMapDic[@"url"] = urlString;
[maps addObject:qqMapDic];
}
return maps;
}
接着在点击导航调用的方法里面,弹出提示框,设置代理方法:
- (void)navgationSender:(id)sender
{
self.maps = [self getInstalledMapAppWithEndLocation:_currentLocationCoordinate];
UIActionSheet *action = [[UIActionSheet alloc] init];
for (NSDictionary *dic in self.maps) {
[action addButtonWithTitle:[NSString stringWithFormat:@"%@", dic[@"title"]]];
}
[action addButtonWithTitle:@"取消"];
action.cancelButtonIndex = self.maps.count;
action.delegate = self;
[action showInView:self.view];
}
#pragma mark UIActionSheetDelegate
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != -1 && buttonIndex < self.maps.count) {
if (buttonIndex == 0) {
[self navAppleMap];
return;
}
NSDictionary *dic = self.maps[buttonIndex];
NSString *urlString = dic[@"url"];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}
}
OK,可以调用第三方地图啦!!!!!!!!
说一下注意事项:
1.引入头文件
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
2.传参
一:百度地图
NSString *urlString = [[NSString stringWithFormat:@"baidumap://map/direction?origin={{我的位置}}&destination=latlng:%f,%f|name=目的地&mode=walking&coord_type=gcj02",endLocation.latitude,endLocation.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
这里面要注意几点:
1,origin={{我的位置}}, 这个是不能被修改的,不然无法把出发位置设置为当前位置
2,destination = latlng:%f,%f|name = 目的地
这里面的 name 的字段不能省略,否则导航会失败,而后面的文字则可以随意
3,coord_type = gcj02
coord_type 允许的值为 bd09ll、gcj02、wgs84,如果你 APP 的地图 SDK 用的是百度地图 SDK,请填 bd09ll,否则就填gcj02,wgs84的话基本是用不上了(需要涉及到地图加密)
二:高德地图
NSString *urlString = [[NSString stringWithFormat:@"iosamap://navi?sourceApplication=%@&backScheme=%@&lat=%f&lon=%f&dev=0&style=2",appName,APP_SCHEMES,endLocation.latitude,endLocation.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
要注意几点:
- sourceApplication=%@&backScheme=%@
sourceApplication代表你自己APP的名称,会在之后跳回的时候显示出来,所以必须填写。backScheme是你APP的URL Scheme,不填是跳不回来的 - dev=0
这里填0就行了,跟上面的gcj02一个意思 ,1代表wgs84, 也用不上。