Installing react-native-mapbox-navigation in iOS
For many years we researched a way to have the Google Direction ability in React Native. Right now this package exists thanks to https://www.homee.com/ team.
You can find the package at https://github.com/homeeondemand/react-native-mapbox-navigation
Unfortunately I had a lot of trouble installing this package, encountered many errors, and wanted to give a step by step tutorial integration.
Create a react-native app
react-native init MapboxNavigation
Check everything is running
Unfortunately Flipper was producing many errors for me on iOS, like:
> cd MapboxNavigation
> react-native run-ios
...
...
The following build commands failed:
CompileC /Users/os/Library/Developer/Xcode/DerivedData/MapboxNavigation-fihdhqqvpzufydfwkiousnssilfq/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/Flipper.build/Objects-normal/x86_64/FlipperRSocketResponder.o /Users/os/Desktop/Bouncing/MapboxNavigation/ios/Pods/Flipper/xplat/Flipper/FlipperRSocketResponder.cpp normal x86_64 c++ com.apple.compilers.llvm.clang.1_0.compiler
(1 failure)
Open your ‘Podfile’ file and replace
use_flipper!
to use_flipper!({ ‘Flipper-Folly’ => ‘2.3.0’ })
Then remove ‘Podfile.lock’ and then run pod install
> react-native run-ios
...
Build Succeeded
Our app is running now
Install react-native-mapbox-navigation
Lets add the package react-native-mapbox-navigation to our project.
yarn add @homee/react-native-mapbox-navigation
Have you secret and public Mapbox Token at hand. You can generate those here:
- Your Public access token: From your account’s tokens page , you can either copy your /default public token/ or click the Create a token button to create a new public token.
- A secret access token with the Downloads:Read scope.
- From your account’s tokens page , click the Create a token button.
- From the token creation page, give your token a name and make sure the box next to the Downloads:Read scope is checked.
- Click the Create token button at the bottom of the page to create your token.
- The token you’ve created is a /secret token/, which means you will only have one opportunity to copy it somewhere secure.
Now, following their documentation and BEFORE you do pod install
, let’s do some previous and necessary steps first.
- Create a ‘.netrc’ file on your computer home folder (not you project folder)
touch ~/.netrc
And open the file with your editor
code ~/.netrc
Add the following to the file
machine api.mapbox.com
login mapbox
password YOUR_SECRET_ACCESS_TOKEN
- Open your ‘.MapboxNavigation.xcworkspace’ project in Xcode
Now as we are using Mapbox Native SDK under the hood we need to have a Objective-C bridging header for swift, otherwise the package won’t work.
To do this:
* From Xcode, select your ‘AppDelegate.m’ file and right click on it.
* Select New File…
* Select Swift File.
* Name your file Dummy or whatever you want, I named it ‘MapboxDirection’.
* In the Group dropdown, make sure to select the group folder for your app, not the project itself.
* After you create the Swift file, you should be prompted to choose if you want to configure an Objective-C Bridging Header. Select “Create Bridging Header”.
Here is aGIF for these steps.
- Place your public token in your project’s ‘Info.plist’ and and add a ‘MGLMapboxAccessToken’ key whose value is your public access token.
<key>MGLMapboxAccessToken</key>
<sring>YOUR_PUBLIC_ACCESS_TOKEN</sring>
Now we can run pod install
from the iOS folder
cd ios ; pod install
You will see all additional packages are installed.
Installing Mapbox-iOS-SDK (6.3.0)
Installing MapboxAccounts (2.3.1)
Installing MapboxCommon (9.2.0)
Installing MapboxCoreNavigation (1.2.1)
Installing MapboxDirections (1.2.0)
Installing MapboxMobileEvents (0.10.8)
Installing MapboxNavigation (1.2.1)
Installing MapboxNavigationNative (30.0.0)
Installing MapboxSpeech (1.0.0)
Installing Polyline (5.0.2)
Installing Solar (2.1.0)
Installing Turf (1.2.0)
Installing react-native-mapbox-navigation (1.0.0)
Check everything is running
Let’s check if everything is running.
> react-native run-ios
...
error Failed to build iOS project. We ran "xcodebuild" command but it exited with error code 65. To debug build logs further, consider building your app with Xcode.app, by opening MapboxNavigation.xcworkspace. Run CLI with --verbose flag for more details.
...
Build system information
error: Multiple commands produce '/Users/os/Library/Developer/Xcode/DerivedData/MapboxNavigation-fihdhqqvpzufydfwkiousnssilfq/Build/Products/Debug-iphonesimulator/MapboxNavigation.app/Assets.car':
1) Target 'MapboxNavigation' (project 'MapboxNavigation') has compile command with input '/Users/os/Desktop/Bouncing/MapboxNavigation/ios/MapboxNavigation/Images.xcassets'
2) That command depends on command in Target 'MapboxNavigation' (project 'MapboxNavigation'): script phase “[CP] Copy Pods Resources”
Ok, the integration guide tells something about this. We need to add some code to the top of the ‘Podfile’:
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
platform :ios, '10.0'
install! 'cocoapods', :disable_input_output_paths => true
...
In the terminal execute:
cd ios; pod update; pod install
Lets try to tun the app again:
> react-native run-ios
...
▸ Build Succeeded
success Successfully built the app
error Failed to get the target build directory. Run CLI with --verbose flag for more details.
Uhmm
> react-native run-ios --verbose
...
▸ Build Succeeded
success Successfully built the app
error Failed to get the target build directory.
Not sure what is happening so I opt for running the project in Xcode to see if there is any other clue of why it is failing.
On Xcode Product -> Build
*Showing Recent Messages*
Signing for “MapboxNavigation” requires a development team. Select a development team in the Signing & Capabilities editor.
Uhm ok ok, let’s select a development team for this project, make sure you do it on all your targets.
Again, On Xcode Product -> Build
Undefined symbols for architecture arm64:
"_swift_getFunctionReplacement", referenced from:
_swift_getFunctionReplacement50 in libswiftCompatibilityDynamicReplacements.a(DynamicReplaceable.cpp.o)
(maybe you meant: _swift_getFunctionReplacement50)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Ok, new error, I searched in the react-native-mapbox-navigation issues and found so many steps to do:
- Go to Project > Build Settings > Library search path
- Remove "(PLATFORM_NAME)"
- Set ‘Don’t Dead-strip Inits and Terms’ to ‘Yes’ for both Project and all Targets
- Set ‘Always Embed Swift Standard Libraries’ to ‘Yes’ in the build settings Project and all Targets.
Next, On Xcode Product -> Build
Seems like this Build does success, so lets run the project in the simulator
https://share.getcloudapp.com/wbu9Lkwq
It failed with this error:
dyld: Library not loaded: @rpath/MapboxMobileEvents.framework/MapboxMobileEvents
Referenced from: /Users/os/Library/Developer/CoreSimulator/Devices/F4BE899E-D625-45DE-9708-649C8263A45A/data/Containers/Bundle/Application/717BD298-BB7F-4AFB-8FA9-8000D3611B4F/MapboxNavigation.app/Frameworks/Mapbox.framework/Mapbox
Reason: image not found
For this we need to add use_frameworks!
to the ‘Podfile’. Unfortunately Flipper can be use with ‘use_framweorks` so I had to disable it
...
install! 'cocoapods', :disable_input_output_paths => true
use_frameworks!
...
# Enables Flipper.
#
# Note that if you have use_frameworks! enabled, Flipper will not work and you should disable these next few lines.
# use_flipper!({ 'Flipper-Folly' => '2.3.0' })
# post_install do |installer|
# flipper_post_install(installer)
# end
...
cd ios; pod update; pod install
Removing CocoaAsyncSocket
Removing CocoaLibEvent
Removing Flipper
Removing Flipper-DoubleConversion
Removing Flipper-Folly
Removing Flipper-Glog
Removing Flipper-PeerTalk
Removing Flipper-RSocket
Removing FlipperKit
Removing OpenSSL-Universal
Removing YogaKit
Next, On Xcode Product -> Build
Undefined symbols for architecture x86_64:
"_OBJC_CLASS_$_RCTViewManager", referenced from:
type metadata for react_native_mapbox_navigation.MapboxNavigationManager in MapboxNavigationManager-00758322f339d0e6dfca28eea53c318c2d7d6f5559454e4f45ca706c8ab22e30.o
"_OBJC_METACLASS_$_RCTViewManager", referenced from:
_OBJC_METACLASS_$_MapboxNavigationManager in MapboxNavigationManager-00758322f339d0e6dfca28eea53c318c2d7d6f5559454e4f45ca706c8ab22e30.o
"_RCTRegisterModule", referenced from:
_initialize_MapboxNavigationManager in MapboxNavigationManager-00758322f339d0e6dfca28eea53c318c9998a9e17a6bf7596501d341d52f1444.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Another error, Undefined symbols for architecture x86_64
* Select your pod project
* In Targets Select MapboxNavigation
* Select Build phase at the top
* Select Link Binary With Libraries
* Click the +
* Search for “MapboxMobileEvents.framework”
* Click Add
* Clean
* Rebuild
Next, On Xcode Product -> Build
This still got me the error, so I had to:
* Clear Xcode Cache
`rm -rf ~/Library/Developer/Xcode/DerivedData`
* Go into iOS folder
`cd iOS`
* Clear CocoaPods Cache
`pod deintegrate && pod cache clean —all`
* Re-Install Pods
`pod install`
Next, On Xcode Product -> Build
The app finally ran
Integrate react-native-mapbox-navigation
Lets change our ‘App.js’ file to the base for react-native-mapbox-navigation
import * as React from 'react';
import {StyleSheet, View} from 'react-native';
import MapboxNavigation from '@homee/react-native-mapbox-navigation';
const App = () => {
return (
<View style={styles.container}>
<MapboxNavigation
origin={[-97.760288, 30.273566]}
destination={[-97.918842, 30.494466]}
shouldSimulateRoute={true}
onLocationChange={(event) => {
const {latitude, longitude} = event.nativeEvent;
}}
onRouteProgressChange={(event) => {
const {
distanceTraveled,
durationRemaining,
fractionTraveled,
distanceRemaining,
} = event.nativeEvent;
}}
onError={(event) => {
const {message} = event.nativeEvent;
}}
onCancelNavigation={() => {
// User tapped the "X" cancel button in the nav UI
// or canceled via the OS system tray on android.
// Do whatever you need to here.
}}
onArrive={() => {
// Called when you arrive at the destination.
}}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default App;
Run the app now.
The app stops and in Xcode get have this error:
Assertion failed: This application’s Info.plist file must include “audio” in UIBackgroundModes. This background mode is used for spoken instructions while the application is in the background.: file
We need to add audio in background mode for this to work
Add to your Info.plist
* Required background modes
* Item 0: audio
Run the app again.
And finally we have the app running https://share.getcloudapp.com/P8ukXRPE
Find the code for this tutorial at our GitLab account https://gitlab.com/alamedadev/mapboxnavigation