diff --git a/README.md b/README.md
index 8e6d0bf9..d62831e3 100644
--- a/README.md
+++ b/README.md
@@ -295,6 +295,11 @@ Array that contains the longitude and latitude for the starting point.
Array that contains the longitude and latitude for the destination point.
`[$longitude, $latitude]`
+#### `waypoints`
+
+Array that contains arrays of longitude and latitude for the waypoints (limit 25 as per the MapBox restrictions).
+`[[$longitude, $latitude], [$longitude, $latitude]]`
+
#### `shouldSimulateRoute`
Boolean that controls route simulation. Set this as `true` to auto navigate which is useful for testing or demo purposes. Defaults to `false`.
@@ -311,6 +316,18 @@ Boolean that toggles voice instructions. Defaults to `false`.
Boolean that controls showing the `StatusView` (iOS only). This is the transparent black bar with the "Simulating Navigation" text shown in the above screenshot. Defaults to `false`.
+#### `vehicleMaxWidth`
+
+Number that sets max width (in meters) of the vehicle. Defaults to `1.6`.
+
+#### `vehicleMaxHeight`
+
+Number that sets max height (in meters) of the vehicle. Defaults to `1.9`.
+
+#### `mute`
+
+Boolean that toggles voice instructions. Defaults to `false`.
+
#### `onLocationChange`
Function that is called frequently during route navigation. It receives `latitude` and `longitude` as parameters that represent the current location during navigation.
diff --git a/android/build.gradle b/android/build.gradle
index 181e82ce..0d5e44b9 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -1,167 +1,99 @@
-// android/build.gradle
-
-// based on:
-//
-// * https://github.com/facebook/react-native/blob/0.60-stable/template/android/build.gradle
-// original location:
-// - https://github.com/facebook/react-native/blob/0.58-stable/local-cli/templates/HelloWorld/android/build.gradle
-//
-// * https://github.com/facebook/react-native/blob/0.60-stable/template/android/app/build.gradle
-// original location:
-// - https://github.com/facebook/react-native/blob/0.58-stable/local-cli/templates/HelloWorld/android/app/build.gradle
-
-// https://www.cognizantsoftvision.com/blog/creating-an-android-native-module-for-react-native/
-
-def DEFAULT_COMPILE_SDK_VERSION = 31
-def DEFAULT_BUILD_TOOLS_VERSION = '30.0.2'
-def DEFAULT_MIN_SDK_VERSION = 21
-def DEFAULT_TARGET_SDK_VERSION = 31
-
-def safeExtGet(prop, fallback) {
- rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
-}
-
-apply plugin: 'com.android.library'
-apply plugin: 'kotlin-android'
-apply plugin: 'maven'
-
buildscript {
- ext.kotlin_version = '1.5.21'
- // The Android Gradle plugin is only required when opening the android folder stand-alone.
- // This avoids unnecessary downloads and potential conflicts when the library is included as a
- // module dependency in an application project.
- // ref: https://docs.gradle.org/current/userguide/tutorial_using_tasks.html#sec:build_script_external_dependencies
- if (project == rootProject) {
- repositories {
- google()
- jcenter()
- }
- dependencies {
- classpath 'com.android.tools.build:gradle:4.2.2'
- }
- }
+ // Buildscript is evaluated before everything else so we can't use getExtOrDefault
+ def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["MapboxNavigation_kotlinVersion"]
- repositories {
- mavenCentral()
- }
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath "com.android.tools.build:gradle:7.2.2"
+ // noinspection DifferentKotlinGradleVersion
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
- dependencies {
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
- }
+def isNewArchitectureEnabled() {
+ return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
}
-apply plugin: 'com.android.library'
-apply plugin: 'kotlin-android'
-apply plugin: 'maven'
+apply plugin: "com.android.library"
+apply plugin: "kotlin-android"
-android {
- compileSdkVersion safeExtGet('compileSdkVersion', DEFAULT_COMPILE_SDK_VERSION)
- buildToolsVersion safeExtGet('buildToolsVersion', DEFAULT_BUILD_TOOLS_VERSION)
- defaultConfig {
- minSdkVersion safeExtGet('minSdkVersion', DEFAULT_MIN_SDK_VERSION)
- targetSdkVersion safeExtGet('targetSdkVersion', DEFAULT_TARGET_SDK_VERSION)
- versionCode 1
- versionName "1.0"
- }
- lintOptions {
- abortOnError false
- }
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
- kotlinOptions {
- jvmTarget = "1.8"
- }
- buildFeatures {
- viewBinding true
- }
-}
-repositories {
- // ref: https://www.baeldung.com/maven-local-repository
- mavenLocal()
- maven {
- // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
- url "$rootDir/../node_modules/react-native/android"
- }
- maven {
- // Android JSC is installed from npm
- url "$rootDir/../node_modules/jsc-android/dist"
- }
- google()
- jcenter()
+def appProject = rootProject.allprojects.find { it.plugins.hasPlugin('com.android.application') }
+
+if (isNewArchitectureEnabled()) {
+ apply plugin: "com.facebook.react"
}
-dependencies {
- //noinspection GradleDynamicVersion
- implementation 'com.facebook.react:react-native:+' // From node_modules
- implementation "com.mapbox.navigation:android:2.1.1"
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
- implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
- implementation 'androidx.cardview:cardview:1.0.0'
+def getExtOrDefault(name) {
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["MapboxNavigation_" + name]
}
-def configureReactNativePom(def pom) {
- def packageJson = new groovy.json.JsonSlurper().parseText(file('../package.json').text)
-
- pom.project {
- name packageJson.title
- artifactId packageJson.name
- version = packageJson.version
- group = "com.homee.mapboxnavigation"
- description packageJson.description
- url packageJson.repository.baseUrl
-
- licenses {
- license {
- name packageJson.license
- url packageJson.repository.baseUrl + '/blob/master/' + packageJson.licenseFilename
- distribution 'repo'
- }
- }
- }
+def getExtOrIntegerDefault(name) {
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["MapboxNavigation_" + name]).toInteger()
}
-afterEvaluate { project ->
- // some Gradle build hooks ref:
- // https://www.oreilly.com/library/view/gradle-beyond-the/9781449373801/ch03.html
- task androidJavadoc(type: Javadoc) {
- source = android.sourceSets.main.java.srcDirs
- classpath += files(android.bootClasspath)
- classpath += files(project.getConfigurations().getByName('compile').asList())
- include '**/*.java'
- }
+android {
+ compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
- task androidJavadocJar(type: Jar, dependsOn: androidJavadoc) {
- from androidJavadoc.destinationDir
+ defaultConfig {
+ minSdkVersion getExtOrIntegerDefault("minSdkVersion")
+ targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
+ buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
}
+ }
- task androidSourcesJar(type: Jar) {
- from android.sourceSets.main.java.srcDirs
- include '**/*.java'
- }
+ lintOptions {
+ disable "GradleCompatible"
+ }
- android.libraryVariants.all { variant ->
- def name = variant.name.capitalize()
- def javaCompileTask = variant.javaCompileProvider.get()
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
- task "jar${name}"(type: Jar, dependsOn: javaCompileTask) {
- from javaCompileTask.destinationDir
- }
- }
+ // Add the block below if you're using Kotlin
+ kotlinOptions {
+ jvmTarget = "17"
+ }
- artifacts {
- archives androidSourcesJar
- archives androidJavadocJar
- }
+ buildFeatures {
+ viewBinding true
+ }
- task installArchives(type: Upload) {
- configuration = configurations.archives
- repositories.mavenDeployer {
- // Deploy to react-native-event-bridge/maven, ready to publish to npm
- repository url: "file://${projectDir}/../android/maven"
- configureReactNativePom pom
- }
- }
}
+
+repositories {
+ mavenCentral()
+ google()
+}
+
+def kotlin_version = getExtOrDefault("kotlinVersion")
+
+dependencies {
+ // For < 0.71, this will be from the local maven repo
+ // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
+ //noinspection GradleDynamicVersion
+ implementation "com.facebook.react:react-native:+"
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
+
+ // mapbox dependencies
+ implementation "com.mapbox.navigation:android:2.19.0"
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+ implementation 'androidx.cardview:cardview:1.0.0'
+}
+
+if (isNewArchitectureEnabled()) {
+ react {
+ jsRootDir = file("../src/")
+ libraryName = "MapboxNavigationView"
+ codegenJavaPackageName = "com.homee.mapboxnavigation"
+ }
+}
\ No newline at end of file
diff --git a/android/gradle.properties b/android/gradle.properties
new file mode 100644
index 00000000..03b0acc8
--- /dev/null
+++ b/android/gradle.properties
@@ -0,0 +1,4 @@
+MapboxNavigation_kotlinVersion=1.6.0
+MapboxNavigation_compileSdkVersion=33
+MapboxNavigation_minSdkVersion=21
+MapboxNavigation_targetSdkVersion=33
\ No newline at end of file
diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..ccebba77
Binary files /dev/null and b/android/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..46549df2
--- /dev/null
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+#Mon Feb 12 09:11:13 IST 2024
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
+networkTimeout=10000
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/android/gradlew b/android/gradlew
new file mode 100755
index 00000000..79a61d42
--- /dev/null
+++ b/android/gradlew
@@ -0,0 +1,244 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/android/gradlew.bat b/android/gradlew.bat
new file mode 100644
index 00000000..6689b85b
--- /dev/null
+++ b/android/gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/android/src/main/java/com/homee/mapboxnavigation/MapboxNavigationManager.kt b/android/src/main/java/com/homee/mapboxnavigation/MapboxNavigationManager.kt
index 03823a5a..f88caeda 100644
--- a/android/src/main/java/com/homee/mapboxnavigation/MapboxNavigationManager.kt
+++ b/android/src/main/java/com/homee/mapboxnavigation/MapboxNavigationManager.kt
@@ -13,77 +13,110 @@ import com.mapbox.maps.TileStoreUsageMode
import javax.annotation.Nonnull
class MapboxNavigationManager(var mCallerContext: ReactApplicationContext) : SimpleViewManager() {
- private var accessToken: String? = null
-
- init {
- mCallerContext.runOnUiQueueThread {
- try {
- val app = mCallerContext.packageManager.getApplicationInfo(mCallerContext.packageName, PackageManager.GET_META_DATA)
- val bundle = app.metaData
- val accessToken = bundle.getString("MAPBOX_ACCESS_TOKEN")
- this.accessToken = accessToken
- ResourceOptionsManager.getDefault(mCallerContext, accessToken).update {
- tileStoreUsageMode(TileStoreUsageMode.READ_ONLY)
- }
- } catch (e: PackageManager.NameNotFoundException) {
- e.printStackTrace()
- }
+ private var accessToken: String? = null
+ init {
+ mCallerContext.runOnUiQueueThread {
+ try {
+ val app = mCallerContext.packageManager.getApplicationInfo(mCallerContext.packageName, PackageManager.GET_META_DATA)
+ val bundle = app.metaData
+ val accessToken = bundle.getString("MAPBOX_ACCESS_TOKEN")
+ this.accessToken = accessToken
+ ResourceOptionsManager.getDefault(mCallerContext, accessToken).update {
+ tileStoreUsageMode(TileStoreUsageMode.READ_ONLY)
}
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ }
}
+ }
+ override fun getName(): String = "MapboxNavigation"
- override fun getName(): String {
- return "MapboxNavigation"
- }
+ public override fun createViewInstance(@Nonnull reactContext: ThemedReactContext): MapboxNavigationView {
+ return MapboxNavigationView(reactContext, this.accessToken)
+ }
- public override fun createViewInstance(@Nonnull reactContext: ThemedReactContext): MapboxNavigationView {
- return MapboxNavigationView(reactContext, this.accessToken)
- }
+ override fun onDropViewInstance(view: MapboxNavigationView) {
+ view.onDropViewInstance()
+ super.onDropViewInstance(view)
+ }
- override fun onDropViewInstance(view: MapboxNavigationView) {
- view.onDropViewInstance()
- super.onDropViewInstance(view)
- }
+ override fun getExportedCustomDirectEventTypeConstants(): MutableMap>? {
+ return MapBuilder.of>(
+ "onLocationChange", MapBuilder.of("registrationName", "onLocationChange"),
+ "onError", MapBuilder.of("registrationName", "onError"),
+ "onCancelNavigation", MapBuilder.of("registrationName", "onCancelNavigation"),
+ "onArrive", MapBuilder.of("registrationName", "onArrive"),
+ "onRouteProgressChange", MapBuilder.of("registrationName", "onRouteProgressChange"),
+ )
+ }
- override fun getExportedCustomDirectEventTypeConstants(): MutableMap>? {
- return MapBuilder.of>(
- "onLocationChange", MapBuilder.of("registrationName", "onLocationChange"),
- "onError", MapBuilder.of("registrationName", "onError"),
- "onCancelNavigation", MapBuilder.of("registrationName", "onCancelNavigation"),
- "onArrive", MapBuilder.of("registrationName", "onArrive"),
- "onRouteProgressChange", MapBuilder.of("registrationName", "onRouteProgressChange"),
- )
+ @ReactProp(name = "origin")
+ fun setOrigin(view: MapboxNavigationView, sources: ReadableArray?) {
+ if (sources == null) {
+ view.setOrigin(null)
+ return
}
+ view.setOrigin(Point.fromLngLat(sources.getDouble(0), sources.getDouble(1)))
+ }
- @ReactProp(name = "origin")
- fun setOrigin(view: MapboxNavigationView, sources: ReadableArray?) {
- if (sources == null) {
- view.setOrigin(null)
- return
- }
- view.setOrigin(Point.fromLngLat(sources.getDouble(0), sources.getDouble(1)))
+ @ReactProp(name = "destination")
+ fun setDestination(view: MapboxNavigationView, sources: ReadableArray?) {
+ if (sources == null) {
+ view.setDestination(null)
+ return
}
+ view.setDestination(Point.fromLngLat(sources.getDouble(0), sources.getDouble(1)))
+ }
- @ReactProp(name = "destination")
- fun setDestination(view: MapboxNavigationView, sources: ReadableArray?) {
- if (sources == null) {
- view.setDestination(null)
- return
- }
- view.setDestination(Point.fromLngLat(sources.getDouble(0), sources.getDouble(1)))
- }
+ @ReactProp(name = "shouldSimulateRoute")
+ fun setShouldSimulateRoute(view: MapboxNavigationView, shouldSimulateRoute: Boolean) {
+ view.setShouldSimulateRoute(shouldSimulateRoute)
+ }
- @ReactProp(name = "shouldSimulateRoute")
- fun setShouldSimulateRoute(view: MapboxNavigationView, shouldSimulateRoute: Boolean) {
- view.setShouldSimulateRoute(shouldSimulateRoute)
- }
+ @ReactProp(name = "showsEndOfRouteFeedback")
+ fun setShowsEndOfRouteFeedback(view: MapboxNavigationView, showsEndOfRouteFeedback: Boolean) {
+ view.setShowsEndOfRouteFeedback(showsEndOfRouteFeedback)
+ }
- @ReactProp(name = "showsEndOfRouteFeedback")
- fun setShowsEndOfRouteFeedback(view: MapboxNavigationView, showsEndOfRouteFeedback: Boolean) {
- view.setShowsEndOfRouteFeedback(showsEndOfRouteFeedback)
- }
+ @ReactProp(name = "mute")
+ fun setMute(view: MapboxNavigationView, mute: Boolean) {
+ view.setMute(mute)
+ }
- @ReactProp(name = "mute")
- fun setMute(view: MapboxNavigationView, mute: Boolean) {
- view.setMute(mute)
- }
-}
+ @ReactProp(name = "waypoints")
+ fun setWaypoints(view: MapboxNavigationView, waypointsArray: ReadableArray?) {
+ waypointsArray?.let {
+ val waypoints = mutableListOf()
+ for (i in 0 until it.size()) {
+ val waypointArray = it.getArray(i)
+ if (waypointArray !== null && waypointArray.size() >= 2) {
+ val longitude = waypointArray.getDouble(0)
+ val latitude = waypointArray.getDouble(1)
+ waypoints.add(Point.fromLngLat(longitude, latitude))
+ }
+ }
+
+ view.setWaypoints(waypoints)
+ }
+ }
+
+ @ReactProp(name = "vehicleMaxHeight")
+ fun setMaxHeight(view: MapboxNavigationView, height: Int?) {
+ if (height == null) {
+ view.setMaxHeight(1.6)
+ return
+ }
+ view.setMaxHeight(height?.toDouble())
+ }
+
+ @ReactProp(name = "vehicleMaxWidth")
+ fun setMaxWidth(view: MapboxNavigationView, width: Int?) {
+ if (width == null) {
+ view.setMaxWidth(1.9)
+ return
+ }
+ view.setMaxWidth(width?.toDouble())
+ }
+
+
+}
\ No newline at end of file
diff --git a/android/src/main/java/com/homee/mapboxnavigation/MapboxNavigationPackage.kt b/android/src/main/java/com/homee/mapboxnavigation/MapboxNavigationPackage.kt
index 4f8c5503..5358ed75 100644
--- a/android/src/main/java/com/homee/mapboxnavigation/MapboxNavigationPackage.kt
+++ b/android/src/main/java/com/homee/mapboxnavigation/MapboxNavigationPackage.kt
@@ -4,16 +4,13 @@ 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.*
class MapboxNavigationPackage : ReactPackage {
- override fun createNativeModules(reactContext: ReactApplicationContext): List {
- return emptyList()
- }
+ override fun createNativeModules(reactContext: ReactApplicationContext): List {
+ return emptyList()
+ }
- override fun createViewManagers(reactContext: ReactApplicationContext): List> {
- return Arrays.asList>(
- MapboxNavigationManager(reactContext)
- )
- }
+ override fun createViewManagers(reactContext: ReactApplicationContext): List> {
+ return listOf(MapboxNavigationManager(reactContext))
+ }
}
\ No newline at end of file
diff --git a/android/src/main/java/com/homee/mapboxnavigation/MapboxNavigationView.kt b/android/src/main/java/com/homee/mapboxnavigation/MapboxNavigationView.kt
index a4d41818..0da01ae5 100644
--- a/android/src/main/java/com/homee/mapboxnavigation/MapboxNavigationView.kt
+++ b/android/src/main/java/com/homee/mapboxnavigation/MapboxNavigationView.kt
@@ -87,9 +87,12 @@ class MapboxNavigationView(private val context: ThemedReactContext, private val
}
private var origin: Point? = null
+ private var waypoints: List? = null
private var destination: Point? = null
private var shouldSimulateRoute = false
private var showsEndOfRouteFeedback = false
+ private var maxHeight: Double? = null
+ private var maxWidth: Double? = null
/**
* Debug tool used to play, pause and seek route progress events that can be used to produce mocked location updates along the route.
*/
@@ -627,7 +630,13 @@ class MapboxNavigationView(private val context: ThemedReactContext, private val
mapboxNavigation.registerVoiceInstructionsObserver(voiceInstructionsObserver)
mapboxNavigation.registerRouteProgressObserver(replayProgressObserver)
- this.origin?.let { this.destination?.let { it1 -> this.findRoute(it, it1) } }
+ // Create a list of coordinates that includes origin, destination, and waypoints
+ val coordinatesList = mutableListOf()
+ this.origin?.let { coordinatesList.add(it) }
+ this.waypoints?.let { coordinatesList.addAll(it) }
+ this.destination?.let { coordinatesList.add(it) }
+
+ findRoute(coordinatesList)
}
override fun onDetachedFromWindow() {
@@ -649,16 +658,22 @@ class MapboxNavigationView(private val context: ThemedReactContext, private val
voiceInstructionsPlayer.shutdown()
}
- private fun findRoute(origin: Point, destination: Point) {
+ private fun findRoute(coordinates: List) {
try {
+ val routeOptionsBuilder = RouteOptions.builder()
+ .applyDefaultNavigationOptions()
+ .applyLanguageAndVoiceUnitOptions(context)
+ .coordinatesList(coordinates)
+ .profile(DirectionsCriteria.PROFILE_DRIVING)
+ .steps(true)
+
+ maxHeight?.let { routeOptionsBuilder.maxHeight(it) }
+ maxWidth?.let { routeOptionsBuilder.maxWidth(it) }
+
+ val routeOptions = routeOptionsBuilder.build()
+
mapboxNavigation.requestRoutes(
- RouteOptions.builder()
- .applyDefaultNavigationOptions()
- .applyLanguageAndVoiceUnitOptions(context)
- .coordinatesList(listOf(origin, destination))
- .profile(DirectionsCriteria.PROFILE_DRIVING)
- .steps(true)
- .build(),
+ routeOptions,
object : RouterCallback {
override fun onRoutesReady(
routes: List,
@@ -749,6 +764,10 @@ class MapboxNavigationView(private val context: ThemedReactContext, private val
this.origin = origin
}
+ fun setWaypoints(waypoints: List) {
+ this.waypoints = waypoints
+ }
+
fun setDestination(destination: Point?) {
this.destination = destination
}
@@ -764,4 +783,12 @@ class MapboxNavigationView(private val context: ThemedReactContext, private val
fun setMute(mute: Boolean) {
this.isVoiceInstructionsMuted = mute
}
-}
+
+ fun setMaxHeight(maxHeight: Double?) {
+ this.maxHeight = maxHeight
+ }
+
+ fun setMaxWidth(maxWidth: Double?) {
+ this.maxWidth = maxWidth
+ }
+}
\ No newline at end of file
diff --git a/android/src/main/res/layout/navigation_view.xml b/android/src/main/res/layout/navigation_view.xml
index a3d68a9e..d8629aaf 100644
--- a/android/src/main/res/layout/navigation_view.xml
+++ b/android/src/main/res/layout/navigation_view.xml
@@ -26,19 +26,20 @@
+ android:layout_gravity="fill|left"
+ android:layout_marginStart="16dp"
+ android:layout_marginTop="8dp" />
+ app:srcCompat="@android:drawable/ic_delete"
+ app:tint="@android:color/darker_gray" />
void;
- onRouteProgressChange?: (event: OnRouteProgressChangeEvent) => void;
- onError?: (event: OnErrorEvent) => void;
- onCancelNavigation?: () => void;
- onArrive?: () => void;
- showsEndOfRouteFeedback?: boolean;
- hideStatusView?: boolean;
- mute?: boolean;
+ origin: Coordinate;
+ destination: Coordinate;
+ shouldSimulateRoute?: boolean;
+ onLocationChange?: (event: OnLocationChangeEvent) => void;
+ onRouteProgressChange?: (event: OnRouteProgressChangeEvent) => void;
+ onError?: (event: OnErrorEvent) => void;
+ onCancelNavigation?: () => void;
+ onArrive?: () => void;
+ showsEndOfRouteFeedback?: boolean;
+ hideStatusView?: boolean;
+ mute?: boolean;
+ waypoints?: Coordinate[];
+ vehicleMaxHeight?: number;
+ vehicleMaxWidth?: number;
}
export {};
diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties
index 7665b0fa..b93c46a5 100755
--- a/example/android/gradle/wrapper/gradle-wrapper.properties
+++ b/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/example/ios/BasicApp.xcodeproj/project.pbxproj b/example/ios/BasicApp.xcodeproj/project.pbxproj
index 33137a91..f6d33fb2 100644
--- a/example/ios/BasicApp.xcodeproj/project.pbxproj
+++ b/example/ios/BasicApp.xcodeproj/project.pbxproj
@@ -564,7 +564,7 @@
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
- "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 ";
+ "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@@ -629,7 +629,7 @@
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
- "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 ";
+ "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
index 39778c91..109f6ac3 100644
--- a/example/ios/Podfile.lock
+++ b/example/ios/Podfile.lock
@@ -235,8 +235,8 @@ PODS:
- React-jsinspector (0.66.4)
- React-logger (0.66.4):
- glog
- - react-native-mapbox-navigation (1.1.0):
- - MapboxNavigation (~> 2.1.0)
+ - react-native-mapbox-navigation (2.0.1):
+ - MapboxNavigation (~> 2.1.1)
- React-Core
- React-perflogger (0.66.4)
- React-RCTActionSheet (0.66.4):
@@ -451,7 +451,7 @@ SPEC CHECKSUMS:
React-jsiexecutor: 94ce921e1d8ce7023366873ec371f3441383b396
React-jsinspector: d0374f7509d407d2264168b6d0fad0b54e300b85
React-logger: 933f80c97c633ee8965d609876848148e3fef438
- react-native-mapbox-navigation: 0966e03abd15664a2255a40f315c91e109a8a054
+ react-native-mapbox-navigation: 04e8379f8a2d308e5a292bdbc3a79ac883e2d1d4
React-perflogger: 93075d8931c32cd1fce8a98c15d2d5ccc4d891bd
React-RCTActionSheet: 7d3041e6761b4f3044a37079ddcb156575fb6d89
React-RCTAnimation: 743e88b55ac62511ae5c2e22803d4f503f2a3a13
@@ -470,4 +470,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: b825e0c0c2130ea0c4924baa443a786ab3686731
-COCOAPODS: 1.11.2
+COCOAPODS: 1.14.3
diff --git a/ios/MapboxNavigationManager.m b/ios/MapboxNavigationManager.m
index 7e4c8f1f..b18c5c7c 100644
--- a/ios/MapboxNavigationManager.m
+++ b/ios/MapboxNavigationManager.m
@@ -13,5 +13,8 @@ @interface RCT_EXTERN_MODULE(MapboxNavigationManager, RCTViewManager)
RCT_EXPORT_VIEW_PROPERTY(showsEndOfRouteFeedback, BOOL)
RCT_EXPORT_VIEW_PROPERTY(hideStatusView, BOOL)
RCT_EXPORT_VIEW_PROPERTY(mute, BOOL)
+RCT_EXPORT_VIEW_PROPERTY(waypoints, NSArray)
+RCT_EXPORT_VIEW_PROPERTY(vehicleMaxHeight, NSNumber)
+RCT_EXPORT_VIEW_PROPERTY(vehicleMaxWidth, NSNumber)
@end
diff --git a/ios/MapboxNavigationView.swift b/ios/MapboxNavigationView.swift
index aa361521..7ea058f9 100644
--- a/ios/MapboxNavigationView.swift
+++ b/ios/MapboxNavigationView.swift
@@ -24,6 +24,10 @@ class MapboxNavigationView: UIView, NavigationViewControllerDelegate {
@objc var origin: NSArray = [] {
didSet { setNeedsLayout() }
}
+
+ @objc var waypoints: NSArray = [] {
+ didSet { setNeedsLayout() }
+ }
@objc var destination: NSArray = [] {
didSet { setNeedsLayout() }
@@ -39,6 +43,8 @@ class MapboxNavigationView: UIView, NavigationViewControllerDelegate {
@objc var onError: RCTDirectEventBlock?
@objc var onCancelNavigation: RCTDirectEventBlock?
@objc var onArrive: RCTDirectEventBlock?
+ @objc var vehicleMaxHeight: NSNumber?
+ @objc var vehicleMaxWidth: NSNumber?
override init(frame: CGRect) {
self.embedded = false
@@ -74,9 +80,30 @@ class MapboxNavigationView: UIView, NavigationViewControllerDelegate {
let originWaypoint = Waypoint(coordinate: CLLocationCoordinate2D(latitude: origin[1] as! CLLocationDegrees, longitude: origin[0] as! CLLocationDegrees))
let destinationWaypoint = Waypoint(coordinate: CLLocationCoordinate2D(latitude: destination[1] as! CLLocationDegrees, longitude: destination[0] as! CLLocationDegrees))
+ var waypointsArray = [originWaypoint]
+
+ // Adding intermediate waypoints if any
+ for waypointArray in waypoints {
+ if let waypointCoordinates = waypointArray as? NSArray, waypointCoordinates.count == 2,
+ let lat = waypointCoordinates[1] as? CLLocationDegrees, let lon = waypointCoordinates[0] as? CLLocationDegrees {
+ let waypoint = Waypoint(coordinate: CLLocationCoordinate2D(latitude: lat, longitude: lon))
+ waypointsArray.append(waypoint)
+ }
+ }
+
+ waypointsArray.append(destinationWaypoint)
+
// let options = NavigationRouteOptions(waypoints: [originWaypoint, destinationWaypoint])
let options = NavigationRouteOptions(waypoints: [originWaypoint, destinationWaypoint], profileIdentifier: .automobileAvoidingTraffic)
+ if let vehicleMaxHeight = vehicleMaxHeight?.doubleValue {
+ options.includesMaxHeightOnMostRestrictiveBridge = true
+ options.maxHeight = vehicleMaxHeight
+ }
+ if let vehicleMaxWidth = vehicleMaxWidth?.doubleValue {
+ options.maxWidth = vehicleMaxWidth
+ }
+
Directions.shared.calculate(options) { [weak self] (_, result) in
guard let strongSelf = self, let parentVC = strongSelf.parentViewController else {
return
diff --git a/react-native-mapbox-navigation.podspec b/react-native-mapbox-navigation.podspec
index 387ebc41..4d42b3b5 100644
--- a/react-native-mapbox-navigation.podspec
+++ b/react-native-mapbox-navigation.podspec
@@ -39,13 +39,13 @@ Pod::Spec.new do |s|
s.homepage = "https://github.com/homeeondemand/react-native-mapbox-navigation"
s.license = { :type => "MIT", :file => "LICENSE" }
s.authors = { "HOMEE" => "support@homee.com" }
- s.platforms = { :ios => "11.0" }
+ s.platforms = { :ios => "12.4" }
s.source = { :git => "https://github.com/homeeondemand/react-native-mapbox-navigation.git", :tag => "#{s.version}" }
s.source_files = "ios/**/*.{h,m,swift}"
s.requires_arc = true
s.dependency "React-Core"
- s.dependency "MapboxNavigation", "~> 2.1.1"
+ s.dependency "MapboxNavigation", "~> 2.17.0"
end
diff --git a/src/typings.ts b/src/typings.ts
index 91c5cd0b..19ced945 100644
--- a/src/typings.ts
+++ b/src/typings.ts
@@ -37,4 +37,7 @@ export interface IMapboxNavigationProps {
showsEndOfRouteFeedback?: boolean;
hideStatusView?: boolean;
mute?: boolean;
+ waypoints?: Coordinate[];
+ vehicleMaxHeight?: number;
+ vehicleMaxWidth?: number;
}