Implement Mapbox Navigation with React Native

Noctis
6 min readJul 16, 2022

--

Hello readers ! If like me you’re struggling to find something to add Mapbox Navigation well this article may be for you.

First of all you may now this package https://github.com/homeeondemand/react-native-mapbox-navigation that was a good project but unfortunately it seems not maintained anymore i tried to make it work but i figure it out that is a dead end so i like to thank and applause👏🏻 homeeondemand team for their work and hope one day they’ll come with something new or some update.

So lets begin ! first of all we will create a brand new react native projet or you can use existant and skip this part

npx react-native init mapnav

So we have our brand new project lets get into it

cd mapnav
code . // this command is to open the project in visual studio code

Go into Podfile in ios folder and proceed as follow

What we did is that we implement Mapbox Navigation SDK 2.6 and to make it work we need to active use_framework! and comment use_flipper!() to avoid some issue so notice that flipper will not be available after this point.

Once it done just do a npx pod-install or cd ios && pod install if you don’t have pod-install command

npx pod-install

Now that we have everything settle open Xcode and the mapnav.xcworkspace

So to resume we installed a SDK to our project and to make any use of it we will need what’s called a BRIDGE yeah not to cross it (What a joke XD) but to link the native function of the SDK to our JS React Native Part And a Swift file with the functionnality that we need but before all of this there is some quests that you must fullfill (but you can also follow the official documentation https://docs.mapbox.com/ios/navigation/guides/get-started/install/) :

Quest 1 :

As a adventurer you’ll go visit this website https://www.mapbox.com and create an account if you don’t have any then !!! you’ll unlock the Quest 2

Quest 2 :

Once your account created you’ll access to a new Weapon called Default Public Token well lets put it aside for now and lets go see the BlackSmith to create our Secret Access Token -> https://account.mapbox.com/access-tokens/create
Name your secret token as you want and dont forget to check Downloads:Read scope.
The token you’ve created is a secret token, which means you will only have one opportunity to copy it somewhere secure. !!!!!

Quest 3 :

Now that we have our public token and our secret token check if you have a .netrc file

cd /Users/dummyHomeMacOSNameORWHATEVERUHAVE
ls -a

if you have already a .netrc file just open it and add at the end the code as follow else create it with touch .netrc and open it (ReplaceYOUR_SECRET_MAPBOX_ACCESS_TOKEN by yours that we created in Quest 2)

machine api.mapbox.com
login mapbox
password YOUR_SECRET_MAPBOX_ACCESS_TOKEN

We almost finish ! don’t lose hope to reach the 5th and final Quest !!!

Quest 4 :

Now that we got everything we need to continue our implementation we can open Info.plist and at the end add this part

<key>MBXAccessToken</key><string>YOURDEFAULT_PUBLIC_TOKEN</string><key>UIBackgroundModes</key><array><string>audio</string><string>location</string></array>

So to resume the MBXAccessToken is to allow the use of MapBox SDK and UIBackgroundModes is to allow the use of audio and location as the app is in background and still get the voice indication of the turn by turn navigation as the location

If you still here well congratulation you’re real adventurer ! lets go for the final Quest ! Beat The Mapbox Navigation Boss

So as i said earlier we will need to create some file to join our SDK to our JS RN part. Lets back to Xcode and go to File -> new -> File …

Select Swift.File and continue

Lets call it MapboxNavigation and as the group folder make sur to select the project group folder and not the project itself !!

If you don’t already have a Bridging Header it will ask you to create one automaticly so click Create Brdiging Header

So In our mapnav-Bridging-Header freshly created we will add this import

#import "React/RCTBridgeModule.h"

In our MapboxNavigation Swift file we will create a function call takeMeToDestination or whatever you want You can also refer to the official doc for more information the only difference here is that we will return the MapboxNavigation View to our rootViewController to render it in React Native.

import Foundationimport MapboxDirectionsimport MapboxCoreNavigationimport MapboxNavigationimport CoreLocation@objc(MapboxNavigation)class MapboxNavigation: NSObject {@objcfunc takeMeToDestination() {let origin = Waypoint(coordinate: CLLocationCoordinate2D(latitude: 38.9131752, longitude: -77.0324047), name: "Mapbox")let destination = Waypoint(coordinate: CLLocationCoordinate2D(latitude: 38.8977, longitude: -77.0365), name: "White House")let routeOptions = NavigationRouteOptions(waypoints: [origin, destination])Directions.shared.calculate(routeOptions) { [weak self] (session, result) inswitch result {case .failure(let error):print(error.localizedDescription)case .success(let response):guard let self = self else { return }// Pass the first generated route to the the NavigationViewControllerlet viewController = NavigationViewController(for: response, routeIndex: 0, routeOptions: routeOptions)viewController.modalPresentationStyle = .fullScreenlet appDelegate = UIApplication.shared.delegateappDelegate!.window!!.rootViewController!.present(viewController, animated: true, completion: nil)}}}}

And finally to make all this work we will need to create a last file so Xcode File -> new -> File… select Objective-C File, we will call it MapboxNavigation.m and dont forget as for the Swift file to select the project group folder and not the project itself.

Past this to our MapboxNavigation.m File :

////  MapboxNavigation.m//  woosher////  Created by Polyrion Inc on 15/07/2022.//#import <Foundation/Foundation.h>#import "React/RCTBridgeModule.h"@interface RCT_EXTERN_REMAP_MODULE(RNMapboxNavigation, MapboxNavigation, NSObject)RCT_EXTERN_METHOD(takeMeToDestination)@end

Now we linked our Swift SDK method and make it accessible to React Native Module Lets test if eveything work :

yarn start

Xcode -> choose a device and build or you can also use

yarn ios

Lets open App.js and remplace everything by :

import {StyleSheet, Text, View, NativeModules} from 'react-native';import React from 'react';const App = () => {NativeModules.RNMapboxNavigation.takeMeToWH();return (<View style={styles.container}><Text>App</Text></View>);};export default App;const styles = StyleSheet.create({container: {flex: 1,},});

You should result with Mapbox Navigation Working.

Troubleshooting :

All this Project was made with React Native 68.2, and 69.1, but you may encounter somme issue with RN 69.0

This concern https://github.com/facebook/react-native/issues/34102

And i’m already searching for a solution that maybe come soon, As for a next part ? Well let me know if you enjoyed this article and if it was useful yo you. I may take some time to i dunno what if ? We put some real origin of the device and pass a real destination that we wanna go to ? And make it all work with permissions that sound fun ? Well lemme know if you’re interested and you’ll receive a new Quest for a new Adventure ;)

Bonus repository link :

RN 68.2 : https://github.com/Polyrion/mapnav

RN 69.1 : https://github.com/Polyrion/mapnav_rn_69.1

--

--