Skip to content

Commit 5b4ecc1

Browse files
authored
Merge pull request #36 from icerockdev/#35-compose-multiplatform
#35 compose multiplatform
2 parents 361b063 + fcad265 commit 5b4ecc1

File tree

16 files changed

+229
-97
lines changed

16 files changed

+229
-97
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ This is a Kotlin Multiplatform library that provides geolocation to common code.
1616

1717
## Features
1818
- **Geolocation tracking** - track user geolocation from common code;
19+
- **Compose Multiplatform** support;
1920

2021
## Requirements
2122
- Gradle version 6.0+
@@ -35,7 +36,10 @@ allprojects {
3536
project build.gradle
3637
```groovy
3738
dependencies {
38-
commonMainApi("dev.icerock.moko:geo:0.5.0")
39+
commonMainApi("dev.icerock.moko:geo:0.6.0")
40+
41+
// Compose Multiplatform
42+
commonMainApi("dev.icerock.moko:geo-compose:0.6.0")
3943
}
4044
```
4145

build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ buildscript {
1515
classpath(libs.mokoGradlePlugin)
1616
classpath(libs.mobileMultiplatformGradlePlugin)
1717
classpath(libs.kotlinSerializationGradlePlugin)
18+
classpath(libs.composeJetBrainsGradlePlugin)
19+
classpath(libs.detektGradlePlugin)
1820
}
1921
}
2022

geo-compose/build.gradle.kts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2023 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
plugins {
6+
id("dev.icerock.moko.gradle.multiplatform.mobile")
7+
id("dev.icerock.moko.gradle.publication")
8+
id("dev.icerock.moko.gradle.stub.javadoc")
9+
id("dev.icerock.moko.gradle.detekt")
10+
id("org.jetbrains.compose")
11+
}
12+
13+
android {
14+
namespace = "dev.icerock.moko.geo.compose"
15+
16+
defaultConfig {
17+
minSdk = 21
18+
}
19+
}
20+
21+
dependencies {
22+
commonMainApi(projects.geo)
23+
commonMainApi(compose.runtime)
24+
25+
androidMainImplementation(libs.appCompat)
26+
androidMainImplementation(compose.foundation)
27+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2023 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package dev.icerock.moko.geo.compose
6+
7+
import android.content.Context
8+
import androidx.compose.runtime.Composable
9+
import androidx.compose.runtime.LaunchedEffect
10+
import androidx.compose.ui.platform.LocalContext
11+
import androidx.compose.ui.platform.LocalLifecycleOwner
12+
import androidx.fragment.app.FragmentActivity
13+
import androidx.fragment.app.FragmentManager
14+
import androidx.lifecycle.LifecycleOwner
15+
import dev.icerock.moko.geo.LocationTracker
16+
17+
@Suppress("FunctionNaming")
18+
@Composable
19+
actual fun BindLocationTrackerEffect(locationTracker: LocationTracker) {
20+
val lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current
21+
val context: Context = LocalContext.current
22+
23+
LaunchedEffect(locationTracker, lifecycleOwner, context) {
24+
val fragmentManager: FragmentManager = (context as FragmentActivity).supportFragmentManager
25+
26+
locationTracker.bind(lifecycleOwner.lifecycle, context, fragmentManager)
27+
}
28+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright 2023 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package dev.icerock.moko.geo.compose
6+
7+
import android.content.Context
8+
import androidx.compose.runtime.Composable
9+
import androidx.compose.runtime.remember
10+
import androidx.compose.ui.platform.LocalContext
11+
import com.google.android.gms.location.LocationRequest
12+
import dev.icerock.moko.geo.LocationTracker
13+
import dev.icerock.moko.permissions.PermissionsController
14+
15+
@Composable
16+
actual fun rememberLocationTrackerFactory(accuracy: LocationTrackerAccuracy): LocationTrackerFactory {
17+
val context: Context = LocalContext.current
18+
return remember(context) {
19+
object : LocationTrackerFactory {
20+
override fun createLocationTracker(): LocationTracker {
21+
return LocationTracker(
22+
permissionsController = PermissionsController(
23+
applicationContext = context.applicationContext
24+
),
25+
priority = accuracy.toPriority()
26+
)
27+
}
28+
29+
override fun createLocationTracker(
30+
permissionsController: PermissionsController
31+
): LocationTracker {
32+
return LocationTracker(
33+
permissionsController = permissionsController,
34+
priority = accuracy.toPriority()
35+
)
36+
}
37+
}
38+
}
39+
}
40+
41+
private fun LocationTrackerAccuracy.toPriority(): Int {
42+
return when (this) {
43+
LocationTrackerAccuracy.Best -> LocationRequest.PRIORITY_HIGH_ACCURACY
44+
LocationTrackerAccuracy.Medium -> LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY
45+
LocationTrackerAccuracy.LowPower -> LocationRequest.PRIORITY_LOW_POWER
46+
}
47+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* Copyright 2023 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package dev.icerock.moko.geo.compose
6+
7+
import androidx.compose.runtime.Composable
8+
import dev.icerock.moko.geo.LocationTracker
9+
10+
@Suppress("FunctionNaming")
11+
@Composable
12+
expect fun BindLocationTrackerEffect(locationTracker: LocationTracker)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright 2023 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package dev.icerock.moko.geo.compose
6+
7+
import androidx.compose.runtime.Composable
8+
import dev.icerock.moko.geo.LocationTracker
9+
import dev.icerock.moko.permissions.PermissionsController
10+
11+
interface LocationTrackerFactory {
12+
fun createLocationTracker(): LocationTracker
13+
fun createLocationTracker(permissionsController: PermissionsController): LocationTracker
14+
}
15+
16+
enum class LocationTrackerAccuracy {
17+
Best,
18+
Medium,
19+
LowPower
20+
}
21+
22+
@Composable
23+
expect fun rememberLocationTrackerFactory(accuracy: LocationTrackerAccuracy): LocationTrackerFactory
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
* Copyright 2023 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package dev.icerock.moko.geo.compose
6+
7+
import androidx.compose.runtime.Composable
8+
import dev.icerock.moko.geo.LocationTracker
9+
10+
// on iOS side we should not do anything to prepare LocationTracker to work
11+
@Suppress("FunctionNaming")
12+
@Composable
13+
actual fun BindLocationTrackerEffect(locationTracker: LocationTracker) = Unit
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2023 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package dev.icerock.moko.geo.compose
6+
7+
import androidx.compose.runtime.Composable
8+
import androidx.compose.runtime.remember
9+
import dev.icerock.moko.geo.LocationTracker
10+
import dev.icerock.moko.permissions.PermissionsController
11+
import platform.CoreLocation.CLLocationAccuracy
12+
import platform.CoreLocation.kCLLocationAccuracyBest
13+
import platform.CoreLocation.kCLLocationAccuracyKilometer
14+
import platform.CoreLocation.kCLLocationAccuracyReduced
15+
16+
@Composable
17+
actual fun rememberLocationTrackerFactory(accuracy: LocationTrackerAccuracy): LocationTrackerFactory {
18+
return remember {
19+
object : LocationTrackerFactory {
20+
override fun createLocationTracker(): LocationTracker {
21+
return LocationTracker(
22+
permissionsController = dev.icerock.moko.permissions.ios.PermissionsController(),
23+
accuracy = accuracy.toIosAccuracy()
24+
)
25+
}
26+
27+
override fun createLocationTracker(
28+
permissionsController: PermissionsController
29+
): LocationTracker {
30+
return LocationTracker(
31+
permissionsController = permissionsController,
32+
accuracy = accuracy.toIosAccuracy()
33+
)
34+
}
35+
}
36+
}
37+
}
38+
39+
private fun LocationTrackerAccuracy.toIosAccuracy(): CLLocationAccuracy {
40+
return when (this) {
41+
LocationTrackerAccuracy.Best -> kCLLocationAccuracyBest
42+
LocationTrackerAccuracy.Medium -> kCLLocationAccuracyKilometer
43+
LocationTrackerAccuracy.LowPower -> kCLLocationAccuracyReduced
44+
}
45+
}

geo/src/androidMain/kotlin/dev/icerock/moko/geo/LocationTracker.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import com.google.android.gms.location.FusedLocationProviderClient
1515
import com.google.android.gms.location.LocationCallback
1616
import com.google.android.gms.location.LocationRequest
1717
import com.google.android.gms.location.LocationResult
18+
import com.google.android.gms.location.LocationServices
1819
import dev.icerock.moko.permissions.Permission
1920
import dev.icerock.moko.permissions.PermissionsController
2021
import kotlinx.coroutines.CoroutineScope
@@ -44,7 +45,7 @@ actual class LocationTracker(
4445
fun bind(lifecycle: Lifecycle, context: Context, fragmentManager: FragmentManager) {
4546
permissionsController.bind(lifecycle, fragmentManager)
4647

47-
locationProviderClient = FusedLocationProviderClient(context)
48+
locationProviderClient = LocationServices.getFusedLocationProviderClient(context)
4849

4950
@SuppressLint("MissingPermission")
5051
if (isStarted) {
@@ -63,7 +64,7 @@ actual class LocationTracker(
6364
override fun onLocationResult(locationResult: LocationResult) {
6465
super.onLocationResult(locationResult)
6566

66-
val lastLocation = locationResult.lastLocation
67+
val lastLocation = locationResult.lastLocation ?: return
6768

6869
val speedAccuracy = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) null
6970
else lastLocation.speedAccuracyMetersPerSecond.toDouble()

0 commit comments

Comments
 (0)