Aller au contenu principal
Version: 6.x.x

App Open Ads

Overview

App open ads are full-screen ads designed to appear during app launch moments. They are similar to interstitial ads but are specifically tailored for two key scenarios:

Cold start — When the user opens the app fresh (not previously in memory). See Handling Cold Starts with Loading Screens for implementation details.

Soft launch — When the user returns to the app from the background. The app is still in memory but was suspended.

In both cases, the ad is displayed before the user reaches the main content. Users can dismiss the ad at any time.

Implementation Steps

At a high level, integrating app open ads involves the following:

  1. Build a manager class that preloads an ad so it's ready when needed.
  2. Display the ad when the app comes to the foreground.
  3. React to ad lifecycle and presentation callbacks.

Create an App Open Ad

Implement a Manager Class

App open ads should appear immediately when the user opens or returns to your app, so it's important to have the ad loaded and ready before it's needed. The best approach is to create a manager class that takes care of loading ads ahead of time, checking whether a loaded ad is still valid, and displaying it at the right moment.

Create a class called AppOpenAdManager:

import android.app.Activity;
import com.azerion.bluestack.appopen.AppOpenAd;
import com.azerion.bluestack.appopen.AppOpenAdListener;

public class AppOpenAdManager implements AppOpenAdListener {

private static final String TAG = "AppOpenAdManager";

private ActivityContextProvider activityContextProvider;
private AppOpenAd appOpenAd;
private OnShowAdCompleteListener onShowAdCompleteListener;

public boolean isShowingAd = false;

public AppOpenAdManager(ActivityContextProvider activityContextProvider) {
this.activityContextProvider = activityContextProvider;
}

public interface OnShowAdCompleteListener {
void onShowAdComplete();
}

public interface ActivityContextProvider {
Activity getActivity();
}

private void initializeAppOpenAd() {
if (appOpenAd == null) {
appOpenAd = new AppOpenAd("APP_OPEN_PLACEMENT_ID");
appOpenAd.setAppOpenAdListener(this);
}
}
}

Standalone Creation

To create an app open ad directly, instantiate an AppOpenAd with a placement ID.

import com.azerion.bluestack.appopen.AppOpenAd;

public class MainActivity extends AppCompatActivity {

private AppOpenAd appOpenAd;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

appOpenAd = new AppOpenAd("APP_OPEN_PLACEMENT_ID");
}
}

Load an App Open Ad

With AppOpenAdManager

The recommended way to load an app open ad is through the AppOpenAdManager class. Add the loadAd() method to the manager class:

public void loadAd(Activity activity) {
initializeAppOpenAd();
appOpenAd.load(activity);
}

Standalone Loading

App open ads can be loaded by calling the load(activity) method:

appOpenAd.load(activity);
info

Ad load call will preload an ad before you show it so that ads can be shown with zero latency when needed. This preloaded ad will expire after a certain period. If you try to show an expired ad, you will get AdError.AD_EXPIRED error in the onAdFailedToDisplay callback. Once the ad expires, you can call load again using the existing instance to preload a new ad.

Show an Ad

With AppOpenAdManager

Before showing the ad, the manager checks whether an ad is already on screen. Add these methods to the AppOpenAdManager class:

public void showAdIfAvailable(Activity activity) {
showAdIfAvailable(activity, new OnShowAdCompleteListener() {
@Override
public void onShowAdComplete() {
// Empty because the user will go back to the activity that shows the ad.
}
});
}

public void showAdIfAvailable(Activity activity, OnShowAdCompleteListener onShowAdCompleteListener) {
initializeAppOpenAd();

if (isShowingAd) {
Log.d(TAG, "The app open ad is already showing.");
return;
}

if (appOpenAd == null || !appOpenAd.isReady()) {
onShowAdCompleteListener.onShowAdComplete();
loadAd(activity);
return;
}

this.onShowAdCompleteListener = onShowAdCompleteListener;
isShowingAd = true;
appOpenAd.show(activity);
}

Standalone Showing

To show an app open ad directly, check isReady() on the AppOpenAd instance and call show(activity).

if (appOpenAd != null && appOpenAd.isReady()) {
appOpenAd.show(activity);
}

Show the Ad During App Foregrounding

To display the ad whenever the user returns to your app, implement a lifecycle observer in your Application class. Create a custom Application class that integrates with Android's lifecycle callbacks:

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.azerion.bluestack.MobileAds;

public class MyApplication extends Application
implements Application.ActivityLifecycleCallbacks,
DefaultLifecycleObserver,
AppOpenAdManager.ActivityContextProvider {

private AppOpenAdManager appOpenAdManager;
private Activity currentActivity;

@Override
public void onCreate() {
super.onCreate();
appOpenAdManager = new AppOpenAdManager(this);
registerActivityLifecycleCallbacks(this);
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}

@Override
public void onActivityStarted(Activity activity) {
if (!appOpenAdManager.isShowingAd) {
currentActivity = activity;
}
}

@Override
public void onStart(LifecycleOwner owner) {
if (MobileAds.isInitialized() && currentActivity != null) {
// Don't show app open ad on launcher/splash activities
// as they manage their own app open ad flow
boolean shouldShowAd = !(currentActivity instanceof CustomLauncherActivity) &&
!(currentActivity instanceof SplashScreenActivity);

if (shouldShowAd) {
appOpenAdManager.showAdIfAvailable(currentActivity);
}
}
}

public void loadAd(Activity activity) {
appOpenAdManager.loadAd(activity);
}

public void showAdIfAvailable(Activity activity,
AppOpenAdManager.OnShowAdCompleteListener listener) {
appOpenAdManager.showAdIfAvailable(activity, listener);
}

@Override
public Activity getActivity() {
return currentActivity;
}

// Other ActivityLifecycleCallbacks methods...
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}

@Override
public void onActivityResumed(Activity activity) {}

@Override
public void onActivityPaused(Activity activity) {}

@Override
public void onActivityStopped(Activity activity) {}

@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}

@Override
public void onActivityDestroyed(Activity activity) {}
}

Don't forget to register your custom Application class in the AndroidManifest.xml:

<manifest>
<application
android:name=".MyApplication"
... >
...
</application>
</manifest>

Destroying an App Open Ad

When you have finished displaying an app open ad, call destroy() to free resources.

@Override
protected void onDestroy() {
if (appOpenAd != null) {
appOpenAd.destroy();
appOpenAd = null;
}
super.onDestroy();
}

Handling Cold Starts with Loading Screens

The examples above focus on showing app open ads when users return to an app that is already in memory (soft launch). Cold starts — when the app is launched fresh and was not previously in memory — require additional consideration.

During a cold start, there is no previously loaded ad ready to show immediately. The delay between requesting an ad and receiving one can create a situation where the user briefly sees app content before an ad unexpectedly appears. This is a poor user experience and should be avoided.

The recommended approach is to use a loading or splash screen during the app's startup sequence and only show the app open ad while that screen is still visible. Here's an example implementation:

import android.content.Intent;
import android.os.Bundle;
import android.os.CountDownTimer;
import androidx.appcompat.app.AppCompatActivity;
import com.azerion.bluestack.MobileAds;
import com.azerion.bluestack.initialization.InitializationListener;
import com.azerion.bluestack.initialization.SDKInitializationStatus;
import java.util.concurrent.TimeUnit;

public class CustomLauncherActivity extends AppCompatActivity {

private static final String TAG = "CustomLauncherActivity";
// Simulate app loading time (5 seconds)
private static final long COUNTER_TIME_MILLISECONDS = 5000L;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);

initializeCMP();
}

private void initializeCMP() {
// Initialize your Consent Management Platform here
// Once consent is obtained, initialize BlueStack SDK
initializeBlueStackSDK();
}

private void initializeBlueStackSDK() {
MobileAds.setDebugModeEnabled(true);
MobileAds.initialize(this, "YOUR_APP_ID", new InitializationListener() {
@Override
public void onInitialized(SDKInitializationStatus status) {
// Load the app open ad after initialization
((MyApplication) getApplication()).loadAd(CustomLauncherActivity.this);
}
});
createTimer();
}

private void navigateToMainActivity() {
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
}

private void createTimer() {
new CountDownTimer(COUNTER_TIME_MILLISECONDS, 1000) {
@Override
public void onTick(long millisUntilFinished) {
Log.d(TAG, "App is done loading in: " +
(TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) + 1));
}

@Override
public void onFinish() {
// Show the app open ad when the splash screen is ready to dismiss
((MyApplication) getApplication()).showAdIfAvailable(
CustomLauncherActivity.this,
new AppOpenAdManager.OnShowAdCompleteListener() {
@Override
public void onShowAdComplete() {
navigateToMainActivity();
}
}
);
}
}.start();
}
}

Follow these guidelines:

  • Allocate sufficient time for ad loading. Set your timer duration to give the SDK enough time to load the ad. In the example above, 5 seconds is typically sufficient. Adjust based on your app's needs and expected network conditions.
  • Show the ad from the loading screen only. If your app finishes loading and has already moved the user to the main content, do not show the ad — the moment has passed.
  • Dismiss the loading screen in onShowAdComplete. Wait for the callback before transitioning to app content. This ensures a smooth flow from splash screen → ad → app content with no flicker or content flash in between.

Ad events

Register for app open events

AppOpenAd delivers lifecycle and presentation events through the AppOpenAdListener interface, which includes both load-related and display-related callbacks. Use the setAppOpenAdListener() method to register your listener:

appOpenAd.setAppOpenAdListener(this);

App Open ad lifecycle events

AppOpenAdListener notifies you when the ad has finished loading or when a load attempt fails. On failure, reset state and attempt to reload when appropriate.

public class AppOpenAdManager implements AppOpenAdListener {

// ...

@Override
public void onAdLoaded() {
Log.i(TAG, "App open ad loaded");
}

@Override
public void onAdFailedToLoad(Exception exception) {
Log.e(TAG, "App open ad failed to load", exception);
}
}

App Open ad full-screen events

AppOpenAdListener also reports when the ad is displayed, clicked, dismissed, or fails to display. After the ad is dismissed or fails to display, reset state, notify the listener, and immediately start loading a new ad so one is ready for the next app foregrounding.

public class AppOpenAdManager implements AppOpenAdListener {

// ...

@Override
public void onAdDisplayed() {
Log.i(TAG, "App open ad displayed");
}

@Override
public void onAdFailedToDisplay(Exception exception) {
Log.e(TAG, "App open ad failed to display", exception);
isShowingAd = false;
if (onShowAdCompleteListener != null) {
onShowAdCompleteListener.onShowAdComplete();
}
Activity activity = activityContextProvider.getActivity();
if (activity != null) {
loadAd(activity);
}
}

@Override
public void onAdClicked() {
Log.i(TAG, "App open ad clicked");
}

@Override
public void onAdDismissed() {
Log.i(TAG, "App open ad dismissed");
isShowingAd = false;
if (onShowAdCompleteListener != null) {
onShowAdCompleteListener.onShowAdComplete();
}
Activity activity = activityContextProvider.getActivity();
if (activity != null) {
loadAd(activity);
}
}
}

Best Practices

App open ads are a great way to monetize your app's loading screen, but it's important to follow best practices so that your users continue to enjoy using your app:

  • Show ads only during natural waiting moments. App open ads work best when users are already expecting a brief pause, such as during app launch or when returning from the background. Avoid surprising users with ads at unexpected times.
  • Always show a splash or loading screen first. See Handling Cold Starts with Loading Screens for details.
  • Initialize the SDK before loading ads. Make sure the BlueStack SDK has fully initialized before you attempt to load an app open ad. Loading ads before initialization may result in failed requests.
  • Preload the ad early. Load the ad as soon as possible so there is no delay when it's time to show it. Avoid loading other ad formats in parallel, as this can strain device resources and reduce fill rates.
  • Respect user experience with frequency controls. See Control Ad Frequency for recommended strategies.
  • Be mindful of new users. Hold off on showing app open ads until users have opened and used your app a few times. This helps build a positive first impression before introducing ads.
  • Handle ad expiration. See Consider Ad Expiration for details on how to manage preloaded ad validity.
  • Coordinate your loading screen with the ad. If you have a loading screen running behind the app open ad and it finishes before the user dismisses the ad, dismiss the loading screen in the onAdDismissed callback to ensure a smooth transition to your app content.

Consider Ad Expiration

A preloaded ad can become stale if too much time passes between loading and displaying. The BlueStack SDK handles ad expiration internally. If you attempt to show an expired ad, you will receive an AdError.AD_EXPIRED error in the onAdFailedToDisplay() callback.

When this occurs, clean up the expired ad reference and call loadAd() to preload a fresh ad for the next opportunity.

Control Ad Frequency

To maintain a positive user experience, avoid showing an app open ad on every single foreground event. Consider implementing frequency controls such as:

  • Skip opportunities — Show an ad on every second or third app open instead of every time.
  • Minimum background duration — Only show an ad if the user was away from the app for a certain amount of time (e.g., 30 seconds, 2 minutes, or 15 minutes).
  • Cooldown after cold start — If you showed an ad during a cold start, skip soft launch ads for a set period afterward.
  • Frequency caps — Limit the total number of app open ads shown per session or per day. Where possible, tailor caps based on user cohorts or engagement levels.