I am creating an android application with Navigation Component implementation. The workflow of SplashFragment (which is startDestination) is that onViewCreated Admob Interstitial request is sent and AD displayed, on ad close i want to navigate the app to DashboardFragment. The navigation works fine when Admob AD is not displayed but after Admob AD displayed the navigation never works and UI is stuck on SplashFragment.
What i tried?
- I tried to resolve this issue by navigating the fragment
onAdShowedFullScreenContentinstead ofonAdDismissedFullScreenContentbut this results in showing a black screen before Admob AD display.
Below is my code
SplashFragment
class SplashFragment : Fragment() {
private var onFinishedFirstCall: Boolean = false
//max wait time is 10 seconds
val SPLASH_TIME_SHORT_WITHOUT_AD = 2000
private var isAdMobIntLoaded = false
var handler = Handler()
private val repository = get<Repository>()
var interstitialadMobAd: InterstitialAd? = null
var isShow = false
private val sharedViewModel: MainViewModel by sharedViewModel()
private val tinyDB = get<TinyDB>()
var isRemoteConfigLoaded = false
var isInitialSetupDone = false
var timer: CountDownTimer? = null
var counter = 4
private var timerStart = false
var remaining: Long = 6000
var isAdReqCompleted = false
override fun onCreate(savedInstanceState: Bundle?) {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.splash_screen_layout, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
nativeRemoteCheck()
}
private fun nativeRemoteCheck() {
repository.onRemoteConfigLoadedListener.observe(
viewLifecycleOwner,
object : Observer<Boolean> {
override fun onChanged(isLoaded: Boolean?) {
//reset saved ad request info which was saved to avoid ad recalls on connectivity changes
resetAdRequestInfo(tinyDB)
if (isLoaded!!) {
isRemoteConfigLoaded = true
initialScreenSetup()
}
}
})
}
private fun initialScreenSetup() {
//Remote config response receive; now proceed
//if purchased or no connectivity proceed with 2 seconds delay
val isInternetConnected = requireContext().isNetworkAvailable()
if (sharedViewModel.getIsPurchased() || !isInternetConnected) {
isInitialSetupDone = true
setupTimer(2000)
} else {
setupTimer(10000)
//not purchased and internet is also connected
sharedViewModel.getSplashIntersConfig()
.observe(viewLifecycleOwner, Observer {
if (it.show) {
isInitialSetupDone = true
//if splash interstial is enabled then send request
adMobExtensionFuntion()
} else {
isInitialSetupDone = true
//if splash interstial ad is not enabled proceed with 2 seconds delay
handler.postDelayed({
nextPage()
}, SPLASH_TIME_SHORT_WITHOUT_AD.toLong())
}
})
}
}
private fun nextPage() {
try {
val navHostFragment =
activity?.supportFragmentManager?.findFragmentById(R.id.main_navigation_graph) as NavHostFragment
val navController = navHostFragment.navController
navController.navigate(R.id.action_splash_to_dashboard)
} catch (ex: Exception) {
}
}
fun adMobExtensionFuntion() {
context?.loadAdmobInterstitial(
AdPlacement.SPLASH,
context?.getString(R.string.admob_Splash_int)!!,
{
interstitialadMobAd = it
sharedViewModel.onIntAdSuccess.postValue(true)
isAdMobIntLoaded = true
isAdReqCompleted = true
interstitialadMobAd?.fullScreenContentCallback =
object : FullScreenContentCallback() {
override fun onAdDismissedFullScreenContent() {
nextPage()
}
override fun onAdFailedToShowFullScreenContent(adError: AdError?) {
}
override fun onAdShowedFullScreenContent() {
}
}
},
{
isAdReqCompleted = true
nextPage()
}
)
}
fun setupTimer(duration: Long) {
timerStart = true
timer = object : CountDownTimer(duration, 1000) {
override fun onTick(millisUntilFinished: Long) {
Log.e("timer1 :", ": ${millisUntilFinished}")
remaining = millisUntilFinished
if (interstitialadMobAd != null) {
onFinish()
}
}
override fun onFinish() {
onFinishedFirstCall = true
if (interstitialadMobAd != null) {
interstitialadMobAd?.show(activity)
timer?.cancel()
} else {
if (interstitialadMobAd == null && !isAdReqCompleted) {
nextPage()
}
timer?.cancel()
}
}
}.start()
}
Navigation Graph
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_navigation_graph"
app:startDestination="@id/splash_fragment">
<fragment
android:id="@+id/splash_fragment"
android:name="mypkgname.ui.splash.SplashFragment"
tools:layout="@layout/splash_screen_layout">
<action
android:id="@+id/action_splash_to_dashboard"
app:destination="@id/dashboard_fragment"
/>
</fragment>
<fragment
android:id="@+id/dashboard_fragment"
android:name="mypkgname.ui.dashboard.DashboardFragment"
tools:layout="@layout/test_dashboard_layout">
<action
android:id="@+id/action_dashboard_to_videoplayer"
app:destination="@id/videoplayer_fragment"
app:enterAnim="@anim/enter_animation" />
</fragment>
<fragment
android:id="@+id/videoplayer_fragment"
android:name="mypkgname.ui.videoplayer.VideoPlayerFragment"
tools:layout="@layout/fragment_videoplayer_layout">
<action
android:id="@+id/action_videoplayer_to_dashboard"
app:destination="@id/dashboard_fragment"
app:exitAnim="@anim/nav_default_exit_anim"
/>
</fragment>
</navigation>
Please note i am using this sdk version of Admob
api 'com.google.android.gms:play-services-ads:20.4.0'
I am unable to figure out the cause of this issue. Can somebody please help me out with this.
Thank you