Native ads not loading on certain Android devices
#852 aperta il 7 mag 2026
Metriche repository
- Star
- (1010 stelle)
- Metriche merge PR
- (Metriche PR in attesa)
Descrizione
What happened?
Native ads load correctly when I use TestIds.NATIVE.
With my real AdMob Native Advanced ad unit, ads do not show on an Android 13 device, but the same real ad unit works on Android 15.
From logcat, I consistently see:
Ads I Ad failed to load : 3
import React, { useEffect, useRef, useState } from 'react'; import { Text, StyleSheet, Image, Platform, View } from 'react-native'; import { useSelector } from 'react-redux'; import { NativeAd, NativeAdView, NativeAsset, NativeAssetType, NativeMediaView, TestIds, } from 'react-native-google-mobile-ads';
const adUnitId = DEV ? TestIds.NATIVE : Platform.OS === 'ios' ? 'ca-app-pub-9xxx' : 'ca-app-pub-9xxx';
const AD_LOAD_TIMEOUT_MS = 12000; const MAX_AD_LOAD_ATTEMPTS = 2;
const wait = (delay: number) => new Promise(resolve => { setTimeout(resolve, delay); });
const createNativeAdWithTimeout = async () => { let timeoutId: ReturnType | null = null; let timedOut = false;
try { const requestPromise = NativeAd.createForAdRequest(adUnitId) .then(ad => { if (timedOut) { ad.destroy(); return null; }
return ad;
})
.catch(error => {
if (timedOut) {
console.log('Native ad failed after timeout', {
adUnitId,
isDevMode: __DEV__,
errorCode: error?.code ?? error?.errorCode,
errorMessage: error?.message ?? error?.nativeErrorMessage,
});
return null;
}
throw error;
});
return await Promise.race([
requestPromise,
new Promise<null>(resolve => {
timeoutId = setTimeout(() => {
timedOut = true;
console.log('Native ad timed out', { adUnitId, isDevMode: __DEV__ });
resolve(null);
}, AD_LOAD_TIMEOUT_MS);
}),
]);
} finally { if (timeoutId) { clearTimeout(timeoutId); } } };
const NativeAdComponent = () => { const userData = useSelector((state: any) => state.userData?.userData); const hasSubscribed = Boolean(userData?.hasSubscribed); const [nativeAd, setNativeAd] = useState<NativeAd | null>(null); const [loading, setLoading] = useState(true); const activeAdRef = useRef<NativeAd | null>(null);
useEffect(() => { let isMounted = true;
const loadAd = async () => {
setLoading(true);
if (hasSubscribed) {
activeAdRef.current?.destroy();
activeAdRef.current = null;
setNativeAd(null);
setLoading(false);
return;
}
for (let attempt = 1; attempt <= MAX_AD_LOAD_ATTEMPTS; attempt += 1) {
try {
const ad = await createNativeAdWithTimeout();
if (!isMounted) {
ad?.destroy();
return;
}
if (ad) {
console.log('Native ad loaded', {
platform: Platform.OS,
adUnitId,
attempt,
});
if (activeAdRef.current && activeAdRef.current !== ad) {
activeAdRef.current.destroy();
}
activeAdRef.current = ad;
setNativeAd(ad);
setLoading(false);
return;
}
console.log('Native ad request returned no ad', {
platform: Platform.OS,
adUnitId,
attempt,
});
} catch (e: any) {
console.log('Native Ad attempt failed', {
platform: Platform.OS,
adUnitId,
attempt,
errorCode: e?.code ?? e?.errorCode,
errorMessage: e?.message ?? e?.nativeErrorMessage,
});
}
if (attempt < MAX_AD_LOAD_ATTEMPTS) {
await wait(1500 * attempt);
}
}
if (isMounted) {
setLoading(false);
}
};
loadAd();
return () => {
isMounted = false;
activeAdRef.current?.destroy();
activeAdRef.current = null;
};
}, [hasSubscribed]);
if (hasSubscribed) { return null; }
if (loading || !nativeAd) { return null; }
return ( {nativeAd.icon && ( <Image source={{ uri: nativeAd.icon.url }} style={styles.icon} /> )} {nativeAd.headline} Sponsored {nativeAd.body && {nativeAd.body}} {nativeAd.callToAction && ( {nativeAd.callToAction} )} ); };
const styles = StyleSheet.create({ container: { backgroundColor: '#FFFFFF', borderRadius: 8, padding: 12, width: '100%', minHeight: 300, alignSelf: 'center', borderBottomColor: '#E5E5E5', borderBottomWidth: 1, overflow: 'hidden', }, sponsored: { fontSize: 12, color: '#888', marginBottom: 6, }, header: { flexDirection: 'row', alignItems: 'center', marginBottom: 8, }, headerText: { flex: 1, }, icon: { width: 40, height: 40, borderRadius: 8, marginRight: 10, }, headline: { fontSize: 16, fontWeight: '600', flex: 1, }, media: { width: '100%', height: 180, borderRadius: 10, marginVertical: 8, }, body: { fontSize: 14, color: '#444', marginVertical: 6, }, cta: { alignSelf: 'flex-start', paddingHorizontal: 14, paddingVertical: 8, borderRadius: 6, fontWeight: '600', marginTop: 8, }, });
export default NativeAdComponent;
Platforms
Only on Android
React Native Info
ystem:
OS: macOS 26.4.1
CPU: (8) arm64 Apple M2
Memory: 138.89 MB / 16.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 20.19.4
path: /Users/mohit/.nvm/versions/node/v20.19.4/bin/node
Yarn:
version: 1.22.19
path: /opt/homebrew/bin/yarn
npm:
version: 10.8.2
path: /Users/mohit/.nvm/versions/node/v20.19.4/bin/npm
Watchman:
version: 2024.12.02.00
path: /opt/homebrew/bin/watchman
Managers:
CocoaPods:
version: 1.16.2
path: /Users/mohit/.gem/ruby/3.2.2/bin/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 25.4
- iOS 26.4
- macOS 26.4
- tvOS 26.4
- visionOS 26.4
- watchOS 26.4
Android SDK:
API Levels:
- "29"
- "30"
- "31"
- "33"
- "34"
- "35"
- "35"
- "36"
Build Tools:
- 30.0.2
- 30.0.3
- 31.0.0
- 33.0.0
- 33.0.1
- 33.0.2
- 34.0.0
- 35.0.0
- 36.0.0
- 36.0.0
System Images:
- android-33 | Google TV Intel x86 Atom
- android-33 | Google APIs ARM 64 v8a
- android-34 | Google TV ARM 64 v8a
- android-35 | Google Play ARM 64 v8a
- android-36 | Google Play ARM 64 v8a
- android-VanillaIceCream | Google Play ARM 64 v8a
Android NDK: Not Found
IDEs:
Android Studio: 2025.2 AI-252.27397.103.2522.14617522
Xcode:
version: 26.4.1/17E202
path: /usr/bin/xcodebuild
Languages:
Java:
version: 17.0.17
path: /opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home/bin/javac
Ruby:
version: 3.2.2
path: /Users/mohit/.rubies/ruby-3.2.2/bin/ruby
npmPackages:
"@react-native-community/cli":
installed: 20.0.0
wanted: 20.0.0
react:
installed: 19.2.0
wanted: 19.2.0
react-native:
installed: 0.83.1
wanted: ^0.83.1
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: true
newArchEnabled: true
iOS:
hermesEnabled: true
newArchEnabled: true
Are your using Typescript?
- My project is using Typescript
package.json
{
"name": "GoalPost",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"lint": "eslint .",
"start": "react-native start",
"test": "jest",
"postinstall": "patch-package"
},
"dependencies": {
"@codler/react-native-keyboard-aware-scroll-view": "^2.0.1",
"@fawazahmed/react-native-read-more": "^3.0.4",
"@gorhom/bottom-sheet": "^5",
"@react-native-async-storage/async-storage": "^2.2.0",
"@react-native-firebase/app": "^23.8.3",
"@react-native-firebase/messaging": "^23.8.3",
"@react-native/new-app-screen": "0.83.0",
"@react-navigation/bottom-tabs": "^7.10.0",
"@react-navigation/elements": "^2.9.5",
"@react-navigation/native": "^7.1.28",
"@react-navigation/native-stack": "^7.10.0",
"@reduxjs/toolkit": "^2.11.2",
"@types/react-native-read-more-text": "^1.0.4",
"link-preview-js": "^4.0.0",
"moment": "^2.30.1",
"patch-package": "^8.0.1",
"postinstall-postinstall": "^2.1.0",
"react": "19.2.0",
"react-native": "^0.83.1",
"react-native-actions-sheet": "^10.1.1",
"react-native-background-timer": "^2.4.1",
"react-native-calendars": "^1.1313.0",
"react-native-controlled-mentions": "^3.1.0",
"react-native-date-picker": "^5.0.13",
"react-native-element-dropdown": "^2.12.4",
"react-native-fast-image": "^8.6.3",
"react-native-football-formation": "^1.0.11",
"react-native-football-lineup": "^0.0.3",
"react-native-gesture-handler": "^2.28.0",
"react-native-get-random-values": "^2.0.0",
"react-native-google-mobile-ads": "^16.3.3",
"react-native-google-places-autocomplete": "^2.6.4",
"react-native-hyperlink": "^0.1.2",
"react-native-iap": "^13.0.4",
"react-native-image-crop-picker": "^0.51.1",
"react-native-linear-gradient": "^2.8.3",
"react-native-otp-textinput": "^1.1.7",
"react-native-pager-view": "^8.0.0",
"react-native-parsed-text": "^0.0.22",
"react-native-permissions": "^5.4.4",
"react-native-phone-number-input": "^2.1.0",
"react-native-reanimated": "^4.2.1",
"react-native-reanimated-carousel": "^4.0.3",
"react-native-safe-area-context": "^5.6.2",
"react-native-screens": "^4.19.0",
"react-native-see-more-inline": "^1.3.0",
"react-native-svg": "^15.15.1",
"react-native-toast-notifications": "^3.4.0",
"react-native-webview": "^13.16.0",
"react-native-worklets": "^0.7.2",
"react-redux": "^9.2.0",
"redux": "^5.0.1",
"redux-persist": "^6.0.0",
"redux-saga": "^1.4.2",
"socket.io-client": "^4.8.3"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@babel/preset-env": "^7.25.3",
"@babel/runtime": "^7.25.0",
"@react-native-community/cli": "20.0.0",
"@react-native-community/cli-platform-android": "20.0.0",
"@react-native-community/cli-platform-ios": "20.0.0",
"@react-native/babel-preset": "0.83.0",
"@react-native/eslint-config": "0.83.0",
"@react-native/metro-config": "0.83.0",
"@react-native/typescript-config": "0.83.0",
"@types/jest": "^29.5.13",
"@types/react": "^19.2.0",
"@types/react-test-renderer": "^19.1.0",
"eslint": "^8.19.0",
"jest": "^29.6.3",
"prettier": "2.8.8",
"react-native-svg-transformer": "^1.5.2",
"react-test-renderer": "19.2.0",
"typescript": "^5.8.3"
},
"engines": {
"node": ">=20"
}
}
app.json
{
"name": "GoalPost",
"displayName": "GoalPost",
"react-native-google-mobile-ads": {
"ios_app_id":"ca-app-pub-9639796024445418~2891414222",
"android_app_id": "ca-app-pub-9639796024445418~6954820301",
"delay_app_measurement_init": false,
"optimize_initialization": true,
"optimize_ad_loading": true,
"sk_ad_network_items": [
"cstr6suwn9.skadnetwork",
"4fzdc2evr5.skadnetwork",
"2fnua5tdw4.skadnetwork",
"ydx93a7ass.skadnetwork",
"p78axxw29g.skadnetwork",
"v72qych5uu.skadnetwork",
"ludvb6z3bs.skadnetwork",
"cp8zw746q7.skadnetwork",
"3sh42y64q3.skadnetwork",
"c6k4g5qg8m.skadnetwork",
"s39g8k73mm.skadnetwork",
"3qy4746246.skadnetwork",
"f38h382jlk.skadnetwork",
"hs6bdukanm.skadnetwork",
"mlmmfzh3r3.skadnetwork",
"v4nxqhlyqp.skadnetwork",
"wzmmz9fp6w.skadnetwork",
"su67r6k2v3.skadnetwork",
"yclnxrl5pm.skadnetwork",
"t38b2kh725.skadnetwork",
"7ug5zh24hu.skadnetwork",
"gta9lk7p23.skadnetwork",
"vutu7akeur.skadnetwork",
"y5ghdn5j9k.skadnetwork",
"v9wttpbfk9.skadnetwork",
"n38lu8286q.skadnetwork",
"47vhws6wlr.skadnetwork",
"kbd757ywx3.skadnetwork",
"9t245vhmpl.skadnetwork",
"a2p9lx4jpn.skadnetwork",
"22mmun2rn5.skadnetwork",
"44jx6755aq.skadnetwork",
"k674qkevps.skadnetwork",
"4468km3ulz.skadnetwork",
"2u9pt9hc89.skadnetwork",
"8s468mfl3y.skadnetwork",
"klf5c3l5u5.skadnetwork",
"ppxm28t8ap.skadnetwork",
"kbmxgpxpgc.skadnetwork",
"uw77j35x4d.skadnetwork",
"578prtvx9j.skadnetwork",
"4dzt52r2t5.skadnetwork",
"tl55sbb4fm.skadnetwork",
"c3frkrj4fj.skadnetwork",
"e5fvkxwrpn.skadnetwork",
"8c4e2ghe7u.skadnetwork",
"3rd42ekr43.skadnetwork",
"97r2b46745.skadnetwork",
"3qcr597p9d.skadnetwork"
]
}
}
ios/Podfile
# Resolve react_native_pods.rb with node to allow for hoisting
# require Pod::Executable.execute_command('node', ['-p',
# 'require.resolve(
# "react-native/scripts/react_native_pods.rb",
# {paths: [process.argv[1]]},
# )', __dir__]).strip
def node_require(script)
# Resolve script with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
"require.resolve(
'#{script}',
{paths: [process.argv[1]]},
)", __dir__]).strip
end
node_require('react-native/scripts/react_native_pods.rb')
node_require('react-native-permissions/scripts/setup.rb')
platform :ios, min_ios_version_supported
prepare_react_native_project!
# linkage = ENV['USE_FRAMEWORKS']
# if linkage != nil
# Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
# use_frameworks! :linkage => linkage.to_sym
# end
use_frameworks! :linkage => :static
setup_permissions([
'LocationAlways',
'LocationWhenInUse',
'Camera',
'PhotoLibrary',
])
target 'GoalPost' do
config = use_native_modules!
pod 'GoogleUtilities', :modular_headers => true
use_react_native!(
:path => config[:reactNativePath],
# An absolute path to your application root.
:app_path => "#{Pod::Config.instance.installation_root}/.."
)
post_install do |installer|
react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false,
# :ccache_enabled => true
)
# Fix Xcode 16 / fmt compile error
installer.pods_project.targets.each do |target|
if target.name == 'fmt'
target.build_configurations.each do |config|
config.build_settings['CLANG_CXX_LANGUAGE_STANDARD'] = 'c++17'
end
end
end
end
end
android/build.gradle
buildscript {
ext {
buildToolsVersion = "36.0.0"
minSdkVersion = 24
compileSdkVersion = 36
targetSdkVersion = 36
ndkVersion = "27.1.12297006"
kotlinVersion = "2.1.20"
}
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin")
classpath 'com.google.gms:google-services:4.4.4'
}
}
apply plugin: "com.facebook.react.rootproject"
android/app/build.gradle
apply plugin: "com.android.application"
apply plugin: "org.jetbrains.kotlin.android"
apply plugin: "com.facebook.react"
apply plugin: 'com.google.gms.google-services'
autolinkLibrariesWithApp()
}
def enableProguardInReleaseBuilds = false
def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+'
android {
ndkVersion rootProject.ext.ndkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
compileSdk rootProject.ext.compileSdkVersion
namespace "com.football.goalpost"
defaultConfig {
applicationId "com.football.goalpost"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 7
versionName "1.0"
missingDimensionStrategy 'store', 'play'
}
signingConfigs {
debug {
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://reactnative.dev/docs/signed-apk-android.
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
}
dependencies {
// The version of react-native is set by the React Native Gradle Plugin
implementation("com.facebook.react:react-android")
// implementation project(path: ':react-native-iap')
implementation 'com.facebook.fresco:animated-gif:3.6.0'
implementation project(':react-native-fast-image')
if (hermesEnabled.toBoolean()) {
implementation("com.facebook.react:hermes-android")
} else {
implementation jscFlavor
}
}
android/settings.gradle
pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") }
plugins { id("com.facebook.react.settings") }
extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
rootProject.name = 'GoalPost'
include ':app'
includeBuild('../node_modules/@react-native/gradle-plugin')
include ':react-native-fast-image'
project(':react-native-fast-image').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fast-image/android')
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="${usesCleartextTraffic}"
android:supportsRtl="true">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize"
android:screenOrientation="portrait"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>