Skip to main content

Setting up an App Open Ad - View-Based

App Open Ads have two possible flows designed to be used together: Cold start and Resuming from background.

Cold start (Splash screen)

The first approach allows you monetise the loading screen of your app. When the user opens the app, the splash screen is displayed. While your app is loading, our SDK will load an Ad. If the ad is loaded in time you can control whether the ad is displayed before the home screen of your app is displayed. The example below is taken from our demo app:
class SplashViewModel(
    private val adManager: CIAppOpenAdManager
) : ViewModel() {
...

    fun load(context: Context) {
        val configuration = CIMobileAdsConfiguration.Builder(publisherId = "<PUBLISHER-ID>")
            .enableAppOpen(placementID = "<PLACEMENT-ID>") // Enable App Open Ads
            .setDebugFeature(true)
            .build()

        backgroundScope.launch {
            // Initialise the ContentIgniteMobile SDK on a background thread.
            val status = CIMobileAds.initialise(
                context = context,
                configuration = configuration
            )
            when (status) {
                CIInitialisationStatus.Succeeded -> {
                    println("CIMobileAds Initialised Successfully")
                    loadAd(context)
                }
                CIInitialisationStatus.Failed -> {
                    println("CIMobileAds Initialisation Failed")
                    _state.update { SplashState.NavigateToHome }
                }
            }
        }
    }

    private fun loadAd(context: Context) {
        adManager.loadAd(context)
        viewModelScope.launch {
            val adLoaded = withTimeout(AD_LOAD_TIMEOUT_MS) {
                adManager.state.first { event ->
                    event == AppOpenState.LOADED || event == AppOpenState.LOAD_FAILED
                } == AppOpenState.LOADED
            }
            _state.value = if (adLoaded) SplashState.AdReady else SplashState.NavigateToHome
        }
    }

    fun showAd(activity: Activity) {
        adManager.show(activity = activity)
        viewModelScope.launch {
            adManager.state.first { it == AppOpenState.DISMISSED || it == AppOpenState.LOAD_FAILED }
            _state.update { SplashState.NavigateToHome }
        }
    }
...
}
You will notice that in this example the SDK initialisation is now performed on Splash Screen and to enable App Open Ads you must use enableAppOpen(placementID: String) in the SDK configuration builder. Passing in the placement ID which will be supplied to you by Content Ignite. From the UI we can control when the ad is shown by responding to the state updates:
class SplashFragment: Fragment(R.layout.fragment_splash) {
...

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    _binding = FragmentSplashBinding.bind(view)

    val navController = findNavController()
    router = AppRouter(navController)

    viewLifecycleOwner.lifecycleScope.launch {
        viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
            viewModel.state.collect { state ->
                when (state) {
                    is SplashState.Loading -> {
                        binding.progressIndicator.isVisible = true
                        viewModel.load(requireContext())
                    }
                    is SplashState.AdReady -> {
                        binding.progressIndicator.isVisible = false
                        viewModel.showAd(requireActivity())
                    }
                    is SplashState.NavigateToHome -> {
                        router.navigateToHome()
                    }
                }
            }
        }
    }
}
...

Resuming from background

For this approach we need to listen to application lifecycle callbacks. The recommended approach is to create a class which inherits Application. Then implement both the DefaultLifecycleObserver and Application.ActivityLifecycleCallbacks interfaces.
class App: Application(), Application.ActivityLifecycleCallbacks, DefaultLifecycleObserver { ... }
Inside the App class implement onCreate() and register the Activity Lifecycle Callbacks:
private lateinit var adManager: CIAppOpenAdManager

override fun onCreate() {
    super<Application>.onCreate()

    adManager = CIAppOpenAdManager

    ProcessLifecycleOwner.get().lifecycle.addObserver(this)
    registerActivityLifecycleCallbacks(this)
}
To keep track of the current Activity, we use the ActivityLifecycleCallbacks:
private var currentActivity: Activity? = null


override fun onActivityStarted(activity: Activity) {
    if (!CIAppOpenAdManager.isShowingAd()) {
        currentActivity = activity
    }
}

override fun onActivityResumed(activity: Activity) { currentActivity = activity }

override fun onActivityPaused(activity: Activity) { currentActivity = null }
Finally we implement onStart() which gets called when the app resumes from the background, and we use the CIAppOpenAdManager to show the ad if one is available and otherwise load the ad for the next opportunity.
override fun onStart(owner: LifecycleOwner) {
    super.onStart(owner)
    currentActivity?.let {
        if (adManager.isAdAvailable()) {
            adManager.show(it)
        } else {
            adManager.loadAd(this@App)
        }
    }
}
Full example code here.