Android 14 version
Hello team,
When I use navigation in android 14 through this error.
I/flutter (12851): The Dart VM service is listening on http://127.0.0.1:32815/uJBo6ChplKw=/ D/FlutterGeolocator(12851): Creating service. D/FlutterGeolocator(12851): Binding to location service. D/FlutterGeolocator(12851): Geolocator foreground service connected D/FlutterGeolocator(12851): Initializing Geolocator services D/FlutterGeolocator(12851): Flutter engine connected. Connected engine count 1 E/AndroidRuntime(12851): FATAL EXCEPTION: main E/AndroidRuntime(12851): Process: com.iconictek.cabtify, PID: 12851 E/AndroidRuntime(12851): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.iconictek.cabtify/com.eopeter.fluttermapboxnavigation.activity.NavigationActivity}: java.lang.SecurityException: com.iconictek.cabtify: One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn't being registered exclusively for system broadcasts E/AndroidRuntime(12851): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3782) E/AndroidRuntime(12851): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3922) E/AndroidRuntime(12851): at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103) E/AndroidRuntime(12851): at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139) E/AndroidRuntime(12851): at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96) E/AndroidRuntime(12851): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2443) E/AndroidRuntime(12851): at android.os.Handler.dispatchMessage(Handler.java:106) E/AndroidRuntime(12851): at android.os.Looper.loopOnce(Looper.java:205) E/AndroidRuntime(12851): at android.os.Looper.loop(Looper.java:294) E/AndroidRuntime(12851): at android.app.ActivityThread.main(ActivityThread.java:8177) E/AndroidRuntime(12851): at java.lang.reflect.Method.invoke(Native Method) E/AndroidRuntime(12851): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552) E/AndroidRuntime(12851): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971) E/AndroidRuntime(12851): Caused by: java.lang.SecurityException: com.iconictek.cabtify: One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn't being registered exclusively for system broadcasts E/AndroidRuntime(12851): at android.os.Parcel.createExceptionOrNull(Parcel.java:3057) E/AndroidRuntime(12851): at android.os.Parcel.createException(Parcel.java:3041) E/AndroidRuntime(12851): at android.os.Parcel.readException(Parcel.java:3024) E/AndroidRuntime(12851): at android.os.Parcel.readException(Parcel.java:2966) E/AndroidRuntime(12851): at android.app.IActivityManager$Stub$Proxy.registerReceiverWithFeature(IActivityManager.java:5684) E/AndroidRuntime(12851): at java.lang.reflect.Method.invoke(Native Method) E/AndroidRuntime(12851): at leakcanary.ServiceWatcher$install$4$2.invoke(ServiceWatcher.kt:93) E/AndroidRuntime(12851): at java.lang.reflect.Proxy.invoke(Proxy.java:1006) E/AndroidRuntime(12851): at $Proxy3.registerReceiverWithFeature(Unknown Source) E/AndroidRuntime(12851): at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1852) E/AndroidRuntime(12851): at android.app.ContextImpl.registerReceiver(ContextImpl.java:1792) E/AndroidRuntime(12851): at android.app.ContextImpl.registerReceiver(ContextImpl.java:1780) E/AndroidRuntime(12851): at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:755) E/AndroidRuntime(12851): at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:755) E/AndroidRuntime(12851): at com.eopeter.fluttermapboxnavigation.activity.NavigationActivity.onCreate(NavigationActivity.kt:142) E/AndroidRuntime(12851): at android.app.Activity.performCreate(Activity.java:8595) E/AndroidRuntime(12851): at android.app.Activity.performCreate(Activity.java:8573) E/AndroidRuntime(12851): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1456) E/AndroidRuntime(12851): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3764) E/AndroidRuntime(12851): ... 12 more E/AndroidRuntime(12851): Caused by: android.os.RemoteException: Remote stack trace: E/AndroidRuntime(12851): at com.android.server.am.ActivityManagerService.registerReceiverWithFeature(ActivityManagerService.java:13927) E/AndroidRuntime(12851): at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:2570) E/AndroidRuntime(12851): at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2720) E/AndroidRuntime(12851): at android.os.Binder.execTransactInternal(Binder.java:1339) E/AndroidRuntime(12851): at android.os.Binder.execTransact(Binder.java:1275) E/AndroidRuntime(12851):
Will be fixed when this is merged and published to pub.dev
https://github.com/eopeter/flutter_mapbox_navigation/pull/374/
For now can update this code in your locally stored pub-cache version of this package and reference it locally in your pubspec.yaml
Will be fixed when this is merged and published to pub.dev
For now can update this code in your locally stored pub-cache version of this package and reference it locally in your pubspec.yaml
can you please add more description to your suggestion
Hi @prof-sarumbo you need to update this file flutter_mapbox_navigation-0.2.2/android/src/main/kotlin/com/eopeter/fluttermapboxnavigation/activity/NavigationActivity.kt
to this `package com.eopeter.fluttermapboxnavigation.activity
import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.location.Location import android.os.Build import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import com.eopeter.fluttermapboxnavigation.FlutterMapboxNavigationPlugin import com.eopeter.fluttermapboxnavigation.R import com.eopeter.fluttermapboxnavigation.databinding.NavigationActivityBinding import com.eopeter.fluttermapboxnavigation.models.MapBoxEvents import com.eopeter.fluttermapboxnavigation.models.MapBoxRouteProgressEvent import com.eopeter.fluttermapboxnavigation.models.Waypoint import com.eopeter.fluttermapboxnavigation.models.WaypointSet import com.eopeter.fluttermapboxnavigation.utilities.CustomInfoPanelEndNavButtonBinder import com.eopeter.fluttermapboxnavigation.utilities.PluginUtilities import com.eopeter.fluttermapboxnavigation.utilities.PluginUtilities.Companion.sendEvent import com.google.gson.Gson import com.mapbox.api.directions.v5.models.DirectionsRoute import com.mapbox.api.directions.v5.models.RouteOptions import com.mapbox.geojson.Point import com.mapbox.maps.MapView import com.mapbox.maps.Style import com.mapbox.maps.plugin.gestures.OnMapLongClickListener import com.mapbox.maps.plugin.gestures.gestures import com.mapbox.navigation.base.extensions.applyDefaultNavigationOptions import com.mapbox.navigation.base.extensions.applyLanguageAndVoiceUnitOptions import com.mapbox.navigation.base.options.NavigationOptions import com.mapbox.navigation.base.route.NavigationRoute import com.mapbox.navigation.base.route.NavigationRouterCallback import com.mapbox.navigation.base.route.RouterFailure import com.mapbox.navigation.base.route.RouterOrigin import com.mapbox.navigation.base.trip.model.RouteLegProgress import com.mapbox.navigation.base.trip.model.RouteProgress import com.mapbox.navigation.core.arrival.ArrivalObserver import com.mapbox.navigation.core.directions.session.RoutesObserver import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp import com.mapbox.navigation.core.trip.session.BannerInstructionsObserver import com.mapbox.navigation.core.trip.session.LocationMatcherResult import com.mapbox.navigation.core.trip.session.LocationObserver import com.mapbox.navigation.core.trip.session.OffRouteObserver import com.mapbox.navigation.core.trip.session.RouteProgressObserver import com.mapbox.navigation.core.trip.session.VoiceInstructionsObserver import com.mapbox.navigation.dropin.map.MapViewObserver import com.mapbox.navigation.dropin.navigationview.NavigationViewListener import com.mapbox.navigation.utils.internal.ifNonNull
class NavigationActivity : AppCompatActivity() { private var finishBroadcastReceiver: BroadcastReceiver? = null private var addWayPointsBroadcastReceiver: BroadcastReceiver? = null private var points: MutableList<Waypoint> = mutableListOf() private var waypointSet: WaypointSet = WaypointSet() private var canResetRoute: Boolean = false private var accessToken: String? = null private var lastLocation: Location? = null private var isNavigationInProgress = false
private val navigationStateListener = object : NavigationViewListener() {
override fun onFreeDrive() {
// Handle free drive state
}
override fun onDestinationPreview() {
// Handle destination preview state
}
override fun onRoutePreview() {
// Handle route preview state
}
override fun onActiveNavigation() {
isNavigationInProgress = true
}
override fun onArrival() {
// Handle arrival state
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setTheme(R.style.Theme_AppCompat_NoActionBar)
binding = NavigationActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.navigationView.addListener(navigationStateListener)
accessToken =
PluginUtilities.getResourceFromContext(this.applicationContext, "mapbox_access_token")
val navigationOptions = NavigationOptions.Builder(this.applicationContext)
.accessToken(accessToken)
.build()
MapboxNavigationApp
.setup(navigationOptions)
.attach(this)
if (FlutterMapboxNavigationPlugin.longPressDestinationEnabled) {
binding.navigationView.registerMapObserver(onMapLongClick)
binding.navigationView.customizeViewOptions {
enableMapLongClickIntercept = false
}
}
val act = this
// Add custom view binders
binding.navigationView.customizeViewBinders {
infoPanelEndNavigationButtonBinder =
CustomInfoPanelEndNavButtonBinder(act)
}
MapboxNavigationApp.current()?.registerBannerInstructionsObserver(bannerInstructionObserver)
MapboxNavigationApp.current()?.registerVoiceInstructionsObserver(voiceInstructionObserver)
MapboxNavigationApp.current()?.registerOffRouteObserver(offRouteObserver)
MapboxNavigationApp.current()?.registerRoutesObserver(routesObserver)
MapboxNavigationApp.current()?.registerLocationObserver(locationObserver)
MapboxNavigationApp.current()?.registerRouteProgressObserver(routeProgressObserver)
MapboxNavigationApp.current()?.registerArrivalObserver(arrivalObserver)
finishBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
finish()
}
}
addWayPointsBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
//get waypoints
val stops = intent.getSerializableExtra("waypoints") as? MutableList<Waypoint>
val nextIndex = 1
if (stops != null) {
//append to points
if (points.count() >= nextIndex)
points.addAll(nextIndex, stops)
else
points.addAll(stops)
}
}
}
// Register broadcast receivers with appropriate flags for Android 14
ContextCompat.registerReceiver(
this,
finishBroadcastReceiver,
IntentFilter(NavigationLauncher.KEY_STOP_NAVIGATION),
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
ContextCompat.RECEIVER_NOT_EXPORTED
} else {
ContextCompat.RECEIVER_EXPORTED
}
)
ContextCompat.registerReceiver(
this,
addWayPointsBroadcastReceiver,
IntentFilter(NavigationLauncher.KEY_ADD_WAYPOINTS),
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
ContextCompat.RECEIVER_NOT_EXPORTED
} else {
ContextCompat.RECEIVER_EXPORTED
}
)
// Set the style Uri
var styleUrlDay = FlutterMapboxNavigationPlugin.mapStyleUrlDay
var styleUrlNight = FlutterMapboxNavigationPlugin.mapStyleUrlNight
if (styleUrlDay == null) styleUrlDay = Style.MAPBOX_STREETS
if (styleUrlNight == null) styleUrlNight = Style.DARK
// set map style
binding.navigationView.customizeViewOptions {
mapStyleUriDay = styleUrlDay
mapStyleUriNight = styleUrlNight
}
if (FlutterMapboxNavigationPlugin.enableFreeDriveMode) {
binding.navigationView.api.routeReplayEnabled(FlutterMapboxNavigationPlugin.simulateRoute)
binding.navigationView.api.startFreeDrive()
return
}
val p = intent.getSerializableExtra("waypoints") as? MutableList<Waypoint>
if (p != null) points = p
points.map { waypointSet.add(it) }
requestRoutes(waypointSet)
}
override fun onDestroy() {
super.onDestroy()
if (FlutterMapboxNavigationPlugin.longPressDestinationEnabled) {
binding.navigationView.unregisterMapObserver(onMapLongClick)
}
binding.navigationView.removeListener(navigationStateListener)
MapboxNavigationApp.current()?.unregisterBannerInstructionsObserver(bannerInstructionObserver)
MapboxNavigationApp.current()?.unregisterVoiceInstructionsObserver(voiceInstructionObserver)
MapboxNavigationApp.current()?.unregisterOffRouteObserver(offRouteObserver)
MapboxNavigationApp.current()?.unregisterRoutesObserver(routesObserver)
MapboxNavigationApp.current()?.unregisterLocationObserver(locationObserver)
MapboxNavigationApp.current()?.unregisterRouteProgressObserver(routeProgressObserver)
MapboxNavigationApp.current()?.unregisterArrivalObserver(arrivalObserver)
// Unregister receivers
finishBroadcastReceiver?.let { unregisterReceiver(it) }
addWayPointsBroadcastReceiver?.let { unregisterReceiver(it) }
}
fun tryCancelNavigation() {
if (isNavigationInProgress) {
isNavigationInProgress = false
sendEvent(MapBoxEvents.NAVIGATION_CANCELLED)
}
}
private fun requestRoutes(waypointSet: WaypointSet) {
sendEvent(MapBoxEvents.ROUTE_BUILDING)
MapboxNavigationApp.current()!!.requestRoutes(
routeOptions = RouteOptions
.builder()
.applyDefaultNavigationOptions()
.applyLanguageAndVoiceUnitOptions(this)
.coordinatesList(waypointSet.coordinatesList())
.waypointIndicesList(waypointSet.waypointsIndices())
.waypointNamesList(waypointSet.waypointsNames())
.language(FlutterMapboxNavigationPlugin.navigationLanguage)
.alternatives(FlutterMapboxNavigationPlugin.showAlternateRoutes)
.voiceUnits(FlutterMapboxNavigationPlugin.navigationVoiceUnits)
.bannerInstructions(FlutterMapboxNavigationPlugin.bannerInstructionsEnabled)
.voiceInstructions(FlutterMapboxNavigationPlugin.voiceInstructionsEnabled)
.steps(true)
.build(),
callback = object : NavigationRouterCallback {
override fun onCanceled(routeOptions: RouteOptions, routerOrigin: RouterOrigin) {
sendEvent(MapBoxEvents.ROUTE_BUILD_CANCELLED)
}
override fun onFailure(reasons: List<RouterFailure>, routeOptions: RouteOptions) {
sendEvent(MapBoxEvents.ROUTE_BUILD_FAILED)
}
override fun onRoutesReady(
routes: List<NavigationRoute>,
routerOrigin: RouterOrigin
) {
sendEvent(
MapBoxEvents.ROUTE_BUILT,
Gson().toJson(routes.map { it.directionsRoute.toJson() })
)
if (routes.isEmpty()) {
sendEvent(MapBoxEvents.ROUTE_BUILD_NO_ROUTES_FOUND)
return
}
binding.navigationView.api.routeReplayEnabled(FlutterMapboxNavigationPlugin.simulateRoute)
binding.navigationView.api.startActiveGuidance(routes)
}
}
)
}
private fun addWaypoint(destination: Point, name: String?) {
val originLocation = lastLocation
val originPoint = originLocation?.let {
Point.fromLngLat(it.longitude, it.latitude)
} ?: return
// we always start a route from the current location
if (addedWaypoints.isEmpty) {
addedWaypoints.add(Waypoint(originPoint))
}
if (!name.isNullOrBlank()) {
addedWaypoints.add(Waypoint(name, destination))
} else {
addedWaypoints.add(Waypoint(destination, true))
}
MapboxNavigationApp.current()!!.requestRoutes(
routeOptions = RouteOptions
.builder()
.applyDefaultNavigationOptions()
.applyLanguageAndVoiceUnitOptions(this)
.coordinatesList(addedWaypoints.coordinatesList())
.waypointIndicesList(addedWaypoints.waypointsIndices())
.waypointNamesList(addedWaypoints.waypointsNames())
.alternatives(true)
.build(),
callback = object : NavigationRouterCallback {
override fun onRoutesReady(
routes: List<NavigationRoute>,
routerOrigin: RouterOrigin
) {
sendEvent(
MapBoxEvents.ROUTE_BUILT,
Gson().toJson(routes.map { it.directionsRoute.toJson() })
)
binding.navigationView.api.routeReplayEnabled(true)
binding.navigationView.api.startActiveGuidance(routes)
}
override fun onFailure(
reasons: List<RouterFailure>,
routeOptions: RouteOptions
) {
sendEvent(MapBoxEvents.ROUTE_BUILD_FAILED)
}
override fun onCanceled(routeOptions: RouteOptions, routerOrigin: RouterOrigin) {
sendEvent(MapBoxEvents.ROUTE_BUILD_CANCELLED)
}
}
)
}
private val routeProgressObserver = RouteProgressObserver { routeProgress ->
//Notify the client
val progressEvent = MapBoxRouteProgressEvent(routeProgress)
FlutterMapboxNavigationPlugin.distanceRemaining = routeProgress.distanceRemaining
FlutterMapboxNavigationPlugin.durationRemaining = routeProgress.durationRemaining
sendEvent(progressEvent)
}
private val arrivalObserver: ArrivalObserver = object : ArrivalObserver {
override fun onFinalDestinationArrival(routeProgress: RouteProgress) {
isNavigationInProgress = false
sendEvent(MapBoxEvents.ON_ARRIVAL)
}
override fun onNextRouteLegStart(routeLegProgress: RouteLegProgress) {
// Handle next route leg start
}
override fun onWaypointArrival(routeProgress: RouteProgress) {
// Handle waypoint arrival
}
}
private val locationObserver = object : LocationObserver {
override fun onNewLocationMatcherResult(locationMatcherResult: LocationMatcherResult) {
lastLocation = locationMatcherResult.enhancedLocation
}
override fun onNewRawLocation(rawLocation: Location) {
// no impl
}
}
private val bannerInstructionObserver = BannerInstructionsObserver { bannerInstructions ->
sendEvent(MapBoxEvents.BANNER_INSTRUCTION, bannerInstructions.primary().text())
}
private val voiceInstructionObserver = VoiceInstructionsObserver { voiceInstructions ->
sendEvent(MapBoxEvents.SPEECH_ANNOUNCEMENT, voiceInstructions.announcement().toString())
}
private val offRouteObserver = OffRouteObserver { offRoute ->
if (offRoute) {
sendEvent(MapBoxEvents.USER_OFF_ROUTE)
}
}
private val routesObserver = RoutesObserver { routeUpdateResult ->
if (routeUpdateResult.navigationRoutes.isNotEmpty()) {
sendEvent(MapBoxEvents.REROUTE_ALONG)
}
}
private val onMapLongClick = object : MapViewObserver(), OnMapLongClickListener {
override fun onAttached(mapView: MapView) {
mapView.gestures.addOnMapLongClickListener(this)
}
override fun onDetached(mapView: MapView) {
mapView.gestures.removeOnMapLongClickListener(this)
}
override fun onMapLongClick(point: Point): Boolean {
ifNonNull(lastLocation) {
val waypointSet = WaypointSet()
waypointSet.add(Waypoint(Point.fromLngLat(it.longitude, it.latitude)))
waypointSet.add(Waypoint(point))
requestRoutes(waypointSet)
}
return false
}
}
private lateinit var binding: NavigationActivityBinding
private val addedWaypoints = WaypointSet()
}`