react-native-google-mobile-ads 5.1.1 → 6.1.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 (176) hide show
  1. package/__tests__/interstitial.test.ts +32 -5
  2. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsAppOpenModule.java +2 -1
  3. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsBannerAdViewManager.java +110 -68
  4. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsCommon.java +5 -11
  5. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsEvent.java +3 -0
  6. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsInterstitialModule.java +38 -20
  7. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsModule.java +45 -0
  8. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsPackage.java +1 -0
  9. package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsRewardedInterstitialModule.java +199 -0
  10. package/docs/ad-inspector.mdx +39 -0
  11. package/docs/displaying-ads-hook.mdx +1 -1
  12. package/docs/displaying-ads.mdx +178 -26
  13. package/docs/migrating-to-v6.mdx +111 -0
  14. package/docs.json +3 -1
  15. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsAppOpenModule.m +1 -0
  16. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsBannerViewManager.m +63 -8
  17. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsCommon.h +4 -0
  18. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsCommon.m +10 -7
  19. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenContentDelegate.h +2 -1
  20. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsFullScreenContentDelegate.m +17 -2
  21. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsInterstitialModule.m +44 -30
  22. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsModule.m +19 -0
  23. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.h +25 -0
  24. package/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.m +173 -0
  25. package/lib/commonjs/AdEventType.js.map +1 -1
  26. package/lib/commonjs/GAMAdEventType.js +30 -0
  27. package/lib/commonjs/GAMAdEventType.js.map +1 -0
  28. package/lib/commonjs/MobileAds.js +9 -2
  29. package/lib/commonjs/MobileAds.js.map +1 -1
  30. package/lib/commonjs/RewardedAdEventType.js.map +1 -1
  31. package/lib/commonjs/TestIds.js +11 -2
  32. package/lib/commonjs/TestIds.js.map +1 -1
  33. package/lib/commonjs/ads/AppOpenAd.js +8 -53
  34. package/lib/commonjs/ads/AppOpenAd.js.map +1 -1
  35. package/lib/commonjs/ads/BannerAd.js +7 -110
  36. package/lib/commonjs/ads/BannerAd.js.map +1 -1
  37. package/lib/commonjs/ads/BaseAd.js +144 -0
  38. package/lib/commonjs/ads/BaseAd.js.map +1 -0
  39. package/lib/commonjs/ads/GAMBannerAd.js +42 -0
  40. package/lib/commonjs/ads/GAMBannerAd.js.map +1 -0
  41. package/lib/commonjs/ads/GAMInterstitialAd.js +48 -0
  42. package/lib/commonjs/ads/GAMInterstitialAd.js.map +1 -0
  43. package/lib/commonjs/ads/InterstitialAd.js +13 -64
  44. package/lib/commonjs/ads/InterstitialAd.js.map +1 -1
  45. package/lib/commonjs/ads/MobileAd.js +131 -12
  46. package/lib/commonjs/ads/MobileAd.js.map +1 -1
  47. package/lib/commonjs/ads/RewardedAd.js +23 -65
  48. package/lib/commonjs/ads/RewardedAd.js.map +1 -1
  49. package/lib/commonjs/ads/RewardedInterstitialAd.js +127 -0
  50. package/lib/commonjs/ads/RewardedInterstitialAd.js.map +1 -0
  51. package/lib/commonjs/hooks/useAppOpenAd.js.map +1 -1
  52. package/lib/commonjs/hooks/useFullScreenAd.js +9 -4
  53. package/lib/commonjs/hooks/useFullScreenAd.js.map +1 -1
  54. package/lib/commonjs/hooks/useInterstitialAd.js.map +1 -1
  55. package/lib/commonjs/hooks/useRewardedAd.js.map +1 -1
  56. package/lib/commonjs/hooks/useRewardedInterstitialAd.js +51 -0
  57. package/lib/commonjs/hooks/useRewardedInterstitialAd.js.map +1 -0
  58. package/lib/commonjs/index.js +80 -0
  59. package/lib/commonjs/index.js.map +1 -1
  60. package/lib/commonjs/types/AdEventsListener.js +6 -0
  61. package/lib/commonjs/types/AdEventsListener.js.map +1 -0
  62. package/lib/commonjs/types/AppEvent.js +2 -0
  63. package/lib/commonjs/types/AppEvent.js.map +1 -0
  64. package/lib/commonjs/types/index.js +149 -0
  65. package/lib/commonjs/types/index.js.map +1 -0
  66. package/lib/commonjs/validateAdRequestOptions.js +0 -38
  67. package/lib/commonjs/validateAdRequestOptions.js.map +1 -1
  68. package/lib/commonjs/version.js +2 -2
  69. package/lib/commonjs/version.js.map +1 -1
  70. package/lib/module/AdEventType.js.map +1 -1
  71. package/lib/module/GAMAdEventType.js +22 -0
  72. package/lib/module/GAMAdEventType.js.map +1 -0
  73. package/lib/module/MobileAds.js +9 -2
  74. package/lib/module/MobileAds.js.map +1 -1
  75. package/lib/module/RewardedAdEventType.js.map +1 -1
  76. package/lib/module/TestIds.js +11 -2
  77. package/lib/module/TestIds.js.map +1 -1
  78. package/lib/module/ads/AppOpenAd.js +10 -37
  79. package/lib/module/ads/AppOpenAd.js.map +1 -1
  80. package/lib/module/ads/BannerAd.js +7 -85
  81. package/lib/module/ads/BannerAd.js.map +1 -1
  82. package/lib/module/ads/BaseAd.js +124 -0
  83. package/lib/module/ads/BaseAd.js.map +1 -0
  84. package/lib/module/ads/GAMBannerAd.js +42 -0
  85. package/lib/module/ads/GAMBannerAd.js.map +1 -0
  86. package/lib/module/ads/GAMInterstitialAd.js +38 -0
  87. package/lib/module/ads/GAMInterstitialAd.js.map +1 -0
  88. package/lib/module/ads/InterstitialAd.js +15 -48
  89. package/lib/module/ads/InterstitialAd.js.map +1 -1
  90. package/lib/module/ads/MobileAd.js +128 -12
  91. package/lib/module/ads/MobileAd.js.map +1 -1
  92. package/lib/module/ads/RewardedAd.js +24 -49
  93. package/lib/module/ads/RewardedAd.js.map +1 -1
  94. package/lib/module/ads/RewardedInterstitialAd.js +130 -0
  95. package/lib/module/ads/RewardedInterstitialAd.js.map +1 -0
  96. package/lib/module/hooks/useAppOpenAd.js.map +1 -1
  97. package/lib/module/hooks/useFullScreenAd.js +9 -4
  98. package/lib/module/hooks/useFullScreenAd.js.map +1 -1
  99. package/lib/module/hooks/useInterstitialAd.js.map +1 -1
  100. package/lib/module/hooks/useRewardedAd.js.map +1 -1
  101. package/lib/module/hooks/useRewardedInterstitialAd.js +38 -0
  102. package/lib/module/hooks/useRewardedInterstitialAd.js.map +1 -0
  103. package/lib/module/index.js +6 -0
  104. package/lib/module/index.js.map +1 -1
  105. package/lib/module/types/AdEventsListener.js +2 -0
  106. package/lib/module/types/AdEventsListener.js.map +1 -0
  107. package/lib/module/types/AppEvent.js +2 -0
  108. package/lib/module/types/AppEvent.js.map +1 -0
  109. package/lib/module/types/index.js +28 -0
  110. package/lib/module/types/index.js.map +1 -0
  111. package/lib/module/validateAdRequestOptions.js +1 -39
  112. package/lib/module/validateAdRequestOptions.js.map +1 -1
  113. package/lib/module/version.js +2 -2
  114. package/lib/module/version.js.map +1 -1
  115. package/lib/typescript/AdEventType.d.ts +4 -8
  116. package/lib/typescript/GAMAdEventType.d.ts +20 -0
  117. package/lib/typescript/MobileAds.d.ts +2 -1
  118. package/lib/typescript/RewardedAdEventType.d.ts +7 -11
  119. package/lib/typescript/TestIds.d.ts +7 -0
  120. package/lib/typescript/ads/AppOpenAd.d.ts +6 -6
  121. package/lib/typescript/ads/BannerAd.d.ts +1 -1
  122. package/lib/typescript/ads/BaseAd.d.ts +35 -0
  123. package/lib/typescript/ads/GAMBannerAd.d.ts +7 -0
  124. package/lib/typescript/ads/GAMInterstitialAd.d.ts +33 -0
  125. package/lib/typescript/ads/InterstitialAd.d.ts +10 -16
  126. package/lib/typescript/ads/MobileAd.d.ts +35 -16
  127. package/lib/typescript/ads/RewardedAd.d.ts +17 -19
  128. package/lib/typescript/ads/RewardedInterstitialAd.d.ts +82 -0
  129. package/lib/typescript/hooks/useAppOpenAd.d.ts +1 -1
  130. package/lib/typescript/hooks/useFullScreenAd.d.ts +2 -1
  131. package/lib/typescript/hooks/useInterstitialAd.d.ts +1 -1
  132. package/lib/typescript/hooks/useRewardedAd.d.ts +1 -1
  133. package/lib/typescript/hooks/useRewardedInterstitialAd.d.ts +9 -0
  134. package/lib/typescript/index.d.ts +7 -1
  135. package/lib/typescript/types/AdEventListener.d.ts +5 -9
  136. package/lib/typescript/types/AdEventsListener.d.ts +8 -0
  137. package/lib/typescript/types/AppEvent.d.ts +13 -0
  138. package/lib/typescript/types/BannerAdProps.d.ts +81 -4
  139. package/lib/typescript/types/GoogleMobileAdsNativeModule.d.ts +12 -6
  140. package/lib/typescript/types/MobileAd.interface.d.ts +37 -12
  141. package/lib/typescript/types/MobileAdsModule.interface.d.ts +9 -0
  142. package/lib/typescript/types/RequestOptions.d.ts +0 -22
  143. package/lib/typescript/types/index.d.ts +11 -0
  144. package/lib/typescript/version.d.ts +1 -1
  145. package/package.json +50 -49
  146. package/src/AdEventType.ts +4 -8
  147. package/src/GAMAdEventType.ts +37 -0
  148. package/src/MobileAds.ts +13 -0
  149. package/src/RewardedAdEventType.ts +7 -11
  150. package/src/TestIds.ts +9 -0
  151. package/src/ads/AppOpenAd.ts +11 -41
  152. package/src/ads/BannerAd.tsx +4 -106
  153. package/src/ads/BaseAd.tsx +156 -0
  154. package/src/ads/GAMBannerAd.tsx +37 -0
  155. package/src/ads/GAMInterstitialAd.ts +45 -0
  156. package/src/ads/InterstitialAd.ts +15 -56
  157. package/src/ads/MobileAd.ts +153 -30
  158. package/src/ads/RewardedAd.ts +29 -55
  159. package/src/ads/RewardedInterstitialAd.ts +143 -0
  160. package/src/hooks/useAppOpenAd.ts +1 -1
  161. package/src/hooks/useFullScreenAd.ts +9 -7
  162. package/src/hooks/useInterstitialAd.ts +1 -1
  163. package/src/hooks/useRewardedAd.ts +1 -1
  164. package/src/hooks/useRewardedInterstitialAd.ts +47 -0
  165. package/src/index.ts +6 -0
  166. package/src/types/AdEventListener.ts +31 -13
  167. package/src/types/AdEventsListener.ts +24 -0
  168. package/src/types/AppEvent.ts +14 -0
  169. package/src/types/BannerAdProps.ts +81 -4
  170. package/src/types/GoogleMobileAdsNativeModule.ts +16 -6
  171. package/src/types/MobileAd.interface.ts +56 -12
  172. package/src/types/MobileAdsModule.interface.ts +10 -0
  173. package/src/types/RequestOptions.ts +0 -24
  174. package/src/types/index.ts +28 -0
  175. package/src/validateAdRequestOptions.ts +0 -45
  176. package/src/version.ts +2 -2
@@ -16,27 +16,39 @@
16
16
  */
17
17
 
18
18
  import { EmitterSubscription } from 'react-native';
19
+ import { isFunction, isOneOf } from '../common';
19
20
  import { NativeError } from '../internal/NativeError';
20
- import { RewardedAdEventType } from '../RewardedAdEventType';
21
21
  import { AdEventType } from '../AdEventType';
22
- import { AdEventListener } from '../types/AdEventListener';
22
+ import { RewardedAdEventType } from '../RewardedAdEventType';
23
+ import { AdEventListener, AdEventPayload } from '../types/AdEventListener';
24
+ import { AdEventsListener } from '../types/AdEventsListener';
25
+ import { AdShowOptions } from '../types/AdShowOptions';
23
26
  import { RequestOptions } from '../types/RequestOptions';
27
+ import { MobileAdInterface } from '../types/MobileAd.interface';
24
28
  import { MobileAdsModuleInterface } from '../types/MobileAdsModule.interface';
25
29
  import { RewardedAdReward } from '../types/RewardedAdReward';
30
+ import { GAMAdEventType } from '../GAMAdEventType';
31
+ import { AppEvent } from '../types/AppEvent';
32
+ import { validateAdShowOptions } from '../validateAdShowOptions';
33
+
34
+ type EventType = AdEventType | RewardedAdEventType | GAMAdEventType;
26
35
 
27
- export class MobileAd {
28
- _type: 'app_open' | 'interstitial' | 'rewarded';
29
- _googleMobileAds: MobileAdsModuleInterface;
30
- _requestId: number;
31
- _adUnitId: string;
32
- _requestOptions: RequestOptions;
33
- _loaded: boolean;
34
- _isLoadCalled: boolean;
35
- _onAdEventHandler: AdEventListener | null;
36
- _nativeListener: EmitterSubscription;
37
-
38
- constructor(
39
- type: 'app_open' | 'interstitial' | 'rewarded',
36
+ export abstract class MobileAd implements MobileAdInterface {
37
+ protected _type: 'app_open' | 'interstitial' | 'rewarded' | 'rewarded_interstitial';
38
+ protected _googleMobileAds: MobileAdsModuleInterface;
39
+ protected _requestId: number;
40
+ protected _adUnitId: string;
41
+ protected _requestOptions: RequestOptions;
42
+ protected _loaded: boolean;
43
+ protected _isLoadCalled: boolean;
44
+ protected _adEventsListeners: Map<number, AdEventsListener<EventType>>;
45
+ protected _adEventListenersMap: Map<EventType, Map<number, AdEventListener<EventType>>>;
46
+ protected _adEventsListenerId: number;
47
+ protected _adEventListenerId: number;
48
+ protected _nativeListener: EmitterSubscription;
49
+
50
+ protected constructor(
51
+ type: 'app_open' | 'interstitial' | 'rewarded' | 'rewarded_interstitial',
40
52
  googleMobileAds: MobileAdsModuleInterface,
41
53
  requestId: number,
42
54
  adUnitId: string,
@@ -50,7 +62,18 @@ export class MobileAd {
50
62
 
51
63
  this._loaded = false;
52
64
  this._isLoadCalled = false;
53
- this._onAdEventHandler = null;
65
+ this._adEventsListeners = new Map();
66
+ this._adEventListenersMap = new Map();
67
+ Object.values({
68
+ ...AdEventType,
69
+ ...RewardedAdEventType,
70
+ ...GAMAdEventType,
71
+ _: AdEventType.LOADED, // since AdEventType.LOADED is overwritten by RewardedAdEventType.LOADED
72
+ }).forEach(type => {
73
+ this._adEventListenersMap.set(type as EventType, new Map());
74
+ });
75
+ this._adEventListenerId = 0;
76
+ this._adEventsListenerId = 0;
54
77
 
55
78
  this._nativeListener = googleMobileAds.emitter.addListener(
56
79
  `google_mobile_ads_${type}_event:${adUnitId}:${requestId}`,
@@ -58,11 +81,11 @@ export class MobileAd {
58
81
  );
59
82
  }
60
83
 
61
- _handleAdEvent(event: {
84
+ protected _handleAdEvent(event: {
62
85
  body: {
63
- type: AdEventType | RewardedAdEventType;
86
+ type: EventType;
64
87
  error?: { code: string; message: string };
65
- data?: RewardedAdReward;
88
+ data?: RewardedAdReward | AppEvent;
66
89
  };
67
90
  }) {
68
91
  const { type, error, data } = event.body;
@@ -76,26 +99,126 @@ export class MobileAd {
76
99
  this._isLoadCalled = false;
77
100
  }
78
101
 
79
- if (this._onAdEventHandler) {
80
- let nativeError;
81
- if (error) {
82
- nativeError = NativeError.fromEvent(error, 'googleMobileAds');
83
- }
102
+ let payload: AdEventPayload<EventType> = data;
103
+ if (error) {
104
+ payload = NativeError.fromEvent(error, 'googleMobileAds');
105
+ }
106
+ this._adEventsListeners.forEach(listener => {
107
+ listener({
108
+ type,
109
+ payload,
110
+ });
111
+ });
112
+ this._getAdEventListeners(type).forEach(listener => {
113
+ listener(payload);
114
+ });
115
+ }
116
+
117
+ protected _addAdEventsListener<T extends EventType>(listener: AdEventsListener<T>) {
118
+ if (!isFunction(listener)) {
119
+ throw new Error(`${this._className}.addAdEventsListener(*) 'listener' expected a function.`);
120
+ }
84
121
 
85
- this._onAdEventHandler(type, nativeError, data);
122
+ const id = this._adEventsListenerId++;
123
+ this._adEventsListeners.set(id, listener as AdEventsListener<EventType>);
124
+ return () => {
125
+ this._adEventsListeners.delete(id);
126
+ };
127
+ }
128
+
129
+ protected _addAdEventListener<T extends EventType>(type: T, listener: AdEventListener<T>) {
130
+ if (
131
+ !(
132
+ isOneOf(type, Object.values(AdEventType)) ||
133
+ (isOneOf(type, Object.values(RewardedAdEventType)) && this._type === 'rewarded')
134
+ )
135
+ ) {
136
+ throw new Error(
137
+ `${this._className}.addAdEventListener(*) 'type' expected a valid event type value.`,
138
+ );
86
139
  }
140
+ if (!isFunction(listener)) {
141
+ throw new Error(
142
+ `${this._className}.addAdEventListener(_, *) 'listener' expected a function.`,
143
+ );
144
+ }
145
+
146
+ const id = this._adEventListenerId++;
147
+ this._getAdEventListeners(type).set(id, listener);
148
+ return () => {
149
+ this._getAdEventListeners(type).delete(id);
150
+ };
151
+ }
152
+
153
+ protected _getAdEventListeners<T extends EventType>(type: T) {
154
+ return this._adEventListenersMap.get(type) as Map<number, AdEventListener<T>>;
87
155
  }
88
156
 
89
- _setAdEventHandler(handler: AdEventListener) {
90
- this._onAdEventHandler = handler;
91
- return () => (this._onAdEventHandler = null);
157
+ protected get _className() {
158
+ return this.constructor.name;
159
+ }
160
+
161
+ protected get _camelCaseType() {
162
+ let type: 'appOpen' | 'interstitial' | 'rewarded' | 'rewardedInterstitial';
163
+ if (this._type === 'app_open') {
164
+ type = 'appOpen';
165
+ } else if (this._type === 'rewarded_interstitial') {
166
+ type = 'rewardedInterstitial';
167
+ } else {
168
+ type = this._type;
169
+ }
170
+ return type;
171
+ }
172
+
173
+ public load() {
174
+ // Prevent multiple load calls
175
+ if (this._loaded || this._isLoadCalled) {
176
+ return;
177
+ }
178
+
179
+ this._isLoadCalled = true;
180
+ const load = this._googleMobileAds.native[`${this._camelCaseType}Load`];
181
+ load(this._requestId, this._adUnitId, this._requestOptions);
182
+ }
183
+
184
+ public show(showOptions?: AdShowOptions) {
185
+ if (!this._loaded) {
186
+ throw new Error(
187
+ `${this._className}.show() The requested ${this._className} has not loaded and could not be shown.`,
188
+ );
189
+ }
190
+
191
+ let options;
192
+ try {
193
+ options = validateAdShowOptions(showOptions);
194
+ } catch (e) {
195
+ if (e instanceof Error) {
196
+ throw new Error(`${this._className}.show(*) ${e.message}.`);
197
+ } else {
198
+ throw e;
199
+ }
200
+ }
201
+
202
+ const show = this._googleMobileAds.native[`${this._camelCaseType}Show`];
203
+ return show(this._requestId, this._adUnitId, options);
204
+ }
205
+
206
+ public abstract addAdEventsListener<T extends never>(listener: AdEventsListener<T>): () => void;
207
+
208
+ public abstract addAdEventListener<T extends never>(type: T, listener: AdEventListener<T>): void;
209
+
210
+ public removeAllListeners() {
211
+ this._adEventsListeners.clear();
212
+ this._adEventListenersMap.forEach((_, type, map) => {
213
+ map.set(type, new Map());
214
+ });
92
215
  }
93
216
 
94
- get adUnitId() {
217
+ public get adUnitId() {
95
218
  return this._adUnitId;
96
219
  }
97
220
 
98
- get loaded() {
221
+ public get loaded() {
99
222
  return this._loaded;
100
223
  }
101
224
  }
@@ -15,17 +15,15 @@
15
15
  *
16
16
  */
17
17
 
18
- import { isFunction, isString } from '../common';
18
+ import { isString } from '../common';
19
19
  import { MobileAds } from '../MobileAds';
20
20
  import { validateAdRequestOptions } from '../validateAdRequestOptions';
21
- import { validateAdShowOptions } from '../validateAdShowOptions';
22
21
  import { MobileAd } from './MobileAd';
22
+ import { AdEventType } from '../AdEventType';
23
+ import { RewardedAdEventType } from '../RewardedAdEventType';
23
24
  import { AdEventListener } from '../types/AdEventListener';
24
- import { AdShowOptions } from '../types/AdShowOptions';
25
+ import { AdEventsListener } from '../types/AdEventsListener';
25
26
  import { RequestOptions } from '../types/RequestOptions';
26
- import { MobileAdInterface } from '../types/MobileAd.interface';
27
-
28
- let _rewardedRequest = 0;
29
27
 
30
28
  /**
31
29
  * A class for interacting and showing Rewarded Ads.
@@ -59,13 +57,11 @@ let _rewardedRequest = 0;
59
57
  * ```js
60
58
  * import { RewardedAdEventType } from 'react-native-google-mobile-ads';
61
59
  *
62
- * rewarded.onAdEvent((type, error, reward) => {
63
- * if (type === RewardedAdEventType.LOADED) {
64
- * rewarded.show();
65
- * }
66
- * if (type === RewardedAdEventType.EARNED_REWARD) {
67
- * console.log('User earned reward of ', reward);
68
- * }
60
+ * rewarded.addAdEventListener(RewardedAdEventType.LOADED. () => {
61
+ * rewarded.show();
62
+ * });
63
+ * rewarded.addAdEventListener(RewardedAdEventType.EARNED_REWARD. (reward) => {
64
+ * console.log('User earned reward of ', reward);
69
65
  * });
70
66
  *
71
67
  * rewarded.load();
@@ -74,7 +70,8 @@ let _rewardedRequest = 0;
74
70
  * The rewarded advert will be presented to the user, and several more events can be triggered such as the user clicking the
75
71
  * advert, closing it or completing the action.
76
72
  */
77
- export class RewardedAd extends MobileAd implements MobileAdInterface {
73
+ export class RewardedAd extends MobileAd {
74
+ protected static _rewardedRequest = 0;
78
75
  /**
79
76
  * Creates a new RewardedAd instance.
80
77
  *
@@ -87,12 +84,11 @@ export class RewardedAd extends MobileAd implements MobileAdInterface {
87
84
  * requestAgent: 'CoolAds',
88
85
  * });
89
86
  *
90
- * rewardedAd.onAdEvent((type, error, data) => {
91
- * console.log('New event: ', type, error);
92
- *
93
- * if (type === RewardedAdEventType.LOADED) {
94
- * rewardedAd.show();
95
- * }
87
+ * rewarded.addAdEventListener(RewardedAdEventType.LOADED. () => {
88
+ * rewarded.show();
89
+ * });
90
+ * rewarded.addAdEventListener(RewardedAdEventType.EARNED_REWARD. (reward) => {
91
+ * console.log('User earned reward of ', reward);
96
92
  * });
97
93
  *
98
94
  * rewardedAd.load();
@@ -101,7 +97,7 @@ export class RewardedAd extends MobileAd implements MobileAdInterface {
101
97
  * @param adUnitId The Ad Unit ID for the Rewarded Ad. You can find this on your Google Mobile Ads dashboard.
102
98
  * @param requestOptions Optional RequestOptions used to load the ad.
103
99
  */
104
- static createForAdRequest(adUnitId: string, requestOptions?: RequestOptions): RewardedAd {
100
+ static createForAdRequest(adUnitId: string, requestOptions?: RequestOptions) {
105
101
  if (!isString(adUnitId)) {
106
102
  throw new Error("RewardedAd.createForAdRequest(*) 'adUnitId' expected an string value.");
107
103
  }
@@ -115,47 +111,25 @@ export class RewardedAd extends MobileAd implements MobileAdInterface {
115
111
  }
116
112
  }
117
113
 
118
- const requestId = _rewardedRequest++;
114
+ const requestId = RewardedAd._rewardedRequest++;
119
115
  return new RewardedAd('rewarded', MobileAds(), requestId, adUnitId, options);
120
116
  }
121
117
 
122
- load() {
123
- // Prevent multiple load calls
124
- if (this._loaded || this._isLoadCalled) {
125
- return;
126
- }
127
-
128
- this._isLoadCalled = true;
129
- this._googleMobileAds.native.rewardedLoad(
130
- this._requestId,
131
- this._adUnitId,
132
- this._requestOptions,
133
- );
134
- }
135
-
136
- onAdEvent(handler: AdEventListener) {
137
- if (!isFunction(handler)) {
138
- throw new Error("RewardedAd.onAdEvent(*) 'handler' expected a function.");
139
- }
140
-
141
- return this._setAdEventHandler(handler);
118
+ addAdEventsListener<T extends AdEventType | RewardedAdEventType>(
119
+ listener: AdEventsListener<T>,
120
+ ): () => void {
121
+ return this._addAdEventsListener(listener);
142
122
  }
143
123
 
144
- show(showOptions?: AdShowOptions) {
145
- if (!this._loaded) {
124
+ addAdEventListener<T extends AdEventType | RewardedAdEventType>(
125
+ type: T,
126
+ listener: AdEventListener<T>,
127
+ ) {
128
+ if (type === AdEventType.LOADED) {
146
129
  throw new Error(
147
- 'RewardedAd.show() The requested RewardedAd has not loaded and could not be shown.',
130
+ 'RewardedAd.addAdEventListener(*) use RewardedAdEventType.LOADED instead of AdEventType.LOADED.',
148
131
  );
149
132
  }
150
-
151
- let options;
152
- try {
153
- options = validateAdShowOptions(showOptions);
154
- } catch (e) {
155
- if (e instanceof Error) {
156
- throw new Error(`RewardedAd.show(*) ${e.message}.`);
157
- }
158
- }
159
- return this._googleMobileAds.native.rewardedShow(this._requestId, this._adUnitId, options);
133
+ return this._addAdEventListener(type, listener);
160
134
  }
161
135
  }
@@ -0,0 +1,143 @@
1
+ /*
2
+ * Copyright (c) 2016-present Invertase Limited & Contributors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this library except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ import { isString } from '../common';
19
+ import { MobileAds } from '../MobileAds';
20
+ import { validateAdRequestOptions } from '../validateAdRequestOptions';
21
+ import { MobileAd } from './MobileAd';
22
+ import { AdEventType } from '../AdEventType';
23
+ import { RewardedAdEventType } from '../RewardedAdEventType';
24
+ import { AdEventListener } from '../types/AdEventListener';
25
+ import { AdEventsListener } from '../types/AdEventsListener';
26
+ import { RequestOptions } from '../types/RequestOptions';
27
+
28
+ /**
29
+ * A class for interacting and showing Rewarded Interstitial Ads.
30
+ *
31
+ * An Rewarded Interstitial advert can be pre-loaded and shown at a suitable point in your apps flow, such as at the end of a level
32
+ * in a game. The content of a rewarded interstital advert can be controlled via your Google Mobile Ads dashboard. Typically users are rewarded
33
+ * after completing a specific advert action (e.g. watching a video or submitting an option via an interactive form).
34
+ * Events (such as the user earning a reward or closing a rewarded interstital advert early) are sent back for you to handle accordingly
35
+ * within your application.
36
+ *
37
+ * #### Example
38
+ *
39
+ * First create a new Rewarded Interstitial instance, passing in your Ad Unit ID from the Google Mobile Ads configuration console, and any additional
40
+ * request options. The example below will present a test advert, and only request a non-personalized ad.
41
+ *
42
+ * ```js
43
+ * import { RewardedInterstitialAd, TestIds } from 'react-native-google-mobile-ads';
44
+ *
45
+ * const rewardedInterstitial = RewardedInterstitialAd.createForAdRequest(TestIds.REWARDED_INTERSTITIAL, {
46
+ * requestNonPersonalizedAdsOnly: true,
47
+ * });
48
+ * ```
49
+ *
50
+ * Each advert needs to be loaded from Google Mobile Ads before being shown. It is recommended this is performed before the user
51
+ * reaches the checkpoint to show the advert, so it's ready to go. Before loading the advert, we need to setup
52
+ * event listeners to listen for updates from Google Mobile Ads, such as advert loaded or failed to load.
53
+ *
54
+ * Event types match the `AdEventType` or `RewardedAdEventType` interface. The potential user reward for rewarded interstitial
55
+ * adverts are passed back to the event handler on advert load and when the user earns the reward.
56
+ *
57
+ * ```js
58
+ * import { RewardedAdEventType } from 'react-native-google-mobile-ads';
59
+ *
60
+ * rewardedInterstitial.addAdEventListener(RewardedAdEventType.LOADED. () => {
61
+ * rewarded.show();
62
+ * });
63
+ * rewardedInterstitial.addAdEventListener(RewardedAdEventType.EARNED_REWARD. (reward) => {
64
+ * console.log('User earned reward of ', reward);
65
+ * });
66
+ *
67
+ * rewardedInterstitial.load();
68
+ * ```
69
+ *
70
+ * The rewarded interstitial advert will be presented to the user, and several more events can be triggered such as the user clicking the
71
+ * advert, closing it or completing the action.
72
+ */
73
+ export class RewardedInterstitialAd extends MobileAd {
74
+ protected static _rewardedInterstitialRequest = 0;
75
+ /**
76
+ * Creates a new RewardedInterstitialAd instance.
77
+ *
78
+ * #### Example
79
+ *
80
+ * ```js
81
+ * import { RewardedInterstitialAd, RewardedAdEventType, TestIds } from 'react-native-google-mobile-ads';
82
+ *
83
+ * const rewardedInterstitialAd = await RewardedInterstitialAd.createForAdRequest(TestIds.REWARDED_INTERSTITIAL, {
84
+ * requestAgent: 'CoolAds',
85
+ * });
86
+ *
87
+ * rewardedInterstitialAd.addAdEventListener(RewardedAdEventType.LOADED. () => {
88
+ * rewardedInterstitialAd.show();
89
+ * });
90
+ * rewardedInterstitialAd.addAdEventListener(RewardedAdEventType.EARNED_REWARD. (reward) => {
91
+ * console.log('User earned reward of ', reward);
92
+ * });
93
+ *
94
+ * rewardedInterstitialAd.load();
95
+ * ```
96
+ *
97
+ * @param adUnitId The Ad Unit ID for the Rewarded Interstitial Ad. You can find this on your Google Mobile Ads dashboard.
98
+ * @param requestOptions Optional RequestOptions used to load the ad.
99
+ */
100
+ static createForAdRequest(adUnitId: string, requestOptions?: RequestOptions) {
101
+ if (!isString(adUnitId)) {
102
+ throw new Error(
103
+ "RewardedInterstitialAd.createForAdRequest(*) 'adUnitId' expected an string value.",
104
+ );
105
+ }
106
+
107
+ let options = {};
108
+ try {
109
+ options = validateAdRequestOptions(requestOptions);
110
+ } catch (e) {
111
+ if (e instanceof Error) {
112
+ throw new Error(`RewardedInterstitialAd.createForAdRequest(_, *) ${e.message}.`);
113
+ }
114
+ }
115
+
116
+ const requestId = RewardedInterstitialAd._rewardedInterstitialRequest++;
117
+ return new RewardedInterstitialAd(
118
+ 'rewarded_interstitial',
119
+ MobileAds(),
120
+ requestId,
121
+ adUnitId,
122
+ options,
123
+ );
124
+ }
125
+
126
+ addAdEventsListener<T extends AdEventType | RewardedAdEventType>(
127
+ listener: AdEventsListener<T>,
128
+ ): () => void {
129
+ return this._addAdEventsListener(listener);
130
+ }
131
+
132
+ addAdEventListener<T extends AdEventType | RewardedAdEventType>(
133
+ type: T,
134
+ listener: AdEventListener<T>,
135
+ ) {
136
+ if (type === AdEventType.LOADED) {
137
+ throw new Error(
138
+ 'RewardedInterstitialAd.addAdEventListener(*) use RewardedAdEventType.LOADED instead of AdEventType.LOADED.',
139
+ );
140
+ }
141
+ return this._addAdEventListener(type, listener);
142
+ }
143
+ }
@@ -33,7 +33,7 @@ import { useFullScreenAd } from './useFullScreenAd';
33
33
  export function useAppOpenAd(
34
34
  adUnitId: string | null,
35
35
  requestOptions: RequestOptions = {},
36
- ): Omit<AdHookReturns, 'adReward'> {
36
+ ): Omit<AdHookReturns, 'reward' | 'isEarnedReward'> {
37
37
  const [appOpenAd, setAppOpenAd] = useState<AppOpenAd | null>(null);
38
38
 
39
39
  useDeepCompareEffect(() => {
@@ -21,9 +21,11 @@ import { AdEventType } from '../AdEventType';
21
21
  import { AppOpenAd } from '../ads/AppOpenAd';
22
22
  import { InterstitialAd } from '../ads/InterstitialAd';
23
23
  import { RewardedAd } from '../ads/RewardedAd';
24
+ import { RewardedInterstitialAd } from '../ads/RewardedInterstitialAd';
24
25
  import { RewardedAdEventType } from '../RewardedAdEventType';
25
26
  import { AdStates, AdHookReturns } from '../types/AdStates';
26
27
  import { AdShowOptions } from '../types/AdShowOptions';
28
+ import { RewardedAdReward } from '../types/RewardedAdReward';
27
29
 
28
30
  const initialState: AdStates = {
29
31
  isLoaded: false,
@@ -35,9 +37,9 @@ const initialState: AdStates = {
35
37
  isEarnedReward: false,
36
38
  };
37
39
 
38
- export function useFullScreenAd<T extends InterstitialAd | RewardedAd | AppOpenAd | null>(
39
- ad: T,
40
- ): AdHookReturns {
40
+ export function useFullScreenAd<
41
+ T extends AppOpenAd | InterstitialAd | RewardedAd | RewardedInterstitialAd | null,
42
+ >(ad: T): AdHookReturns {
41
43
  const [state, setState] = useReducer<Reducer<AdStates, Partial<AdStates>>>(
42
44
  (prevState, newState) => ({ ...prevState, ...newState }),
43
45
  initialState,
@@ -65,7 +67,7 @@ export function useFullScreenAd<T extends InterstitialAd | RewardedAd | AppOpenA
65
67
  if (!ad) {
66
68
  return;
67
69
  }
68
- const unsubscribe = ad.onAdEvent((type, error, data) => {
70
+ const unsubscribe = (ad as RewardedAd).addAdEventsListener(({ type, payload }) => {
69
71
  switch (type) {
70
72
  case AdEventType.LOADED:
71
73
  setState({ isLoaded: true });
@@ -80,13 +82,13 @@ export function useFullScreenAd<T extends InterstitialAd | RewardedAd | AppOpenA
80
82
  setState({ isClicked: true });
81
83
  break;
82
84
  case AdEventType.ERROR:
83
- setState({ error: error });
85
+ setState({ error: payload as Error });
84
86
  break;
85
87
  case RewardedAdEventType.LOADED:
86
- setState({ isLoaded: true, reward: data });
88
+ setState({ isLoaded: true, reward: payload as RewardedAdReward });
87
89
  break;
88
90
  case RewardedAdEventType.EARNED_REWARD:
89
- setState({ isEarnedReward: true, reward: data });
91
+ setState({ isEarnedReward: true, reward: payload as RewardedAdReward });
90
92
  break;
91
93
  }
92
94
  });
@@ -33,7 +33,7 @@ import { useFullScreenAd } from './useFullScreenAd';
33
33
  export function useInterstitialAd(
34
34
  adUnitId: string | null,
35
35
  requestOptions: RequestOptions = {},
36
- ): Omit<AdHookReturns, 'adReward'> {
36
+ ): Omit<AdHookReturns, 'reward' | 'isEarnedReward'> {
37
37
  const [interstitialAd, setInterstitialAd] = useState<InterstitialAd | null>(null);
38
38
 
39
39
  useDeepCompareEffect(() => {
@@ -33,7 +33,7 @@ import { useFullScreenAd } from './useFullScreenAd';
33
33
  export function useRewardedAd(
34
34
  adUnitId: string | null,
35
35
  requestOptions: RequestOptions = {},
36
- ): Omit<AdHookReturns, 'adReward'> {
36
+ ): AdHookReturns {
37
37
  const [rewardedAd, setRewardedAd] = useState<RewardedAd | null>(null);
38
38
 
39
39
  useDeepCompareEffect(() => {
@@ -0,0 +1,47 @@
1
+ /*
2
+ * Copyright (c) 2016-present Invertase Limited & Contributors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this library except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ import { useState } from 'react';
19
+ import useDeepCompareEffect from 'use-deep-compare-effect';
20
+
21
+ import { RewardedInterstitialAd } from '../ads/RewardedInterstitialAd';
22
+ import { AdHookReturns } from '../types/AdStates';
23
+ import { RequestOptions } from '../types/RequestOptions';
24
+
25
+ import { useFullScreenAd } from './useFullScreenAd';
26
+
27
+ /**
28
+ * React Hook for Rewarded Interstitial Ad.
29
+ *
30
+ * @param adUnitId The Ad Unit ID for the Rewarded Interstitial Ad. You can find this on your Google Mobile Ads dashboard. You can destroy ad instance by setting this value to null.
31
+ * @param requestOptions Optional RequestOptions used to load the ad.
32
+ */
33
+ export function useRewardedInterstitialAd(
34
+ adUnitId: string | null,
35
+ requestOptions: RequestOptions = {},
36
+ ): AdHookReturns {
37
+ const [rewardedInterstitialAd, setRewardedInterstitialAd] =
38
+ useState<RewardedInterstitialAd | null>(null);
39
+
40
+ useDeepCompareEffect(() => {
41
+ setRewardedInterstitialAd(() => {
42
+ return adUnitId ? RewardedInterstitialAd.createForAdRequest(adUnitId, requestOptions) : null;
43
+ });
44
+ }, [adUnitId, requestOptions]);
45
+
46
+ return useFullScreenAd(rewardedInterstitialAd);
47
+ }
package/src/index.ts CHANGED
@@ -29,12 +29,18 @@ export { MaxAdContentRating } from './MaxAdContentRating';
29
29
  export { TestIds } from './TestIds';
30
30
  export { AdEventType } from './AdEventType';
31
31
  export { BannerAdSize } from './BannerAdSize';
32
+ export { GAMAdEventType } from './GAMAdEventType';
32
33
  export { RewardedAdEventType } from './RewardedAdEventType';
33
34
  export { AdsConsent } from './AdsConsent';
34
35
  export { AppOpenAd } from './ads/AppOpenAd';
35
36
  export { InterstitialAd } from './ads/InterstitialAd';
36
37
  export { RewardedAd } from './ads/RewardedAd';
38
+ export { RewardedInterstitialAd } from './ads/RewardedInterstitialAd';
37
39
  export { BannerAd } from './ads/BannerAd';
40
+ export { GAMBannerAd } from './ads/GAMBannerAd';
41
+ export { GAMInterstitialAd } from './ads/GAMInterstitialAd';
38
42
  export { useAppOpenAd } from './hooks/useAppOpenAd';
39
43
  export { useInterstitialAd } from './hooks/useInterstitialAd';
40
44
  export { useRewardedAd } from './hooks/useRewardedAd';
45
+ export { useRewardedInterstitialAd } from './hooks/useRewardedInterstitialAd';
46
+ export * from './types';