Few things are more frustrating in Android development than a third-party SDK that fails silently. If you are integrating the Meta Audience Network (formerly Facebook Audience Network) and facing "No Fill" errors, generic load failures, or immediate crashes on Android 9+ (API 28+), the issue likely stems from strict Network Security configurations or improper lifecycle initialization.
This guide provides a root cause analysis and a production-grade solution for fixing initialization failures in the Meta Audience Network SDK using Kotlin and Java.
The Symptoms
Developers typically encounter one of two scenarios when this implementation is broken:
- The "Cleartext" Crash/Error: The app runs on Android 8.0, but fails on Android 9.0+. Logs indicate
IOExceptionorCleartext HTTP traffic to ... not permitted. - The Silent Failure:
AdListener.onErrortriggers immediately with generic codes, or the SDK simply never attempts to fetch an ad.
Root Cause Analysis
1. Android 9+ Network Security Layer
Starting with Android 9 (API level 28), cleartext (HTTP) traffic is disabled by default. While Meta uses HTTPS for its core requests, the Audience Network acts as a mediator for various demand sources. Some creative assets (images/videos) or tracking pixels from third-party bidders may still rely on HTTP.
If your application does not explicitly permit cleartext traffic for these ad requests, the Android OS blocks the connection, causing the SDK to fail initialization or ad rendering.
2. The Initialization Race Condition
In older versions of the SDK, initialization was often lazy or handled implicitly during the first ad request. Modern versions of the Meta Audience Network SDK require explicit, synchronous-style initialization in your Application class.
Attempting to load a BannerAd or InterstitialAd before AudienceNetworkAds.initialize() completes successfully will result in an immediate failure.
Solution Part 1: Configuring Network Security
You must modify your Network Security Configuration to allow the SDK to fetch assets over HTTP when necessary.
Step 1: Create the XML Configuration
Create a file named network_security_config.xml in your res/xml directory.
File: res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!--
Allow cleartext traffic for ad networks.
While HTTPS is preferred, mediation often requires this generic permission
to ensure high fill rates from legacy demand partners.
-->
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
Step 2: Reference in Manifest
Apply this configuration to your AndroidManifest.xml within the <application> tag.
File: src/main/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.your.package">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name=".MyApplication"
android:networkSecurityConfig="@xml/network_security_config"
android:hardwareAccelerated="true"
...>
<!-- Meta Application ID -->
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="@string/facebook_app_id"/>
</application>
</manifest>
Note: Hardware acceleration (android:hardwareAccelerated="true") is strictly required for video ads and sophisticated creative rendering.
Solution Part 2: Explicit Initialization
You must initialize the SDK inside your custom Application class. Do not initialize this in your MainActivity; doing so risks memory leaks and race conditions if the activity is recreated.
Kotlin Implementation
File: MyApplication.kt
package com.your.package
import android.app.Application
import android.util.Log
import com.facebook.ads.AudienceNetworkAds
import com.facebook.ads.AdSettings
class MyApplication : Application() {
companion object {
private const val TAG = "MetaAdsInit"
}
override fun onCreate() {
super.onCreate()
initializeMetaAudienceNetwork()
}
private fun initializeMetaAudienceNetwork() {
// ENABLE DEBUGGING: Only for development builds.
// This provides detailed logs on why ads might not fill.
if (BuildConfig.DEBUG) {
AdSettings.turnOnSDKDebugger(this)
// Replace with your device's hash ID from Logcat
// AdSettings.addTestDevice("YOUR_DEVICE_HASH_ID")
}
if (!AudienceNetworkAds.isInitialized(this)) {
AudienceNetworkAds
.buildInitSettings(this)
.withInitListener { result ->
if (result.isSuccess) {
Log.d(TAG, "Meta Audience Network initialized successfully.")
} else {
Log.e(TAG, "Meta Initialization Failed: ${result.message}")
}
}
.initialize()
}
}
}
Java Implementation
File: MyApplication.java
package com.your.package;
import android.app.Application;
import android.util.Log;
import com.facebook.ads.AudienceNetworkAds;
import com.facebook.ads.AdSettings;
public class MyApplication extends Application {
private static final String TAG = "MetaAdsInit";
@Override
public void onCreate() {
super.onCreate();
initializeMetaAudienceNetwork();
}
private void initializeMetaAudienceNetwork() {
// Debugging configuration
if (BuildConfig.DEBUG) {
AdSettings.turnOnSDKDebugger(this);
}
if (!AudienceNetworkAds.isInitialized(this)) {
AudienceNetworkAds
.buildInitSettings(this)
.withInitListener(new AudienceNetworkAds.InitListener() {
@Override
public void onInitialized(AudienceNetworkAds.InitResult result) {
if (result.isSuccess()) {
Log.d(TAG, "Meta Audience Network initialized successfully.");
} else {
Log.e(TAG, "Meta Initialization Failed: " + result.getMessage());
}
}
})
.initialize();
}
}
}
Critical Implementation Details
The Test Mode Requirement
One of the most common reasons for "Initialization Failed" or "No Fill" during development is failing to register the test device. Meta does not serve live ads to debug builds to prevent click fraud.
- Run the app with the code above.
- Filter Logcat for "Audience Network".
- Look for a log entry resembling:
Test mode device hash: <HASH_ID>. - Add
AdSettings.addTestDevice("<HASH_ID>")before initialization.
Handling ProGuard / R8
If your release build fails to initialize while your debug build works, R8 (the code shrinker) is likely stripping required Meta SDK classes.
Ensure your proguard-rules.pro includes the standard Keep rules for the Audience Network:
-keep class com.facebook.ads.** { *; }
-dontwarn com.facebook.ads.**
Hardware Acceleration
Meta's MediaView (used for Native Ads) and Interstitial Video ads rely heavily on GPU rendering. If you have disabled hardware acceleration at the Activity or Application level to save memory, Meta ads will fail to render, often crashing the initialization process entirely. Ensure android:hardwareAccelerated="true" is set in the Manifest.
Verification
To verify the fix:
- Uninstall the existing app from the device (to clear cached preferences).
- Clean and Rebuild the project in Android Studio.
- Launch the app.
- Check Logcat for
Meta Audience Network initialized successfully.
Once you see the success log in the Application class, you can safely request ads in your Activities or Fragments.