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