I have dialog fragment containes list of users so When my dialog fragment is showing and I change let's say the language or activate or disactivate dark mode or any other config change my dialog fragment dissmiss and lose state
so this how i create the dialog :
CheckableContactsDialog.newInstance(object : CheckableContactListener {
override fun onPositiveClick(selected: MutableList<String>) {
checkableContactsDialog?.dismiss()
if (mVCall != null) {
val (phones, phoneFlat) = extractPhonesNumberFromContacts(
context, selected
)
if (phones.isEmpty()) {
return
}
inviteNewUsers(phoneFlat)
}
}
override fun onNegativeClick() {
checkableContactsDialog?.dismiss()
}
})
After configchange like language change or activate or desactivate dark mode and trigger the onPositiveClick event and checkableContactsDialog?.dismiss() called this error appear
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.zetabox.totrapp, PID: 4368
java.lang.IllegalStateException: Fragment CheckableContactsDialog{58e7d9c} (77fb6c1e-6986-4eb0-8e35-c1ee51f4e0c9) not associated with a fragment manager.
at androidx.fragment.app.Fragment.getParentFragmentManager(Fragment.java:1040)
at androidx.fragment.app.DialogFragment.dismissInternal(DialogFragment.java:350)
at androidx.fragment.app.DialogFragment.dismiss(DialogFragment.java:307)
at com.google.android.material.bottomsheet.BottomSheetDialogFragment.dismiss(BottomSheetDialogFragment.java:47)
at com.zetabox.totrapp.ui.call.CallActivity$showAddUserDialog$1.onPositiveClick(CallActivity.kt:2123)
at com.zetabox.totrapp.ui.dialogs.CheckableContactsDialog.init$lambda-7(CheckableContactsDialog.kt:231)
at com.zetabox.totrapp.ui.dialogs.CheckableContactsDialog.$r8$lambda$BXYvl1NNrhMJYwo5PbYyZJ1LQtM(Unknown Source:0)
at com.zetabox.totrapp.ui.dialogs.CheckableContactsDialog$$ExternalSyntheticLambda0.onClick(Unknown Source:2)
at android.view.View.performClick(View.java:7171)
at android.view.View.performClickInternal(View.java:7148)
at android.view.View.access$3500(View.java:802)
at android.view.View$PerformClick.run(View.java:27409)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7650)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:503)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
Related
The scenario is when the app is on Fragment A and then kept the app in the background for some time. After resuming from the background the initial state of the app is in Fragment A but then suddenly app restarts from startDestination in the navigation component causing the below crash.
Fatal Exception: java.lang.IllegalArgumentException: Navigation action/destination com.app.gulfcraftv2:id/action_splashFragment_to_nav_home cannot be found from the current destination Destination(com.app.gulfcraftv2:id/companyFragment) class=com.precise.gulfcraft.ui.companydetail.CompanyDetailFragment
at androidx.navigation.NavController.navigate(NavController.kt:1540)
at androidx.navigation.NavController.navigate(NavController.kt:1472)
at androidx.navigation.NavController.navigate(NavController.kt:1930)
at com.precise.gulfcraft.ui.splash.SplashFragment.onCreate$lambda-6(SplashFragment.kt:75)
at com.precise.gulfcraft.ui.splash.SplashFragment.lambda$Aso8YI02DbFhfWptH-qrBUU0ulU()
at com.precise.gulfcraft.ui.splash.-$$Lambda$SplashFragment$Aso8YI02DbFhfWptH-qrBUU0ulU.run(:2)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7562)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Note - The launch mode used is singleTop
The crash is happening in the below section.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
try {
Handler(Looper.getMainLooper()).postDelayed({
findNavController().navigate(SplashFragmentDirections.actionSplashFragmentToNavHome())
}, 3000)
} catch (e: Exception) {
}
}
check first if this is your current destination with following function
fun navigate(destination: NavDirections) = with(findNavController()) {
currentDestination?.getAction(destination.actionId)
?.let { navigate(destination) }
}
I have a MainActivity using a DrawerLayout and tabs with 2 fragments.
My first fragment contains a list of elements in a RecyclerView, and I can click on each element to "select" it (which calls a SDK function to login to a hardware device). When selected, this triggers a change on the Fragment's ViewModel:
// Selected device changes when an item is clicked
private val _devices = MutableLiveData<List<DeviceListItemViewModel>>()
private val _selectedDevice = MutableLiveData<ConnectedDevice>()
val devices: LiveData<List<DeviceListItemViewModel>> by this::_devices
val selectedDevice: LiveData<ConnectedDevice> by this::_selectedDevice
Then I have a shared ViewModel between both fragments, which also has a currentDevice variable like this:
private val _currentDevice = MutableLiveData<ConnectedDevice>()
val currentDevice: LiveData<ConnectedDevice> by this::_currentDevice
So in the Fragment that contains the list, I have the following code to update the shared ViewModel variable:
private val mViewModel: DeviceManagementViewModel by viewModels()
private val mSharedViewModel: MainActivityViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
Log.d(classTag, "Fragment view created")
val binding = ActivityMainDevicesManagementFragmentBinding.bind(view)
binding.apply {
viewModel = mViewModel
lifecycleOwner = viewLifecycleOwner
}
// Observe fragment ViewModel
// If any device is clicked on the list, do the login on the shared ViewModel
mViewModel.selectedDevice.observe(this, {
mSharedViewModel.viewModelScope.launch {
if (it != null) {
mSharedViewModel.setCurrentDevice(videoDevice = it)
} else mSharedViewModel.unsetCurrentDevice()
}
})
}
The problem is that if the shared ViewModel's currentDevice variable is set, I get exceptions whenever I try to open a Dialog or start a new activity. If I modify the setCurrentDevice function in the shared ViewModel, then it works fine (or if I don't select any device).
The exceptions I see are this when starting a new Activity:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.placeholder.easyview/com.example.myapp.activities.settings.SettingsActivity}: java.lang.IllegalArgumentException: display must not be null
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3430)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3594)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2067)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7698)
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:952)
Caused by: java.lang.IllegalArgumentException: display must not be null
at android.app.ContextImpl.createDisplayContext(ContextImpl.java:2386)
at android.content.ContextWrapper.createDisplayContext(ContextWrapper.java:977)
at com.android.internal.policy.DecorContext.<init>(DecorContext.java:50)
at com.android.internal.policy.PhoneWindow.generateDecor(PhoneWindow.java:2348)
at com.android.internal.policy.PhoneWindow.installDecor(PhoneWindow.java:2683)
at com.android.internal.policy.PhoneWindow.getDecorView(PhoneWindow.java:2116)
at androidx.appcompat.app.AppCompatActivity.initViewTreeOwners(AppCompatActivity.java:219)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:194)
at com.example.myapp.activities.settings.SettingsActivity.onCreate(SettingsActivity.kt:34)
at android.app.Activity.performCreate(Activity.java:8000)
at android.app.Activity.performCreate(Activity.java:7984)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1310)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3403)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3594)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2067)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7698)
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:952)
And this if I try to open a Dialog:
java.lang.ArrayIndexOutOfBoundsException: length=16; index=2448
at android.view.InsetsState.peekSource(InsetsState.java:374)
at android.view.InsetsSourceConsumer.updateSource(InsetsSourceConsumer.java:291)
at android.view.InsetsController.updateState(InsetsController.java:654)
at android.view.InsetsController.onStateChanged(InsetsController.java:621)
at android.view.ViewRootImpl.setView(ViewRootImpl.java:1058)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:409)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:110)
at android.app.Dialog.show(Dialog.java:340)
at android.app.AlertDialog$Builder.show(AlertDialog.java:1131)
at com.example.myapp.activities.main.fragments.DeviceManagementFragment.showAddDeviceMethodDialog(DeviceManagementFragment.kt:151)
at com.example.myapp.activities.main.fragments.DeviceManagementFragment.access$showAddDeviceMethodDialog(DeviceManagementFragment.kt:33)
at com.example.myapp.activities.main.fragments.DeviceManagementFragment$onViewCreated$$inlined$apply$lambda$1.onClick(DeviceManagementFragment.kt:52)
at android.view.View.performClick(View.java:7448)
at android.view.View.performClickInternal(View.java:7425)
at android.view.View.access$3600(View.java:810)
at android.view.View$PerformClick.run(View.java:28309)
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:7698)
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:952)
EDIT: Looks like the problem actually lies in the other fragment, where I have the following code (in onViewCreated method):
// If the shared view model device changes, this must change too
mSharedViewModel.currentDevice.observe(this, {
if (it != null) {
mViewModel.setCurrentDevice(it)
} else mViewModel.unsetCurrentDevice()
})
mViewModel.currentDevice.observe(this, {
if (it != null) {
mViewModel.fetchChannels()
}
})
If I comment out the second part (where the fetchChannels occurs), it works well. Even if I comment out the fetchChannels call only, it works.
This is the code of the fetchChannels function:
fun fetchChannels() = viewModelScope.launch {
Log.d(classTag, "Getting channels for device ${currentDevice.value}")
currentDevice.value?.let {
val fetchedChannels = deviceLibManager.getChannels(it.videoDevice)
_currentDevice.value?.channels?.clear()
_currentDevice.value?.channels?.addAll(fetchedChannels)
if (fetchedChannels.isNotEmpty()) {
_currentDevice.value?.currentChannel = fetchedChannels[0]
}
}
}
The following line is the one giving me trouble:
val fetchedChannels = deviceLibManager.getChannels(it.videoDevice)
That function is just this:
suspend fun getChannels(videoDevice: VideoDevice): List<VideoChannel> {
try {
Log.i(classTag, "Getting channels from device ${videoDevice}")
val channels = videoDevice.getChannelsAsync()
return channels
} catch (exception: Exception) {
when (exception) {
is UnknownVendorException -> {
Log.w(classTag, "Device ${videoDevice} cannot get channels because the vendor is unknown")
}
is NetworkException -> {
Log.w(classTag, "Device ${videoDevice} cannot get channels because it is unreachable")
}
else -> {
Log.w(classTag, "Device ${videoDevice} cannot get channels, reason: ${exception.message}")
}
}
return emptyList()
}
}
And the implementation in the SDK is this:
override suspend fun getChannelsAsync(): List<VideoChannel> = withContext(Dispatchers.IO) {
Log.i(classTag, "Trying to get channels for device: $logName")
val channels = ArrayList<VideoChannel>()
getZeroChannel()?.let {
channels.add(it)
}
channels.addAll(getAllChannels())
if (channels.isNotEmpty()) {
Log.i(classTag, "Successfully retrieved ${channels.size} channels for device: $logName")
return#withContext channels
} else {
Log.w(classTag, "Error retrieving channels for device $logName or no channels exist")
throw Exception()
}
}
The other functions just make a network call and retrieve some data, it should not be messing with the UI at all.
I am testing with a Xiaomi Mi A3 using Android 10.
Can someone help me? Thank you.
So I don't really know why but I found the answer.
In the SDK, the functions getZeroChannel and getAllChannels were not suspending functions, although they make a network call. So what I did is:
Move the withContext(Dispatchers.IO) part to those two functions (the ones who actually make the network call), and make them suspend functions.
Remove the withContext(Dispatchers.IO) part from getChannelsAsync function. Keep it as a suspend function though.
After these changes everything works as expected. I still don't know why, so if someone could shed some light, that would be very much appreciated.
In my app I use this method to detect the keyboard on screen. It works perfectly on api 28+ But once I go below api 28 it starts to cause crashes.
private fun isKeyboardOpen() {
window?.decorView?.setOnApplyWindowInsetsListener { v, insets ->
val systemWindowInsets = insets.inset(0,0,0,200)
imeVisible = ViewCompat.getRootWindowInsets(requireView())?.getInsets(ime())
if(imeVisible != null){
if(imeVisible?.bottom!! > 0){
ivWeatherIcon1.visibility = View.INVISIBLE
} else {
ivWeatherIcon1.visibility = View.VISIBLE
}
}
systemWindowInsets
}
}
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.app, PID: 8062
java.lang.NoSuchMethodError: No virtual method inset(IIII)Landroid/view/WindowInsets; in class Landroid/view/WindowInsets; or its super classes (declaration of 'android.view.WindowInsets' appears in /system/framework/framework.jar!classes2.dex)
at com.app.framework.presentation.workouts.reframe.Workout$isKeyboardOpen$1.onApplyWindowInsets(WorkoutMoodReframe.kt:881)
at android.view.View.dispatchApplyWindowInsets(View.java:9225)
at android.view.ViewGroup.dispatchApplyWindowInsets(ViewGroup.java:6929)
at android.view.ViewRootImpl.dispatchApplyInsets(ViewRootImpl.java:1568)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1812)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1392)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6752)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
at android.view.Choreographer.doCallbacks(Choreographer.java:723)
at android.view.Choreographer.doFrame(Choreographer.java:658)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Is there a way to make this method work back to api 23?
Obviously, keyboard appearance support does not support api <28 yet, so until backward compatibility for getInsets (ime ()) is released - you can use the following code:
private fun isKeyboardOpen() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
// your code above
} else {
// code from source below
}
}
How to check visibility of software keyboard in Android?
private fun setupGeckoView() {
val runtime = GeckoRuntime.create(this) // crashes on this line
geckoSession.open(runtime)
geckoView.setSession(geckoSession)
val url = String(Base64.decode(MYURL, Base64.DEFAULT))
geckoSession.loadUri(url)
geckoSession.progressDelegate = createProgressDelegate()
geckoSession.settings.allowJavascript = true
}
i call setUpGeckoView methon in onCreat() but when i click back and
reopen the app then app crashes with IllegalStateException saying
"Failed to initialize GeckoRuntime. It works first time only crashed when i click back and then open app again"
Logs are given below
Process: arholding.kargoshop.mk, PID: 16444
java.lang.RuntimeException: Unable to start activity ComponentInfo{arholding.kargoshop.mk/arholding.kargoshop.mk.SeckoActivity}: java.lang.IllegalStateException: Failed to initialize GeckoRuntime
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3447)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3594)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2146)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:7762)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1047)
Caused by: java.lang.IllegalStateException: Failed to initialize GeckoRuntime
at org.mozilla.geckoview.GeckoRuntime.create(GeckoRuntime.java:458)
at org.mozilla.geckoview.GeckoRuntime.create(GeckoRuntime.java:333)
at arholding.kargoshop.mk.SeckoActivity.setupGeckoView(SeckoActivity.kt:23)
at arholding.kargoshop.mk.SeckoActivity.onCreate(SeckoActivity.kt:19)
at android.app.Activity.performCreate(Activity.java:7981)
at android.app.Activity.performCreate(Activity.java:7970)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
This exception will be thrown if there is already an active Gecko instance running. There are many ways to resolve this problem.
Solution 1: Get the default runtime for the given context.
Change your code from
val runtime = GeckoRuntime.create(this)
to
val runtime = GeckoRuntime.getDefault(this)
Solution 2: Kill the process when exit app by finishing activity, add this code into your activity.
override fun onDestroy() {
Process.killProcess(Process.myPid())
super.onDestroy()
}
Solution 3: Only create a new instance if there is no active instance running
private fun setupGeckoView() {
if (geckoRuntime == null) {
geckoRuntime = GeckoRuntime.create(this)
}
geckoSession.open(geckoRuntime!!)
geckoView.setSession(geckoSession)
val url = String(Base64.decode(MYURL, Base64.DEFAULT))
geckoSession.loadUri(url)
geckoSession.progressDelegate = createProgressDelegate()
geckoSession.settings.allowJavascript = true
}
companion object {
var geckoRuntime: GeckoRuntime? = null
}
I am learning kotlin. i set button click handler in the xml as shown below in the code..when the button is clicked i call the method beginSearch(), but then the App crash and i receive the below posted
error.
please let me know how to fix this error.
Activity
private fun clickHandler(v : View?) : Unit {
when(v?.id) {
R.id.btnCheckSearchResult -> beginSearch("Trump")
}
}
button:
<Button
android:id="#+id/btnCheckSearchResult"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Check Search Result"
android:layout_below="#id/etSearchEntry"
android:onClick="clickHandler"/>
error:
--------- beginning of crash
2019-07-09 15:02:06.146 14883-14883/com.example.retrofitkotlin_v10 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.retrofitkotlin_v10, PID: 14883
java.lang.IllegalStateException: Could not find method clickHandler(View) in a parent or ancestor Context for android:onClick attribute defined on view class android.support.v7.widget.AppCompatButton with id 'btnCheckSearchResult'
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.resolveMethod(AppCompatViewInflater.java:424)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:381)
at android.view.View.performClick(View.java:6256)
at android.view.View$PerformClick.run(View.java:24701)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
java.lang.IllegalStateException: Could not find method
clickHandler(View) in a parent or ancestor Context for android:onClick
attribute defined on view class
android.support.v7.widget.AppCompatButton with id
'btnCheckSearchResult'
Remove android:onClick="clickHandler" from XML
And try with
btnCheckSearchResult.setOnClickListener {
beginSearch("Trump")
}
And
import kotlinx.android.synthetic.main.your_layout.*
Function must be public (or protected).
public fun clickHandler(v : View?) : Unit {
when(v?.id) {
R.id.btnCheckSearchResult -> beginSearch("Trump")
}
}
P.S - You could also use setOnClickListener as the other answers have pointed out.
Just use
btnCheckSearchResult.setOnClickListener {
beginSearch("Trump")
}
or
btnCheckSearchResult.setOnClickListener({
beginSearch("Trump")
})
make your function public
public fun clickHandler(v : View?) : Unit {
when(v?.id) {
R.id.btnCheckSearchResult -> beginSearch("Trump")
}
}