前言
术语:
- 应用外导航:是指以URL跳转的方式(在iOS中就是以URL Scheme的方式),直接跳到对应的地图APP中,直接利用对方的功能来导航。这样的优点,一是接入方便,二是不增加自己APP的开销。
- 应用内导航:是指使用地图服务提供的SDK(如高德,百度),直接将导航功能嵌入到我们自己的APP内部。
需求:跳转到已经安装的地图
背景:为了减少app内存开支,以URI跳转的方式直接跳转到对应的地图进行导航,让最专业的人做最专业的事。
I 开发步骤
1.1 添加Scheme白名单
iOS 9 之后涉及到app跳转时,系统会自动到项目info.plist下检测是否设置相关平台Scheme。
<!--具体方法:在项目的info.plist中添加LSApplicationQueriesSchemes字段,类型是Array,然后添加Item。-->
<key>LSApplicationQueriesSchemes</key>
<array>
<string>baidumap</string>
<string>iosamap</string>
<string>comgooglemaps</string>
<string>qqmap</string>
</array>
苹果自带地图:if ( [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"http://maps.apple.com/"]]) {
百度地图 :
baidumap://
高德地图 :
iosamap://
谷歌地图:
comgooglemaps://
腾讯地图:
qqmap://
1.2 检测是否安装相应APP
使用canOpenURL:
方法来检测该手机是否安装相应APP
- (void)showSheet
{
NSString * appleMap = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"http://maps.apple.com/"]] ? @"苹果地图" : nil;
NSString * baiduMap = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"baidumap://"]] ? @"百度地图" : nil;
NSString * gaodeMap = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"iosamap://"]] ? @"高德地图":nil;
//谷歌地图:不能用,需翻_墙
NSString * googleMap = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"comgooglemaps://"]] ? nil :nil;
//
NSString * tencentMap = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"qqmap://map/"]] ? nil : nil;
UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:@"请选择您已经安装的导航工具" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:gaodeMap otherButtonTitles:appleMap,baiduMap,tencentMap,nil];//googleMap
[actionSheet showInView:[UIApplication sharedApplication].keyWindow];
}
1.3 封装跳转URL
- 地址系列
// //腾讯,type=bus 或 type=drive 或 type=walk 或 type=bike referer开发者key:
NSString * tencentAddressUrl = [[NSString stringWithFormat:@"qqmap://map/routeplan?type=walk&from=%@&to=%@&policy=1&referer=%@",mb.start, mb.end,_appName] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
//苹果
NSString *appleAddressUrl = [[NSString stringWithFormat:@"http://maps.apple.com/?saddr=%@&daddr=%@&dirflg=w",_start, mb.end] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
//百度
NSString *baiduAddressUrl = [[NSString stringWithFormat:@"baidumap://map/direction?origin=%@&destination=%@&mode=walking®ion=%@&src=%@",mb.start, mb.end,_city,_appName] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
//高德
NSString *gaodeAddressUrl = [[NSString stringWithFormat:@"iosamap://path?sourceApplication=%@&sid=BGVIS1&sname=%@&did=BGVIS2&dname=%@&dev=0&m=2&t=2",_appName,mb.start,mb.end] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
//谷歌
NSString *googleAddressUrl = [[NSString stringWithFormat:@"comgooglemaps://?x-source=%@&x-success=%@&saddr=%@&daddr=%@&directionsmode=bicycling",_appName,_urlScheme,mb.start, mb.end] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
- 通过经纬度参数打开
NSString * baiduUrlStr = [[NSString stringWithFormat:@"baidumap://map/direction?origin={{我的位置}}&destination=latlng:%f,%f|name=目的地&mode=driving&coord_type=gcj02",mb.Coordinate2D.latitude, mb.Coordinate2D.longitude] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSString * goooleUrlStr = [[NSString stringWithFormat:@"comgooglemaps://?x-source=%@&x-success=%@&saddr=&daddr=%f,%f&directionsmode=driving",_appName,_urlScheme,mb.Coordinate2D.latitude, mb.Coordinate2D.longitude] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSString * gaodeUrlStr= [[NSString stringWithFormat:@"iosamap://navi?sourceApplication=%@&backScheme=%@&lat=%f&lon=%f&dev=0&style=2",_appName,_urlScheme,mb.Coordinate2D.latitude, mb.Coordinate2D.longitude] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
- 方便弹回来
为了能够跳转回的自己的APP,需要在 URL Types里填写你的app的 URL Schemes
II 代码封装
完整代码获取,请联系我:#公号:iOS逆向
。
2.1 API
#import <MapKit/MKMapItem.h>//用于苹果自带地图
#import <MapKit/MKTypes.h>//用于苹果自带地图
/**
地图类型
*/
typedef enum : NSUInteger {
k_MapSelect4Apple = 0,
k_MapSelect4Baidu,
k_MapSelect4Google,
k_MapSelect4Gaode,
k_MapSelect4Tencent
} k_MapSelect;
/**
跳转URL的参数类型
*/
typedef enum : NSUInteger {
/**
地址
*/
k_MapNavStyle4Address = 0,
/**
经纬度
*/
k_MapNavStyle4Coordinates
} k_MapNavStyle;
@interface MapNavigationManager : NSObject
+ (void)showSheetWithCity:(NSString *)city start:(NSString *)start end:(NSString *)end;
+ (void)showSheetWithCoordinate2D:(CLLocationCoordinate2D)Coordinate2D;
@end
用法
NSString *start = @"";
[ERPMapNavManager showSheetWithCity:self.models.delivery.cityName start:start end:self.models.delivery.address];
2.2 核心实现
NSString * urlString = [self getUrlStr:index];
if (urlString != nil) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}
2.3 注意事项
- 腾讯地图需要给默认开始位置:https://lbs.qq.com/webApi/uriV1/uriGuide/uriMobileGuide
NSString *start = mb.start.length>0 ?mb.start :@"我的位置";
- 创建UIActionSheet时,otherButtonTitles参数最多支持3个,因为推荐使用
UIAlertController
。
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"请选择您已经安装的导航工具" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
__weak __typeof__(self) weakSelf = self;
if(gaodeMap){
UIAlertAction *action = [UIAlertAction actionWithTitle:gaodeMap style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
NSString * urlString = [self getUrlStr:k_MapSelect4Gaode];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}];
[alert addAction:action];
}
if(appleMap){
UIAlertAction *action = [UIAlertAction actionWithTitle:appleMap style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
if(weakSelf.style == k_MapNavStyle4Coordinates)
{
MKMapItem *currentLocation = [MKMapItem mapItemForCurrentLocation];
MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:self.Coordinate2D addressDictionary:nil]];
[MKMapItem openMapsWithItems:@[currentLocation, toLocation]
launchOptions:@{MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving,MKLaunchOptionsShowsTrafficKey: [NSNumber numberWithBool:YES]}];
return;
}
NSString * urlString = [self getUrlStr:k_MapSelect4Apple];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}];
[alert addAction:action];
}
UIAlertAction *action = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
[alert addAction:action];
[[QCT_Common getCurrentVC] presentViewController:alert animated:YES completion:^{
}];
see also
用代码修改图片颜色:https://blog.csdn.net/z929118967/article/details/104353863
UIImage *icon_right = [UIImage imageNamed:@"icon_right"];
icon_right = [icon_right imageWithRenderingMode:(UIImageRenderingModeAlwaysTemplate)];
tmp.image =icon_right;
tmp.tintColor = UIColor.whiteColor;
百度地图App:[http://developer.baidu.com/map/wiki/index.php?title=uri/api/ios
](http://developer.baidu.com/map/wiki/index.php?title=uri/api/ios
)
百度地图:[http://lbsyun.baidu.com/index.php?title=uri/api/ios
](http://lbsyun.baidu.com/index.php?title=uri/api/ios
)
苹果地图:[https://developer.apple.com/reference/mapkit/mkmapitem
](https://developer.apple.com/reference/mapkit/mkmapitem
)
腾讯地图:[http://lbs.qq.com/uri_v1/guide-route.html
](http://lbs.qq.com/uri_v1/guide-route.html
)