之前做过android地图开发,在自己的APP里集成第三方的地图sdk(百度,高德,腾讯,搜狗等),来实现导航,基于LBS周边搜索,定位,路线规划等功能需求,这种方法比较麻烦。同时还增加了app的体积,还有如果这个第三方地图软件的sdk更新了,那你自己的app还的做相应的更新,在react-native这种方法估计也可以,但是没去尝试,因为需求简单,就是实现导航,所以就用了接下来介绍这种方法,直接用url跳转到第三放的地图软件来导航,但首先要检测这个第三方的app有没有安装,没安装当然就不显示。目前只检测市场主流的几款地图app(百度地图,高德地图,腾讯地图,ios的苹果地图)
相关的参数要求:
苹果地图:具体的地址
高德地图:具体的地址,经纬度
百度地图:具体的地址,
腾讯地图:具体的地址,经纬度
总结下来,要实现这种跳转导航,必须要把地址经纬度都传过去。
如果后续我发现只传地址就能在不同的app实现导航功能,会及时更新此文章的。欢迎大家留言。
效果图:
1 ios集成方法
1)新建一个react-native项目,用xcode打开,同时添加白名单
2)项目目录下新建一个class,命名为UtilMap,如图
3)编写UtilMap.m
#import "UtilMap.h"
#import
#import
@implementation UtilMap
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(addEvent:(NSString *)name url:(NSString *)url lon:(NSString *)lon lat:(NSString *) lat address:(NSString*) address)
{
RCTLogInfo(@"地图app=== %@ url %@-----经度:%@------纬度:%@------地址:%@", name, url,lon,lat,address);
if ([url isEqualToString : @"ios"]) {
[self appleMap:lon andB:lat andC:address];
}else{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
}
}
RCT_EXPORT_METHOD(findEvents:(NSString *)lon lat:(NSString *)lat address:(NSString*)address resolver:(RCTResponseSenderBlock)callback)
{
NSMutableArray *maps = [NSMutableArray array];
//苹果地图
if ([[UIApplication sharedApplication]canOpenURL:[NSURL URLWithString:@"http://maps.apple.com/"]]) {
NSMutableDictionary *iosMapDic = [NSMutableDictionary dictionary];
iosMapDic[@"title"] = @"苹果地图";
iosMapDic[@"url"] = @"ios";
[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=name=%@&mode=driving&coord_type=gcj02",address] 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",@"导航功能",@"nav123456",[lat doubleValue],[lon doubleValue]] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
gaodeMapDic[@"url"] = urlString;
[maps 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",[lat doubleValue],[lon doubleValue],address] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
qqMapDic[@"url"] = urlString;
[maps addObject:qqMapDic];
}
NSMutableDictionary *cancalMapDic = [NSMutableDictionary dictionary];
cancalMapDic[@"title"] = @"取消";
[maps addObject:cancalMapDic];
// RCTLogInfo(@"地图app===经度:",maps);
callback(@[maps]);
}
//苹果地图
//跳转到苹果自带地图
- (void)appleMap:(NSString*)lon andB:(NSString*)lat andC:(NSString*)address{
RCTLogInfo(@"地图app===经度:%@------纬度:%@------地址:%@",lon,lat,address);
// MKMapItem *currentLoc = [MKMapItem mapItemForCurrentLocation];
//
// MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:CLLocationCoordinate2DMake([lat doubleValue], [lon doubleValue]) addressDictionary:nil]];
//
// MKMapItem *aaa = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:CLLocationCoordinate2DMake([lat doubleValue], [lon doubleValue]) addressDictionary:nil]];
//
// NSArray *items = @[currentLoc,toLocation];
// NSDictionary *dic = @{
// MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving,
// MKLaunchOptionsMapTypeKey : @(MKMapTypeStandard),
// MKLaunchOptionsShowsTrafficKey : @(YES)
// };
// [MKMapItem openMapsWithItems:items launchOptions:dic];
//MKMapItem 使用场景: 1. 跳转原生地图 2.计算线路
MKMapItem *currentLocation = [MKMapItem mapItemForCurrentLocation];
//地理编码器
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
//我们假定一个终点坐标,测试地址:121.226669,31.998277
[geocoder geocodeAddressString:address completionHandler:^(NSArray * _Nullable placemarks, NSError * _Nullable error) {
CLPlacemark *endPlacemark = placemarks.lastObject;
RCTLogInfo(@"Longitude = %f", endPlacemark.location.coordinate.longitude);
RCTLogInfo(@"Latitude = %f", endPlacemark.location.coordinate.latitude);
//创建一个地图的地标对象o
MKPlacemark *endMKPlacemark = [[MKPlacemark alloc] initWithPlacemark:endPlacemark];
//在地图上标注一个点(终点)
MKMapItem *endMapItem = [[MKMapItem alloc] initWithPlacemark:endMKPlacemark];
//MKLaunchOptionsDirectionsModeKey 指定导航模式
//NSString * const MKLaunchOptionsDirectionsModeDriving; 驾车
//NSString * const MKLaunchOptionsDirectionsModeWalking; 步行
//NSString * const MKLaunchOptionsDirectionsModeTransit; 公交
[MKMapItem openMapsWithItems:@[currentLocation, endMapItem]
launchOptions:@{MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving,MKLaunchOptionsShowsTrafficKey: [NSNumber numberWithBool:YES]}];
}];
}
@end
具体什么意思,请看react-native 的官网及相关的ios地图原生开发
2 android集成
1)将新建的项目用android studio打开,同时新建一个maputil的包名和UtilMap类,
2)UtilMap.java
package com.mapdemo.maputil;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.net.Uri;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableNativeArray;
import com.facebook.react.bridge.WritableNativeMap;
public class UtilMap extends ReactContextBaseJavaModule {
public UtilMap(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return "UtilMap";
}
/*
检测手机是否安装了相应的地图app。返回的数据格式为:[{title:'dadasda'url:app地图URL},{title:'dadasda'url:app地图URL},{title:'dadasda'url:app地图URL}]
*/
@ReactMethod
public void findEvents(
String lon,
String lat,
String address,
Callback successCallback) throws Exception {
WritableArray array = new WritableNativeArray();
//百度地图app检测
if (isAppInstalled(getReactApplicationContext(), "com.baidu.BaiduMap")) {
WritableNativeMap ob = new WritableNativeMap();
ob.putString("title", "百度地图");
ob.putString("url", "baidumap://map/direction?origin=我的位置&destination=name=" + address + "&mode=driving&coord_type=gcj02");
array.pushMap(ob);
}
//高德地图app检测
if (isAppInstalled(getReactApplicationContext(), "com.autonavi.minimap")) {
WritableNativeMap ob = new WritableNativeMap();
ob.putString("title", "高德地图");
ob.putString("url", "androidamap://navi?sourceApplication=导航功能&backScheme=nav123456&lat=" + lat + "&lon=" + lon + "&dev=0&style=2");
array.pushMap(ob);
}
//腾讯地图app检测
if (isAppInstalled(getReactApplicationContext(), "com.tencent.map")) {
WritableNativeMap ob = new WritableNativeMap();
ob.putString("title", "腾讯地图");
ob.putString("url", "qqmap://map/routeplan?from=我的位置&type=drive&tocoord=" + lat + "," + lon + "&to=" + address + "&coord_type=1&policy=0");
array.pushMap(ob);
}
WritableNativeMap ob = new WritableNativeMap();
ob.putString("title", "取消");
ob.putString("url", "");
array.pushMap(ob);
successCallback.invoke(array);
}
@ReactMethod
public void addEvent(String title,
String url,
String lon,
String lag,
String address) {
//打开对应的app
if(!url.equals("")){
Intent i1 = new Intent();
i1.setData(Uri.parse(url));
getReactApplicationContext().startActivity(i1);
}
}
/**
* 查看是否安装了这个导航软件
* 高德地图 com.autonavi.minimap
* 百度地图 com.baidu.BaiduMap
* 腾讯地图 com.tencent.map
*
* @param context
* @param packagename
* @return
*/
public boolean isAppInstalled(Context context, String packagename) {
PackageInfo packageInfo;
try {
packageInfo = context.getPackageManager().getPackageInfo(packagename, 0);
} catch (Exception e) {
packageInfo = null;
e.printStackTrace();
}
if (packageInfo == null) {
return false;
} else {
return true;
}
}
}
3)UtilMapPackage.java
package com.mapdemo.maputil;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class UtilMapPackage implements ReactPackage {
@Override
public List createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List createNativeModules(ReactApplicationContext reactContext) {
List modules = new ArrayList<>();
modules.add(new UtilMap(reactContext));
return modules;
}
}
4)在MainApplication中注册这个模块
3 react-native 调用原生
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, { Component } from 'react';
import { ActionSheet, WingBlank, WhiteSpace, Button, Toast } from 'antd-mobile';
import {
Platform,
StyleSheet,
Text,
View,
TouchableOpacity,
NativeModules,
Linking,
Alert
} from 'react-native';
let lon = '121.2477511168'; // ---经度 121.248078
let lat = '31.0913734181'; // ---纬度 31.091769
let name = '上海松江王家厍路55弄';//
let UtilMapManager = NativeModules.UtilMap;
export default class App extends Component {
iosmap() {
let array = [];
UtilMapManager.findEvents(lon, lat, name, (events) => {
events.map((index, item) => {
array.push(index.title);
})
if (array.length > 2) {
ActionSheet.showActionSheetWithOptions({
options: array,
cancelButtonIndex: array.length - 1,
maskClosable: true,
},
(buttonIndex) => {
//跳到原生方法对应的app地图导航内
UtilMapManager.addEvent(events[buttonIndex].title, events[buttonIndex].url, lon, lat, name);//lon是经度,,,log是维度
});
} else if (array.length == 2) {
if (events.length == 2 && events[0].url == 'ios') {
//只针对ios平台
UtilMapManager.addEvent(events[0].title, events[0].url, lon, lat, name);
} else {
ActionSheet.showActionSheetWithOptions({
options: array,
cancelButtonIndex: array.length - 1,
maskClosable: true,
},
(buttonIndex) => {
//跳到原生方法对应的app地图导航内
UtilMapManager.addEvent(events[buttonIndex].title, events[buttonIndex].url, lon, lat, name);//lon是经度,log是维度
});
}
} else {//只适用于android平台
Alert.alert('没有可用的地图软件!');
}
})
}
render() {
return (
打开导航软件
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});