react-native-google-mobile-ads 6.0.1 → 6.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsCommon.java +9 -3
  2. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsEvent.java +2 -0
  3. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsPackage.java +1 -0
  4. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsRewardedInterstitialModule.java +199 -0
  5. package/docs/displaying-ads-hook.mdx +1 -1
  6. package/docs/displaying-ads.mdx +132 -1
  7. package/docs/european-user-consent.mdx +31 -0
  8. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsAppOpenModule.m +1 -2
  9. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsCommon.h +3 -0
  10. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsCommon.m +18 -1
  11. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsInterstitialModule.m +1 -2
  12. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.h +25 -0
  13. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.m +173 -0
  14. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedModule.m +18 -18
  15. package/lib/commonjs/BannerAdSize.js +2 -0
  16. package/lib/commonjs/BannerAdSize.js.map +1 -1
  17. package/lib/commonjs/MobileAds.js +5 -2
  18. package/lib/commonjs/MobileAds.js.map +1 -1
  19. package/lib/commonjs/TestIds.js +6 -2
  20. package/lib/commonjs/TestIds.js.map +1 -1
  21. package/lib/commonjs/ads/MobileAd.js +16 -4
  22. package/lib/commonjs/ads/MobileAd.js.map +1 -1
  23. package/lib/commonjs/ads/RewardedInterstitialAd.js +127 -0
  24. package/lib/commonjs/ads/RewardedInterstitialAd.js.map +1 -0
  25. package/lib/commonjs/hooks/useFullScreenAd.js.map +1 -1
  26. package/lib/commonjs/hooks/useRewardedAd.js.map +1 -1
  27. package/lib/commonjs/hooks/useRewardedInterstitialAd.js +51 -0
  28. package/lib/commonjs/hooks/useRewardedInterstitialAd.js.map +1 -0
  29. package/lib/commonjs/index.js +19 -1
  30. package/lib/commonjs/index.js.map +1 -1
  31. package/lib/commonjs/version.js +1 -1
  32. package/lib/commonjs/version.js.map +1 -1
  33. package/lib/module/BannerAdSize.js +2 -0
  34. package/lib/module/BannerAdSize.js.map +1 -1
  35. package/lib/module/MobileAds.js +5 -2
  36. package/lib/module/MobileAds.js.map +1 -1
  37. package/lib/module/TestIds.js +6 -2
  38. package/lib/module/TestIds.js.map +1 -1
  39. package/lib/module/ads/MobileAd.js +16 -4
  40. package/lib/module/ads/MobileAd.js.map +1 -1
  41. package/lib/module/ads/RewardedInterstitialAd.js +130 -0
  42. package/lib/module/ads/RewardedInterstitialAd.js.map +1 -0
  43. package/lib/module/hooks/useFullScreenAd.js.map +1 -1
  44. package/lib/module/hooks/useRewardedAd.js.map +1 -1
  45. package/lib/module/hooks/useRewardedInterstitialAd.js +38 -0
  46. package/lib/module/hooks/useRewardedInterstitialAd.js.map +1 -0
  47. package/lib/module/index.js +2 -0
  48. package/lib/module/index.js.map +1 -1
  49. package/lib/module/version.js +1 -1
  50. package/lib/module/version.js.map +1 -1
  51. package/lib/typescript/BannerAdSize.d.ts +10 -1
  52. package/lib/typescript/TestIds.d.ts +2 -0
  53. package/lib/typescript/ads/MobileAd.d.ts +3 -2
  54. package/lib/typescript/ads/RewardedInterstitialAd.d.ts +82 -0
  55. package/lib/typescript/hooks/useFullScreenAd.d.ts +2 -1
  56. package/lib/typescript/hooks/useRewardedAd.d.ts +1 -1
  57. package/lib/typescript/hooks/useRewardedInterstitialAd.d.ts +9 -0
  58. package/lib/typescript/index.d.ts +3 -1
  59. package/lib/typescript/types/GoogleMobileAdsNativeModule.d.ts +11 -6
  60. package/lib/typescript/version.d.ts +1 -1
  61. package/package.json +8 -8
  62. package/src/BannerAdSize.ts +12 -1
  63. package/src/MobileAds.ts +9 -0
  64. package/src/TestIds.ts +4 -0
  65. package/src/ads/MobileAd.ts +16 -6
  66. package/src/ads/RewardedInterstitialAd.ts +143 -0
  67. package/src/hooks/useFullScreenAd.ts +4 -3
  68. package/src/hooks/useRewardedAd.ts +1 -1
  69. package/src/hooks/useRewardedInterstitialAd.ts +47 -0
  70. package/src/index.ts +2 -0
  71. package/src/types/GoogleMobileAdsNativeModule.ts +15 -6
  72. package/src/version.ts +1 -1
@@ -40,7 +40,7 @@ import javax.annotation.Nullable;
40
40
 
41
41
  public class ReactNativeGoogleMobileAdsCommon {
42
42
 
43
- static AdSize getAdSizeForAdaptiveBanner(ReactViewGroup reactViewGroup) {
43
+ static AdSize getAdSizeForAdaptiveBanner(String preDefinedAdSize, ReactViewGroup reactViewGroup) {
44
44
 
45
45
  try {
46
46
  Display display =
@@ -52,6 +52,10 @@ public class ReactNativeGoogleMobileAdsCommon {
52
52
  display.getMetrics(outMetrics);
53
53
  int adWidth = (int) (outMetrics.widthPixels / outMetrics.density);
54
54
 
55
+ if ("INLINE_ADAPTIVE_BANNER".equals(preDefinedAdSize)) {
56
+ return AdSize.getCurrentOrientationInlineAdaptiveBannerAdSize(
57
+ reactViewGroup.getContext(), adWidth);
58
+ }
55
59
  return AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(
56
60
  reactViewGroup.getContext(), adWidth);
57
61
  } catch (Exception e) {
@@ -60,8 +64,10 @@ public class ReactNativeGoogleMobileAdsCommon {
60
64
  }
61
65
 
62
66
  static AdSize getAdSize(String preDefinedAdSize, ReactViewGroup reactViewGroup) {
63
- if ("ADAPTIVE_BANNER".equals(preDefinedAdSize)) {
64
- return ReactNativeGoogleMobileAdsCommon.getAdSizeForAdaptiveBanner(reactViewGroup);
67
+ if (preDefinedAdSize.matches(
68
+ "ADAPTIVE_BANNER|ANCHORED_ADAPTIVE_BANNER|INLINE_ADAPTIVE_BANNER")) {
69
+ return ReactNativeGoogleMobileAdsCommon.getAdSizeForAdaptiveBanner(
70
+ preDefinedAdSize, reactViewGroup);
65
71
  } else {
66
72
  return ReactNativeGoogleMobileAdsCommon.stringToAdSize(preDefinedAdSize);
67
73
  }
@@ -26,6 +26,8 @@ public class ReactNativeGoogleMobileAdsEvent implements NativeEvent {
26
26
  public static final String GOOGLE_MOBILE_ADS_EVENT_INTERSTITIAL =
27
27
  "google_mobile_ads_interstitial_event";
28
28
  public static final String GOOGLE_MOBILE_ADS_EVENT_REWARDED = "google_mobile_ads_rewarded_event";
29
+ public static final String GOOGLE_MOBILE_ADS_EVENT_REWARDED_INTERSTITIAL =
30
+ "google_mobile_ads_rewarded_interstitial_event";
29
31
 
30
32
  public static final String GOOGLE_MOBILE_ADS_EVENT_LOADED = "loaded";
31
33
  public static final String GOOGLE_MOBILE_ADS_EVENT_ERROR = "error";
@@ -37,6 +37,7 @@ public class ReactNativeGoogleMobileAdsPackage implements ReactPackage {
37
37
  modules.add(new ReactNativeGoogleMobileAdsAppOpenModule(reactContext));
38
38
  modules.add(new ReactNativeGoogleMobileAdsInterstitialModule(reactContext));
39
39
  modules.add(new ReactNativeGoogleMobileAdsRewardedModule(reactContext));
40
+ modules.add(new ReactNativeGoogleMobileAdsRewardedInterstitialModule(reactContext));
40
41
  return modules;
41
42
  }
42
43
 
@@ -0,0 +1,199 @@
1
+ package io.invertase.googlemobileads;
2
+
3
+ /*
4
+ * Copyright (c) 2016-present Invertase Limited & Contributors
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this library except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ *
18
+ */
19
+
20
+ import static io.invertase.googlemobileads.ReactNativeGoogleMobileAdsCommon.buildAdRequest;
21
+ import static io.invertase.googlemobileads.ReactNativeGoogleMobileAdsCommon.getCodeAndMessageFromAdError;
22
+ import static io.invertase.googlemobileads.ReactNativeGoogleMobileAdsCommon.sendAdEvent;
23
+ import static io.invertase.googlemobileads.ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_CLOSED;
24
+ import static io.invertase.googlemobileads.ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_ERROR;
25
+ import static io.invertase.googlemobileads.ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_OPENED;
26
+ import static io.invertase.googlemobileads.ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_REWARDED_EARNED_REWARD;
27
+ import static io.invertase.googlemobileads.ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_REWARDED_LOADED;
28
+
29
+ import android.app.Activity;
30
+ import android.util.SparseArray;
31
+ import androidx.annotation.NonNull;
32
+ import androidx.annotation.Nullable;
33
+ import com.facebook.react.bridge.Arguments;
34
+ import com.facebook.react.bridge.Promise;
35
+ import com.facebook.react.bridge.ReactApplicationContext;
36
+ import com.facebook.react.bridge.ReactMethod;
37
+ import com.facebook.react.bridge.ReadableMap;
38
+ import com.facebook.react.bridge.WritableMap;
39
+ import com.google.android.gms.ads.FullScreenContentCallback;
40
+ import com.google.android.gms.ads.LoadAdError;
41
+ import com.google.android.gms.ads.OnUserEarnedRewardListener;
42
+ import com.google.android.gms.ads.rewarded.RewardItem;
43
+ import com.google.android.gms.ads.rewarded.ServerSideVerificationOptions;
44
+ import com.google.android.gms.ads.rewardedinterstitial.RewardedInterstitialAd;
45
+ import com.google.android.gms.ads.rewardedinterstitial.RewardedInterstitialAdLoadCallback;
46
+ import io.invertase.googlemobileads.common.ReactNativeModule;
47
+
48
+ public class ReactNativeGoogleMobileAdsRewardedInterstitialModule extends ReactNativeModule {
49
+ private static final String SERVICE = "RNGoogleMobileAdsRewardedInterstitialModule";
50
+ private static SparseArray<RewardedInterstitialAd> rewardedInterstitialAdArray =
51
+ new SparseArray<>();
52
+
53
+ public ReactNativeGoogleMobileAdsRewardedInterstitialModule(
54
+ ReactApplicationContext reactContext) {
55
+ super(reactContext, SERVICE);
56
+ }
57
+
58
+ private void sendRewardedInterstitialEvent(
59
+ String type,
60
+ int requestId,
61
+ String adUnitId,
62
+ @Nullable WritableMap error,
63
+ @Nullable WritableMap data) {
64
+ sendAdEvent(
65
+ ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_REWARDED_INTERSTITIAL,
66
+ requestId,
67
+ type,
68
+ adUnitId,
69
+ error,
70
+ data);
71
+ }
72
+
73
+ @ReactMethod
74
+ public void rewardedInterstitialLoad(
75
+ int requestId, String adUnitId, ReadableMap adRequestOptions) {
76
+ Activity activity = getCurrentActivity();
77
+ if (activity == null) {
78
+ WritableMap error = Arguments.createMap();
79
+ error.putString("code", "null-activity");
80
+ error.putString(
81
+ "message",
82
+ "Rewarded Interstitial ad attempted to load but the current Activity was null.");
83
+ sendRewardedInterstitialEvent(
84
+ GOOGLE_MOBILE_ADS_EVENT_ERROR, requestId, adUnitId, error, null);
85
+ return;
86
+ }
87
+ activity.runOnUiThread(
88
+ () -> {
89
+ RewardedInterstitialAdLoadCallback rewardedAdLoadCallback =
90
+ new RewardedInterstitialAdLoadCallback() {
91
+ @Override
92
+ public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
93
+ WritableMap error = Arguments.createMap();
94
+ String[] codeAndMessage = getCodeAndMessageFromAdError(loadAdError);
95
+ error.putString("code", codeAndMessage[0]);
96
+ error.putString("message", codeAndMessage[1]);
97
+ sendRewardedInterstitialEvent(
98
+ GOOGLE_MOBILE_ADS_EVENT_ERROR, requestId, adUnitId, error, null);
99
+ }
100
+
101
+ @Override
102
+ public void onAdLoaded(@NonNull RewardedInterstitialAd rewardedInterstitialAd) {
103
+ RewardItem rewardItem = rewardedInterstitialAd.getRewardItem();
104
+ WritableMap data = Arguments.createMap();
105
+ data.putString("type", rewardItem.getType());
106
+ data.putInt("amount", rewardItem.getAmount());
107
+
108
+ if (adRequestOptions.hasKey("serverSideVerificationOptions")) {
109
+ ReadableMap serverSideVerificationOptions =
110
+ adRequestOptions.getMap("serverSideVerificationOptions");
111
+
112
+ if (serverSideVerificationOptions != null) {
113
+ ServerSideVerificationOptions.Builder options =
114
+ new ServerSideVerificationOptions.Builder();
115
+
116
+ if (serverSideVerificationOptions.hasKey("userId")) {
117
+ options.setUserId(serverSideVerificationOptions.getString("userId"));
118
+ }
119
+
120
+ if (serverSideVerificationOptions.hasKey("customData")) {
121
+ options.setCustomData(
122
+ serverSideVerificationOptions.getString("customData"));
123
+ }
124
+
125
+ rewardedInterstitialAd.setServerSideVerificationOptions(options.build());
126
+ }
127
+ }
128
+
129
+ FullScreenContentCallback fullScreenContentCallback =
130
+ new FullScreenContentCallback() {
131
+ @Override
132
+ public void onAdShowedFullScreenContent() {
133
+ sendRewardedInterstitialEvent(
134
+ GOOGLE_MOBILE_ADS_EVENT_OPENED, requestId, adUnitId, null, null);
135
+ }
136
+
137
+ @Override
138
+ public void onAdDismissedFullScreenContent() {
139
+ sendRewardedInterstitialEvent(
140
+ GOOGLE_MOBILE_ADS_EVENT_CLOSED, requestId, adUnitId, null, null);
141
+ }
142
+ };
143
+
144
+ rewardedInterstitialAd.setFullScreenContentCallback(fullScreenContentCallback);
145
+
146
+ rewardedInterstitialAdArray.put(requestId, rewardedInterstitialAd);
147
+ sendRewardedInterstitialEvent(
148
+ GOOGLE_MOBILE_ADS_EVENT_REWARDED_LOADED, requestId, adUnitId, null, data);
149
+ }
150
+ };
151
+
152
+ RewardedInterstitialAd.load(
153
+ activity, adUnitId, buildAdRequest(adRequestOptions), rewardedAdLoadCallback);
154
+ });
155
+ }
156
+
157
+ @ReactMethod
158
+ public void rewardedInterstitialShow(
159
+ int requestId, String adUnitId, ReadableMap showOptions, Promise promise) {
160
+ if (getCurrentActivity() == null) {
161
+ rejectPromiseWithCodeAndMessage(
162
+ promise,
163
+ "null-activity",
164
+ "Rewarded Interstitial ad attempted to show but the current Activity was null.");
165
+ return;
166
+ }
167
+ getCurrentActivity()
168
+ .runOnUiThread(
169
+ () -> {
170
+ RewardedInterstitialAd rewardedInterstitialAd =
171
+ rewardedInterstitialAdArray.get(requestId);
172
+
173
+ boolean immersiveModeEnabled = false;
174
+ if (showOptions.hasKey("immersiveModeEnabled")) {
175
+ immersiveModeEnabled = showOptions.getBoolean("immersiveModeEnabled");
176
+ }
177
+ rewardedInterstitialAd.setImmersiveMode(immersiveModeEnabled);
178
+
179
+ OnUserEarnedRewardListener onUserEarnedRewardListener =
180
+ new OnUserEarnedRewardListener() {
181
+ @Override
182
+ public void onUserEarnedReward(@NonNull RewardItem rewardItem) {
183
+ WritableMap data = Arguments.createMap();
184
+ data.putString("type", rewardItem.getType());
185
+ data.putInt("amount", rewardItem.getAmount());
186
+ sendRewardedInterstitialEvent(
187
+ GOOGLE_MOBILE_ADS_EVENT_REWARDED_EARNED_REWARD,
188
+ requestId,
189
+ adUnitId,
190
+ null,
191
+ data);
192
+ }
193
+ };
194
+
195
+ rewardedInterstitialAd.show(getCurrentActivity(), onUserEarnedRewardListener);
196
+ promise.resolve(null);
197
+ });
198
+ }
199
+ }
@@ -1,6 +1,6 @@
1
1
  # Hooks
2
2
 
3
- The AdMob package provides hooks to help you to display ads in a functional component with tiny code. The supported ad formats are full-screen ads: App open, Interstitial & Rewarded.
3
+ The AdMob package provides hooks to help you to display ads in a functional component with tiny code. The supported ad formats are full-screen ads: App open, Interstitial, Rewarded, and Rewarded Interstitial.
4
4
 
5
5
  ## Load an ad
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Displaying Ads
2
2
 
3
- The AdMob package allows you to display three types of adverts; Interstitial, Rewarded & Banner.
3
+ The Google Mobile Ads package allows you to display five types of adverts; App Open, Interstitial, Rewarded, Rewarded Interstitial, and Banner.
4
4
 
5
5
  ## App Open Ads
6
6
 
@@ -265,6 +265,137 @@ If you request an Advert as in the example above, AdMob will call your server wi
265
265
 
266
266
  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](https://developers.google.com/admob/android/rewarded-video-ssv).
267
267
 
268
+ ## Rewarded Interstitial Ads
269
+
270
+ Rewarded Interstitial Ads are full-screen ads that cover the interface of an app until closed by the user. The content of a rewarded interstitial
271
+ advert is controlled via the Google AdMob dashboard.
272
+
273
+ The purpose of a rewarded interstitial ad is to reward users with _something_ after completing an action inside of the advert, such
274
+ as watching a video or submitting an option via an interactive form. If the user completes the action, you can reward them
275
+ with something (e.g. in-game currency). Unlike rewarded ads, users aren't required to opt-in to view a rewarded interstitial.
276
+
277
+ To create a new rewarded interstitial ad, call the `createForAdRequest` method from the `RewardedInterstitialAd` class. The first argument
278
+ of the method is the "Ad Unit ID". For testing, we can use a Test ID, however for production the ID from the
279
+ Google AdMob dashboard under "Ad units" should be used:
280
+
281
+ ```js
282
+ import { RewardedInterstitialAd, TestIds } from 'react-native-google-mobile-ads';
283
+
284
+ const adUnitId = __DEV__
285
+ ? TestIds.REWARDED_INTERSTITIAL
286
+ : 'ca-app-pub-xxxxxxxxxxxxx/yyyyyyyyyyyyyy';
287
+
288
+ const rewardedInterstitial = RewardedInterstitialAd.createForAdRequest(adUnitId, {
289
+ requestNonPersonalizedAdsOnly: true,
290
+ keywords: ['fashion', 'clothing'],
291
+ });
292
+ ```
293
+
294
+ The second argument is additional optional request options object to be sent whilst loading an advert, such as keywords & location.
295
+ Setting additional request options helps AdMob choose better tailored ads from the network. View the [`RequestOptions`](/reference/admob/requestoptions)
296
+ documentation to view the full range of options available.
297
+
298
+ The call to `createForAdRequest` returns an instance of the [`RewardedInterstitialAd`](/reference/admob/rewardedinterstitialad) class,
299
+ which provides a number of utilities for loading and displaying rewarded interstitial ads.
300
+
301
+ To listen to events, such as when the advert from the network has loaded or when an error occurs, we can subscribe via the
302
+ `addAdEventListener` method:
303
+
304
+ ```js
305
+ import React, { useEffect, useState } from 'react';
306
+ import { Button } from 'react-native';
307
+ import {
308
+ RewardedInterstitialAd,
309
+ RewardedAdEventType,
310
+ TestIds,
311
+ } from 'react-native-google-mobile-ads';
312
+
313
+ const adUnitId = __DEV__
314
+ ? TestIds.REWARDED_INTERSTITIAL
315
+ : 'ca-app-pub-xxxxxxxxxxxxx/yyyyyyyyyyyyyy';
316
+
317
+ const rewardedInterstitial = RewardedInterstitialAd.createForAdRequest(adUnitId, {
318
+ requestNonPersonalizedAdsOnly: true,
319
+ keywords: ['fashion', 'clothing'],
320
+ });
321
+
322
+ function App() {
323
+ const [loaded, setLoaded] = useState(false);
324
+
325
+ useEffect(() => {
326
+ const unsubscribeLoaded = rewardedInterstitial.addAdEventListener(
327
+ RewardedAdEventType.LOADED,
328
+ () => {
329
+ setLoaded(true);
330
+ },
331
+ );
332
+ const unsubscribeEarned = rewardedInterstitial.addAdEventListener(
333
+ RewardedAdEventType.EARNED_REWARD,
334
+ reward => {
335
+ console.log('User earned reward of ', reward);
336
+ },
337
+ );
338
+
339
+ // Start loading the rewarded interstitial ad straight away
340
+ rewardedInterstitial.load();
341
+
342
+ // Unsubscribe from events on unmount
343
+ return () => {
344
+ unsubscribeLoaded();
345
+ unsubscribeEarned();
346
+ };
347
+ }, []);
348
+
349
+ // No advert ready to show yet
350
+ if (!loaded) {
351
+ return null;
352
+ }
353
+
354
+ return (
355
+ <Button
356
+ title="Show Rewarded Interstitial Ad"
357
+ onPress={() => {
358
+ rewardedInterstitial.show();
359
+ }}
360
+ />
361
+ );
362
+ }
363
+ ```
364
+
365
+ The code above subscribes to the rewarded interstitial ad events (via `addAdEventListener()`) and immediately starts to load a new advert from
366
+ the network (via `load()`). Once an advert is available, local state is set, re-rendering the component showing a `Button`.
367
+ When pressed, the `show` method on the rewarded interstitial ad instance is called and the advert is shown over-the-top of your
368
+ application.
369
+
370
+ Like Interstitial Ads, you can listen to the events with the `addAdEventListener` such as when the user clicks the advert or closes
371
+ 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
372
+ advert action. An additional `reward` payload is sent with the event, containing the amount and type of rewarded (specified via the dashboard).
373
+
374
+ To learn more, view the [`RewardedAdEventType`](/reference/admob/rewardedadeventtype) documentation.
375
+
376
+ If needed, you can reuse the existing instance of the `RewardedInterstitialAd` class to load more adverts and show them when required.
377
+
378
+ 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.
379
+
380
+ You can customize SSV parameters when your SSV callback is called by setting the `serverSideVerificationOptions` field in your [`RequestOptions`](/reference/admob/requestoptions) parameter.
381
+
382
+ ```js
383
+ const rewardedInterstitialAd = RewardedInterstitialAd.createForAdRequest(adUnitId, {
384
+ serverSideVerificationOptions: {
385
+ userId: '9999',
386
+ customData: 'my-custom-data',
387
+ },
388
+ });
389
+ ```
390
+
391
+ If you request an Advert as in the example above, AdMob will call your server with the `userId` and `customData` fields as shown below:
392
+
393
+ ```
394
+ [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
395
+ ```
396
+
397
+ 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](https://developers.google.com/admob/android/rewarded-video-ssv).
398
+
268
399
  ## Banner Ads
269
400
 
270
401
  Banner ads are partial adverts which can be integrated within your existing application. Unlike Interstitial and Rewarded Ads,
@@ -18,6 +18,16 @@ ad requests to Google serve personalized ads, with ad selection based on the use
18
18
 
19
19
  ## Handling consent
20
20
 
21
+ To setup and configure ads consent collection, first of all:
22
+
23
+ - Enable and configure GDPR and IDFA messaging in the [Privacy & messaging section of AdMob's Web Console](https://apps.admob.com/v2/privacymessaging).
24
+
25
+ - For Android, add the following rule into
26
+ `android/app/proguard-rules.pro`:
27
+ ```
28
+ -keep class com.google.android.gms.internal.consent_sdk.** { *; }
29
+ ```
30
+
21
31
  ### Delaying app measurement
22
32
 
23
33
  By default, the Google Mobile Ads SDK initializes app measurement and begins sending user-level event data to Google immediately when the app starts.
@@ -83,6 +93,13 @@ The method returns an `AdsConsentInfo` interface, which provides information abo
83
93
  - `OBTAINED`: User consent already obtained.
84
94
  - **isConsentFormAvailable**: A boolean value. If `true` a consent form is available.
85
95
 
96
+ **Note:** The return status of this call is the status of *form presentation and response collection*, **not
97
+ the the actual user consent**. It simply indicates if you now have a consent response to decode.
98
+ (_i.e._ if user consent is **required**, the form has been presented, and user has
99
+ **denied** the consent, the status returned by this method will be `OBTAINED`,
100
+ and not `REQUIRED` as some may expect). To check the actual consent status
101
+ see [Inspecting consent choices] below.
102
+
86
103
  ### Gathering user consent
87
104
 
88
105
  To request consent, call these methods as early as possible within your app before presenting any ads.
@@ -132,6 +149,11 @@ if (storeAndAccessInformationOnDevice === false) {
132
149
  }
133
150
  ```
134
151
 
152
+ **Note:** Don't try to use this functionality to enforce user consent on iOS,
153
+ this will likely result in failed app review upon submission to Apple Store, based on [review guideline 3.2.2.vi](https://developer.apple.com/app-store/review/guidelines/#3.2.2):
154
+
155
+ > ...Apps should not require users to rate the app, review the app, watch videos, download other apps, tap on advertisements, enable tracking...
156
+
135
157
  ### Testing
136
158
 
137
159
  When developing the consent flow, the behavior of the `AdsConsent` responses may not be reliable due to the environment
@@ -167,3 +189,12 @@ import { AdsConsent } from 'react-native-google-mobile-ads';
167
189
 
168
190
  AdsConsent.reset();
169
191
  ```
192
+
193
+ ### Troubleshooting
194
+
195
+ In case of troubles, double-check the original documentation for underlying
196
+ UMP SDK for [Android](https://developers.google.com/admob/ump/android/quick-start) /
197
+ [iOS](https://developers.google.com/admob/ump/ios/quick-start).
198
+
199
+ <!-- links -->
200
+ [Inspecting consent choices]: #inspecting-consent-choices
@@ -82,8 +82,7 @@ RCT_EXPORT_METHOD(appOpenShow
82
82
  : (RCTPromiseResolveBlock)resolve
83
83
  : (RCTPromiseRejectBlock)reject) {
84
84
  if (self.appOpenAd) {
85
- [self.appOpenAd
86
- presentFromRootViewController:RCTSharedApplication().delegate.window.rootViewController];
85
+ [self.appOpenAd presentFromRootViewController:RNGoogleMobileAdsCommon.currentViewController];
87
86
  resolve([NSNull null]);
88
87
  } else {
89
88
  [RNSharedUtils
@@ -36,6 +36,8 @@
36
36
 
37
37
  + (BOOL)isAdManagerUnit:(NSString *)unitId;
38
38
 
39
+ + (nullable UIViewController *)currentViewController;
40
+
39
41
  @end
40
42
 
41
43
  @interface RNGADInterstitial : GADInterstitialAd
@@ -51,6 +53,7 @@
51
53
  extern NSString *const GOOGLE_MOBILE_ADS_EVENT_APP_OPEN;
52
54
  extern NSString *const GOOGLE_MOBILE_ADS_EVENT_INTERSTITIAL;
53
55
  extern NSString *const GOOGLE_MOBILE_ADS_EVENT_REWARDED;
56
+ extern NSString *const GOOGLE_MOBILE_ADS_EVENT_REWARDED_INTERSTITIAL;
54
57
 
55
58
  extern NSString *const GOOGLE_MOBILE_ADS_EVENT_LOADED;
56
59
  extern NSString *const GOOGLE_MOBILE_ADS_EVENT_ERROR;
@@ -22,6 +22,8 @@
22
22
  NSString *const GOOGLE_MOBILE_ADS_EVENT_APP_OPEN = @"google_mobile_ads_app_open_event";
23
23
  NSString *const GOOGLE_MOBILE_ADS_EVENT_INTERSTITIAL = @"google_mobile_ads_interstitial_event";
24
24
  NSString *const GOOGLE_MOBILE_ADS_EVENT_REWARDED = @"google_mobile_ads_rewarded_event";
25
+ NSString *const GOOGLE_MOBILE_ADS_EVENT_REWARDED_INTERSTITIAL =
26
+ @"google_mobile_ads_rewarded_interstitial_event";
25
27
  NSString *const GOOGLE_MOBILE_ADS_EVENT_LOADED = @"loaded";
26
28
  NSString *const GOOGLE_MOBILE_ADS_EVENT_ERROR = @"error";
27
29
  NSString *const GOOGLE_MOBILE_ADS_EVENT_OPENED = @"opened";
@@ -188,9 +190,13 @@ NSString *const GOOGLE_MOBILE_ADS_EVENT_REWARDED_EARNED_REWARD = @"rewarded_earn
188
190
  return GADAdSizeFullBanner;
189
191
  } else if ([value isEqualToString:@"LEADERBOARD"]) {
190
192
  return GADAdSizeLeaderboard;
191
- } else if ([value isEqualToString:@"ADAPTIVE_BANNER"]) {
193
+ } else if ([value isEqualToString:@"ADAPTIVE_BANNER"] ||
194
+ [value isEqualToString:@"ANCHORED_ADAPTIVE_BANNER"]) {
192
195
  CGFloat viewWidth = [[UIScreen mainScreen] bounds].size.width;
193
196
  return GADCurrentOrientationAnchoredAdaptiveBannerAdSizeWithWidth(viewWidth);
197
+ } else if ([value isEqualToString:@"INLINE_ADAPTIVE_BANNER"]) {
198
+ CGFloat viewWidth = [[UIScreen mainScreen] bounds].size.width;
199
+ return GADCurrentOrientationInlineAdaptiveBannerAdSizeWithWidth(viewWidth);
194
200
  } else {
195
201
  return GADAdSizeBanner;
196
202
  }
@@ -203,4 +209,15 @@ NSString *const GOOGLE_MOBILE_ADS_EVENT_REWARDED_EARNED_REWARD = @"rewarded_earn
203
209
  return [unitId hasPrefix:@"/"];
204
210
  }
205
211
 
212
+ + (UIViewController *)currentViewController {
213
+ UIViewController *controller = [[[UIApplication sharedApplication] keyWindow] rootViewController];
214
+ UIViewController *presentedController = controller.presentedViewController;
215
+
216
+ while (presentedController && ![presentedController isBeingDismissed]) {
217
+ controller = presentedController;
218
+ presentedController = controller.presentedViewController;
219
+ }
220
+ return controller;
221
+ }
222
+
206
223
  @end
@@ -121,8 +121,7 @@ RCT_EXPORT_METHOD(interstitialShow
121
121
  : (RCTPromiseRejectBlock)reject) {
122
122
  GADInterstitialAd *interstitial = interstitialMap[requestId];
123
123
  if (interstitial) {
124
- [interstitial
125
- presentFromRootViewController:RCTSharedApplication().delegate.window.rootViewController];
124
+ [interstitial presentFromRootViewController:RNGoogleMobileAdsCommon.currentViewController];
126
125
  resolve([NSNull null]);
127
126
  } else {
128
127
  [RNSharedUtils
@@ -0,0 +1,25 @@
1
+ //
2
+ /**
3
+ * Copyright (c) 2016-present Invertase Limited & Contributors
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this library except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ *
17
+ */
18
+
19
+ #import <Foundation/Foundation.h>
20
+
21
+ #import <React/RCTBridgeModule.h>
22
+
23
+ @interface RNGoogleMobileAdsRewardedInterstitialModule : NSObject <RCTBridgeModule>
24
+
25
+ @end