Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class _NavigationSampleState extends State<NavigationSample> {
);
}
// Note: make sure user has also granted location permissions before starting navigation session.
await GoogleMapsNavigator.initializeNavigationSession();
await GoogleMapsNavigator.initializeNavigationSession(taskRemovedBehavior: TaskRemovedBehavior.continueService);
setState(() {
_navigationSessionInitialized = true;
});
Expand Down Expand Up @@ -158,6 +158,15 @@ class _NavigationSampleState extends State<NavigationSample> {
}
```

#### Task Removed Behavior

The `taskRemovedBehavior` parameter of navigation session initialization defines how the navigation should behave when a task is removed from the recent apps list on Android. It can either:

- `TaskRemovedBehavior.continueService`: Continue running in the background. (default)
- `TaskRemovedBehavior.quitService`: Shut down immediately.

This parameter has only an effect on Android.

### Add a map view

```dart
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import com.google.android.libraries.navigation.NavigationRoadStretchRenderingDat
import com.google.android.libraries.navigation.NavigationTrafficData
import com.google.android.libraries.navigation.Navigator
import com.google.android.libraries.navigation.Navigator.AudioGuidance
import com.google.android.libraries.navigation.Navigator.TaskRemovedBehavior
import com.google.android.libraries.navigation.RouteSegment
import com.google.android.libraries.navigation.RoutingOptions
import com.google.android.libraries.navigation.RoutingOptions.RoutingStrategy
Expand Down Expand Up @@ -1055,4 +1056,14 @@ object Convert {
ImageDescriptorDto()
}
}

fun taskRemovedBehaviorDtoToTaskRemovedBehavior(
behavior: TaskRemovedBehaviorDto?
): @TaskRemovedBehavior Int {
return when (behavior) {
TaskRemovedBehaviorDto.CONTINUESERVICE -> TaskRemovedBehavior.CONTINUE_SERVICE
TaskRemovedBehaviorDto.QUITSERVICE -> TaskRemovedBehavior.QUIT_SERVICE
else -> TaskRemovedBehavior.CONTINUE_SERVICE
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import com.google.android.libraries.navigation.NavigationApi.NavigatorListener
import com.google.android.libraries.navigation.NavigationUpdatesOptions
import com.google.android.libraries.navigation.NavigationUpdatesOptions.GeneratedStepImagesType
import com.google.android.libraries.navigation.Navigator
import com.google.android.libraries.navigation.Navigator.TaskRemovedBehavior
import com.google.android.libraries.navigation.RoadSnappedLocationProvider
import com.google.android.libraries.navigation.RouteSegment
import com.google.android.libraries.navigation.RoutingOptions
Expand All @@ -43,7 +44,6 @@ import com.google.android.libraries.navigation.TermsAndConditionsUIParams
import com.google.android.libraries.navigation.TimeAndDistance
import com.google.android.libraries.navigation.Waypoint
import com.google.maps.flutter.navigation.Convert.convertTravelModeFromDto
import com.google.maps.flutter.navigation.GoogleMapsNavigationSessionManager.Companion.navigationReadyListener
import io.flutter.plugin.common.BinaryMessenger
import java.lang.ref.WeakReference

Expand Down Expand Up @@ -117,6 +117,7 @@ private constructor(private val navigationSessionEventApi: NavigationSessionEven
private var weakActivity: WeakReference<Activity>? = null
private var turnByTurnEventsEnabled: Boolean = false
private var weakLifecycleOwner: WeakReference<LifecycleOwner>? = null
private var taskRemovedBehavior: @TaskRemovedBehavior Int = 0

override fun onCreate(owner: LifecycleOwner) {
weakLifecycleOwner = WeakReference(owner)
Expand Down Expand Up @@ -170,6 +171,7 @@ private constructor(private val navigationSessionEventApi: NavigationSessionEven
/** Creates Navigator instance. */
fun createNavigationSession(
abnormalTerminationReportingEnabled: Boolean,
behavior: TaskRemovedBehaviorDto,
callback: (Result<Unit>) -> Unit,
) {
if (navigator != null) {
Expand All @@ -180,6 +182,7 @@ private constructor(private val navigationSessionEventApi: NavigationSessionEven
callback(Result.success(Unit))
return
}
taskRemovedBehavior = Convert.taskRemovedBehaviorDtoToTaskRemovedBehavior(behavior)

// Align API behavior with iOS:
// If the terms haven't yet been accepted throw an error.
Expand All @@ -202,6 +205,7 @@ private constructor(private val navigationSessionEventApi: NavigationSessionEven
object : NavigatorListener {
override fun onNavigatorReady(newNavigator: Navigator) {
navigator = newNavigator
navigator?.setTaskRemovedBehavior(taskRemovedBehavior)
registerNavigationListeners()
isNavigationSessionInitialized = true
navigationReadyListener?.onNavigationReady(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ class GoogleMapsNavigationSessionMessageHandler : NavigationSessionApi {

override fun createNavigationSession(
abnormalTerminationReportingEnabled: Boolean,
behavior: TaskRemovedBehaviorDto,
callback: (Result<Unit>) -> Unit,
) {
manager().createNavigationSession(abnormalTerminationReportingEnabled, callback)
manager().createNavigationSession(abnormalTerminationReportingEnabled, behavior, callback)
}

override fun isInitialized(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,26 @@ enum class LaneShapeDto(val raw: Int) {
}
}

/** Determines how application should behave when a application task is removed. */
enum class TaskRemovedBehaviorDto(val raw: Int) {
/**
* The default state, indicating that navigation guidance, location updates, and notification
* should persist after user removes the application task.
*/
CONTINUESERVICE(0),
/**
* Indicates that navigation guidance, location updates, and notification should shut down
* immediately when the user removes the application task.
*/
QUITSERVICE(1);

companion object {
fun ofRaw(raw: Int): TaskRemovedBehaviorDto? {
return values().firstOrNull { it.raw == raw }
}
}
}

/**
* Object containing map options used to initialize Google Map view.
*
Expand Down Expand Up @@ -5022,6 +5042,7 @@ interface NavigationSessionApi {
/** General. */
fun createNavigationSession(
abnormalTerminationReportingEnabled: Boolean,
behavior: TaskRemovedBehaviorDto,
callback: (Result<Unit>) -> Unit,
)

Expand Down Expand Up @@ -5137,7 +5158,8 @@ interface NavigationSessionApi {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val abnormalTerminationReportingEnabledArg = args[0] as Boolean
api.createNavigationSession(abnormalTerminationReportingEnabledArg) {
val behaviorArg = TaskRemovedBehaviorDto.ofRaw(args[1] as Int)!!
api.createNavigationSession(abnormalTerminationReportingEnabledArg, behaviorArg) {
result: Result<Unit> ->
val error = result.exceptionOrNull()
if (error != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import com.google.android.libraries.navigation.AlternateRoutesStrategy
import com.google.android.libraries.navigation.NavigationRoadStretchRenderingData
import com.google.android.libraries.navigation.NavigationTrafficData
import com.google.android.libraries.navigation.Navigator.AudioGuidance
import com.google.android.libraries.navigation.Navigator.TaskRemovedBehavior
import com.google.android.libraries.navigation.RoutingOptions.RoutingStrategy
import com.google.android.libraries.navigation.SpeedAlertSeverity
import com.google.android.libraries.navigation.TimeAndDistance
Expand Down Expand Up @@ -605,4 +606,20 @@ internal class ConvertTest {
assertEquals(10.0, imageDescriptor.width)
assertEquals(20.0, imageDescriptor.height)
}

@Test
fun taskRemovedBehaviorDtoToTaskRemovedBehavior_returnsExpectedValue() {
assertEquals(
TaskRemovedBehavior.QUIT_SERVICE,
Convert.taskRemovedBehaviorDtoToTaskRemovedBehavior(TaskRemovedBehaviorDto.QUITSERVICE),
)
assertEquals(
TaskRemovedBehavior.CONTINUE_SERVICE,
Convert.taskRemovedBehaviorDtoToTaskRemovedBehavior(TaskRemovedBehaviorDto.CONTINUESERVICE),
)
assertEquals(
TaskRemovedBehavior.CONTINUE_SERVICE,
Convert.taskRemovedBehaviorDtoToTaskRemovedBehavior(null),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ class GoogleMapsNavigationSessionMessageHandler: NavigationSessionApi {
}

func createNavigationSession(abnormalTerminationReportingEnabled: Bool,
// taskRemovedBehaviourValue is Android only value and not used on
// iOS.
behavior: TaskRemovedBehaviorDto,
completion: @escaping (Result<Void, Error>) -> Void) {
do {
try GoogleMapsNavigationSessionManager.shared
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,16 @@ enum LaneShapeDto: Int {
case uTurnRight = 9
}

/// Determines how application should behave when a application task is removed.
enum TaskRemovedBehaviorDto: Int {
/// The default state, indicating that navigation guidance,
/// location updates, and notification should persist after user removes the application task.
case continueService = 0
/// Indicates that navigation guidance, location updates, and notification should shut down
/// immediately when the user removes the application task.
case quitService = 1
}

/// Object containing map options used to initialize Google Map view.
///
/// Generated class from Pigeon that represents data sent in messages.
Expand Down Expand Up @@ -4618,6 +4628,7 @@ class NavigationSessionApiCodec: FlutterStandardMessageCodec {
protocol NavigationSessionApi {
/// General.
func createNavigationSession(abnormalTerminationReportingEnabled: Bool,
behavior: TaskRemovedBehaviorDto,
completion: @escaping (Result<Void, Error>) -> Void)
func isInitialized() throws -> Bool
func cleanup() throws
Expand Down Expand Up @@ -4694,17 +4705,18 @@ enum NavigationSessionApiSetup {
createNavigationSessionChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
let abnormalTerminationReportingEnabledArg = args[0] as! Bool
api
.createNavigationSession(
abnormalTerminationReportingEnabled: abnormalTerminationReportingEnabledArg
) { result in
switch result {
case .success:
reply(wrapResult(nil))
case let .failure(error):
reply(wrapError(error))
}
let behaviorArg = TaskRemovedBehaviorDto(rawValue: args[1] as! Int)!
api.createNavigationSession(
abnormalTerminationReportingEnabled: abnormalTerminationReportingEnabledArg,
behavior: behaviorArg
) { result in
switch result {
case .success:
reply(wrapResult(nil))
case let .failure(error):
reply(wrapError(error))
}
}
}
} else {
createNavigationSessionChannel.setMessageHandler(nil)
Expand Down
11 changes: 11 additions & 0 deletions lib/src/method_channel/convert/navigation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,14 @@ extension ConvertNavigationViewOptions on NavigationViewOptions {
return NavigationViewOptionsDto(navigationUIEnabledPreference: preference);
}
}

extension ConvertTaskRemovedBehavior on TaskRemovedBehavior {
TaskRemovedBehaviorDto toDto() {
switch (this) {
case TaskRemovedBehavior.continueService:
return TaskRemovedBehaviorDto.continueService;
case TaskRemovedBehavior.quitService:
return TaskRemovedBehaviorDto.quitService;
}
}
}
19 changes: 15 additions & 4 deletions lib/src/method_channel/messages.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,16 @@ enum LaneShapeDto {
uTurnRight,
}

/// Determines how application should behave when a application task is removed.
enum TaskRemovedBehaviorDto {
/// The default state, indicating that navigation guidance,
/// location updates, and notification should persist after user removes the application task.
continueService,

/// Indicates that navigation guidance, location updates, and notification should shut down immediately when the user removes the application task.
quitService,
}

/// Object containing map options used to initialize Google Map view.
class MapOptionsDto {
MapOptionsDto({
Expand Down Expand Up @@ -5346,8 +5356,8 @@ class NavigationSessionApi {
_NavigationSessionApiCodec();

/// General.
Future<void> createNavigationSession(
bool abnormalTerminationReportingEnabled) async {
Future<void> createNavigationSession(bool abnormalTerminationReportingEnabled,
TaskRemovedBehaviorDto behavior) async {
const String __pigeon_channelName =
'dev.flutter.pigeon.google_navigation_flutter.NavigationSessionApi.createNavigationSession';
final BasicMessageChannel<Object?> __pigeon_channel =
Expand All @@ -5356,8 +5366,9 @@ class NavigationSessionApi {
pigeonChannelCodec,
binaryMessenger: __pigeon_binaryMessenger,
);
final List<Object?>? __pigeon_replyList = await __pigeon_channel
.send(<Object?>[abnormalTerminationReportingEnabled]) as List<Object?>?;
final List<Object?>? __pigeon_replyList = await __pigeon_channel.send(
<Object?>[abnormalTerminationReportingEnabled, behavior.index])
as List<Object?>?;
if (__pigeon_replyList == null) {
throw _createConnectionError(__pigeon_channelName);
} else if (__pigeon_replyList.length > 1) {
Expand Down
8 changes: 4 additions & 4 deletions lib/src/method_channel/session_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ class NavigationSessionAPIImpl {
}

/// Creates navigation session in the native platform and returns navigation session controller.
Future<void> createNavigationSession(
bool abnormalTerminationReportingEnabled) async {
Future<void> createNavigationSession(bool abnormalTerminationReportingEnabled,
TaskRemovedBehavior taskRemovedBehavior) async {
// Setup session API streams.
ensureSessionAPISetUp();
try {
// Create native navigation session manager.
await _sessionApi
.createNavigationSession(abnormalTerminationReportingEnabled);
await _sessionApi.createNavigationSession(
abnormalTerminationReportingEnabled, taskRemovedBehavior.toDto());
} on PlatformException catch (e) {
switch (e.code) {
case 'notAuthorized':
Expand Down
7 changes: 5 additions & 2 deletions lib/src/navigator/google_navigation_flutter_navigator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,12 @@ class GoogleMapsNavigator {
/// reporting abnormal SDK terminations such as the app crashes while the SDK is still running.
///
static Future<void> initializeNavigationSession(
{bool abnormalTerminationReportingEnabled = true}) async {
{bool abnormalTerminationReportingEnabled = true,
TaskRemovedBehavior taskRemovedBehavior =
TaskRemovedBehavior.continueService}) async {
await GoogleMapsNavigationPlatform.instance.navigationSessionAPI
.createNavigationSession(abnormalTerminationReportingEnabled);
.createNavigationSession(
abnormalTerminationReportingEnabled, taskRemovedBehavior);

// Enable road-snapped location updates if there are subscriptions to them.
if ((_roadSnappedLocationUpdatedController?.hasListener ?? false) ||
Expand Down
26 changes: 26 additions & 0 deletions lib/src/types/navigation_initialization_params.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2025 Google LLC
//
// 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.

/// Determines how application should behave when a application task is removed.
///
/// Android only.
/// {@category Navigation}
enum TaskRemovedBehavior {
/// The default state, indicating that navigation guidance,
/// location updates, and notification should persist after user removes the application task.
continueService,

/// Indicates that navigation guidance, location updates, and notification should shut down immediately when the user removes the application task.
quitService,
}
1 change: 1 addition & 0 deletions lib/src/types/types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export 'lat_lng.dart';
export 'lat_lng_bounds.dart';
export 'markers.dart';
export 'navigation_destinations.dart';
export 'navigation_initialization_params.dart';
export 'navigation_view_types.dart';
export 'navinfo.dart';
export 'polygons.dart';
Expand Down
13 changes: 12 additions & 1 deletion pigeons/messages.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1182,11 +1182,22 @@ class NavInfoDto {
final int? timeToNextDestinationSeconds;
}

/// Determines how application should behave when a application task is removed.
enum TaskRemovedBehaviorDto {
/// The default state, indicating that navigation guidance,
/// location updates, and notification should persist after user removes the application task.
continueService,

/// Indicates that navigation guidance, location updates, and notification should shut down immediately when the user removes the application task.
quitService,
}

@HostApi(dartHostTestHandler: 'TestNavigationSessionApi')
abstract class NavigationSessionApi {
/// General.
@async
void createNavigationSession(bool abnormalTerminationReportingEnabled);
void createNavigationSession(bool abnormalTerminationReportingEnabled,
TaskRemovedBehaviorDto behavior);
bool isInitialized();
void cleanup();
@async
Expand Down
Loading
Loading