Is it possible to use RSocket in android with kotlin? - android

I'm trying to use Rsocket in android to communicate with the spring-boot server with kotlin. unfortunately, rsocket doesn't have good documentation. I try this code from the rsocket kotlin Github pages but I got an error.
This is my dependency:
implementation("io.rsocket.kotlin:rsocket-core:0.12.0")
implementation("io.rsocket.kotlin:rsocket-transport-ktor:0.12.0")
implementation("io.rsocket.kotlin:rsocket-transport-ktor-client:0.12.0")
implementation("io.ktor:ktor-client-cio:1.4.3")
This is my code:
CoroutineScope(Dispatchers.Main).launch {
val client = HttpClient(CIO) {
install(WebSockets)
install(RSocketSupport)
}
val rSocket: RSocket = client.rSocket("http://demo.rsocket.io/")
val stream: Flow<Payload> = rSocket.requestStream(Payload.Empty)
stream.take(5).map { payload: Payload ->
println(payload.data.readText())
}
}
The error that I have got:
2021-06-04 17:38:49.682 31873-31873/com.example.rsockettest E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.rsockettest, PID: 31873
java.lang.NoSuchMethodError: No static method getSeconds(I)D in class Lkotlin/time/DurationKt; or its super classes (declaration of 'kotlin.time.DurationKt' appears in /data/app/~~TL05n0pUBJZXhnzTYygaSg==/com.example.rsockettest-iWVKDxzJU4GvHrKyFG8j5A==/base.apk)
at io.rsocket.kotlin.keepalive.KeepAlive.<init>(KeepAlive.kt:22)
at io.rsocket.kotlin.core.RSocketConnectorBuilder$ConnectionConfigBuilder.<init>(RSocketConnectorBuilder.kt:70)
at io.rsocket.kotlin.core.RSocketConnectorBuilder.<init>(RSocketConnectorBuilder.kt:28)
at io.rsocket.kotlin.core.RSocketConnectorBuilderKt.RSocketConnector(RSocketConnectorBuilder.kt:112)
at io.rsocket.kotlin.core.RSocketConnectorBuilderKt.RSocketConnector$default(RSocketConnectorBuilder.kt:111)
at io.rsocket.kotlin.transport.ktor.client.RSocketSupport$Config.<init>(RSocketSupport.kt:30)
at io.rsocket.kotlin.transport.ktor.client.RSocketSupport$Feature.prepare(RSocketSupport.kt:36)
at io.rsocket.kotlin.transport.ktor.client.RSocketSupport$Feature.prepare(RSocketSupport.kt:33)
at io.ktor.client.HttpClientConfig$install$3.invoke(HttpClientConfig.kt:77)
at io.ktor.client.HttpClientConfig$install$3.invoke(HttpClientConfig.kt:74)
at io.ktor.client.HttpClientConfig.install(HttpClientConfig.kt:97)
at io.ktor.client.HttpClient.<init>(HttpClient.kt:172)
at io.ktor.client.HttpClient.<init>(HttpClient.kt:81)
at io.ktor.client.HttpClientKt.HttpClient(HttpClient.kt:43)
at com.example.rsockettest.MainActivity$onCreate$1.invokeSuspend(MainActivity.kt:41)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
2021-06-04 17:38:49.722 31873-31873/com.example.rsockettest I/Process: Sending signal. PID: 31873 SIG: 9
if it's not possible to use rsocket in android, can you offer for instead for that? I want to build an application that streams data reactively.

Related

java.lang.IllegalStateException: 'awaitClose { yourCallbackOrListener.cancel() }' should be used in the end of callbackFlow block

I am getting an error the first time the user sign in, however, there is no error the second time the user open the app
from the logcat the awaiClose function is triggered. so where is the error come from?!
The code
val userIdFlow = callbackFlow {
val listener = FirebaseAuth.AuthStateListener { firebaseAuth ->
Timber.tag("Auth_Util").d("Changed")
firebaseAuth.currentUser?.let {
Timber.tag("Auth_Util").d("user exist, id = ${it.uid}")
trySend(it.uid) // the line mentioned in the error message (AuthUtil.kt:38)
}
}
auth.addAuthStateListener(listener)
awaitClose {
Timber.tag("Auth_Util").d("Closed")
auth.removeAuthStateListener(listener)
}
}
The Logcat
2022-10-13 16:00:11.541 6972-6972 Auth_Util com.hussienFahmy.myGpaManager D Changed
2022-10-13 16:00:11.541 6972-6972 Auth_Util com.hussienFahmy.myGpaManager D user exist, id = g11Hbz2EUWXGSE0WnbcF2nJRUPQ2
2022-10-13 16:00:11.543 6972-6972 Auth_Util com.hussienFahmy.myGpaManager D Closed
2022-10-13 16:00:11.716 6972-6972 AndroidRuntime com.hussienFahmy.myGpaManager E FATAL EXCEPTION: main
Process: com.hussienFahmy.myGpaManager, PID: 6972
java.lang.IllegalStateException: 'awaitClose { yourCallbackOrListener.cancel() }' should be used in the end of callbackFlow block.
Otherwise, a callback/listener may leak in case of external cancellation.
See callbackFlow API documentation for the details.
at kotlinx.coroutines.flow.CallbackFlowBuilder.collectTo(Builders.kt:343)
at kotlinx.coroutines.flow.internal.ChannelFlow$collectToFun$1.invokeSuspend(ChannelFlow.kt:60)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.EventLoop.processUnconfinedEvent(EventLoop.common.kt:69)
at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:245)
at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:161)
at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:397)
at kotlinx.coroutines.CancellableContinuationImpl.completeResume(CancellableContinuationImpl.kt:513)
at kotlinx.coroutines.channels.AbstractChannel$ReceiveElement.completeResumeReceive(AbstractChannel.kt:908)
at kotlinx.coroutines.channels.ArrayChannel.offerInternal(ArrayChannel.kt:83)
at kotlinx.coroutines.channels.AbstractSendChannel.trySend-JP2dKIU(AbstractChannel.kt:155)
at kotlinx.coroutines.channels.ChannelCoroutine.trySend-JP2dKIU(Unknown Source:2)
at com.hussienFahmy.myGpaManager.network.AuthUtil$userIdFlow$1.invokeSuspend$lambda-1(AuthUtil.kt:38)
at com.hussienFahmy.myGpaManager.network.AuthUtil$userIdFlow$1.$r8$lambda$gz_nO4N2PXNldWwFNxezrd-NGHg(Unknown Source:0)
at com.hussienFahmy.myGpaManager.network.AuthUtil$userIdFlow$1$$ExternalSyntheticLambda0.onAuthStateChanged(Unknown Source:2)
at com.google.firebase.auth.zzk.run(com.google.firebase:firebase-auth##21.0.8:1)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:236)
at android.app.ActivityThread.main(ActivityThread.java:8057)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:620)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1011)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}#1daddb6, Dispatchers.Main.immediate]

How to request API using Retrofit in a Foreground Service in Android 12(Api 31)?

My app has a specific requirement of uploading files as multipart using retrofit and LiveData in the background(App Navigation works while uploading data to the server.). The app requires chained network requests on the bases of the response it gets. I've used the Foreground service for network requests. this procedure works well in Android 9,10,11.
UploadFragment.kt
class UploadFragment : BaseFragment() {
....
private fun uploadFilesToServer() {
val intent = Intent(requireActivity(), MyFileUploadingService::class.java)
ContextCompat.startForegroundService(requireActivity(), intent)
}
}
FileUploadService.kt
class FileUploadService : LifecycleService() {
....
private fun registerObservers() {
viewModel?.uploadLiveData!!.observe(this) { response ->
val dataResponse: DataUploadResponse = response.responseBody!!.data!!
if (dataResponse.error == null) {
....
// Repeat
} else {
stopSelf()
}
}
}
}
I'm getting an error while observing response using LiveData.
val dataResponse: DataUploadResponse = response.responseBody!!.data!!
Error Log
2022-08-24 13:08:59.792 26140-26140/com.myapp.demo E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myapp.demo, PID: 26140
java.lang.NullPointerException
at com.myapp.demo.service.FileUploadService$registerObservers$1.onChanged(FileUploadService.kt:242)
at com.myapp.demo.service.FileUploadService$registerObservers$1.onChanged(FileUploadService.kt:54)
at androidx.lifecycle.LiveData.considerNotify(LiveData.java:133)
at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:151)
at androidx.lifecycle.LiveData.setValue(LiveData.java:309)
at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:50)
at androidx.lifecycle.LiveData$1.run(LiveData.java:93)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7870)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)

Why The App Crashed After Processed a Command Using a setOnClickListener?

So I am using firebase to upload my data by filling a form and sending a cover picture. After I filled the form and provide the picture, I pressed a "save" button, which is basically sending all those information and pictures to firebase and then return to the main activity. Before the main activity appears, the app crashed and this error appears:
2022-08-16 20:49:53.847 21445-21445/com.example.gesit E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.gesit, PID: 21445
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.material.button.MaterialButton.setEnabled(boolean)' on a null object reference
at com.example.gesit.TambahProduk.saveProductInformation$lambda-6(TambahProduk.kt:313)
at com.example.gesit.TambahProduk.$r8$lambda$WSqVgd-3d_M5F9vVqHMPnqwiv5o(Unknown Source:0)
at com.example.gesit.TambahProduk$$ExternalSyntheticLambda3.onComplete(Unknown Source:2)
at com.google.android.gms.tasks.zzi.run(com.google.android.gms:play-services-tasks##18.0.1:1)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8751)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
What caused this crash? Thanks.
Code for sending data and picture to firebase:
private fun saveProductInformation(downloadedUrl: String) {
auth = FirebaseAuth.getInstance()
val uid = auth.currentUser?.uid.toString()
databaseReference =
FirebaseDatabase.getInstance()
.getReference("User")
val productName = productName.text.toString()
val productInfo =
DataProduk(productName, uid)
if (uid != null) {
databaseReference.child(uid).setValue(productInformation)
.addOnCompleteListener {
saveButton.isEnabled = false
Toast.makeText(this#AddProduct,"Product added",Toast.LENGTH_SHORT).show()
hideProgressBar()
}
}
}

FirebaseRemoteConfigServerException when connect for remote config

I have created a Firebase project and add google-services.json to app module.
I have setup Firebase remote config as follow :
private fun initFirebaseRemoteConfig() {
val remoteConfig = Firebase.remoteConfig
val configSettings = remoteConfigSettings {
minimumFetchIntervalInSeconds = if (BuildConfig.DEBUG) 0 else 3600
}
//remoteConfig.setDefaultsAsync(R.xml.remote_config_defaults)
remoteConfig.setConfigSettingsAsync(configSettings)
remoteConfig.fetchAndActivate().addOnCompleteListener { task ->
val updated = task.result
if (task.isSuccessful) {
Timber.d("Config params updated: $updated")
} else {
Timber.d("Unsuccessful")
}
}
}
I receive following exception on this line task.result as follow :
com.google.android.gms.tasks.RuntimeExecutionException: com.google.firebase.remoteconfig.FirebaseRemoteConfigServerException: Fetch failed: The user is not authorized to access the project. Please make sure you are using the API key that corresponds to your Firebase project.
at com.google.android.gms.tasks.zzu.getResult(com.google.android.gms:play-services-tasks##17.0.2:15)
at com.sample.android.tmdb.TmdbApp.initFirebaseRemoteConfig$lambda-0(TmdbApp.kt:34)
at com.sample.android.tmdb.TmdbApp.lambda$P4-jkzwf9-IJZ17_EtnpghkBXis(Unknown Source:0)
at com.sample.android.tmdb.-$$Lambda$TmdbApp$P4-jkzwf9-IJZ17_EtnpghkBXis.onComplete(Unknown Source:0)
at com.google.android.gms.tasks.zzi.run(com.google.android.gms:play-services-tasks##17.0.2:4)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at com.google.android.gms.internal.tasks.zzb.dispatchMessage(com.google.android.gms:play-services-tasks##17.0.2:6)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: com.google.firebase.remoteconfig.FirebaseRemoteConfigServerException: Fetch failed: The user is not authorized to access the project. Please make sure you are using the API key that corresponds to your Firebase project.
at com.google.firebase.remoteconfig.internal.ConfigFetchHandler.createExceptionWithGenericMessage(ConfigFetchHandler.java:380)
at com.google.firebase.remoteconfig.internal.ConfigFetchHandler.fetchFromBackend(ConfigFetchHandler.java:333)
at com.google.firebase.remoteconfig.internal.ConfigFetchHandler.fetchFromBackendAndCacheResponse(ConfigFetchHandler.java:278)
at com.google.firebase.remoteconfig.internal.ConfigFetchHandler.lambda$fetchIfCacheExpiredAndNotThrottled$1$ConfigFetchHandler(ConfigFetchHandler.java:215)
at com.google.firebase.remoteconfig.internal.-$$Lambda$ConfigFetchHandler$PAoFtfQiOtbXSTeK4H2aFJ-JNJI.then(Unknown Source:8)
at com.google.android.gms.tasks.zzg.run(com.google.android.gms:play-services-tasks##17.0.2:2)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
Caused by: com.google.firebase.remoteconfig.FirebaseRemoteConfigServerException: Forbidden
at com.google.firebase.remoteconfig.internal.ConfigFetchHttpClient.fetch(ConfigFetchHttpClient.java:195)
at com.google.firebase.remoteconfig.internal.ConfigFetchHandler.fetchFromBackend(ConfigFetchHandler.java:307)
at com.google.firebase.remoteconfig.internal.ConfigFetchHandler.fetchFromBackendAndCacheResponse(ConfigFetchHandler.java:278) 
at com.google.firebase.remoteconfig.internal.ConfigFetchHandler.lambda$fetchIfCacheExpiredAndNotThrottled$1$ConfigFetchHandler(ConfigFetchHandler.java:215) 
at com.google.firebase.remoteconfig.internal.-$$Lambda$ConfigFetchHandler$PAoFtfQiOtbXSTeK4H2aFJ-JNJI.then(Unknown Source:8) 
at com.google.android.gms.tasks.zzg.run(com.google.android.gms:play-services-tasks##17.0.2:2) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
at java.lang.Thread.run(Thread.java:923) 

kotlin.coroutines.intrinsics.CoroutineSingletons cannot be cast to retrofit2.Response

So I am using retrofit with coroutines, and declared a method in service:
#GET("notifications")
suspend fun getNotificationsAsync(#QueryMap paramsHashMap:HashMap<String,String>): Response<JsonObject>
In repo:
suspend inline fun <reified T> notificationApiForPagingAsync(hashMapParams: HashMap<String,String>, onPrepare:()->Unit, onSuccess:(list:List<T>)->Unit, onError:(errorMessage:String)->Unit){
// crashing on below line
val response=notificationService.getNotificationsAsync(hashMapParams)
safeApiCallForPaging(response,onPrepare = onPrepare
, onSuccess = {
val listOfNotification=it.data?.fromJsonTo<List<Notification>>("notifications")?: emptyList()
onSuccess(listOfNotification as #kotlin.ParameterName(name = "list") List<T>)
}, onError = onError)
}
And calling from DataSource like this:
coroutineScope.launch(Dispatchers.IO) {
makeLoadAfter(params, callback) // notificationApiForPagingAsync of repo will be called from here
}
And it gives the following error:
AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1
Process: com.package.name.dev, PID: 20173
java.lang.ClassCastException: kotlin.coroutines.intrinsics.CoroutineSingletons cannot be cast to retrofit2.Response
at com.package.name.notification.NewNotificationViewModel$configurePaging$1.invoke(NewNotificationViewModel.kt:53)
at com.package.name.notification.NewNotificationViewModel$configurePaging$1.invoke(NewNotificationViewModel.kt:15)
at com.package.name.common.paging.GenericDataSource.makeLoadAfter(GenericDataSource.kt:85)
at com.package.name.common.paging.GenericDataSource$loadAfter$1.invokeSuspend(GenericDataSource.kt:32)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)
E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-2
Process: com.package.name.dev, PID: 20173
kotlinx.coroutines.CoroutinesInternalError: Fatal exception in coroutines machinery for DispatchedContinuation[LimitingDispatcher#53edd6d[dispatcher = DefaultDispatcher], Continuation at com.package.name.common.paging.GenericDataSource$loadAfter$1.invokeSuspend(GenericDataSource.kt:32)#a30868f]. Please read KDoc to 'handleFatalException' method and report this incident to maintainers
at kotlinx.coroutines.DispatchedTask.handleFatalException$kotlinx_coroutines_core(Dispatched.kt:278)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:249)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)
Caused by: java.lang.IllegalStateException: Job StandaloneCoroutine{Cancelling}#d4d1184 is already complete or completing, but is being completed with CompletedExceptionally[kotlinx.coroutines.JobCancellationException: StandaloneCoroutine is cancelling; job=StandaloneCoroutine{Cancelling}#d4d1184]
at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:788)
at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:111)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:334)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594) 
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60) 
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740) 
Caused by: kotlinx.coroutines.JobCancellationException: StandaloneCoroutine is cancelling; job=StandaloneCoroutine{Cancelling}#d4d1184
Caused by: java.lang.ClassCastException: kotlin.coroutines.intrinsics.CoroutineSingletons cannot be cast to retrofit2.Response
at com.package.name.notification.NewNotificationViewModel$configurePaging$1.invoke(NewNotificationViewModel.kt:53)
at com.package.name.notification.NewNotificationViewModel$configurePaging$1.invoke(NewNotificationViewModel.kt:15)
at com.package.name.common.paging.GenericDataSource.makeLoadAfter(GenericDataSource.kt:85)
at com.package.name.common.paging.GenericDataSource$loadAfter$1.invokeSuspend(GenericDataSource.kt:32)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)
Things to consider here:
In the DataSource, I have created a separate scope, also tried with GlobalScope and viewModelScope but getting the same exception.
But if I call this API from ViewModel directly instead of DataSource, it works fine.
The current version of kotlin I am using is: 1.3.61
Let me know if more code is needed.
This addressed here. The only way I could get it working is by removing inline and crossinline from my suspended function.

Categories

Resources