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.
- package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsCommon.java +9 -3
- package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsEvent.java +2 -0
- package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsPackage.java +1 -0
- package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsRewardedInterstitialModule.java +199 -0
- package/docs/displaying-ads-hook.mdx +1 -1
- package/docs/displaying-ads.mdx +132 -1
- package/docs/european-user-consent.mdx +31 -0
- package/ios/RNGoogleMobileAds/RNGoogleMobileAdsAppOpenModule.m +1 -2
- package/ios/RNGoogleMobileAds/RNGoogleMobileAdsCommon.h +3 -0
- package/ios/RNGoogleMobileAds/RNGoogleMobileAdsCommon.m +18 -1
- package/ios/RNGoogleMobileAds/RNGoogleMobileAdsInterstitialModule.m +1 -2
- package/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.h +25 -0
- package/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedInterstitialModule.m +173 -0
- package/ios/RNGoogleMobileAds/RNGoogleMobileAdsRewardedModule.m +18 -18
- package/lib/commonjs/BannerAdSize.js +2 -0
- package/lib/commonjs/BannerAdSize.js.map +1 -1
- package/lib/commonjs/MobileAds.js +5 -2
- package/lib/commonjs/MobileAds.js.map +1 -1
- package/lib/commonjs/TestIds.js +6 -2
- package/lib/commonjs/TestIds.js.map +1 -1
- package/lib/commonjs/ads/MobileAd.js +16 -4
- package/lib/commonjs/ads/MobileAd.js.map +1 -1
- package/lib/commonjs/ads/RewardedInterstitialAd.js +127 -0
- package/lib/commonjs/ads/RewardedInterstitialAd.js.map +1 -0
- package/lib/commonjs/hooks/useFullScreenAd.js.map +1 -1
- package/lib/commonjs/hooks/useRewardedAd.js.map +1 -1
- package/lib/commonjs/hooks/useRewardedInterstitialAd.js +51 -0
- package/lib/commonjs/hooks/useRewardedInterstitialAd.js.map +1 -0
- package/lib/commonjs/index.js +19 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/version.js +1 -1
- package/lib/commonjs/version.js.map +1 -1
- package/lib/module/BannerAdSize.js +2 -0
- package/lib/module/BannerAdSize.js.map +1 -1
- package/lib/module/MobileAds.js +5 -2
- package/lib/module/MobileAds.js.map +1 -1
- package/lib/module/TestIds.js +6 -2
- package/lib/module/TestIds.js.map +1 -1
- package/lib/module/ads/MobileAd.js +16 -4
- package/lib/module/ads/MobileAd.js.map +1 -1
- package/lib/module/ads/RewardedInterstitialAd.js +130 -0
- package/lib/module/ads/RewardedInterstitialAd.js.map +1 -0
- package/lib/module/hooks/useFullScreenAd.js.map +1 -1
- package/lib/module/hooks/useRewardedAd.js.map +1 -1
- package/lib/module/hooks/useRewardedInterstitialAd.js +38 -0
- package/lib/module/hooks/useRewardedInterstitialAd.js.map +1 -0
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/version.js +1 -1
- package/lib/module/version.js.map +1 -1
- package/lib/typescript/BannerAdSize.d.ts +10 -1
- package/lib/typescript/TestIds.d.ts +2 -0
- package/lib/typescript/ads/MobileAd.d.ts +3 -2
- package/lib/typescript/ads/RewardedInterstitialAd.d.ts +82 -0
- package/lib/typescript/hooks/useFullScreenAd.d.ts +2 -1
- package/lib/typescript/hooks/useRewardedAd.d.ts +1 -1
- package/lib/typescript/hooks/useRewardedInterstitialAd.d.ts +9 -0
- package/lib/typescript/index.d.ts +3 -1
- package/lib/typescript/types/GoogleMobileAdsNativeModule.d.ts +11 -6
- package/lib/typescript/version.d.ts +1 -1
- package/package.json +8 -8
- package/src/BannerAdSize.ts +12 -1
- package/src/MobileAds.ts +9 -0
- package/src/TestIds.ts +4 -0
- package/src/ads/MobileAd.ts +16 -6
- package/src/ads/RewardedInterstitialAd.ts +143 -0
- package/src/hooks/useFullScreenAd.ts +4 -3
- package/src/hooks/useRewardedAd.ts +1 -1
- package/src/hooks/useRewardedInterstitialAd.ts +47 -0
- package/src/index.ts +2 -0
- package/src/types/GoogleMobileAdsNativeModule.ts +15 -6
- package/src/version.ts +1 -1
package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsCommon.java
CHANGED
|
@@ -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 (
|
|
64
|
-
|
|
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
|
}
|
package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsEvent.java
CHANGED
|
@@ -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";
|
package/android/src/main/java/io/invertase/googlemobileads/ReactNativeGoogleMobileAdsPackage.java
CHANGED
|
@@ -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
|
|
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
|
|
package/docs/displaying-ads.mdx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Displaying Ads
|
|
2
2
|
|
|
3
|
-
The
|
|
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×tamp=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
|