I’m building my own app in Android
I’m using Navigation component
to navigate between fragments.
It’s logged IllegalArgumentException
: Navigation action/destination cannot be found from the current destination in Crashlytics of Firebase. Testers and I have tried the test many times but haven’t been able to reproduce that problem and it didn’t crash.
Here is the log:
# Platform: android
# Version: 1.3.7 (21)
# Issue: 5e74ae9f3447101130fd8f601b280d25
# Session: 66B17B0D019100010A53E3F0F30562E7_DNE_0_v2
# Date: Tue Aug 06 2024 08:23:28 GMT+0700 (Indochina Time)
Fatal Exception: java.lang.IllegalArgumentException: Navigation action/destination com.highsecure.drawsketch.sketchpaint:id/action_mainFragment_to_dashBoardFragment cannot be found from the current destination Destination(com.highsecure.drawsketch.sketchpaint:id/featureSelectionFragment) label=fragment_feature_selection class=com.example.ardrawsketch.ui.featureselection.FeatureSelectionFragment
at androidx.navigation.NavController.navigate(NavController.kt:1691)
at androidx.navigation.NavController.navigate(NavController.kt:1609)
at androidx.navigation.NavController.navigate(NavController.kt:1591)
at androidx.navigation.NavController.navigate(NavController.kt:1574)
at com.example.ardrawsketch.ui.activity.MainActivity$setupViews$1$1$1.invokeSuspend(MainActivity.kt:54)
at com.example.ardrawsketch.ui.activity.MainActivity$setupViews$1$1$1.invoke(:12)
at com.example.ardrawsketch.ui.activity.MainActivity$setupViews$1$1$1.invoke(:8)
at kotlinx.coroutines.flow.FlowKt__ReduceKt$first$$inlined$collectWhile$2.emit(Limit.kt:142)
at kotlinx.coroutines.flow.StateFlowImpl.collect(StateFlow.kt:396)
at kotlinx.coroutines.flow.FlowKt__ReduceKt.first(Reduce.kt:213)
at kotlinx.coroutines.flow.FlowKt.first(:1)
at com.example.ardrawsketch.ui.activity.MainActivity$setupViews$1$1.invokeSuspend(MainActivity.kt:43)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:365)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25)
at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110)
at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
at kotlinx.coroutines.BuildersKt.launch(:1)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
at kotlinx.coroutines.BuildersKt.launch$default(:1)
at com.example.ardrawsketch.ui.activity.MainActivity.setupViews$lambda$0(MainActivity.kt:42)
at com.example.ardrawsketch.ui.activity.MainActivity.$r8$lambda$1WSZW11IMUxPs7-1lyyEmF1Ssik()
at com.example.ardrawsketch.ui.activity.MainActivity$$ExternalSyntheticLambda0.run(D8$$SyntheticClass)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:246)
at android.app.ActivityThread.main(ActivityThread.java:8653)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
Here is my code in version that older than 1.7.3 version:
@AndroidEntryPoint
class MainActivity :
BaseActivity<ActivityMainBinding, ActivityMainViewModel>(R.id.nav_host, R.navigation.nav_main) {
...
override fun setupViews() {
setStatusBarColor(R.color.white)
binding.main.post {
when (loginState) {
OnBoardingState.FIRST_TIME.value -> {
if (isLanguageSet) {
47 -> navHostController.navigate(R.id.action_mainFragment_to_onBoardingFragment)
} else {
navHostController.navigate(R.id.action_mainFragment_to_languageFragment)
}
}
OnBoardingState.FINISHED.value -> {
54 -> navHostController.navigate(R.id.action_mainFragment_to_dashBoardFragment)
}
}
true
}
}
...
}
Here is my 1.7.3 version code:
@AndroidEntryPoint
class MainActivity :
BaseActivity<ActivityMainBinding, ActivityMainViewModel>(R.id.nav_host, R.navigation.nav_main) {
...
override fun setupViews() {
setStatusBarColor(R.color.white)
binding.main.post {
when (loginState) {
LoginState.FIRST_TIME.value -> {
if (isLanguageSet) {
safeNavigate(
navHostController?.currentDestination?.id,
R.id.action_mainFragment_to_onBoardingFragment
)
} else {
safeNavigate(
navHostController?.currentDestination?.id,
R.id.action_mainFragment_to_languageFragment
)
}
}
LoginState.LOGGED_IN.value -> {
safeNavigate(
navHostController?.currentDestination?.id,
R.id.action_mainFragment_to_dashBoardFragment
)
}
}
}
}
...
}
abstract class BaseActivity<Binding : ViewBinding, ViewModel : androidx.lifecycle.ViewModel> :
AppCompatActivity {
@IdRes
private var navId: Int? = null
@NavigationRes
private var navResource: Int? = null
/**
* The NavController for the activity's navigation graph.
*/
protected var navHostController: NavController? = null
/**
* The ViewBinding for the activity.
*/
protected lateinit var binding: Binding
/**
* This method should return the ViewBinding for the activity.
*/
protected abstract fun getViewBinding(): Binding
/**
* The ViewModel for the activity.
*/
protected lateinit var viewModel: ViewModel
/**
* This method should return the Class object for the ViewModel.
*/
protected abstract fun getViewModelClass(): Class<ViewModel>
constructor()
constructor(@IdRes navId: Int, @NavigationRes navResource: Int) {
this.navId = navId
this.navResource = navResource
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = getViewBinding()
viewModel = ViewModelProvider(this)[getViewModelClass()]
setContentView(binding.root)
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
init()
}
private fun init() {
setupNav()
setupViews()
}
/**
* Set up the navigation for the activity.
*/
private fun setupNav() {
if (navId != null && navResource != null) {
val navHostFragment =
supportFragmentManager.findFragmentById(navId!!) as NavHostFragment
if (navHostController == null) {
navHostController = navHostFragment.navController
navHostController?.setGraph(navResource!!, intent.extras)
}
}
}
/**
* This method should set up the views for the activity.
*/
abstract fun setupViews()
protected fun safeNavigate(
currentDestination: Int?,
action: Int,
bundle: Bundle? = null
) {
if (navHostController?.currentDestination?.id == currentDestination) {
lifecycle.addObserver(object : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (event == Lifecycle.Event.ON_RESUME) {
lifecycle.removeObserver(this)
try {
navHostController?.navigate(action, bundle)
} catch (e: IllegalArgumentException) {
e.printStackTrace()
}
}
}
})
}
}
protected fun safeNavigate(
currentDestination: Int?,
action: NavDirections
) {
if (navHostController?.currentDestination?.id == currentDestination) {
lifecycle.addObserver(object : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (event == Lifecycle.Event.ON_RESUME) {
lifecycle.removeObserver(this)
try {
navHostController?.navigate(action)
} catch (e: IllegalArgumentException) {
e.printStackTrace()
}
}
}
})
}
}
}
I tried to catch the IllegalArgumentException
error but it’s still logged in the crashlytics of Firebase:
protected fun safeNavigate(
currentDestination: Int?,
action: NavDirections
) {
if (navHostController?.currentDestination?.id == currentDestination) {
lifecycle.addObserver(object : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (event == Lifecycle.Event.ON_RESUME) {
lifecycle.removeObserver(this)
try {
navHostController?.navigate(action)
} catch (e: IllegalArgumentException) {
e.printStackTrace()
}
}
}
})
}
}
VuNgN is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.