ERROR  Error: RewardedAd.show() The requested RewardedAd has not loaded and could not be shown., js engine: hermes
 ERROR  Error: RewardedAd.show() The requested RewardedAd has not loaded and could not be shown., js engine: hermes
 ERROR  Error: RewardedAd.show() The requested RewardedAd has not loaded and could not be shown., js engine: hermes
 ERROR  Error: RewardedAd.show() The requested RewardedAd has not loaded and could not be shown., js engine: hermes
 LOG  Ad event: error Payload: [Error: [googleMobileAds/internal-error] Internal error.]
 LOG  Ad failed to load with error: [googleMobileAds/internal-error] Internal error.
 LOG  Ad event: error Payload: [Error: [googleMobileAds/internal-error] Internal error.]
 LOG  Ad failed to load with error: [googleMobileAds/internal-error] Internal error.

bu hataları alıyoruz bunları düzelt. dökümantasyonu da atıyorum. // src/context/CoinContext.tsx

import React, {
  createContext,
  useState,
  useEffect,
  useCallback,
  ReactNode,
} from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { Alert } from 'react-native';
import {
  RewardedAd,
  RewardedAdEventType,
  AdEventType,
  RewardedAdReward,
  TestIds,
} from 'react-native-google-mobile-ads';
import { useApp } from '../context/AppContext'; // useApp bağlamını içe aktar

const INITIAL_COINS = 15;
const REWARD_AMOUNT = 15;

const adUnitId =
  __DEV__ ? TestIds.REWARDED : 'ca-app-pub-xxxxxxxxxxxxx/yyyyyyyyyyyyyy';

interface CoinContextProps {
  coins: number;
  addCoins: (amount: number) => void;
  deductCoins: (amount: number) => void;
  checkAndRefillCoins: () => Promise<void>;
  showRewardedAd: () => void;
}

export const CoinContext = createContext<CoinContextProps>({
  coins: INITIAL_COINS,
  addCoins: () => {},
  deductCoins: () => {},
  checkAndRefillCoins: async () => {},
  showRewardedAd: () => {},
});

interface CoinProviderProps {
  children: ReactNode;
}

export const CoinProvider: React.FC<CoinProviderProps> = ({ children }) => {
  const { t } = useApp(); // t fonksiyonunu al
  const [coins, setCoins] = useState<number>(INITIAL_COINS);
  const [rewardedAd, setRewardedAd] = useState<RewardedAd | null>(null);
  const [isAdLoaded, setIsAdLoaded] = useState<boolean>(false);

  const addCoins = useCallback(
    (amount: number) => {
      setCoins((prevCoins) => {
        const newCoins = prevCoins + amount;
        saveCoins(newCoins);
        return newCoins;
      });
    },
    [] // bağımlılıklar boş kalabilir, çünkü saveCoins bağımlılık içerir
  );

  const deductCoins = useCallback(
    (amount: number) => {
      setCoins((prevCoins) => {
        const newCoins = Math.max(prevCoins - amount, 0);
        saveCoins(newCoins);
        return newCoins;
      });
    },
    []
  );

  const saveCoins = useCallback(async (newCoins: number) => {
    try {
      await AsyncStorage.setItem('coins', JSON.stringify(newCoins));
    } catch (error) {
      console.error(t('coinSaveError'), error);
    }
  }, [t]);

  const checkAndRefillCoins = useCallback(async () => {
    try {
      const lastRefillDate = await AsyncStorage.getItem('lastRefillDate');
      const currentDate = new Date().toDateString();
      if (lastRefillDate !== currentDate) {
        if (coins < INITIAL_COINS) {
          setCoins(INITIAL_COINS);
          await saveCoins(INITIAL_COINS);
        }
        await AsyncStorage.setItem('lastRefillDate', currentDate);
      }
    } catch (error) {
      console.error(t('coinCheckError'), error);
    }
  }, [coins, saveCoins, t]);

  const setupRewardedAd = useCallback(() => {
    const ad = RewardedAd.createForAdRequest(adUnitId, {
      keywords: [t('gameKeyword'), t('rewardsKeyword')],
    });

    const allEventsListener = ad.addAdEventsListener(({ type, payload }) => {
      console.log(t('adEvent'), type, 'Payload:', payload);

      if (type === RewardedAdEventType.LOADED) {
        setIsAdLoaded(true);
        console.log(t('adLoaded'));
      }
      if (type === RewardedAdEventType.EARNED_REWARD) {
        const reward = payload as RewardedAdReward;
        addCoins(REWARD_AMOUNT);
        Alert.alert(t('rewardEarnedTitle'), t('rewardEarnedMessage', { amount: REWARD_AMOUNT }));
        console.log(`${t('userEarned')} ${reward.amount} ${reward.name}`);
      }
      if (type === AdEventType.ERROR) {
        const error = payload as Error;
        console.log(`${t('adLoadError')}:`, error.message);
        setIsAdLoaded(false);
        setupRewardedAd(); // Yeni bir reklam kurulumunu başlatın
      }
      if (type === AdEventType.CLOSED) {
        setIsAdLoaded(false);
        setupRewardedAd(); // Yeni bir reklam kurulumunu başlatın
      }
    });

    // Reklamı yükleyin
    ad.load();

    // Rewarded ad instance'ını ayarlayın
    setRewardedAd(ad);

    // Cleanup fonksiyonu
    return () => {
      allEventsListener();
    };
  }, [addCoins, setupRewardedAd, t]);

  useEffect(() => {
    let cleanupAd: (() => void) | undefined;

    const initialize = async () => {
      // Coin'leri depolamadan yükleme
      try {
        const coinsData = await AsyncStorage.getItem('coins');
        const initialCoins: number = coinsData ? JSON.parse(coinsData) : INITIAL_COINS;
        setCoins(initialCoins);
      } catch (error) {
        console.error(t('coinLoadError'), error);
      }

      // Rewarded ad'i ayarla
      cleanupAd = setupRewardedAd();
    };

    initialize();

    // Günlük coin kontrolü ve refill
    checkAndRefillCoins();
    const dailyCheck = setInterval(checkAndRefillCoins, 24 * 60 * 60 * 1000);

    return () => {
      // Cleanup işlemi
      if (cleanupAd) cleanupAd();
      clearInterval(dailyCheck);
    };
  }, [setupRewardedAd, checkAndRefillCoins, t]);

  const showRewardedAd = useCallback(() => {
    if (rewardedAd && isAdLoaded) {
      rewardedAd.show().catch((error) => {
        console.error(t('adShowError'), error);
        Alert.alert(
          t('adErrorTitle'),
          t('adErrorMessage')
        );
      });
    } else {
      Alert.alert(
        t('adNotReadyTitle'),
        t('adNotReadyMessage')
      );
      // Reklam tekrar yüklemeyi deneyin
      setupRewardedAd();
    }
  }, [rewardedAd, isAdLoaded, setupRewardedAd, t]);

  return (
    <CoinContext.Provider
      value={{ coins, addCoins, deductCoins, checkAndRefillCoins, showRewardedAd }}
    >
      {children}
    </CoinContext.Provider>
  );
};


Migrating to v6
onAdEvent Removed
onAdEvent had two problems:

Only one listener could be registered to an ad instance. Attempting to register a second listener replaced previous listeners
There were type conflicts around the event payload because typescript didn't know which event was sent to the listener
In order to resolve these problems, onAdEvent is replaced by addAdEventListener and addAdEventsListener.

addAdEventListener
With each call to addAdEventListener, you add a listener for one specific event type. The event type to listen for is the first argument and your event handler is the second argument. The type event payload type for the handler is automatically inferred from the event type you passed.


 import {
   AdEventType,
   RewardedAd,
   RewardedAdEventType
 } from 'react-native-google-mobile-ads';

 const rewardedAd = RewardedAd.createForAdRequest('...');
-rewardedAd.onAdEvent((type, error, reward) => {
-  if (type === RewardedAdEventType.LOADED) {
-    console.log('Ad has loaded');
-  }
-  if (type === RewardedAdEventType.EARNED_REWARD) {
-    console.log('User earned reward of ', reward);
-  }
-  if (type === AdEventType.ERROR) {
-    console.log('Ad failed to load with error: ', error);
-  }
-}
+rewardedAd.addAdEventListener(RewardedAdEventType.LOADED, () => {
+  console.log('Ad has loaded');
+});
+rewardedAd.addAdEventListener(RewardedAdEventType.EARNED_REWARD, (reward) => {
+  console.log('User earned reward of ', reward);
+});
+rewardedAd.addAdEventListener(AdEventType.ERROR, (error) => {
+  console.log('Ad failed to load with error: ', error);
+});
To unsubscribe from an event, call the function returned from addAdEventListener.


const unsubscribe = interstitialAd.addAdEventListener(AdEventType.LOADED, () => {
  console.log('Ad has loaded');
});

// Sometime later...
unsubscribe();
addAdEventsListener
With addAdEventsListener, you can listen for all of event types as legacy onAdEvent did. The handler now passes an object with event type and payload. You have to cast the payload to a corresponding type in order to use in typescript.


import {
  AdEventType,
  RewardedAd,
  RewardedAdEventType,
  RewardedAdReward
} from 'react-native-google-mobile-ads';

const rewardedAd = RewardedAd.createForAdRequest('...');
-rewardedAd.onAdEvent((type, error, reward) => {
+rewardedAd.addAdEventsListener(({ type, payload }) => {
   if (type === RewardedAdEventType.LOADED) {
     console.log('Ad has loaded');
   }
   if (type === RewardedAdEventType.EARNED_REWARD) {
+    const reward = payload as RewardedAdReward;
     console.log(`User earned reward, name: ${reward.name}, amount: ${reward.amount}`);
   }
   if (type === AdEventType.ERROR) {
+    const error = payload as Error;
     console.log('Ad failed to load with error: ', error.message);
   }
 }
To unsubscribe from events, call the function returned from addAdEventsListener.


const unsubscribe = interstitialAd.addAdEventsListener(({ type, payload }) => {
  console.log('Ad event: ', type, payload);
});

// Sometime later...
unsubscribe();
removeAllListeners
You can remove all listeners registered with addAdEventListener and addAdEventsListener by calling removeAllListeners method.


interstitialAd.addAdEventListener(AdEventType.LOADED, () => {
  console.log('Ad has loaded');
});
interstitialAd.addAdEventsListener(({ type, payload }) => {
  console.log('Ad event: ', type, payload);
});

// Sometime later...
interstitialAd.removeAllListeners();




Rewarded Ads
Rewarded Ads are full-screen ads that cover the interface of an app until closed by the user. The content of a rewarded advert is controlled via the Google AdMob dashboard.

The purpose of a rewarded ad is to reward users with something after completing an action inside of the advert, such as watching a video or submitting an option via an interactive form. If the user completes the action, you can reward them with something (e.g. in-game currency).

To create a new rewarded ad, call the createForAdRequest method from the RewardedAd class. The first argument of the method is the "Ad Unit ID". For testing, we can use a Test ID, however for production the ID from the Google AdMob dashboard under "Ad units" should be used:


import { RewardedAd, TestIds } from 'react-native-google-mobile-ads';

const adUnitId = __DEV__ ? TestIds.REWARDED : 'ca-app-pub-xxxxxxxxxxxxx/yyyyyyyyyyyyyy';

const rewarded = RewardedAd.createForAdRequest(adUnitId, {
  keywords: ['fashion', 'clothing'],
});
The second argument is additional optional request options object to be sent whilst loading an advert, such as keywords & location. Setting additional request options helps AdMob choose better tailored ads from the network. View the RequestOptions source code to see the full range of options available.

The call to createForAdRequest returns an instance of the RewardedAd class, which provides a number of utilities for loading and displaying rewarded ads.

To listen to events, such as when the advert from the network has loaded or when an error occurs, we can subscribe via the addAdEventListener method:


import React, { useEffect, useState } from 'react';
import { Button } from 'react-native';
import { RewardedAd, RewardedAdEventType, TestIds } from 'react-native-google-mobile-ads';

const adUnitId = __DEV__ ? TestIds.REWARDED : 'ca-app-pub-xxxxxxxxxxxxx/yyyyyyyyyyyyyy';

const rewarded = RewardedAd.createForAdRequest(adUnitId, {
  keywords: ['fashion', 'clothing'],
});

function App() {
  const [loaded, setLoaded] = useState(false);

  useEffect(() => {
    const unsubscribeLoaded = rewarded.addAdEventListener(RewardedAdEventType.LOADED, () => {
      setLoaded(true);
    });
    const unsubscribeEarned = rewarded.addAdEventListener(
      RewardedAdEventType.EARNED_REWARD,
      reward => {
        console.log('User earned reward of ', reward);
      },
    );

    // Start loading the rewarded ad straight away
    rewarded.load();

    // Unsubscribe from events on unmount
    return () => {
      unsubscribeLoaded();
      unsubscribeEarned();
    };
  }, []);

  // No advert ready to show yet
  if (!loaded) {
    return null;
  }

  return (
    <Button
      title="Show Rewarded Ad"
      onPress={() => {
        rewarded.show();
      }}
    />
  );
}
The code above subscribes to the rewarded ad events (via addAdEventListener()) and immediately starts to load a new advert from the network (via load()). Once an advert is available, local state is set, re-rendering the component showing a Button. When pressed, the show method on the rewarded ad instance is called and the advert is shown over-the-top of your application.

Like Interstitial Ads, you can listen to the events with the addAdEventListener such as when the user clicks the advert or closes the advert and returns back to your app. However, you can listen to an extra EARNED_REWARD event which is triggered when user completes the advert action. An additional reward payload is sent with the event, containing the amount and type of rewarded (specified via the dashboard).

To learn more, view the RewardedAdEventType source code.

If needed, you can reuse the existing instance of the RewardedAd class to load more adverts and show them when required.

While the EARNED_REWARD event only occurs on the client, Server Side Verification (or SSV) can be used for confirming a user completed an advert action. For this, you have to specify the Server Side Verification callback URL in your Ads dashboard.

You can customize SSV parameters when your SSV callback is called by setting the serverSideVerificationOptions field in your RequestOptions parameter.


const rewardedAd = RewardedAd.createForAdRequest(adUnitId, {
  serverSideVerificationOptions: {
    userId: '9999',
    customData: 'my-custom-data',
  },
});
If you request an Advert as in the example above, AdMob will call your server with the userId and customData fields as shown below:


[14/Aug/2020 12:51:43] "GET /views/admob-ssv/?ad_network=...&ad_unit=...&custom_data=my-custom-data&reward_amount=1&reward_item=test_reward_item&timestamp=1597377102267&transaction_id=148cc85...&user_id=9999&signature=MEUCIQCQSi3cQ2PlxlEAkpN...&key_id=3335... HTTP/1.1" 200 0
You still need to verify these incoming requests yourself to ensure they are genuine. To learn more about callback parameters and verifying, see the AdMob SDK Server Side Verification(SSV) documentation.