icerockdev / moko-geo Goto Github PK
View Code? Open in Web Editor NEWGeolocation access for mobile (android & ios) Kotlin Multiplatform development
Home Page: https://moko.icerock.dev/
License: Apache License 2.0
Geolocation access for mobile (android & ios) Kotlin Multiplatform development
Home Page: https://moko.icerock.dev/
License: Apache License 2.0
java.lang.ClassCastException: com.sar.app.android.MainActivity cannot be cast to androidx.fragment.app.FragmentActivity
at dev.icerock.moko.geo.compose.BindLocationTrackerEffect_androidKt$BindLocationTrackerEffect$1.invokeSuspend(BindLocationTrackerEffect.android.kt:24)
I am using Koin, and I have tried injecting it from iosMain and androidMain, and also creating it in my composable with the factory, both result in the same error when running on Android. It works perfectly on iOS though, with both methods, ironically enough, since it is Kotlin code.
It does work in the demo code, but I can not see any reason why my setup should cause this to happen. Hopefully anyone has a tip for this.
My setup:
Compose Multiplatform (also using navigation)
Koin
Ktor
MapComposeMP
ConstraintLayout Multiplatform
KotlinX Serialization
SQLDelight
MOKO MVVM
MOKO Geo Compose
MOKO Permissions (I do manage permissions myself though, shouldn't be related)
Coil3
geo locations works on the iOS side, but its not working for android. im using a pixel 7 device
Can't use it when accuracy is stuck at 45 degreees, it works perfectly fine on Google Maps so device is not the issue here. It varies A LOT also, so the feature is useless.
2024-05-09 18:09:25.472 27978-28143 MapViewModel com.sar.app.android D Map rotation: 0.0
2024-05-09 18:09:30.685 27978-28851 MapViewModel com.sar.app.android D User Azimuth: Azimuth(azimuthDegrees=31.391294479370117, azimuthAccuracyDegrees=45.0)
2024-05-09 18:09:30.685 27978-28851 MapViewModel com.sar.app.android D Map rotation: 0.0
2024-05-09 18:09:35.893 27978-28851 MapViewModel com.sar.app.android D User Azimuth: Azimuth(azimuthDegrees=124.52422332763672, azimuthAccuracyDegrees=45.0)
2024-05-09 18:09:35.893 27978-28851 MapViewModel com.sar.app.android D Map rotation: 0.0
2024-05-09 18:09:41.137 27978-28082 MapViewModel com.sar.app.android D User Azimuth: Azimuth(azimuthDegrees=124.52422332763672, azimuthAccuracyDegrees=45.0)
2024-05-09 18:09:41.138 27978-28082 MapViewModel com.sar.app.android D Map rotation: 0.0
2024-05-09 18:09:46.356 27978-28977 MapViewModel com.sar.app.android D User Azimuth: Azimuth(azimuthDegrees=57.98143005371094, azimuthAccuracyDegrees=45.0)
1.3.70 released https://blog.jetbrains.com/kotlin/2020/03/kotlin-1-3-70-released/
but now waiting kotlinx.coroutines update to 1.3.70 - https://github.com/Kotlin/kotlinx.coroutines/releases
and moko-mvvm release - https://github.com/icerockdev/moko-mvvm/releases
and moko-permissions release - https://github.com/icerockdev/moko-permissions/releases
and moko-parcelize release - https://github.com/icerockdev/moko-parcelize/releases
In 0.9.0 was binary incompatible changes, so we should add support of 0.9.0 in update
Need func or property to get user location one time
This line suspends forever on android emulator (Nexus 4 API 23):
val coords = locationTracker.getLocationsFlow().first()
On real device it works correctly.
Hi
i found a problem with the Channel design.
Currently everytime there is a new location it gets send to the channel
trackerScope.launch {
extendedLocationsChannel.send(extendedLocation)
locationsChannel.send(latLng)
}
But when the app starts tracking but watches only one flow (e.g. only getLocationsFlow()
),
there is never a receive action on the second channel (extendedLocationsChannel
)
This leds to the issue that locationsChannel.send(latLng)
is not called after 64 locations where send because the channels are implemented as:
private val locationsChannel = Channel<LatLng>(Channel.BUFFERED)
private val extendedLocationsChannel = Channel<ExtendedLocation>(Channel.BUFFERED)
And in the docs they mention
/**
* Requests a buffered channel with the default buffer capacity in the `Channel(...)` factory function.
* The default capacity for a channel that [suspends][BufferOverflow.SUSPEND] on overflow
* is 64 and can be overridden by setting [DEFAULT_BUFFER_PROPERTY_NAME] on JVM.
* For non-suspending channels, a buffer of capacity 1 is used.
*/
public const val BUFFERED: Int = -2
so this should be changed to
/**
* Requests a conflated channel in the `Channel(...)` factory function. This is a shortcut to creating
* a channel with [`onBufferOverflow = DROP_OLDEST`][BufferOverflow.DROP_OLDEST].
*/
public const val CONFLATED: Int = -1
Currently we are using your library. In our app we need functionality to get
altitude, accuracy, angle
screenModelScope.launch {
locationTracker?.getLocationsFlow()?.distinctUntilChanged()?.collect {
AppLogger.log("new location: $it.")
state.value.latitude = it.latitude
state.value.longitude = it.longitude
}
}
How can we do that.Does this functionality exist or not? Please do update as soon as possible. If not, we then have to move on to next library thanks. Since this seems great library for multiplatform, we don't want to switch.
Current LocationTracker
implementation is nailed to the FusedLocationProviderClient
. Therefore moko-geo
is unable to work properly on android devices without Google Services installed. Google Services are unavailable/not installed/not used on lots of chinese devices and some of open source firmwares.
This issue is somewhat releated to #16, because running moko-geo
sample app on AVD image without Google APIs/Google Play leads to the same result with related log messages:
W/GooglePlayServicesUtil: dev.icerock.moko.samples.geo.debug requires the Google Play Store, but it is missing.
W/GoogleApiManager: The service for com.google.android.gms.internal.location.zzaz is not available [...]
There are at least couple of alternatives that can be used instead of FusedLocationProviderClient
:
com.yandex.mapkit.location.LocationManager
from Yandex MapKit (don't really know what they are using as underlying GPS service)android.location.LocationManager
from Android SDKBesides, as a user of moko-geo
I would like to have an ability to use my own bindings to location services from other custom private/device specific SDK's. So it's also would be nice to have an interface allowing to do such bindings and some APIs allowing to choose different implementations at runtime.
to use coroutines 1.4.2-native-mt we should update code of UIDispatcher, so we should update kotlin and coroutines
I tested this library on Android. It works perfectly fine, if GPS is enabled. If not, nothing happens. The official docs state that an app should check the settings and prompt a system dialog to enable GPS. Would be nice to see this feature.
Thanks.
In order for the library to work on Android, one needs to import the gms location library. This step is not described in the README.
Hello,
I tried to use this library in my project. For the android part everything works as expected, but for iOS it's not. I am trying to initialize my dependencies as in readme:
let viewModel = TrackerViewModel(
locationTracker: LocationTracker(
permissionsController: PermissionsController(),
accuracy: kCLLocationAccuracyBest
)
)
But it's not possible. Firstly, there's no such class as LocationTracker
- there's GeoLocationTracker
instead. This wouldn't be a problem but the PermissionController
doesn't exist either. The only thing that is accessible is PermissionsPermissionsControllerProtocol
which is (of course) a protocol so it'd require an iOS specific implementation. Is there some bug in the library or I am doing sth wrong?
This is my shared module gradle file:
plugins {
kotlin("multiplatform")
id("com.android.library")
kotlin("plugin.serialization") //version "1.4.32"
id("io.realm.kotlin") version "0.10.0"
}
dependencies {
commonMainApi("dev.icerock.moko:geo:0.5.0")
}
kotlin {
android()
listOf(
iosX64(),
iosArm64(),
).forEach {
it.binaries.framework {
baseName = "shared"
}
}
sourceSets {
val coroutineVersion = "1.6.0"
val ktor_version = "1.6.7"
val serialization_version = "1.3.2"
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutineVersion-native-mt") {
version { strictly("$coroutineVersion-native-mt") }
}
implementation("io.ktor:ktor-client-core:$ktor_version")
implementation("io.ktor:ktor-client-serialization:$ktor_version")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$serialization_version")
implementation("io.ktor:ktor-client-logging:$ktor_version")
implementation("io.realm.kotlin:library-base:0.10.0")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.3.2")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val androidMain by getting {
dependencies {
implementation("io.ktor:ktor-client-android:$ktor_version")
}
}
val androidTest by getting {
dependencies {
implementation(kotlin("test-junit"))
implementation("junit:junit:4.13.2")
}
}
val iosX64Main by getting
val iosArm64Main by getting
val iosMain by creating {
dependsOn(commonMain)
iosX64Main.dependsOn(this)
iosArm64Main.dependsOn(this)
dependencies {
implementation("io.ktor:ktor-client-ios:$ktor_version")
}
}
val iosX64Test by getting
val iosArm64Test by getting
val iosTest by creating {
dependsOn(commonTest)
iosX64Test.dependsOn(this)
iosArm64Test.dependsOn(this)
}
}
}
android {
compileSdk = 31
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdk = 21
targetSdk = 31
}
}
I tried other options (commonMainImplementation instead of ..api, export etc.) but the effect was always the same. I'd be very grateful for some hints
moko-geo
is crashing when used with moko-permissions
0.18.0 due to changes introduced in icerockdev/moko-permissions#114
java.lang.NoSuchMethodError: No interface method bind(Landroidx/lifecycle/Lifecycle;Landroidx/fragment/app/FragmentManager;)V in class Ldev/icerock/moko/permissions/PermissionsController; or its super classes (declaration of 'dev.icerock.moko.permissions.PermissionsController' appears in /data/app/~~mzYr2CSSRJBzdyXB69qEMw==/house.letmein.app.debug-L3ibmEofzpfG5nL4uKKVAA==/base.apk!classes25.dex)
at dev.icerock.moko.geo.LocationTracker.bind(LocationTracker.kt:46)
at dev.icerock.moko.geo.compose.BindLocationTrackerEffect_androidKt$BindLocationTrackerEffect$1.invokeSuspend(BindLocationTrackerEffect.android.kt:26)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
at androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch(AndroidUiDispatcher.android.kt:81)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(AndroidUiDispatcher.android.kt:41)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.run(AndroidUiDispatcher.android.kt:57)
at android.os.Handler.handleCallback(Handler.java:958)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8177)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [androidx.compose.ui.platform.MotionDurationScaleImpl@1f23d75, androidx.compose.runtime.BroadcastFrameClock@5c010a, StandaloneCoroutine{Cancelling}@739ad7b, AndroidUiDispatcher@e8c8798]
Keep using moko-permissions
0.17.0 till moko-geo is updated
LocationTracker.bind
and BindLocationTrackerEffect
should be updated to adapt to a new PermissionsController.bind
API. While releasing a new version of this library it would be nice to include also bumping other dependencies to the newest versions.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.