I'm developing my first app and learning as I go. The app communicates with a URL to fetch data, and sometimes to send data in a POST. Since my last gradle update to 7.1.1, my app is crashing when I open 2 different activities where such a communication is happening.
Here's the error I'm getting:
E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1
Process: com.creoconcept.sifoa, PID: 7255
java.lang.IllegalStateException: No activity
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1366)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841)
at androidx.fragment.app.FragmentManager.dispatchPause(FragmentManager.java:2802)
at androidx.fragment.app.FragmentController.dispatchPause(FragmentController.java:295)
at androidx.fragment.app.FragmentActivity.onPause(FragmentActivity.java:366)
at com.creoconcept.sifoa.DisplayMyQrCode.onPause(DisplayMyQrCode.kt:63)
at com.creoconcept.sifoa.DisplayMyQrCode$checkCodeScanned$1$run$1.invoke(DisplayMyQrCode.kt:37)
at com.creoconcept.sifoa.DisplayMyQrCode$checkCodeScanned$1$run$1.invoke(DisplayMyQrCode.kt:26)
at com.creoconcept.sifoa.Confs$communicateWithSifoaApi$1$1.invokeSuspend(Confs.kt:64)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
I/Process: Sending signal. PID: 7255 SIG: 9
It looks like it has something to do with coroutines. I'm used to doing the same type of thing in jQuery, using ajax or $.get(), and don't quite understand this coroutines thing yet. I'm just trying to fetch some JSON from a URL, and it seems to be a much more complicated thing in Kotlin/Android than it is in jQuery.
Here's some of my code:
fun communicateWithSifoaApi(url:String, callback: (newRef: String) -> Unit){
CoroutineScope(Dispatchers.Default).launch {
withContext(Dispatchers.IO) {
callback(URL(api_url + url).readText())
}
}
}
Here's how I'm doing POSTs:
fun sendPostToApi(url:String, dataString:String, callback: (response: String) -> Unit){
val mURL = URL(api_url + url)
CoroutineScope(Dispatchers.Default).launch {
withContext(Dispatchers.IO) {
with(mURL.openConnection() as HttpURLConnection) {
requestMethod = "POST"
val wr = OutputStreamWriter(outputStream)
wr.write(base64encoding.base64EncodeString(dataString))
wr.flush()
BufferedReader(InputStreamReader(inputStream)).use {
val response = StringBuffer()
var inputLine = it.readLine()
while (inputLine != null) {
response.append(inputLine)
inputLine = it.readLine()
}
callback(response.toString())
}
}
}
}
}
I used to have GlobalScope.launch here, but after the update I started getting the "delicate API" message so I changed it to CoroutineScope(Dispatchers.Default).launch after some Googleing. Before that I was using doAsync which seemed the most similar to jQuery's Ajax, but that was deprecated.
There's also an error now in FragmentManager.java, it now since the update says Cannot resolve symbol 'R' for androidx.fragment.R. I don't know if this has something to do with the problem.
I'd appreciate any help. Thanks.
fragment xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".GoToShoppingCartButton">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/goToShoppingCartButton"
android:layout_width="70sp"
android:layout_height="70sp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:backgroundTint="@color/buyButtonColor"
android:clickable="true"
android:contentDescription="@string/checkout"
android:src="@drawable/cart"
android:tint="@color/buyButtonTextColor"
app:backgroundTint="@color/buyButtonColor"
app:fabCustomSize="70sp"
app:fabSize="auto"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</FrameLayout>
Fragment .kt file:
package com.creoconcept.sifoa
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.google.android.material.floatingactionbutton.FloatingActionButton
class GoToShoppingCartButton : Fragment(R.layout.fragment_go_to_shopping_cart_button) {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_go_to_shopping_cart_button, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.findViewById<FloatingActionButton>(R.id.goToShoppingCartButton).setOnClickListener {
activity?.let {
val intent = Intent(it, ShoppingCart::class.java).apply {}
it.startActivity(intent)
}
}
}
}
code in a different activity, where the fragment is called:
private fun refreshGoToCartButton(){
val buttonFragment =supportFragmentManager.findFragmentByTag("goToCartButton")
if(buttonFragment != null) {
val ft = supportFragmentManager.beginTransaction()
if (shoppingCartArray.isNotEmpty()) {
ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out).show(buttonFragment).commit()
} else {
ft.hide(buttonFragment).commit()
}
} else if (shoppingCartArray.isNotEmpty()) {
supportFragmentManager.commit {
setReorderingAllowed(true)
add<GoToShoppingCartButton>(R.id.browseImgsWrapper,"goToCartButton")
}
}
}
Please note though that the crash happens even when i never even open the activity where this fragment is being used.