react-native 调用原生module跳转第三方地图软件实现导航功能

之前做过android地图开发,在自己的APP里集成第三方的地图sdk(百度,高德,腾讯,搜狗等),来实现导航,基于LBS周边搜索,定位,路线规划等功能需求,这种方法比较麻烦。同时还增加了app的体积,还有如果这个第三方地图软件的sdk更新了,那你自己的app还的做相应的更新,在react-native这种方法估计也可以,但是没去尝试,因为需求简单,就是实现导航,所以就用了接下来介绍这种方法,直接用url跳转到第三放的地图软件来导航,但首先要检测这个第三方的app有没有安装,没安装当然就不显示。目前只检测市场主流的几款地图app(百度地图,高德地图,腾讯地图,ios的苹果地图)

相关的参数要求:
苹果地图:具体的地址
高德地图:具体的地址,经纬度
百度地图:具体的地址,
腾讯地图:具体的地址,经纬度

总结下来,要实现这种跳转导航,必须要把地址经纬度都传过去。

如果后续我发现只传地址就能在不同的app实现导航功能,会及时更新此文章的。欢迎大家留言。

效果图:


1 ios集成方法

    
1)新建一个react-native项目,用xcode打开,同时添加白名单

react-native 调用原生module跳转第三方地图软件实现导航功能_第1张图片

2)项目目录下新建一个class,命名为UtilMap,如图


react-native 调用原生module跳转第三方地图软件实现导航功能_第2张图片

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类,
react-native 调用原生module跳转第三方地图软件实现导航功能_第3张图片

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中注册这个模块

react-native 调用原生module跳转第三方地图软件实现导航功能_第4张图片


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,
  },
});

你可能感兴趣的:(js,react-native,android,ios)