react-native-google-mobile-ads 5.0.1 → 6.0.0

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 (198) hide show
  1. package/RNGoogleMobileAds.podspec +1 -1
  2. package/__tests__/interstitial.test.ts +32 -5
  3. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsAppOpenModule.java +2 -1
  4. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsBannerAdViewManager.java +110 -68
  5. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsCommon.java +5 -11
  6. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsConsentModule.java +19 -5
  7. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsEvent.java +1 -0
  8. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsInterstitialModule.java +38 -20
  9. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsModule.java +45 -0
  10. package/docs/ad-inspector.mdx +39 -0
  11. package/docs/common-reasons-for-ads-not-showing.mdx +26 -24
  12. package/docs/displaying-ads-hook.mdx +99 -0
  13. package/docs/displaying-ads.mdx +49 -29
  14. package/docs/european-user-consent.mdx +34 -5
  15. package/docs/index.mdx +4 -4
  16. package/docs/migrating-to-v5.mdx +17 -8
  17. package/docs/migrating-to-v6.mdx +111 -0
  18. package/docs.json +5 -2
  19. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsAppOpenModule.m +1 -0
  20. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsBannerViewManager.m +63 -8
  21. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsCommon.h +3 -0
  22. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsCommon.m +8 -7
  23. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsConsentModule.m +14 -0
  24. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenContentDelegate.h +2 -1
  25. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenContentDelegate.m +17 -2
  26. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsInterstitialModule.m +44 -30
  27. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsModule.m +19 -0
  28. package/lib/commonjs/AdEventType.js.map +1 -1
  29. package/lib/commonjs/AdsConsent.js +47 -16
  30. package/lib/commonjs/AdsConsent.js.map +1 -1
  31. package/lib/commonjs/AdsConsentPurposes.js +47 -0
  32. package/lib/commonjs/AdsConsentPurposes.js.map +1 -0
  33. package/lib/commonjs/AdsConsentSpecialFeatures.js +39 -0
  34. package/lib/commonjs/AdsConsentSpecialFeatures.js.map +1 -0
  35. package/lib/commonjs/GAMAdEventType.js +30 -0
  36. package/lib/commonjs/GAMAdEventType.js.map +1 -0
  37. package/lib/commonjs/MobileAds.js +4 -0
  38. package/lib/commonjs/MobileAds.js.map +1 -1
  39. package/lib/commonjs/RewardedAdEventType.js.map +1 -1
  40. package/lib/commonjs/TestIds.js +5 -0
  41. package/lib/commonjs/TestIds.js.map +1 -1
  42. package/lib/commonjs/ads/AppOpenAd.js +8 -53
  43. package/lib/commonjs/ads/AppOpenAd.js.map +1 -1
  44. package/lib/commonjs/ads/BannerAd.js +7 -110
  45. package/lib/commonjs/ads/BannerAd.js.map +1 -1
  46. package/lib/commonjs/ads/BaseAd.js +144 -0
  47. package/lib/commonjs/ads/BaseAd.js.map +1 -0
  48. package/lib/commonjs/ads/GAMBannerAd.js +42 -0
  49. package/lib/commonjs/ads/GAMBannerAd.js.map +1 -0
  50. package/lib/commonjs/ads/GAMInterstitialAd.js +48 -0
  51. package/lib/commonjs/ads/GAMInterstitialAd.js.map +1 -0
  52. package/lib/commonjs/ads/InterstitialAd.js +13 -64
  53. package/lib/commonjs/ads/InterstitialAd.js.map +1 -1
  54. package/lib/commonjs/ads/MobileAd.js +119 -12
  55. package/lib/commonjs/ads/MobileAd.js.map +1 -1
  56. package/lib/commonjs/ads/RewardedAd.js +23 -65
  57. package/lib/commonjs/ads/RewardedAd.js.map +1 -1
  58. package/lib/commonjs/hooks/useAppOpenAd.js +51 -0
  59. package/lib/commonjs/hooks/useAppOpenAd.js.map +1 -0
  60. package/lib/commonjs/hooks/useFullScreenAd.js +125 -0
  61. package/lib/commonjs/hooks/useFullScreenAd.js.map +1 -0
  62. package/lib/commonjs/hooks/useInterstitialAd.js +51 -0
  63. package/lib/commonjs/hooks/useInterstitialAd.js.map +1 -0
  64. package/lib/commonjs/hooks/useRewardedAd.js +51 -0
  65. package/lib/commonjs/hooks/useRewardedAd.js.map +1 -0
  66. package/lib/commonjs/index.js +102 -0
  67. package/lib/commonjs/index.js.map +1 -1
  68. package/lib/commonjs/types/AdEventsListener.js +6 -0
  69. package/lib/commonjs/types/AdEventsListener.js.map +1 -0
  70. package/lib/commonjs/types/AdStates.js +6 -0
  71. package/lib/commonjs/types/AdStates.js.map +1 -0
  72. package/lib/commonjs/types/AppEvent.js +2 -0
  73. package/lib/commonjs/types/AppEvent.js.map +1 -0
  74. package/lib/commonjs/types/index.js +149 -0
  75. package/lib/commonjs/types/index.js.map +1 -0
  76. package/lib/commonjs/validateAdRequestOptions.js +0 -38
  77. package/lib/commonjs/validateAdRequestOptions.js.map +1 -1
  78. package/lib/commonjs/version.js +2 -2
  79. package/lib/commonjs/version.js.map +1 -1
  80. package/lib/module/AdEventType.js.map +1 -1
  81. package/lib/module/AdsConsent.js +44 -16
  82. package/lib/module/AdsConsent.js.map +1 -1
  83. package/lib/module/AdsConsentPurposes.js +39 -0
  84. package/lib/module/AdsConsentPurposes.js.map +1 -0
  85. package/lib/module/AdsConsentSpecialFeatures.js +31 -0
  86. package/lib/module/AdsConsentSpecialFeatures.js.map +1 -0
  87. package/lib/module/GAMAdEventType.js +22 -0
  88. package/lib/module/GAMAdEventType.js.map +1 -0
  89. package/lib/module/MobileAds.js +4 -0
  90. package/lib/module/MobileAds.js.map +1 -1
  91. package/lib/module/RewardedAdEventType.js.map +1 -1
  92. package/lib/module/TestIds.js +5 -0
  93. package/lib/module/TestIds.js.map +1 -1
  94. package/lib/module/ads/AppOpenAd.js +10 -37
  95. package/lib/module/ads/AppOpenAd.js.map +1 -1
  96. package/lib/module/ads/BannerAd.js +7 -85
  97. package/lib/module/ads/BannerAd.js.map +1 -1
  98. package/lib/module/ads/BaseAd.js +124 -0
  99. package/lib/module/ads/BaseAd.js.map +1 -0
  100. package/lib/module/ads/GAMBannerAd.js +42 -0
  101. package/lib/module/ads/GAMBannerAd.js.map +1 -0
  102. package/lib/module/ads/GAMInterstitialAd.js +38 -0
  103. package/lib/module/ads/GAMInterstitialAd.js.map +1 -0
  104. package/lib/module/ads/InterstitialAd.js +15 -48
  105. package/lib/module/ads/InterstitialAd.js.map +1 -1
  106. package/lib/module/ads/MobileAd.js +116 -12
  107. package/lib/module/ads/MobileAd.js.map +1 -1
  108. package/lib/module/ads/RewardedAd.js +24 -49
  109. package/lib/module/ads/RewardedAd.js.map +1 -1
  110. package/lib/module/hooks/useAppOpenAd.js +38 -0
  111. package/lib/module/hooks/useAppOpenAd.js.map +1 -0
  112. package/lib/module/hooks/useFullScreenAd.js +114 -0
  113. package/lib/module/hooks/useFullScreenAd.js.map +1 -0
  114. package/lib/module/hooks/useInterstitialAd.js +38 -0
  115. package/lib/module/hooks/useInterstitialAd.js.map +1 -0
  116. package/lib/module/hooks/useRewardedAd.js +38 -0
  117. package/lib/module/hooks/useRewardedAd.js.map +1 -0
  118. package/lib/module/index.js +9 -0
  119. package/lib/module/index.js.map +1 -1
  120. package/lib/module/types/AdEventsListener.js +2 -0
  121. package/lib/module/types/AdEventsListener.js.map +1 -0
  122. package/lib/module/types/AdStates.js +2 -0
  123. package/lib/module/types/AdStates.js.map +1 -0
  124. package/lib/module/types/AppEvent.js +2 -0
  125. package/lib/module/types/AppEvent.js.map +1 -0
  126. package/lib/module/types/index.js +28 -0
  127. package/lib/module/types/index.js.map +1 -0
  128. package/lib/module/validateAdRequestOptions.js +1 -39
  129. package/lib/module/validateAdRequestOptions.js.map +1 -1
  130. package/lib/module/version.js +2 -2
  131. package/lib/module/version.js.map +1 -1
  132. package/lib/typescript/AdEventType.d.ts +4 -8
  133. package/lib/typescript/AdsConsentPurposes.d.ts +148 -0
  134. package/lib/typescript/AdsConsentSpecialFeatures.d.ts +22 -0
  135. package/lib/typescript/GAMAdEventType.d.ts +20 -0
  136. package/lib/typescript/MobileAds.d.ts +2 -1
  137. package/lib/typescript/RewardedAdEventType.d.ts +7 -11
  138. package/lib/typescript/TestIds.d.ts +5 -0
  139. package/lib/typescript/ads/AppOpenAd.d.ts +6 -6
  140. package/lib/typescript/ads/BannerAd.d.ts +1 -1
  141. package/lib/typescript/ads/BaseAd.d.ts +35 -0
  142. package/lib/typescript/ads/GAMBannerAd.d.ts +7 -0
  143. package/lib/typescript/ads/GAMInterstitialAd.d.ts +33 -0
  144. package/lib/typescript/ads/InterstitialAd.d.ts +10 -16
  145. package/lib/typescript/ads/MobileAd.d.ts +34 -16
  146. package/lib/typescript/ads/RewardedAd.d.ts +17 -19
  147. package/lib/typescript/hooks/useAppOpenAd.d.ts +9 -0
  148. package/lib/typescript/hooks/useFullScreenAd.d.ts +5 -0
  149. package/lib/typescript/hooks/useInterstitialAd.d.ts +9 -0
  150. package/lib/typescript/hooks/useRewardedAd.d.ts +9 -0
  151. package/lib/typescript/index.d.ts +10 -1
  152. package/lib/typescript/types/AdEventListener.d.ts +5 -9
  153. package/lib/typescript/types/AdEventsListener.d.ts +8 -0
  154. package/lib/typescript/types/AdStates.d.ts +85 -0
  155. package/lib/typescript/types/AdsConsent.interface.d.ts +216 -0
  156. package/lib/typescript/types/AppEvent.d.ts +13 -0
  157. package/lib/typescript/types/BannerAdProps.d.ts +81 -4
  158. package/lib/typescript/types/GoogleMobileAdsNativeModule.d.ts +3 -2
  159. package/lib/typescript/types/MobileAd.interface.d.ts +37 -12
  160. package/lib/typescript/types/MobileAdsModule.interface.d.ts +9 -0
  161. package/lib/typescript/types/RequestOptions.d.ts +0 -22
  162. package/lib/typescript/types/index.d.ts +11 -0
  163. package/lib/typescript/version.d.ts +1 -1
  164. package/package.json +55 -50
  165. package/src/AdEventType.ts +4 -8
  166. package/src/AdsConsent.ts +75 -20
  167. package/src/AdsConsentPurposes.ts +182 -0
  168. package/src/AdsConsentSpecialFeatures.ts +48 -0
  169. package/src/GAMAdEventType.ts +37 -0
  170. package/src/MobileAds.ts +4 -0
  171. package/src/RewardedAdEventType.ts +7 -11
  172. package/src/TestIds.ts +5 -0
  173. package/src/ads/AppOpenAd.ts +11 -41
  174. package/src/ads/BannerAd.tsx +4 -106
  175. package/src/ads/BaseAd.tsx +156 -0
  176. package/src/ads/GAMBannerAd.tsx +37 -0
  177. package/src/ads/GAMInterstitialAd.ts +45 -0
  178. package/src/ads/InterstitialAd.ts +15 -56
  179. package/src/ads/MobileAd.ts +142 -29
  180. package/src/ads/RewardedAd.ts +29 -55
  181. package/src/hooks/useAppOpenAd.ts +46 -0
  182. package/src/hooks/useFullScreenAd.ts +105 -0
  183. package/src/hooks/useInterstitialAd.ts +46 -0
  184. package/src/hooks/useRewardedAd.ts +46 -0
  185. package/src/index.ts +9 -0
  186. package/src/types/AdEventListener.ts +31 -13
  187. package/src/types/AdEventsListener.ts +24 -0
  188. package/src/types/AdStates.ts +87 -0
  189. package/src/types/AdsConsent.interface.ts +220 -0
  190. package/src/types/AppEvent.ts +14 -0
  191. package/src/types/BannerAdProps.ts +81 -4
  192. package/src/types/GoogleMobileAdsNativeModule.ts +3 -2
  193. package/src/types/MobileAd.interface.ts +56 -12
  194. package/src/types/MobileAdsModule.interface.ts +10 -0
  195. package/src/types/RequestOptions.ts +0 -24
  196. package/src/types/index.ts +28 -0
  197. package/src/validateAdRequestOptions.ts +0 -45
  198. package/src/version.ts +2 -2
@@ -19,7 +19,7 @@ Pod::Spec.new do |s|
19
19
  s.social_media_url = 'http://twitter.com/invertaseio'
20
20
  s.ios.deployment_target = "10.0"
21
21
  s.source_files = 'ios/**/*.{h,m}'
22
- s.frameworks = "AppTrackingTransparency"
22
+ s.weak_frameworks = "AppTrackingTransparency"
23
23
 
24
24
  # React Native dependencies
25
25
  s.dependency 'React-Core'
@@ -1,4 +1,4 @@
1
- import { InterstitialAd } from '../src';
1
+ import { AdEventType, InterstitialAd } from '../src';
2
2
 
3
3
  describe('Google Mobile Ads Interstitial', function () {
4
4
  describe('createForAdRequest', function () {
@@ -34,17 +34,44 @@ describe('Google Mobile Ads Interstitial', function () {
34
34
  });
35
35
  });
36
36
 
37
- describe('onAdEvent', function () {
38
- it('throws if handler is not a function', function () {
37
+ describe('addAdEventsListener', function () {
38
+ it('throws if listener is not a function', function () {
39
39
  const i = InterstitialAd.createForAdRequest('abc');
40
40
 
41
41
  // @ts-ignore
42
- expect(() => i.onAdEvent('foo')).toThrowError("'handler' expected a function");
42
+ expect(() => i.addAdEventsListener('foo')).toThrowError("'listener' expected a function");
43
43
  });
44
44
 
45
45
  it('returns an unsubscriber function', function () {
46
46
  const i = InterstitialAd.createForAdRequest('abc');
47
- const unsub = i.onAdEvent(() => {});
47
+ const unsub = i.addAdEventsListener(() => {});
48
+ expect(unsub).toBeDefined();
49
+ unsub();
50
+ });
51
+ });
52
+
53
+ describe('addAdEventListener', function () {
54
+ it('throws if type is not a AdEventType', function () {
55
+ const i = InterstitialAd.createForAdRequest('abc');
56
+
57
+ // @ts-ignore
58
+ expect(() => i.addAdEventListener('foo')).toThrowError(
59
+ "'type' expected a valid event type value.",
60
+ );
61
+ });
62
+
63
+ it('throws if listener is not a function', function () {
64
+ const i = InterstitialAd.createForAdRequest('abc');
65
+
66
+ // @ts-ignore
67
+ expect(() => i.addAdEventListener(AdEventType.LOADED, 'foo')).toThrowError(
68
+ "'listener' expected a function",
69
+ );
70
+ });
71
+
72
+ it('returns an unsubscriber function', function () {
73
+ const i = InterstitialAd.createForAdRequest('abc');
74
+ const unsub = i.addAdEventListener(AdEventType.LOADED, () => {});
48
75
  expect(unsub).toBeDefined();
49
76
  unsub();
50
77
  });
@@ -119,7 +119,8 @@ public class ReactNativeGoogleMobileAdsAppOpenModule extends ReactNativeModule {
119
119
  }
120
120
 
121
121
  @ReactMethod
122
- public void appOpenShow(int requestId, ReadableMap showOptions, Promise promise) {
122
+ public void appOpenShow(
123
+ int requestId, String adUnitId, ReadableMap showOptions, Promise promise) {
123
124
  if (getCurrentActivity() == null) {
124
125
  rejectPromiseWithCodeAndMessage(
125
126
  promise,
@@ -20,6 +20,7 @@ package io.invertase.googlemobileads;
20
20
  import android.view.ViewGroup;
21
21
  import androidx.annotation.NonNull;
22
22
  import com.facebook.react.bridge.Arguments;
23
+ import com.facebook.react.bridge.ReadableArray;
23
24
  import com.facebook.react.bridge.ReadableMap;
24
25
  import com.facebook.react.bridge.WritableMap;
25
26
  import com.facebook.react.common.MapBuilder;
@@ -33,22 +34,31 @@ import com.google.android.gms.ads.AdListener;
33
34
  import com.google.android.gms.ads.AdRequest;
34
35
  import com.google.android.gms.ads.AdSize;
35
36
  import com.google.android.gms.ads.AdView;
37
+ import com.google.android.gms.ads.BaseAdView;
36
38
  import com.google.android.gms.ads.LoadAdError;
39
+ import com.google.android.gms.ads.admanager.AdManagerAdView;
40
+ import com.google.android.gms.ads.admanager.AppEventListener;
41
+ import java.util.ArrayList;
42
+ import java.util.List;
37
43
  import java.util.Map;
38
44
  import javax.annotation.Nonnull;
45
+ import javax.annotation.Nullable;
39
46
 
40
47
  public class ReactNativeGoogleMobileAdsBannerAdViewManager
41
48
  extends SimpleViewManager<ReactViewGroup> {
42
49
  private static final String REACT_CLASS = "RNGoogleMobileAdsBannerView";
43
- private String EVENT_AD_LOADED = "onAdLoaded";
44
- private String EVENT_AD_FAILED_TO_LOAD = "onAdFailedToLoad";
45
- private String EVENT_AD_OPENED = "onAdOpened";
46
- private String EVENT_AD_CLOSED = "onAdClosed";
50
+ private final String EVENT_AD_LOADED = "onAdLoaded";
51
+ private final String EVENT_AD_FAILED_TO_LOAD = "onAdFailedToLoad";
52
+ private final String EVENT_AD_OPENED = "onAdOpened";
53
+ private final String EVENT_AD_CLOSED = "onAdClosed";
54
+ private final String EVENT_APP_EVENT = "onAppEvent";
55
+ private final int COMMAND_ID_RECORD_MANUAL_IMPRESSION = 1;
47
56
 
48
- private Boolean requested = false;
49
57
  private AdRequest request;
50
- private AdSize size;
58
+ private List<AdSize> sizes;
51
59
  private String unitId;
60
+ private Boolean manualImpressionsEnabled;
61
+ private boolean isFluid;
52
62
 
53
63
  @Nonnull
54
64
  @Override
@@ -59,24 +69,7 @@ public class ReactNativeGoogleMobileAdsBannerAdViewManager
59
69
  @Nonnull
60
70
  @Override
61
71
  public ReactViewGroup createViewInstance(@Nonnull ThemedReactContext themedReactContext) {
62
- ReactViewGroup viewGroup = new ReactViewGroup(themedReactContext);
63
- AdView adView = new AdView(themedReactContext);
64
- viewGroup.addView(adView);
65
- setAdListener(viewGroup);
66
- return viewGroup;
67
- }
68
-
69
- private AdView getAdView(ReactViewGroup viewGroup) {
70
- return (AdView) viewGroup.getChildAt(0);
71
- }
72
-
73
- private void resetAdView(ReactViewGroup reactViewGroup) {
74
- AdView oldAdView = getAdView(reactViewGroup);
75
- AdView newAdView = new AdView(reactViewGroup.getContext());
76
- reactViewGroup.removeViewAt(0);
77
- if (oldAdView != null) oldAdView.destroy();
78
- reactViewGroup.addView(newAdView);
79
- setAdListener(reactViewGroup);
72
+ return new ReactViewGroup(themedReactContext);
80
73
  }
81
74
 
82
75
  @Override
@@ -86,6 +79,26 @@ public class ReactNativeGoogleMobileAdsBannerAdViewManager
86
79
  return builder.build();
87
80
  }
88
81
 
82
+ @Nullable
83
+ @Override
84
+ public Map<String, Integer> getCommandsMap() {
85
+ return MapBuilder.of("recordManualImpression", COMMAND_ID_RECORD_MANUAL_IMPRESSION);
86
+ }
87
+
88
+ @Override
89
+ public void receiveCommand(
90
+ @NonNull ReactViewGroup reactViewGroup, String commandId, @Nullable ReadableArray args) {
91
+ super.receiveCommand(reactViewGroup, commandId, args);
92
+ int commandIdInt = Integer.parseInt(commandId);
93
+
94
+ if (commandIdInt == COMMAND_ID_RECORD_MANUAL_IMPRESSION) {
95
+ BaseAdView adView = getAdView(reactViewGroup);
96
+ if (adView instanceof AdManagerAdView) {
97
+ ((AdManagerAdView) adView).recordManualImpression();
98
+ }
99
+ }
100
+ }
101
+
89
102
  @ReactProp(name = "unitId")
90
103
  public void setUnitId(ReactViewGroup reactViewGroup, String value) {
91
104
  unitId = value;
@@ -98,62 +111,62 @@ public class ReactNativeGoogleMobileAdsBannerAdViewManager
98
111
  requestAd(reactViewGroup);
99
112
  }
100
113
 
101
- @ReactProp(name = "size")
102
- public void setSize(ReactViewGroup reactViewGroup, String value) {
103
- size = ReactNativeGoogleMobileAdsCommon.getAdSize(value, reactViewGroup);
104
-
105
- WritableMap payload = Arguments.createMap();
106
-
107
- int width = size.getWidth();
108
- int height = size.getHeight();
109
-
110
- payload.putDouble("width", width);
111
- payload.putDouble("height", height);
112
-
113
- if (size != AdSize.FLUID) {
114
- sendEvent(reactViewGroup, "onSizeChange", payload);
114
+ @ReactProp(name = "sizes")
115
+ public void setSizes(ReactViewGroup reactViewGroup, ReadableArray value) {
116
+ List<AdSize> sizeList = new ArrayList<>();
117
+ for (Object size : value.toArrayList()) {
118
+ if (size instanceof String) {
119
+ String sizeString = (String) size;
120
+ sizeList.add(ReactNativeGoogleMobileAdsCommon.getAdSize(sizeString, reactViewGroup));
121
+ }
115
122
  }
123
+ sizes = sizeList;
116
124
  requestAd(reactViewGroup);
117
125
  }
118
126
 
119
- private void setAdListener(ReactViewGroup reactViewGroup) {
120
- final AdView adView = getAdView(reactViewGroup);
127
+ @ReactProp(name = "manualImpressionsEnabled")
128
+ public void setManualImpressionsEnabled(ReactViewGroup reactViewGroup, boolean value) {
129
+ this.manualImpressionsEnabled = value;
130
+ requestAd(reactViewGroup);
131
+ }
121
132
 
133
+ private BaseAdView initAdView(ReactViewGroup reactViewGroup) {
134
+ BaseAdView oldAdView = getAdView(reactViewGroup);
135
+ if (oldAdView != null) {
136
+ oldAdView.destroy();
137
+ reactViewGroup.removeView(oldAdView);
138
+ }
139
+ BaseAdView adView;
140
+ if (ReactNativeGoogleMobileAdsCommon.isAdManagerUnit(unitId)) {
141
+ adView = new AdManagerAdView(reactViewGroup.getContext());
142
+ } else {
143
+ adView = new AdView(reactViewGroup.getContext());
144
+ }
122
145
  adView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
123
146
  adView.setAdListener(
124
147
  new AdListener() {
125
148
  @Override
126
149
  public void onAdLoaded() {
127
- int top;
128
- int left;
129
- int width;
130
- int height;
131
-
132
- if (size == AdSize.FLUID) {
133
- top = 0;
150
+ AdSize adSize = adView.getAdSize();
151
+ int left, top, width, height;
152
+ if (isFluid) {
153
+ // TODO size=FLUID is still not working
134
154
  left = 0;
155
+ top = 0;
135
156
  width = reactViewGroup.getWidth();
136
157
  height = reactViewGroup.getHeight();
137
158
  } else {
138
- top = adView.getTop();
139
159
  left = adView.getLeft();
140
- width = adView.getAdSize().getWidthInPixels(reactViewGroup.getContext());
141
- height = adView.getAdSize().getHeightInPixels(reactViewGroup.getContext());
160
+ top = adView.getTop();
161
+ width = adSize.getWidthInPixels(reactViewGroup.getContext());
162
+ height = adSize.getHeightInPixels(reactViewGroup.getContext());
142
163
  }
143
-
144
- // TODO size=FLUID not loading ad, height of child FrameLayout incorrect?
145
164
  adView.measure(width, height);
146
165
  adView.layout(left, top, left + width, top + height);
147
166
 
148
167
  WritableMap payload = Arguments.createMap();
149
-
150
- if (size != AdSize.FLUID) {
151
- payload.putInt("width", (int) PixelUtil.toDIPFromPixel(width) + 1);
152
- payload.putInt("height", (int) PixelUtil.toDIPFromPixel(height) + 1);
153
- } else {
154
- payload.putInt("width", (int) PixelUtil.toDIPFromPixel(width));
155
- payload.putInt("height", (int) PixelUtil.toDIPFromPixel(height));
156
- }
168
+ payload.putDouble("width", PixelUtil.toDIPFromPixel(width));
169
+ payload.putDouble("height", PixelUtil.toDIPFromPixel(height));
157
170
 
158
171
  sendEvent(reactViewGroup, EVENT_AD_LOADED, payload);
159
172
  }
@@ -175,23 +188,52 @@ public class ReactNativeGoogleMobileAdsBannerAdViewManager
175
188
  sendEvent(reactViewGroup, EVENT_AD_CLOSED, null);
176
189
  }
177
190
  });
191
+ if (adView instanceof AdManagerAdView) {
192
+ ((AdManagerAdView) adView)
193
+ .setAppEventListener(
194
+ new AppEventListener() {
195
+ @Override
196
+ public void onAppEvent(@NonNull String name, @Nullable String data) {
197
+ WritableMap payload = Arguments.createMap();
198
+ payload.putString("name", name);
199
+ payload.putString("data", data);
200
+ sendEvent(reactViewGroup, EVENT_APP_EVENT, payload);
201
+ }
202
+ });
203
+ }
204
+ reactViewGroup.addView(adView);
205
+ return adView;
206
+ }
207
+
208
+ @Nullable
209
+ private BaseAdView getAdView(ReactViewGroup reactViewGroup) {
210
+ return (BaseAdView) reactViewGroup.getChildAt(0);
178
211
  }
179
212
 
180
213
  private void requestAd(ReactViewGroup reactViewGroup) {
181
- if (size == null || unitId == null || request == null) {
214
+ if (sizes == null || unitId == null || request == null || manualImpressionsEnabled == null) {
182
215
  return;
183
216
  }
184
217
 
185
- if (requested) {
186
- resetAdView(reactViewGroup);
218
+ BaseAdView adView = initAdView(reactViewGroup);
219
+ adView.setAdUnitId(unitId);
220
+
221
+ isFluid = false;
222
+ if (adView instanceof AdManagerAdView) {
223
+ if (sizes.contains(AdSize.FLUID)) {
224
+ isFluid = true;
225
+ ((AdManagerAdView) adView).setAdSizes(AdSize.FLUID);
226
+ } else {
227
+ ((AdManagerAdView) adView).setAdSizes(sizes.toArray(new AdSize[0]));
228
+ }
229
+ if (manualImpressionsEnabled) {
230
+ ((AdManagerAdView) adView).setManualImpressionsEnabled(true);
231
+ }
232
+ } else {
233
+ adView.setAdSize(sizes.get(0));
187
234
  }
188
235
 
189
- AdView adView = getAdView(reactViewGroup);
190
- adView.setAdUnitId(unitId);
191
- adView.setAdSize(size);
192
236
  adView.loadAd(request);
193
-
194
- requested = true;
195
237
  }
196
238
 
197
239
  private void sendEvent(ReactViewGroup reactViewGroup, String type, WritableMap payload) {
@@ -17,13 +17,11 @@ package io.invertase.googlemobileads;
17
17
  *
18
18
  */
19
19
 
20
- import android.location.Location;
21
20
  import android.os.Bundle;
22
21
  import android.util.DisplayMetrics;
23
22
  import android.view.Display;
24
23
  import com.facebook.react.bridge.Arguments;
25
24
  import com.facebook.react.bridge.ReactContext;
26
- import com.facebook.react.bridge.ReadableArray;
27
25
  import com.facebook.react.bridge.ReadableMap;
28
26
  import com.facebook.react.bridge.WritableMap;
29
27
  import com.facebook.react.views.view.ReactViewGroup;
@@ -165,15 +163,6 @@ public class ReactNativeGoogleMobileAdsCommon {
165
163
  builder.setContentUrl(Objects.requireNonNull(adRequestOptions.getString("contentUrl")));
166
164
  }
167
165
 
168
- if (adRequestOptions.hasKey("location")) {
169
- ReadableArray locationArray = adRequestOptions.getArray("location");
170
- Location location = new Location("");
171
- location.setLatitude(Objects.requireNonNull(locationArray).getDouble(0));
172
- location.setLongitude(Objects.requireNonNull(locationArray).getDouble(1));
173
-
174
- builder.setLocation(location);
175
- }
176
-
177
166
  if (adRequestOptions.hasKey("requestAgent")) {
178
167
  builder.setRequestAgent(Objects.requireNonNull(adRequestOptions.getString("requestAgent")));
179
168
  }
@@ -264,4 +253,9 @@ public class ReactNativeGoogleMobileAdsCommon {
264
253
  codeAndMessage[1] = message;
265
254
  return codeAndMessage;
266
255
  }
256
+
257
+ public static boolean isAdManagerUnit(String unitId) {
258
+ if (unitId == null) return false;
259
+ return unitId.startsWith("/");
260
+ }
267
261
  }
@@ -16,11 +16,13 @@ package io.invertase.googlemobileads;
16
16
  * limitations under the License.
17
17
  *
18
18
  */
19
-
19
+ import android.content.SharedPreferences;
20
+ import android.preference.PreferenceManager;
20
21
  import com.facebook.react.bridge.Arguments;
21
22
  import com.facebook.react.bridge.Promise;
22
23
  import com.facebook.react.bridge.ReactApplicationContext;
23
24
  import com.facebook.react.bridge.ReactMethod;
25
+ import com.facebook.react.bridge.ReadableArray;
24
26
  import com.facebook.react.bridge.ReadableMap;
25
27
  import com.facebook.react.bridge.WritableMap;
26
28
  import com.google.android.ump.ConsentDebugSettings;
@@ -28,7 +30,6 @@ import com.google.android.ump.ConsentInformation;
28
30
  import com.google.android.ump.ConsentRequestParameters;
29
31
  import com.google.android.ump.UserMessagingPlatform;
30
32
  import io.invertase.googlemobileads.common.ReactNativeModule;
31
- import java.util.List;
32
33
  import javax.annotation.Nonnull;
33
34
 
34
35
  public class ReactNativeGoogleMobileAdsConsentModule extends ReactNativeModule {
@@ -63,10 +64,10 @@ public class ReactNativeGoogleMobileAdsConsentModule extends ReactNativeModule {
63
64
  new ConsentDebugSettings.Builder(getApplicationContext());
64
65
 
65
66
  if (options.hasKey("testDeviceIdentifiers")) {
66
- List<Object> devices = options.getArray("testDeviceIdentifiers").toArrayList();
67
+ ReadableArray devices = options.getArray("testDeviceIdentifiers");
67
68
 
68
- for (Object device : devices) {
69
- debugSettingsBuilder.addTestDeviceHashedId((String) device);
69
+ for (int i = 0; i < devices.size(); i++) {
70
+ debugSettingsBuilder.addTestDeviceHashedId(devices.getString(i));
70
71
  }
71
72
  }
72
73
 
@@ -152,4 +153,17 @@ public class ReactNativeGoogleMobileAdsConsentModule extends ReactNativeModule {
152
153
  public void reset() {
153
154
  consentInformation.reset();
154
155
  }
156
+
157
+ @ReactMethod
158
+ public void getTCString(Promise promise) {
159
+ try {
160
+ SharedPreferences prefs =
161
+ PreferenceManager.getDefaultSharedPreferences(getReactApplicationContext());
162
+ // https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#in-app-details
163
+ String tcString = prefs.getString("IABTCF_TCString", null);
164
+ promise.resolve(tcString);
165
+ } catch (Exception e) {
166
+ rejectPromiseWithCodeAndMessage(promise, "consent-string-error", e.toString());
167
+ }
168
+ }
155
169
  }
@@ -32,6 +32,7 @@ public class ReactNativeGoogleMobileAdsEvent implements NativeEvent {
32
32
  public static final String GOOGLE_MOBILE_ADS_EVENT_OPENED = "opened";
33
33
  public static final String GOOGLE_MOBILE_ADS_EVENT_CLICKED = "clicked";
34
34
  public static final String GOOGLE_MOBILE_ADS_EVENT_CLOSED = "closed";
35
+ public static final String GOOGLE_MOBILE_ADS_EVENT_APP_EVENT = "app_event";
35
36
 
36
37
  public static final String GOOGLE_MOBILE_ADS_EVENT_REWARDED_LOADED = "rewarded_loaded";
37
38
  public static final String GOOGLE_MOBILE_ADS_EVENT_REWARDED_EARNED_REWARD =
@@ -20,6 +20,7 @@ package io.invertase.googlemobileads;
20
20
  import static io.invertase.googlemobileads.ReactNativeGoogleMobileAdsCommon.buildAdRequest;
21
21
  import static io.invertase.googlemobileads.ReactNativeGoogleMobileAdsCommon.getCodeAndMessageFromAdError;
22
22
  import static io.invertase.googlemobileads.ReactNativeGoogleMobileAdsCommon.sendAdEvent;
23
+ import static io.invertase.googlemobileads.ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_APP_EVENT;
23
24
  import static io.invertase.googlemobileads.ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_CLICKED;
24
25
  import static io.invertase.googlemobileads.ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_CLOSED;
25
26
  import static io.invertase.googlemobileads.ReactNativeGoogleMobileAdsEvent.GOOGLE_MOBILE_ADS_EVENT_ERROR;
@@ -38,6 +39,8 @@ import com.facebook.react.bridge.ReadableMap;
38
39
  import com.facebook.react.bridge.WritableMap;
39
40
  import com.google.android.gms.ads.FullScreenContentCallback;
40
41
  import com.google.android.gms.ads.LoadAdError;
42
+ import com.google.android.gms.ads.admanager.AdManagerInterstitialAd;
43
+ import com.google.android.gms.ads.admanager.AppEventListener;
41
44
  import com.google.android.gms.ads.interstitial.InterstitialAd;
42
45
  import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback;
43
46
  import io.invertase.googlemobileads.common.ReactNativeModule;
@@ -74,7 +77,6 @@ public class ReactNativeGoogleMobileAdsInterstitialModule extends ReactNativeMod
74
77
 
75
78
  @Override
76
79
  public void onAdLoaded(@NonNull InterstitialAd interstitialAd) {
77
-
78
80
  interstitialAd.setFullScreenContentCallback(
79
81
  new FullScreenContentCallback() {
80
82
  @Override
@@ -96,7 +98,23 @@ public class ReactNativeGoogleMobileAdsInterstitialModule extends ReactNativeMod
96
98
  GOOGLE_MOBILE_ADS_EVENT_OPENED, requestId, adUnitId, null);
97
99
  }
98
100
  });
99
-
101
+ if (interstitialAd instanceof AdManagerInterstitialAd) {
102
+ ((AdManagerInterstitialAd) interstitialAd)
103
+ .setAppEventListener(
104
+ new AppEventListener() {
105
+ @Override
106
+ public void onAppEvent(@NonNull String name, @Nullable String data) {
107
+ WritableMap payload = Arguments.createMap();
108
+ payload.putString("name", name);
109
+ payload.putString("data", data);
110
+ sendInterstitialEvent(
111
+ GOOGLE_MOBILE_ADS_EVENT_APP_EVENT,
112
+ requestId,
113
+ adUnitId,
114
+ payload);
115
+ }
116
+ });
117
+ }
100
118
  interstitialAdArray.put(requestId, interstitialAd);
101
119
  sendInterstitialEvent(GOOGLE_MOBILE_ADS_EVENT_LOADED, requestId, adUnitId, null);
102
120
  }
@@ -111,16 +129,25 @@ public class ReactNativeGoogleMobileAdsInterstitialModule extends ReactNativeMod
111
129
  }
112
130
  };
113
131
 
114
- InterstitialAd.load(
115
- currentActivity,
116
- adUnitId,
117
- buildAdRequest(adRequestOptions),
118
- interstitialAdLoadCallback);
132
+ if (ReactNativeGoogleMobileAdsCommon.isAdManagerUnit(adUnitId)) {
133
+ AdManagerInterstitialAd.load(
134
+ currentActivity,
135
+ adUnitId,
136
+ buildAdRequest(adRequestOptions),
137
+ interstitialAdLoadCallback);
138
+ } else {
139
+ InterstitialAd.load(
140
+ currentActivity,
141
+ adUnitId,
142
+ buildAdRequest(adRequestOptions),
143
+ interstitialAdLoadCallback);
144
+ }
119
145
  });
120
146
  }
121
147
 
122
148
  @ReactMethod
123
- public void interstitialShow(int requestId, ReadableMap showOptions, Promise promise) {
149
+ public void interstitialShow(
150
+ int requestId, String adUnitId, ReadableMap showOptions, Promise promise) {
124
151
  if (getCurrentActivity() == null) {
125
152
  rejectPromiseWithCodeAndMessage(
126
153
  promise,
@@ -134,9 +161,7 @@ public class ReactNativeGoogleMobileAdsInterstitialModule extends ReactNativeMod
134
161
  InterstitialAd interstitialAd = interstitialAdArray.get(requestId);
135
162
  if (interstitialAd == null) {
136
163
  rejectPromiseWithCodeAndMessage(
137
- promise,
138
- "null-interstitialAd",
139
- "Interstitial ad attempted to show but its object was null.");
164
+ promise, "not-ready", "Interstitial ad attempted to show but was not ready.");
140
165
  return;
141
166
  }
142
167
 
@@ -146,15 +171,8 @@ public class ReactNativeGoogleMobileAdsInterstitialModule extends ReactNativeMod
146
171
  interstitialAd.setImmersiveMode(false);
147
172
  }
148
173
 
149
- String a = String.valueOf(requestId);
150
-
151
- if (interstitialAd != null) {
152
- interstitialAd.show(getCurrentActivity());
153
- promise.resolve(null);
154
- } else {
155
- rejectPromiseWithCodeAndMessage(
156
- promise, "not-ready", "Interstitial ad attempted to show but was not ready.");
157
- }
174
+ interstitialAd.show(getCurrentActivity());
175
+ promise.resolve(null);
158
176
  });
159
177
  }
160
178
  }
@@ -17,6 +17,7 @@ package io.invertase.googlemobileads;
17
17
  *
18
18
  */
19
19
 
20
+ import androidx.annotation.Nullable;
20
21
  import com.facebook.react.bridge.Arguments;
21
22
  import com.facebook.react.bridge.Promise;
22
23
  import com.facebook.react.bridge.ReactApplicationContext;
@@ -24,8 +25,10 @@ import com.facebook.react.bridge.ReactMethod;
24
25
  import com.facebook.react.bridge.ReadableMap;
25
26
  import com.facebook.react.bridge.WritableArray;
26
27
  import com.facebook.react.bridge.WritableMap;
28
+ import com.google.android.gms.ads.AdInspectorError;
27
29
  import com.google.android.gms.ads.AdRequest;
28
30
  import com.google.android.gms.ads.MobileAds;
31
+ import com.google.android.gms.ads.OnAdInspectorClosedListener;
29
32
  import com.google.android.gms.ads.RequestConfiguration;
30
33
  import com.google.android.gms.ads.initialization.AdapterStatus;
31
34
  import com.google.android.gms.ads.initialization.InitializationStatus;
@@ -140,4 +143,46 @@ public class ReactNativeGoogleMobileAdsModule extends ReactNativeModule {
140
143
  MobileAds.setRequestConfiguration(buildRequestConfiguration(requestConfiguration));
141
144
  promise.resolve(null);
142
145
  }
146
+
147
+ @ReactMethod
148
+ public void openAdInspector(Promise promise) {
149
+ if (getCurrentActivity() == null) {
150
+ rejectPromiseWithCodeAndMessage(
151
+ promise,
152
+ "null-activity",
153
+ "Ad Inspector attempted to open but the current Activity was null.");
154
+ return;
155
+ }
156
+ getCurrentActivity()
157
+ .runOnUiThread(
158
+ () -> {
159
+ MobileAds.openAdInspector(
160
+ getApplicationContext(),
161
+ new OnAdInspectorClosedListener() {
162
+ @Override
163
+ public void onAdInspectorClosed(@Nullable AdInspectorError adInspectorError) {
164
+ if (adInspectorError != null) {
165
+ String code = "";
166
+ switch (adInspectorError.getCode()) {
167
+ case AdInspectorError.ERROR_CODE_INTERNAL_ERROR:
168
+ code = "INTERNAL_ERROR";
169
+ break;
170
+ case AdInspectorError.ERROR_CODE_FAILED_TO_LOAD:
171
+ code = "FAILED_TO_LOAD";
172
+ break;
173
+ case AdInspectorError.ERROR_CODE_NOT_IN_TEST_MODE:
174
+ code = "NOT_IN_TEST_MODE";
175
+ break;
176
+ case AdInspectorError.ERROR_CODE_ALREADY_OPEN:
177
+ code = "ALREADY_OPEN";
178
+ break;
179
+ }
180
+ rejectPromiseWithCodeAndMessage(
181
+ promise, code, adInspectorError.getMessage());
182
+ }
183
+ promise.resolve(null);
184
+ }
185
+ });
186
+ });
187
+ }
143
188
  }
@@ -0,0 +1,39 @@
1
+ # Ad Inspector
2
+
3
+ Ad inspector is an in-app overlay that enables authorized devices to perform real-time analysis of test ad requests directly within a mobile app.
4
+
5
+ Using ad inspector, you can:
6
+
7
+ - Inspect your ad units
8
+ - Check whether your ads are filling as expected
9
+ - Identify errors and view details about how to resolve them
10
+ - View the details for each Open Bidding ad network per request
11
+ - View the mediation details for each ad network per request
12
+ - Test individual third-party Open Bidding or waterfall mediation ad sources
13
+ - Verify that you've correctly configured each ad unit for Open Bidding and waterfall mediation
14
+
15
+ To see more information about ad inspector, see the [official documentation](https://developers.google.com/admob/android/ad-inspector).
16
+
17
+ ## Launch ad inspector
18
+
19
+ Ad inspector can be launched from anywhere in your app. There are three different ways to launch ad inspector.
20
+
21
+ 1. Use the launch button from the debug menu.
22
+ 2. Use the gesture that you selected in the ad inspector settings.
23
+ 3. Programmatically using the provided API.
24
+
25
+ More information about laucnhing ad inspector is available in [official documentation](https://developers.google.com/admob/android/ad-inspector#launch_ad_inspector).
26
+
27
+ ### Launch programmatically
28
+
29
+ Ad inspector can be launched programmatically with the `openAdInspector` method in the `MobileAds` instance.
30
+
31
+ ```js
32
+ try {
33
+ await MobileAds().openAdInspector();
34
+ // The promise will resolve when the inspector is closed.
35
+ } catch (error) {
36
+ // The promise will reject if ad inspector is closed due to an error.
37
+ console.log(error);
38
+ }
39
+ ```