[🐛] Bug Report Title - RewardedAd.show() The requested RewardedAd has not loaded and could not be shown - in IOS
What happened?
So I am making a basic normal 2D game in react native and I in my game if user wants more coins then he can watch Rewarded Ad, So I implemented Rewarded Ads in my Page. But the problem is The ad is not loading, it fails everytime, I tried every solution but still facing same problem.
Error : RewardedAd.show() The requested RewardedAd has not loaded and could not be shown
Here is my Wallet.Js code (I Removed the CSS from this code, so you can focus on main code) :
import React, { useEffect, useState } from "react"; import { View, Text, Image, StyleSheet, TouchableOpacity, Modal, Animated, ImageBackground, } from "react-native"; import { RewardedAd, RewardedAdEventType, TestIds } from 'react-native-google-mobile-ads';
const adUnitId = DEV ? TestIds.REWARDED : 'ca-app-pub-3764917219536492/9321659815';
export function adMobRewardedAds() { const rewardedAd = RewardedAd.createForAdRequest(adUnitId, { requestNonPersonalizedAdsOnly: true, keywords: ['xx'], });
const [isLoaded, setIsLoaded] = useState(false);
useEffect(() => { const unsubscribeLoaded = rewardedAd.addAdEventListener( RewardedAdEventType.LOADED, () => { setIsLoaded(true); } );
const unsubscribeEarned = rewardedAd.addAdEventListener(
RewardedAdEventType.EARNED_REWARD,
reward => {
console.log('User earned reward of ', reward);
}
);
rewardedAd.load();
return () => {
unsubscribeLoaded();
unsubscribeEarned();
};
}, []);
const openAd = () => { try { if (isLoaded) { rewardedAd.show(); console.log("Reward showed"); } else { throw new Error("Ad not loaded yet"); } } catch (error) { rewardedAd.load(); console.log("Ad loaded"); } };
return { isLoaded, openAd, }; }
const Wallet = ({ balance, setBalance, navigation }) => { const { isLoaded, openAd } = adMobRewardedAds(); const [showAdModal, setShowAdModal] = useState(false); const [showRewardModal, setShowRewardModal] = useState(false); const [visible, setVisible] = useState(false); const [message, setMessage] = useState(""); const [animation, setAnimation] = useState(new Animated.Value(0));
const showMessage = (message) => { setMessage(message); setVisible(true); Animated.spring(animation, { toValue: 1, friction: 4, tension: 40, useNativeDriver: true, }).start(() => { setTimeout(() => { Animated.spring(animation, { toValue: 0, friction: 4, tension: 40, useNativeDriver: true, }).start(() => { setVisible(false); }); }, 2000); }); };
const handleGiftBox = (cost, numCoupons) => { setShowRewardModal(false); if (balance >= cost) { setBalance(balance - cost); navigation.navigate("Rewardscreen", { numCoupons }); } else { showMessage("You're broke! Get a job!"); } };
return ( <View style={styles.container}> <Image source={require("../assets/arrow.png")} style={styles.Bicon} /> <View style={styles.Coincontainer}> <Text style={styles.balanceText}> <Image source={require("../assets/coin.png")} style={styles.icon} /> {parseFloat(balance).toFixed(2)} </Text> {visible && ( <Animated.View style={[ styles.toastContainer, { transform: [{ scale: animation }], opacity: animation, }, ]}> <Text style={styles.toastText}>{message}</Text> </Animated.View> )} <TouchableOpacity style={styles.Walletcontainer} onPress={() => setShowAdModal(true)}> <Image source={require("../assets/wallet.png")} style={styles.Wicon} /> </TouchableOpacity> </View> <View> <Text>{" "}</Text> </View>
<Modal
animationType="slide"
transparent={true}
visible={showAdModal}
onRequestClose={() => {
setShowAdModal(false);
}}>
<View style={styles.modalContainer}>
<View style={styles.modalContent}>
<Image
source={{ uri: "https://via.placeholder.com/300x250" }}
style={styles.adImage}
/>
<View style={styles.adInfoContainer}>
<Text style={styles.adTitle}>Watch Ad to Earn Coins!</Text>
<Text style={styles.adDescription}>
Watch this ad to earn 50 coins! You will be rewarded with 50
coins after watching the ad.
</Text>
</View>
<TouchableOpacity
style={styles.modalButton}
onPress={() => {
openAd();
setShowAdModal(false);
}}>
<Text style={styles.modalButtonText}>Watch Ad</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.modalRewardButton}
onPress={() => {
setShowAdModal(false);
setShowRewardModal(true);
}}>
<Text style={styles.modalButtonText}>Reward</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
<Modal
animationType="slide"
transparent={true}
visible={showRewardModal}
onRequestClose={() => {
setShowRewardModal(false);
}}>
<View style={styles.rewardModalContainer}>
<ImageBackground
source={require("../assets/Rbg.png")}
style={styles.rewardBackgroundImage}>
<TouchableOpacity
style={styles.Giftbox}
onPress={() => handleGiftBox(2000, 1)}>
<Image
source={require("../assets/Gift.png")}
style={styles.GiftboxImage}
/>
<View style={styles.GiftboxCard}>
<Text
style={[
styles.Giftboxprice,
balance < 2000 ? { color: "red" } : null,
]}>
2000{" "}
<Image
source={require("../assets/coin.png")}
style={styles.Cicon}
/>
</Text>
</View>
</TouchableOpacity>
<TouchableOpacity
style={styles.Giftbox}
onPress={() => handleGiftBox(5000, 3)}>
<Image
source={require("../assets/megaGift.png")}
style={styles.GiftboxImage}
/>
<View style={styles.GiftboxCard}>
<Text
style={[
styles.Giftboxprice,
balance < 5000 ? { color: "red" } : null,
]}>
5000{" "}
<Image
source={require("../assets/coin.png")}
style={styles.Cicon}
/>
</Text>
</View>
</TouchableOpacity>
</ImageBackground>
</View>
</Modal>
</View>
); };
Platforms
iOS, but have not tested behavior on Android
React Native Info
System:
OS: macOS 13.6.4
CPU: (8) arm64 Apple M1
Memory: 58.84 MB / 8.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 20.15.0
path: /usr/local/bin/node
Yarn:
version: 1.22.22
path: /opt/homebrew/bin/yarn
npm:
version: 10.7.0
path: /usr/local/bin/npm
Watchman:
version: 2024.06.24.00
path: /opt/homebrew/bin/watchman
Managers:
CocoaPods:
version: 1.15.2
path: /opt/homebrew/bin/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 23.2
- iOS 17.2
- macOS 14.2
- tvOS 17.2
- visionOS 1.0
- watchOS 10.2
Android SDK: Not Found
IDEs:
Android Studio: 2022.1 AI-221.6008.13.2211.9619390
Xcode:
version: 15.2/15C500b
path: /usr/bin/xcodebuild
Languages:
Java:
version: 22.0.1
path: /usr/bin/javac
Ruby:
version: 3.3.3
path: /opt/homebrew/opt/ruby/bin/ruby
npmPackages:
"@react-native-community/cli": Not Found
react:
installed: 18.2.0
wanted: 18.2.0
react-native:
installed: 0.74.2
wanted: 0.74.2
react-native-macos: Not Found
npmGlobalPackages:
"react-native": Not Found
Android:
hermesEnabled: true
newArchEnabled: false
iOS:
hermesEnabled: true
newArchEnabled: false
Are your using Typescript?
- [ ] My project is using Typescript
package.json
{
"name": "minebuddy",
"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"
},
"dependencies": {
"@react-native-async-storage/async-storage": "^1.23.1",
"@react-navigation/native": "^6.1.17",
"@react-navigation/native-stack": "^6.10.0",
"react": "18.2.0",
"react-native": "0.74.2",
"react-native-admob": "^1.3.2",
"react-native-eject": "^0.2.0",
"react-native-google-mobile-ads": "^13.6.1",
"react-native-safe-area-context": "^4.10.7",
"react-native-screens": "^3.32.0",
"react-native-sound": "^0.11.2",
"react-navigation": "^4.4.4",
"react-navigation-stack": "^2.10.4"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@babel/preset-env": "^7.20.0",
"@babel/runtime": "^7.20.0",
"@react-native/babel-preset": "0.74.84",
"@react-native/eslint-config": "0.74.84",
"@react-native/metro-config": "0.74.84",
"@react-native/typescript-config": "0.74.84",
"@types/react": "^18.2.6",
"@types/react-test-renderer": "^18.0.0",
"babel-jest": "^29.6.3",
"eslint": "^8.19.0",
"jest": "^29.6.3",
"prettier": "2.8.8",
"react-test-renderer": "18.2.0",
"typescript": "5.0.4"
},
"engines": {
"node": ">=18"
}
}
app.json
{
"name": "minebuddy",
"displayName": "minebuddy",
"slug": "minebuddy",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/images/icon.png",
"scheme": "myapp",
"userInterfaceStyle": "automatic",
"splash": {
"image": "./assets/images/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"ios": {
"supportsTablet": true
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/images/adaptive-icon.png",
"backgroundColor": "#ffffff"
}
},
"web": {
"bundler": "metro",
"output": "static",
"favicon": "./assets/images/favicon.png"
},
"plugins": [
"expo-router"
],
"experiments": {
"typedRoutes": true
},
"react-native-google-mobile-ads": {
"android_app_id": "ca-app-pub-3940256099942544~3347511713",
"ios_app_id": "ca-app-pub-3764917219536492~3984104045"
}
}
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
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
$RNGoogleMobileAdsAsStaticFramework = true
target 'minebuddy' do
config = use_native_modules!
use_react_native!(
:path => config[:reactNativePath],
# An absolute path to your application root.
:app_path => "#{Pod::Config.instance.installation_root}/.."
)
pod 'RNGoogleMobileAds', :path => '../node_modules/react-native-google-mobile-ads'
target 'minebuddyTests' do
inherit! :complete
# Pods for testing
end
post_install do |installer|
# https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false,
# :ccache_enabled => true
)
end
end
android/build.gradle
No response
android/app/build.gradle
No response
android/settings.gradle
No response
AndroidManifest.xml
No response
The same issue, successfully loaded in the simulator, but unable to load successfully in the real machine
I had the same issue on both Android and iOS devices. This error occurs due to the requestId in MobileAd.ts of the library. In the following code, the requestId is passed to the load method:
public load() {
// Prevent multiple load calls
if (this._loaded || this._isLoadCalled) {
return;
}
this._isLoadCalled = true;
const load: AdLoadFunction = NativeModules[this._nativeModule][`${this._camelCaseType}Load`];
load(this._requestId, this._adUnitId, this._requestOptions);
}
In my case, the problem was happening because when calling load, a requestId was being passed, and when calling show, another requestId was being passed. This indicated that different instances were being called. The solution I implemented and that worked was to add RewardedAd.createForAdRequest inside the useEffect, as shown below:
const [loaded, setLoaded] = useState(false);
let rewarded;
useEffect(() => {
rewarded = RewardedAd.createForAdRequest(constants.adUnitIdRewarded, {
requestNonPersonalizedAdsOnly: true
});
const loadAd = () => {
console.log('Loading rewarded ad');
rewarded.load();
};
const unsubscribeLoaded = rewarded.addAdEventListener(RewardedAdEventType.LOADED, () => {
console.log('Rewarded ad loaded');
setLoaded(true);
});
const unsubscribeEarned = rewarded.addAdEventListener(RewardedAdEventType.EARNED_REWARD, reward => {
console.log('Reward earned:', reward);
});
const unsubscribeClosed = rewarded.addAdEventListener(AdEventType.CLOSED, () => {
console.log('Rewarded ad closed');
setLoaded(false);
loadAd();
});
const unsubscribeFailed = rewarded.addAdEventListener(AdEventType.ERROR, error => {
console.error('Failed to load rewarded ad:', error);
setLoaded(false);
});
loadAd();
return () => {
unsubscribeLoaded();
unsubscribeEarned();
unsubscribeClosed();
unsubscribeFailed();
};
}, [loaded]);
const showRewardedAd = () => {
rewarded.show();
};
See if this solution works for you as well.
Hello 👋, to help manage issues we automatically close stale issues.
This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?
This issue will be closed in 15 days if no further activity occurs.
Thank you for your contributions.