flutter_mapbox_navigation

repository·master·Indexed 42 days ago

https://github.com/eopeter/flutter_mapbox_navigation

A Flutter plugin providing a full-fledged turn-by-turn navigation UI and engine using Mapbox. It supports driving, cycling, and walking directions with traffic avoidance and voice instructions. The library offers both a singleton MapBoxNavigation instance for full-screen navigation and a MapBoxNavigationView widget for embedding navigation into a custom widget tree via a MapBoxNavigationViewController.

Tokens
8K
Snippets
28
Records
31
Agent score
54%

What's inside flutter_mapbox_navigation

  1. Use the flutter_mapbox_navigation_example for implementation guidance

    master
    The flutter_mapbox_navigation_example project serves as a complete reference implementation for the flutter_mapbox_navigation plugin. Developers can use this example project to understand how to integrate the plugin into a Flutter application, observe the correct setup for Android and iOS, and see how the navigation APIs are invoked in a real-world context.
  2. Customize the iOS launch screen assets

    master

    To customize the launch screen for your iOS application, replace the image files located in the example/ios/Runner/Assets.xcassets/LaunchImage.imageset/ directory with your own assets.

    Alternatively, you can manage these assets using Xcode:

    1. Open your Flutter project's iOS workspace using open ios/Runner.xcworkspace.
    2. In the Xcode Project Navigator, select Runner/Assets.xcassets.
    3. Drag and drop your desired images into the asset catalog.
    open ios/Runner.xcworkspace
  3. Configure iOS for Mapbox Navigation

    master

    Setting up iOS requires configuring access tokens, location permissions, and background modes.

    1. Mapbox Access Token: Create an access token with DOWNLOADS:READ scope. Add it to your .netrc file in your home directory:
    machine api.mapbox.com
      login mapbox
      password PRIVATE_MAPBOX_API_TOKEN
    1. App Target Configuration: In your project editor, set MBXAccessToken to your Mapbox access token under 'Custom iOS Target Properties' in the Info tab.

    2. Location Permissions: Set NSLocationWhenInUseUsageDescription to: Shows your location on the map and helps improve OpenStreetMap.

    3. Background Modes: Enable Audio, AirPlay, and Picture in Picture and Location updates in the Capabilities tab (or add audio and location to the UIBackgroundModes array in Info.plist).

    4. Embedded Views: If embedding the navigation view, add io.flutter.embedded_views_preview set to <true/> in your info.plist.

    <dict>
        <key>io.flutter.embedded_views_preview</key>
        <true/>
    </dict>
  4. Embed MapBoxNavigationView in your widget tree

    master

    Instead of using the full-screen navigation UI, you can embed the navigation view into your own widget tree using MapBoxNavigationView and a MapBoxNavigationViewController.

    1. Declare a controller: MapBoxNavigationViewController _controller;
    2. Add the widget: Use MapBoxNavigationView and capture the controller in the onCreated callback.
    3. Build and Start: Use the controller to buildRoute(wayPoints: ...) and then startNavigation().
    MapBoxNavigationView(
      options: _options,
      onRouteEvent: _onRouteEvent,
      onCreated: (MapBoxNavigationViewController controller) async {
        _controller = controller;
      },
    )
    MapBoxNavigationView(
        options: _options,
        onRouteEvent: _onRouteEvent,
        onCreated: (MapBoxNavigationViewController controller) async {
          _controller = controller;
        }),
  5. Configure Android for Mapbox Navigation

    master

    Android setup involves adding access tokens, permissions, and updating the Activity type.

    1. Access Token: Create <YOUR_FLUTTER_APP_ROOT>/android/app/src/main/res/values/mapbox_access_token.xml with the following content:
    <?xml version="1.0" encoding="utf-8"?>
    <resources xmlns:tools="http://schemas.android.com/tools">
        <string name="mapbox_access_token" translatable="false" tools:ignore="UnusedResources">ADD_MAPBOX_ACCESS_TOKEN_HERE</string>
    </resources>
    1. Permissions: Add these to your app-level AndroidManifest.xml:
    • android.permission.ACCESS_COARSE_LOCATION
    • android.permission.ACCESS_FINE_LOCATION
    • android.permission.ACCESS_NETWORK_STATE
    1. Downloads Token: Add MAPBOX_DOWNLOADS_TOKEN=sk.XXXXXXXXXXXXXXX to your gradle.properties file (ideally in your $USER_HOME/.gradle to keep it private).

    2. MainActivity Update: Change MainActivity to extend FlutterFragmentActivity instead of FlutterActivity to avoid IllegalStateException regarding ViewModelStoreOwner.

    3. Kotlin BOM: Add implementation platform("org.jetbrains.kotlin:kotlin-bom:1.8.0") to android/app/build.gradle.

    //import io.flutter.embedding.android.FlutterActivity
    import io.flutter.embedding.android.FlutterFragmentActivity
    
    class MainActivity: FlutterFragmentActivity() {
    }
  6. Understand the RouteEvent model

    master

    The RouteEvent class is used to receive updates from the navigation service. It encapsulates the type of event that occurred and provides associated data. The eventType is a MapBoxEvent enum, and the data field contains payload information that varies depending on the event type:

    • MapBoxEvent.progress_change: The data field contains a RouteProgressEvent object.
    • MapBoxEvent.navigation_finished: The data field contains a MapBoxFeedback object (parsed from a JSON string).
    • MapBoxEvent.on_map_tap: The data field contains a WayPoint object (parsed from a JSON string on iOS or directly from a Map on Android).
    • Other events: The data field contains a JSON-encoded string of the event data.
    // Example of how RouteEvent structure maps to data types:
    // If eventType == MapBoxEvent.progress_change -> data is RouteProgressEvent
    // If eventType == MapBoxEvent.navigation_finished -> data is MapBoxFeedback
    // If eventType == MapBoxEvent.on_map_tap -> data is WayPoint
  7. Use MapBoxNavigation to manage turn-by-turn navigation

    master

    The MapBoxNavigation class is a singleton provider used to start, manage, and end navigation sessions. You access it via MapBoxNavigation.instance.

    Key capabilities include:

    • Starting turn-by-turn navigation with specific waypoints.
    • Starting 'Free-drive' mode (passive navigation without a set destination).
    • Adding waypoints to an active navigation session.
    • Monitoring remaining distance and duration.
    • Registering event listeners for route updates.
    // Access the singleton instance
    final navigation = MapBoxNavigation.instance;
    
    // Start navigation with waypoints
    await navigation.startNavigation(
      wayPoints: [startPoint, destinationPoint],
      options: myOptions,
    );
  8. Understand the RouteStep model

    master

    A RouteStep object represents a single distinct maneuver along a route and the approach to the next maneuver. It corresponds to a single instruction the user must follow to complete a portion of the route (e.g., "Turn left, then follow the road").

    Key properties include:

    • name: The name of the step.
    • instructions: The textual instruction for the user.
    • distance: The distance to the next maneuver.
    • expectedTravelTime: The estimated time to complete the step.
    // Example of what a RouteStep represents
    final step = RouteStep(
      'Turn Left',
      'Turn left onto Main Street',
      150.0,
      30.0,
    );
  9. Use MapBoxNavigation to start turn-by-turn navigation

    master

    To start navigation, define a list of WayPoint objects and call startNavigation on the MapBoxNavigation.instance.

    final cityhall = WayPoint(name: "City Hall", latitude: 42.886448, longitude: -78.878372);
    final downtown = WayPoint(name: "Downtown Buffalo", latitude: 42.8866177, longitude: -78.8814924);
    
    var wayPoints = List<WayPoint>();
    wayPoints.add(cityhall);
    wayPoints.add(downtown);
    
    await MapBoxNavigation.instance.startNavigation(wayPoints: wayPoints);
  10. Configure MapBoxNavigation default options

    master

    You can set global default options for the navigation experience using MapBoxNavigation.instance.setDefaultOptions with a MapBoxOptions object.

    Key properties include:

    • initialLatitude, initialLongitude, zoom
    • mode: e.g., MapBoxNavigationMode.drivingWithTraffic
    • mapStyleUrlDay, mapStyleUrlNight
    • voiceInstructionsEnabled, bannerInstructionsEnabled
    • units: e.g., VoiceUnits.imperial
    MapBoxNavigation.instance.setDefaultOptions(MapBoxOptions(
                     initialLatitude: 36.1175275,
                     initialLongitude: -115.1839524,
                     zoom: 13.0,
                     tilt: 0.0,
                     bearing: 0.0,
                     enableRefresh: false,
                     alternatives: true,
                     voiceInstructionsEnabled: true,
                     bannerInstructionsEnabled: true,
                     allowsUTurnAtWayPoints: true,
                     mode: MapBoxNavigationMode.drivingWithTraffic,
                     mapStyleUrlDay: "https://url_to_day_style",
                     mapStyleUrlNight: "https://url_to_night_style",
                     units: VoiceUnits.imperial,
                     simulateRoute: true,
                     language: "en"))
  11. Listen to MapBox Navigation events

    master

    Register a route event listener using MapBoxNavigation.instance.registerRouteEventListener to react to navigation changes like progress, route building, or arrival.

    Common event types include:

    • MapBoxEvent.progress_change: Provides RouteProgressEvent containing arrival status and current step instructions.
    • MapBoxEvent.route_building / MapBoxEvent.route_built: Indicates route calculation status.
    • MapBoxEvent.navigation_running: Indicates navigation has started.
    • MapBoxEvent.on_arrival: Triggered when the destination is reached.
    • MapBoxEvent.navigation_finished / MapBoxEvent.navigation_cancelled: Indicates navigation has ended.
    MapBoxNavigation.instance.registerRouteEventListener(_onRouteEvent);
    
    Future<void> _onRouteEvent(e) async {
      switch (e.eventType) {
        case MapBoxEvent.progress_change:
          var progressEvent = e.data as RouteProgressEvent;
          _arrived = progressEvent.arrived;
          if (progressEvent.currentStepInstruction != null)
            _instruction = progressEvent.currentStepInstruction;
          break;
        case MapBoxEvent.navigation_running:
          _isNavigating = true;
          break;
        // ... other cases
      }
    }