AdMob App Open Ad with Splash Screen in Android Studio (Kotlin)

App Open Ads are a special type of AdMob ad format designed to appear when users launch or switch back to your app. These ads don’t interrupt gameplay or user flow — they are shown during app startup or loading time, typically on the Splash Screen.

Image: by Google

App Open Ads automatically adapt to screen sizes and display a small branding area, ensuring your app logo or splash design remains visible during loading.

Image: by Google

Step-by-Step Implementation (Kotlin)

1. Add Dependencies:

// Lifecycle
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.9.4")
implementation("androidx.lifecycle:lifecycle-process:2.9.4")
// AdMob SDK
implementation("com.google.android.gms:play-services-ads:24.7.0")


2. Create MyApplication:

import android.app.Application
import com.example.hindianimetv.R
import com.google.android.gms.ads.MobileAds

class MyApplication : Application() {

lateinit var appOpenAdManager: AppOpenAdManager
private set

override fun onCreate() {
super.onCreate()

// Initialize Ads SDK
MobileAds.initialize(this)

// Create App Open Ad Manager
val adUnitId = getString(R.string.admob_AppOpenId) // Open Ad Id
appOpenAdManager = AppOpenAdManager(this, adUnitId)
}
}


3. Declare in AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>

<application
android:name=".util.MyApplication"
...
        <activity
android:name=".ui.activity.SplashActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
        ...
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="@string/admob_AppId" />

</application>
</manifest>


4.Create AppOpenManager:

import android.app.Activity
import android.app.Application
import android.os.Bundle
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
import com.example.hindianimetv.ui.activity.SplashActivity
import com.google.android.gms.ads.AdError
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.FullScreenContentCallback
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.appopen.AppOpenAd
import java.util.Date
class AppOpenAdManager(
private val application: Application,
private val adUnitId: String
) : Application.ActivityLifecycleCallbacks, DefaultLifecycleObserver {

private var appOpenAd: AppOpenAd? = null
private var currentActivity: Activity? = null
private var isShowingAd = false
private var loadTime: Long = 0
private var isLoadingAd = false

init {
application.registerActivityLifecycleCallbacks(this)
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
}

// Ad Checking
private fun isAdAvailable(): Boolean {
return appOpenAd != null && wasLoadTimeLessThanNHoursAgo()
}

private fun wasLoadTimeLessThanNHoursAgo(): Boolean {
val diff = Date().time - loadTime
return diff < 4 * 3600000L // 4 Hour
}

// Loading App Open Ad
fun fetchAd() {
if (isLoadingAd || isAdAvailable()) return

isLoadingAd = true
val request = AdRequest.Builder().build()

AppOpenAd.load(
application,
adUnitId,
request,
object : AppOpenAd.AppOpenAdLoadCallback() {
override fun onAdLoaded(ad: AppOpenAd) {
appOpenAd = ad
isLoadingAd = false
loadTime = Date().time
}

override fun onAdFailedToLoad(error: LoadAdError) {
isLoadingAd = false
}
}
)
}

// Show ad if available
fun showAdIfAvailable(activity: Activity, onAdDismissed: () -> Unit = {}) {
if (isShowingAd || !isAdAvailable()) {
fetchAd()
onAdDismissed()
return
}

appOpenAd?.fullScreenContentCallback = object : FullScreenContentCallback() {
override fun onAdShowedFullScreenContent() {
isShowingAd = true
}

override fun onAdDismissedFullScreenContent() {
appOpenAd = null
isShowingAd = false
onAdDismissed()
fetchAd() // Load next ad
}

override fun onAdFailedToShowFullScreenContent(error: AdError) {
appOpenAd = null
isShowingAd = false
onAdDismissed()
fetchAd()
}
}

try {
appOpenAd?.show(activity)
} catch (_: Exception) {
onAdDismissed()
}
}

override fun onStart(owner: LifecycleOwner) {
currentActivity?.let { activity ->
if (activity !is SplashActivity && !isShowingAd) {
showAdIfAvailable(activity)
}
}
}

// Activity Lifecycle Callbacks
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}

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

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

override fun onActivityPaused(activity: Activity) {}

override fun onActivityStopped(activity: Activity) {}

override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}

override fun onActivityDestroyed(activity: Activity) {
if (currentActivity == activity) currentActivity = null
}
}


6. Create SplashActivity: 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activity.SplashActivity">

<com.google.android.material.card.MaterialCardView
android:id="@+id/logoCard"
android:layout_width="150dp"
android:layout_height="150dp"
app:cardCornerRadius="12dp"
app:cardElevation="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:strokeWidth="0dp">

<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/ic_launcher_background" />
</com.google.android.material.card.MaterialCardView>

<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="8dp"
android:layout_marginTop="24dp"
android:indeterminate="true"
android:layout_marginStart="26dp"
android:layout_marginEnd="26dp"
android:indeterminateTint="@color/color_primary"
android:progressDrawable="@android:drawable/progress_horizontal"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/logoCard" />


<TextView
android:id="@+id/loadingText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:text="Loading..."
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/progressBar" />

</androidx.constraintlayout.widget.ConstraintLayout>

and

import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.example.hindianimetv.R
import com.example.hindianimetv.util.MyApplication
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class SplashActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)

val app = application as MyApplication
app.appOpenAdManager.fetchAd() // Preload ad in background

lifecycleScope.launch {
delay(3000)
navigateToMain()
}
}

private fun navigateToMain() {
val app = application as MyApplication
app.appOpenAdManager.showAdIfAvailable(this) {
startActivity(Intent(this, MainActivity::class.java))
finish()
}
}
}


7. Add Ad Unit Id:

<!--  AdMob Test IDs  -->
<string name="admob_AppId">ca-app-pub-3940256099942544~3347511713</string>
<string name="admob_AppOpenId">ca-app-pub-3940256099942544/9257395921</string>


Implementing AdMob App Open Ads with a Splash Screen in Android Studio (Kotlin) is one of the smartest ways to increase app revenue without harming user experience.

No comments:

Post a Comment