ionic-planb-logistic-app-fl.../GOOGLE_NAVIGATION_SETUP.md
Jean-Philippe Brule 46af8f55a2 Implement Google Navigation Flutter integration for turn-by-turn delivery navigation
Adds complete Google Navigation support with:
- LocationPermissionService for runtime location permissions
- NavigationSessionService for session and route management
- NavigationPage for full-screen turn-by-turn navigation UI
- NavigationTermsAndConditionsDialog for service acceptance
- Comprehensive i18n support (English/French)
- Android minSdk=23 with Java NIO desugaring
- iOS location permissions in Info.plist
- Error handling with user-friendly dialogs
- Location update and arrival notifications

Includes detailed setup guide and implementation documentation with API key
configuration instructions, integration examples, and testing checklist.

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 20:43:29 -05:00

9.8 KiB

Google Navigation Flutter Setup Guide

This document provides detailed instructions for completing the Google Navigation Flutter implementation.

Overview

The implementation includes:

  • Location permissions handling with user dialogs
  • Google Navigation session management
  • Turn-by-turn navigation for delivery destinations
  • Terms and Conditions acceptance for navigation services
  • i18n support (English/French)
  • Proper error handling and logging

Prerequisites

Before implementing, you need:

  1. Google Cloud Project with Navigation SDK enabled
  2. API Keys for both Android and iOS platforms
  3. Configuration in Android and iOS native files

Part 1: API Key Configuration

Android Setup

  1. Open android/app/build.gradle.kts
  2. Add your Android API key to the metadata section in AndroidManifest.xml:
<application>
  <meta-data
      android:name="com.google.android.geo.API_KEY"
      android:value="YOUR_ANDROID_API_KEY" />
</application>

Alternatively, use Secrets Gradle Plugin for better security:

// In android/app/build.gradle.kts
android {
  buildTypes {
    debug {
      manifestPlaceholders = [googleMapsApiKey: "YOUR_ANDROID_API_KEY"]
    }
    release {
      manifestPlaceholders = [googleMapsApiKey: "YOUR_ANDROID_API_KEY_RELEASE"]
    }
  }
}

Then in AndroidManifest.xml:

<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="${googleMapsApiKey}" />

iOS Setup

  1. Open ios/Runner/AppDelegate.swift
  2. The API key is already configured in the provideAPIKey() method:
import GoogleMaps

@main
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GMSServices.provideAPIKey("YOUR_IOS_API_KEY")
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

Replace YOUR_IOS_API_KEY with your actual Google Cloud Navigation API key.

Part 2: Integration with Deliveries Page

To add navigation button to deliveries, update lib/pages/deliveries_page.dart:

import '../pages/navigation_page.dart';

// In your delivery item or action menu:
ElevatedButton(
  onPressed: () {
    Navigator.of(context).push(
      MaterialPageRoute(
        builder: (context) => NavigationPage(
          delivery: delivery,
          destinationLatitude: delivery.latitude,
          destinationLongitude: delivery.longitude,
          onNavigationComplete: () {
            // Handle navigation completion
            // Update delivery status
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(
                content: Text(
                  AppLocalizations.of(context)?.navigationArrived ??
                      'Navigation completed',
                ),
              ),
            );
          },
          onNavigationCancelled: () {
            // Handle cancellation
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(
                content: Text(
                  AppLocalizations.of(context)?.cancel ?? 'Navigation cancelled',
                ),
              ),
            );
          },
        ),
      ),
    );
  },
  child: Text(AppLocalizations.of(context)?.navigateToAddress ?? 'Navigate'),
)

Part 3: Location Permissions

The app uses the permission_handler package for location permissions. Permissions are already configured in:

  • Android: android/app/src/main/AndroidManifest.xml

    • Required: INTERNET, ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION
    • Optional background modes for continuous navigation
  • iOS: ios/Runner/Info.plist

    • NSLocationWhenInUseUsageDescription: When app is active
    • NSLocationAlwaysAndWhenInUseUsageDescription: Always
    • NSLocationAlwaysUsageDescription: Background location
    • Background mode: "location" enabled

Part 4: Available Classes and Services

NavigationPage

Main UI widget for turn-by-turn navigation.

NavigationPage(
  delivery: deliveryObject,
  destinationLatitude: 33.5731,
  destinationLongitude: -7.5898,
  onNavigationComplete: () { /* Handle arrival */ },
  onNavigationCancelled: () { /* Handle cancellation */ },
)

LocationPermissionService

Handles location permission requests and checks.

final permissionService = LocationPermissionService();

// Check current permission status
final hasPermission = await permissionService.hasLocationPermission();

// Request permission
final result = await permissionService.requestLocationPermission();
result.when(
  granted: () { /* Permission granted */ },
  denied: () { /* Permission denied */ },
  permanentlyDenied: () { /* Need to open settings */ },
  error: (message) { /* Handle error */ },
);

NavigationSessionService

Manages the Google Navigation session lifecycle.

final sessionService = NavigationSessionService();

// Initialize session
await sessionService.initializeSession();

// Set controller from the navigation view
await sessionService.setController(navigationViewController);

// Calculate and set route
final route = await sessionService.calculateRoute(
  startLatitude: 33.5731,
  startLongitude: -7.5898,
  destinationLatitude: 33.5745,
  destinationLongitude: -7.5850,
);

// Listen to events
sessionService.addArrivalListener((info) {
  print('Arrived at destination');
});

sessionService.addLocationListener((location) {
  print('Location: ${location.latitude}, ${location.longitude}');
});

// Start/stop navigation
await sessionService.startNavigation();
await sessionService.stopNavigation();

// Cleanup when done
await sessionService.cleanup();

NavigationTermsAndConditionsDialog

Dialog component to show T&C for navigation services.

showDialog(
  context: context,
  builder: (context) => NavigationTermsAndConditionsDialog(
    onAccept: () {
      // Save acceptance and proceed with navigation
    },
    onDecline: () {
      // User declined, don't start navigation
    },
  ),
);

Part 5: Error Handling

The implementation includes comprehensive error handling for:

  1. Location Permission Errors

    • Permission denied
    • Permission permanently denied
    • System errors
  2. Navigation Initialization Errors

    • Session initialization failure
    • Controller not available
    • Route calculation failure
  3. Runtime Errors

    • Network issues
    • Location acquisition timeout
    • Navigation start/stop failures

All errors are displayed through user-friendly dialogs with action buttons.

Part 6: Internationalization

Navigation strings are available in English and French:

  • navigationTcTitle, navigationTcDescription
  • locationPermissionRequired, locationPermissionMessage
  • navigationArrived, navigatingTo

Add custom translations to lib/l10n/app_*.arb files as needed.

Part 7: Testing Checklist

Android Testing

  • Test on API level 23+ device
  • Verify minSdk=23 is set
  • Check desugaring is enabled
  • Test location permissions request
  • Verify navigation starts correctly
  • Test with GPS disabled/enabled
  • Verify Terms & Conditions dialog shows

iOS Testing

  • Test on iOS 16.0+ device
  • Verify Info.plist has all location keys
  • Test location permissions request
  • Verify background location mode is enabled
  • Test navigation with map open
  • Verify arrival notification
  • Check attribution text is visible

Common Issues and Solutions

Issue: "Navigation SDK not available"

  • Solution: Verify API key is correctly added and Navigation SDK is enabled in Google Cloud Console

Issue: "Location permission always denied"

  • Solution: Clear app data and reinstall, or open app settings and manually enable location

Issue: "Navigation session fails to initialize"

  • Solution: Check that controller is properly created before calling methods

Issue: "Routes not calculating"

  • Solution: Ensure start and destination coordinates are valid and within service areas

Part 8: Production Considerations

Before releasing to production:

  1. API Key Security

    • Use separate API keys for Android and iOS
    • Restrict API keys by platform and package name
    • Rotate keys periodically
  2. Analytics

    • Track navigation start/completion rates
    • Monitor location permission denial rates
    • Log any navigation errors
  3. User Experience

    • Provide clear instructions for permission requests
    • Show progress during initialization
    • Handle network failures gracefully
  4. Compliance

    • Ensure proper attribution to Google
    • Display Terms & Conditions for navigation
    • Comply with EEA data regulations if applicable

Files Created/Modified

Created Files

  • lib/services/location_permission_service.dart - Permission handling
  • lib/services/navigation_session_service.dart - Session management
  • lib/pages/navigation_page.dart - Navigation UI
  • lib/components/navigation_tc_dialog.dart - T&C dialog

Modified Files

  • android/app/build.gradle.kts - Added minSdk=23, desugaring
  • ios/Podfile - iOS configuration (already set)
  • ios/Runner/Info.plist - Location permissions (updated)
  • lib/l10n/app_en.arb - English translations
  • lib/l10n/app_fr.arb - French translations

Next Steps

  1. Add your API keys to Android and iOS configurations
  2. Test location permissions flow
  3. Integrate navigation button into delivery items
  4. Test navigation on real devices
  5. Monitor and handle edge cases in production

For more information, refer to: