You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
*Breaking changes*
- Location flow, permission flow and settings flow are now *SharedFlow*. Using *StateFlow* is conceptually wrong because it does not necessarily mean the *current* state. If you used `.value` on the previous flows, you can now use `replayCache.last()`.
- `LocationFetcher.location` is now a `SharedFlow<Either<Nel<Error>, Location>>`. It now reports the errors in the left side of the `Either` value in case it failed to obtain a location.
- `LocationFetcher.permissionStatus` and `LocationFetcher.settingsStatus` are now `SharedFlow<Boolean>`. The old enums `PermissionStatus` and `SettingsStatus` are now deprecated.
- Removed `LocationFetcher.requestLocationPermissionOnLifecycle` and `LocationFetcher.requestEnableLocationSettingsOnLifecycle` configs from `LocationFetcher.Config`. Instead of requesting permissions and setting enablement on their own, it's now requested automatically once the location flows is subscribed to.
- Removed the possibility to ask for location indefinitely. We now use (and require) a rationale for asking for location. If user denies the permission once, the rationale is shown and we ask the permission one more time. If the user denies it, we respect the user decision and don't ask again. This is in accordance with Google's best practices and policies on location fetching. The rationale is a `String` passed to the `LocationFetcher` builders.
*Other changes*
- Added `LocationFetcher.shouldShowRationale(): Boolean`. Should return true after user denied location permission once. It's used internally to decide whether to show a rationale to the user before asking for permission again, but it's also exposed as an API.
.onEach { /* Location got enabled or disabled in device settings */ }
26
-
.launchIn(lifecycleScope)
27
-
28
-
permissionStatus
29
-
.onEach { /* App allowed or disallowed to access the device's location. */ }
30
-
.launchIn(lifecycleScope)
31
-
}
19
+
repeatOnLifecycle(Lifecycle.State.STARTED) {
20
+
locationFetcher.location
21
+
.onEach { errorsOrLocation ->
22
+
errorsOrLocation.map { location ->
23
+
// Got location
24
+
}.handleError { errors ->
25
+
// Optional. Handle errors. This is optional because errors
26
+
// (no location permission, or setting disabled), will try to be
27
+
// automatically handled by lib.
28
+
}
29
+
}
30
+
.launchIn(this)
31
+
32
+
// Optional, redundant as erros are already reported to 'location' flow.
33
+
locationFetcher.settingsStatus
34
+
.onEach { /* Location got enabled or disabled in device settings */ }
35
+
.launchIn(this)
36
+
37
+
// Optional, redundant as erros are already reported to 'location' flow.
38
+
locationFetcher.permissionStatus
39
+
.onEach { /* App allowed or disallowed to access the device's location. */ }
40
+
.launchIn(this)
32
41
}
33
42
}
34
43
}
@@ -37,49 +46,68 @@ class MyActivity : ComponentActivity() {
37
46
38
47
This library provides a simple location component, `LocationFetcher`, requiring only either an `ComponentActivity` instance or a `Context` instance, to make your Android app location-aware.
39
48
40
-
The service uses GPS and network as location providers by default and thus the app needs to declare use of the `ACCESS_FINE_LOCATION` and `ACCESS_COARSE_LOCATION` permissions on its `AndroidManifest.xml`.
49
+
If the device's location services are disabled, or if your app is not allowed location permissions by the user, this library will automatically ask the user to enable location services in settings or to allow the necessary permissions as soon as you start collecting the `LocationFetcher.location` flow.
50
+
51
+
The service uses GPS and network as location providers by default and thus the app needs to declare use of the `ACCESS_FINE_LOCATION` and `ACCESS_COARSE_LOCATION` permissions on its `AndroidManifest.xml`. Those permissions are already declared in this library, so manifest merging takes care of it.
41
52
42
53
You can personalize your `LocationRequest` to suit your needs.
43
54
44
-
If the device's location services are disabled, or if your app is not allowed location permissions by the user, this library can (optionally) automatically ask the user to enable location services in settings or to allow the necessary permissions.
55
+
## Installation with Gradle
45
56
46
-
##Installation
57
+
### Setup Maven Central on project-level build.gradle
47
58
48
-
### Using Gradle
59
+
This library is hosted in Maven Central, so you must set it up for your project before adding the module-level dependency.
49
60
50
-
On project-level `build.gradle`, add [Jitpack](https://jitpack.io/) repository:
61
+
#### New way
51
62
52
-
```groovy
63
+
The new way to install dependencies repositories is through the `dependencyResolutionManagement` DSL in `settings.gradle(.kts)`.
On any `ComponentActivity` or `Context` class, you can instantiate a `LocationFetcher` by calling the extension functions on `ComponentActivity` or `Context`:
84
112
85
113
```kotlin
@@ -94,12 +122,20 @@ LocationFetcher(this)
94
122
95
123
If `LocationFetcher` is created with a `ComponentActivity`, it will be able to show dialogs to request the user to enable permission in Android settings and to allow the app to obtain the device's location. If `LocationFetcher` is created with a non-`ComponentActivity``Context`, it won't be able to show dialogs.
96
124
97
-
Once instantiated, the component gives you three `Flow`s to collect: one for new locations, one for settings status, and one for location permissions status:
125
+
#### Permission rationale
126
+
127
+
In accordance with Google's best practices and policies, if user denies location permission, we must tell the user the rationale for the need of the user location, then we can ask permission a last time. If denied again, we must respect the user's decision.
128
+
129
+
The rationale must be passed to `LocationFetcher` builders. It will be shown to the user as an `AlertDialog`.
130
+
131
+
### Collecting location
132
+
133
+
Once instantiated, the component gives you three `Flow`s to collect: one for new locations, one for settings status, and one for location permissions status. Usually, you only need to collect the location flow, as errors also flow through it already.
To manually request location permissions or location settings enablement, you can call the following APIs:
@@ -118,7 +154,7 @@ Results will be delivered on the aforementioned flows.
118
154
(Note: for GPS and Network providers, only `interval` and `smallestDisplacement` are used. If you want to use all options, limit providers to `LocationRequest.Provider.Fused`)
119
155
120
156
```kotlin
121
-
locationFetcher {
157
+
locationFetcher("We need your permission to use your location for showing nearby items") {
122
158
fastestInterval =5000
123
159
interval =15000
124
160
maxWaitTime =100000
@@ -131,8 +167,6 @@ locationFetcher {
131
167
LocationRequest.Provider.Fused
132
168
)
133
169
numUpdates =Int.MAX_VALUE
134
-
requestLocationPermissionOnLifecycle:Lifecycle.State?// no effect if built with Context
135
-
requestEnableLocationSettingsOnLifecycle:Lifecycle.State?// no effect if built with Context
136
170
debug =false
137
171
}
138
172
```
@@ -141,6 +175,7 @@ Alternatively, you might prefer to create a standalone configuration instance. I
141
175
142
176
```kotlin
143
177
val config =LocationFetcher.config(
178
+
rationale ="We need your permission to use your location for showing nearby items",
144
179
fastestInterval =5000,
145
180
interval =15000,
146
181
maxWaitTime =100000,
@@ -153,9 +188,7 @@ val config = LocationFetcher.config(
153
188
LocationRequest.Provider.Fused
154
189
),
155
190
numUpdates =Int.MAX_VALUE,
156
-
requestLocationPermissions =true, // no effect if built with Context
157
-
requestEnableLocationSettings =true, // no effect if built with Context
0 commit comments