Skip to content

Commit 8bc03c1

Browse files
feat: support navigation disposal on app exit on android (#289)
Release-As: 0.5.1 --------- Co-authored-by: Joonas Kerttula <[email protected]>
1 parent 3082395 commit 8bc03c1

File tree

18 files changed

+184
-32
lines changed

18 files changed

+184
-32
lines changed

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ class _NavigationSampleState extends State<NavigationSample> {
122122
);
123123
}
124124
// Note: make sure user has also granted location permissions before starting navigation session.
125-
await GoogleMapsNavigator.initializeNavigationSession();
125+
await GoogleMapsNavigator.initializeNavigationSession(taskRemovedBehavior: TaskRemovedBehavior.continueService);
126126
setState(() {
127127
_navigationSessionInitialized = true;
128128
});
@@ -158,6 +158,15 @@ class _NavigationSampleState extends State<NavigationSample> {
158158
}
159159
```
160160

161+
#### Task Removed Behavior
162+
163+
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:
164+
165+
- `TaskRemovedBehavior.continueService`: Continue running in the background. (default)
166+
- `TaskRemovedBehavior.quitService`: Shut down immediately.
167+
168+
This parameter has only an effect on Android.
169+
161170
### Add a map view
162171

163172
```dart

android/src/main/kotlin/com/google/maps/flutter/navigation/Convert.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import com.google.android.libraries.navigation.NavigationRoadStretchRenderingDat
4545
import com.google.android.libraries.navigation.NavigationTrafficData
4646
import com.google.android.libraries.navigation.Navigator
4747
import com.google.android.libraries.navigation.Navigator.AudioGuidance
48+
import com.google.android.libraries.navigation.Navigator.TaskRemovedBehavior
4849
import com.google.android.libraries.navigation.RouteSegment
4950
import com.google.android.libraries.navigation.RoutingOptions
5051
import com.google.android.libraries.navigation.RoutingOptions.RoutingStrategy
@@ -1055,4 +1056,14 @@ object Convert {
10551056
ImageDescriptorDto()
10561057
}
10571058
}
1059+
1060+
fun taskRemovedBehaviorDtoToTaskRemovedBehavior(
1061+
behavior: TaskRemovedBehaviorDto?
1062+
): @TaskRemovedBehavior Int {
1063+
return when (behavior) {
1064+
TaskRemovedBehaviorDto.CONTINUESERVICE -> TaskRemovedBehavior.CONTINUE_SERVICE
1065+
TaskRemovedBehaviorDto.QUITSERVICE -> TaskRemovedBehavior.QUIT_SERVICE
1066+
else -> TaskRemovedBehavior.CONTINUE_SERVICE
1067+
}
1068+
}
10581069
}

android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsNavigationSessionManager.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import com.google.android.libraries.navigation.NavigationApi.NavigatorListener
3131
import com.google.android.libraries.navigation.NavigationUpdatesOptions
3232
import com.google.android.libraries.navigation.NavigationUpdatesOptions.GeneratedStepImagesType
3333
import com.google.android.libraries.navigation.Navigator
34+
import com.google.android.libraries.navigation.Navigator.TaskRemovedBehavior
3435
import com.google.android.libraries.navigation.RoadSnappedLocationProvider
3536
import com.google.android.libraries.navigation.RouteSegment
3637
import com.google.android.libraries.navigation.RoutingOptions
@@ -43,7 +44,6 @@ import com.google.android.libraries.navigation.TermsAndConditionsUIParams
4344
import com.google.android.libraries.navigation.TimeAndDistance
4445
import com.google.android.libraries.navigation.Waypoint
4546
import com.google.maps.flutter.navigation.Convert.convertTravelModeFromDto
46-
import com.google.maps.flutter.navigation.GoogleMapsNavigationSessionManager.Companion.navigationReadyListener
4747
import io.flutter.plugin.common.BinaryMessenger
4848
import java.lang.ref.WeakReference
4949

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

121122
override fun onCreate(owner: LifecycleOwner) {
122123
weakLifecycleOwner = WeakReference(owner)
@@ -170,6 +171,7 @@ private constructor(private val navigationSessionEventApi: NavigationSessionEven
170171
/** Creates Navigator instance. */
171172
fun createNavigationSession(
172173
abnormalTerminationReportingEnabled: Boolean,
174+
behavior: TaskRemovedBehaviorDto,
173175
callback: (Result<Unit>) -> Unit,
174176
) {
175177
if (navigator != null) {
@@ -180,6 +182,7 @@ private constructor(private val navigationSessionEventApi: NavigationSessionEven
180182
callback(Result.success(Unit))
181183
return
182184
}
185+
taskRemovedBehavior = Convert.taskRemovedBehaviorDtoToTaskRemovedBehavior(behavior)
183186

184187
// Align API behavior with iOS:
185188
// If the terms haven't yet been accepted throw an error.
@@ -202,6 +205,7 @@ private constructor(private val navigationSessionEventApi: NavigationSessionEven
202205
object : NavigatorListener {
203206
override fun onNavigatorReady(newNavigator: Navigator) {
204207
navigator = newNavigator
208+
navigator?.setTaskRemovedBehavior(taskRemovedBehavior)
205209
registerNavigationListeners()
206210
isNavigationSessionInitialized = true
207211
navigationReadyListener?.onNavigationReady(true)

android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsNavigationSessionMessageHandler.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ class GoogleMapsNavigationSessionMessageHandler : NavigationSessionApi {
2727

2828
override fun createNavigationSession(
2929
abnormalTerminationReportingEnabled: Boolean,
30+
behavior: TaskRemovedBehaviorDto,
3031
callback: (Result<Unit>) -> Unit,
3132
) {
32-
manager().createNavigationSession(abnormalTerminationReportingEnabled, callback)
33+
manager().createNavigationSession(abnormalTerminationReportingEnabled, behavior, callback)
3334
}
3435

3536
override fun isInitialized(): Boolean {

android/src/main/kotlin/com/google/maps/flutter/navigation/messages.g.kt

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,26 @@ enum class LaneShapeDto(val raw: Int) {
507507
}
508508
}
509509

510+
/** Determines how application should behave when a application task is removed. */
511+
enum class TaskRemovedBehaviorDto(val raw: Int) {
512+
/**
513+
* The default state, indicating that navigation guidance, location updates, and notification
514+
* should persist after user removes the application task.
515+
*/
516+
CONTINUESERVICE(0),
517+
/**
518+
* Indicates that navigation guidance, location updates, and notification should shut down
519+
* immediately when the user removes the application task.
520+
*/
521+
QUITSERVICE(1);
522+
523+
companion object {
524+
fun ofRaw(raw: Int): TaskRemovedBehaviorDto? {
525+
return values().firstOrNull { it.raw == raw }
526+
}
527+
}
528+
}
529+
510530
/**
511531
* Object containing map options used to initialize Google Map view.
512532
*
@@ -5022,6 +5042,7 @@ interface NavigationSessionApi {
50225042
/** General. */
50235043
fun createNavigationSession(
50245044
abnormalTerminationReportingEnabled: Boolean,
5045+
behavior: TaskRemovedBehaviorDto,
50255046
callback: (Result<Unit>) -> Unit,
50265047
)
50275048

@@ -5137,7 +5158,8 @@ interface NavigationSessionApi {
51375158
channel.setMessageHandler { message, reply ->
51385159
val args = message as List<Any?>
51395160
val abnormalTerminationReportingEnabledArg = args[0] as Boolean
5140-
api.createNavigationSession(abnormalTerminationReportingEnabledArg) {
5161+
val behaviorArg = TaskRemovedBehaviorDto.ofRaw(args[1] as Int)!!
5162+
api.createNavigationSession(abnormalTerminationReportingEnabledArg, behaviorArg) {
51415163
result: Result<Unit> ->
51425164
val error = result.exceptionOrNull()
51435165
if (error != null) {

android/src/test/kotlin/com/google/maps/flutter/navigation/ConvertTest.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import com.google.android.libraries.navigation.AlternateRoutesStrategy
2929
import com.google.android.libraries.navigation.NavigationRoadStretchRenderingData
3030
import com.google.android.libraries.navigation.NavigationTrafficData
3131
import com.google.android.libraries.navigation.Navigator.AudioGuidance
32+
import com.google.android.libraries.navigation.Navigator.TaskRemovedBehavior
3233
import com.google.android.libraries.navigation.RoutingOptions.RoutingStrategy
3334
import com.google.android.libraries.navigation.SpeedAlertSeverity
3435
import com.google.android.libraries.navigation.TimeAndDistance
@@ -605,4 +606,20 @@ internal class ConvertTest {
605606
assertEquals(10.0, imageDescriptor.width)
606607
assertEquals(20.0, imageDescriptor.height)
607608
}
609+
610+
@Test
611+
fun taskRemovedBehaviorDtoToTaskRemovedBehavior_returnsExpectedValue() {
612+
assertEquals(
613+
TaskRemovedBehavior.QUIT_SERVICE,
614+
Convert.taskRemovedBehaviorDtoToTaskRemovedBehavior(TaskRemovedBehaviorDto.QUITSERVICE),
615+
)
616+
assertEquals(
617+
TaskRemovedBehavior.CONTINUE_SERVICE,
618+
Convert.taskRemovedBehaviorDtoToTaskRemovedBehavior(TaskRemovedBehaviorDto.CONTINUESERVICE),
619+
)
620+
assertEquals(
621+
TaskRemovedBehavior.CONTINUE_SERVICE,
622+
Convert.taskRemovedBehaviorDtoToTaskRemovedBehavior(null),
623+
)
624+
}
608625
}

ios/google_navigation_flutter/Sources/google_navigation_flutter/GoogleMapsNavigationSessionMessageHandler.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ class GoogleMapsNavigationSessionMessageHandler: NavigationSessionApi {
5757
}
5858

5959
func createNavigationSession(abnormalTerminationReportingEnabled: Bool,
60+
// taskRemovedBehaviourValue is Android only value and not used on
61+
// iOS.
62+
behavior: TaskRemovedBehaviorDto,
6063
completion: @escaping (Result<Void, Error>) -> Void) {
6164
do {
6265
try GoogleMapsNavigationSessionManager.shared

ios/google_navigation_flutter/Sources/google_navigation_flutter/messages.g.swift

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,16 @@ enum LaneShapeDto: Int {
372372
case uTurnRight = 9
373373
}
374374

375+
/// Determines how application should behave when a application task is removed.
376+
enum TaskRemovedBehaviorDto: Int {
377+
/// The default state, indicating that navigation guidance,
378+
/// location updates, and notification should persist after user removes the application task.
379+
case continueService = 0
380+
/// Indicates that navigation guidance, location updates, and notification should shut down
381+
/// immediately when the user removes the application task.
382+
case quitService = 1
383+
}
384+
375385
/// Object containing map options used to initialize Google Map view.
376386
///
377387
/// Generated class from Pigeon that represents data sent in messages.
@@ -4618,6 +4628,7 @@ class NavigationSessionApiCodec: FlutterStandardMessageCodec {
46184628
protocol NavigationSessionApi {
46194629
/// General.
46204630
func createNavigationSession(abnormalTerminationReportingEnabled: Bool,
4631+
behavior: TaskRemovedBehaviorDto,
46214632
completion: @escaping (Result<Void, Error>) -> Void)
46224633
func isInitialized() throws -> Bool
46234634
func cleanup() throws
@@ -4694,17 +4705,18 @@ enum NavigationSessionApiSetup {
46944705
createNavigationSessionChannel.setMessageHandler { message, reply in
46954706
let args = message as! [Any?]
46964707
let abnormalTerminationReportingEnabledArg = args[0] as! Bool
4697-
api
4698-
.createNavigationSession(
4699-
abnormalTerminationReportingEnabled: abnormalTerminationReportingEnabledArg
4700-
) { result in
4701-
switch result {
4702-
case .success:
4703-
reply(wrapResult(nil))
4704-
case let .failure(error):
4705-
reply(wrapError(error))
4706-
}
4708+
let behaviorArg = TaskRemovedBehaviorDto(rawValue: args[1] as! Int)!
4709+
api.createNavigationSession(
4710+
abnormalTerminationReportingEnabled: abnormalTerminationReportingEnabledArg,
4711+
behavior: behaviorArg
4712+
) { result in
4713+
switch result {
4714+
case .success:
4715+
reply(wrapResult(nil))
4716+
case let .failure(error):
4717+
reply(wrapError(error))
47074718
}
4719+
}
47084720
}
47094721
} else {
47104722
createNavigationSessionChannel.setMessageHandler(nil)

lib/src/method_channel/convert/navigation.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,14 @@ extension ConvertNavigationViewOptions on NavigationViewOptions {
206206
return NavigationViewOptionsDto(navigationUIEnabledPreference: preference);
207207
}
208208
}
209+
210+
extension ConvertTaskRemovedBehavior on TaskRemovedBehavior {
211+
TaskRemovedBehaviorDto toDto() {
212+
switch (this) {
213+
case TaskRemovedBehavior.continueService:
214+
return TaskRemovedBehaviorDto.continueService;
215+
case TaskRemovedBehavior.quitService:
216+
return TaskRemovedBehaviorDto.quitService;
217+
}
218+
}
219+
}

lib/src/method_channel/messages.g.dart

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,16 @@ enum LaneShapeDto {
430430
uTurnRight,
431431
}
432432

433+
/// Determines how application should behave when a application task is removed.
434+
enum TaskRemovedBehaviorDto {
435+
/// The default state, indicating that navigation guidance,
436+
/// location updates, and notification should persist after user removes the application task.
437+
continueService,
438+
439+
/// Indicates that navigation guidance, location updates, and notification should shut down immediately when the user removes the application task.
440+
quitService,
441+
}
442+
433443
/// Object containing map options used to initialize Google Map view.
434444
class MapOptionsDto {
435445
MapOptionsDto({
@@ -5346,8 +5356,8 @@ class NavigationSessionApi {
53465356
_NavigationSessionApiCodec();
53475357

53485358
/// General.
5349-
Future<void> createNavigationSession(
5350-
bool abnormalTerminationReportingEnabled) async {
5359+
Future<void> createNavigationSession(bool abnormalTerminationReportingEnabled,
5360+
TaskRemovedBehaviorDto behavior) async {
53515361
const String __pigeon_channelName =
53525362
'dev.flutter.pigeon.google_navigation_flutter.NavigationSessionApi.createNavigationSession';
53535363
final BasicMessageChannel<Object?> __pigeon_channel =
@@ -5356,8 +5366,9 @@ class NavigationSessionApi {
53565366
pigeonChannelCodec,
53575367
binaryMessenger: __pigeon_binaryMessenger,
53585368
);
5359-
final List<Object?>? __pigeon_replyList = await __pigeon_channel
5360-
.send(<Object?>[abnormalTerminationReportingEnabled]) as List<Object?>?;
5369+
final List<Object?>? __pigeon_replyList = await __pigeon_channel.send(
5370+
<Object?>[abnormalTerminationReportingEnabled, behavior.index])
5371+
as List<Object?>?;
53615372
if (__pigeon_replyList == null) {
53625373
throw _createConnectionError(__pigeon_channelName);
53635374
} else if (__pigeon_replyList.length > 1) {

0 commit comments

Comments
 (0)