@capacitor-community/admob 5.0.0 → 5.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +113 -5
  2. package/android/build.gradle +3 -0
  3. package/android/src/main/java/com/getcapacitor/community/admob/AdMob.java +24 -0
  4. package/android/src/main/java/com/getcapacitor/community/admob/banner/BannerExecutor.java +23 -4
  5. package/android/src/main/java/com/getcapacitor/community/admob/consent/AdConsentExecutor.java +145 -0
  6. package/android/src/main/java/com/getcapacitor/community/admob/rewarded/AdRewardExecutor.java +0 -1
  7. package/dist/docs.json +295 -0
  8. package/dist/esm/consent/consent-debug-geography.enum.d.ts +19 -0
  9. package/dist/esm/consent/consent-debug-geography.enum.js +21 -0
  10. package/dist/esm/consent/consent-debug-geography.enum.js.map +1 -0
  11. package/dist/esm/consent/consent-definition.interface.d.ts +26 -0
  12. package/dist/esm/consent/consent-definition.interface.js +2 -0
  13. package/dist/esm/consent/consent-definition.interface.js.map +1 -0
  14. package/dist/esm/consent/consent-info.interface.d.ts +13 -0
  15. package/dist/esm/consent/consent-info.interface.js +2 -0
  16. package/dist/esm/consent/consent-info.interface.js.map +1 -0
  17. package/dist/esm/consent/consent-request-options.interface.d.ts +20 -0
  18. package/dist/esm/consent/consent-request-options.interface.js +2 -0
  19. package/dist/esm/consent/consent-request-options.interface.js.map +1 -0
  20. package/dist/esm/consent/consent-status.enum.d.ts +23 -0
  21. package/dist/esm/consent/consent-status.enum.js +25 -0
  22. package/dist/esm/consent/consent-status.enum.js.map +1 -0
  23. package/dist/esm/consent/index.d.ts +5 -0
  24. package/dist/esm/consent/index.js +6 -0
  25. package/dist/esm/consent/index.js.map +1 -0
  26. package/dist/esm/definitions.d.ts +2 -1
  27. package/dist/esm/definitions.js.map +1 -1
  28. package/dist/esm/index.d.ts +1 -0
  29. package/dist/esm/index.js +1 -0
  30. package/dist/esm/index.js.map +1 -1
  31. package/dist/esm/web.d.ts +4 -1
  32. package/dist/esm/web.js +17 -0
  33. package/dist/esm/web.js.map +1 -1
  34. package/dist/plugin.cjs.js +62 -0
  35. package/dist/plugin.cjs.js.map +1 -1
  36. package/dist/plugin.js +62 -0
  37. package/dist/plugin.js.map +1 -1
  38. package/ios/Plugin/Banner/BannerExecutor.swift +17 -4
  39. package/ios/Plugin/Consent/ConsentExecutor.swift +87 -0
  40. package/ios/Plugin/Plugin.m +3 -0
  41. package/ios/Plugin/Plugin.swift +47 -2
  42. package/package.json +5 -2
package/README.md CHANGED
@@ -134,20 +134,48 @@ export async function initialize(): Promise<void> {
134
134
  }
135
135
 
136
136
  AdMob.initialize({
137
- requestTrackingAuthorization: true,
138
137
  testingDevices: ['2077ef9a63d2b398840261c8221a0c9b'],
139
138
  initializeForTesting: true,
140
139
  });
141
140
  }
142
141
  ```
143
142
 
144
- You can use option `requestTrackingAuthorization`. This change permission to require `AppTrackingTransparency` in iOS >= 14:
145
- https://developers.google.com/admob/ios/ios14
143
+ Send and array of device Ids in `testingDevices? to use production like ads on your specified devices -> https://developers.google.com/admob/android/test-ads#enable_test_devices
146
144
 
147
- Default value is `true`. If you don't want to track, set requestTrackingAuthorization `false`.
145
+ ### User Message Platform (UMP)
148
146
 
149
- Send and array of device Ids in `testingDevices? to use production like ads on your specified devices -> https://developers.google.com/admob/android/test-ads#enable_test_devices
147
+ Later this year, Google will require all publishers serving ads to EEA and UK users to use a Google-certified Consent Management Platform (CMP)
148
+
149
+ Currently we just support Google's consent management solution.
150
+
151
+ To use UMP, you must [create your GDPR messages](https://support.google.com/admob/answer/10113207?hl=en&ref_topic=10105230&sjid=6731900490614517032-AP)
152
+
153
+ You may need to [setup IDFA messages](https://support.google.com/admob/answer/10115027?hl=en), it will work along with GDPR messages and will show when users are not in EEA and UK.
154
+
155
+ Example of how to use UMP
156
+
157
+ ```ts
158
+ import { AdMob, AdmobConsentStatus, AdmobConsentDebugGeography } from '@capacitor-community/admob';
150
159
 
160
+ async showConsent() {
161
+ const consentInfo = await AdMob.requestConsentInfo();
162
+
163
+ if (consentInfo.isConsentFormAvailable && consentInfo.status === AdmobConsentStatus.REQUIRED) {
164
+ const {status} = await AdMob.showConsentForm();
165
+ }
166
+ }
167
+ ```
168
+
169
+ If you testing on real device, you have to set `debugGeography` and add your device ID to `testDeviceIdentifiers`. You can find your device ID with logcat (Android) or XCode (iOS).
170
+
171
+ ```ts
172
+ const consentInfo = await AdMob.requestConsentInfo({
173
+ debugGeography: AdmobConsentDebugGeography.EEA,
174
+ testDeviceIdentifiers: ['YOUR_DEVICE_ID']
175
+ });
176
+ ```
177
+
178
+ **Note**: When testing, if you choose not consent (Manage -> Confirm Choices). The ads may not load/show. Even on testing enviroment. This is normal. It will work on Production so don't worry.
151
179
 
152
180
  ### Show Banner
153
181
 
@@ -273,6 +301,9 @@ AdMob.addListener(RewardAdPluginEvents.Rewarded, async () => {
273
301
  * [`addListener(BannerAdPluginEvents.Opened, ...)`](#addlistenerbanneradplugineventsopened-)
274
302
  * [`addListener(BannerAdPluginEvents.Closed, ...)`](#addlistenerbanneradplugineventsclosed-)
275
303
  * [`addListener(BannerAdPluginEvents.AdImpression, ...)`](#addlistenerbanneradplugineventsadimpression-)
304
+ * [`requestConsentInfo(...)`](#requestconsentinfo)
305
+ * [`showConsentForm()`](#showconsentform)
306
+ * [`resetConsentInfo()`](#resetconsentinfo)
276
307
  * [`prepareInterstitial(...)`](#prepareinterstitial)
277
308
  * [`showInterstitial()`](#showinterstitial)
278
309
  * [`addListener(InterstitialAdPluginEvents.FailedToLoad, ...)`](#addlistenerinterstitialadplugineventsfailedtoload-)
@@ -510,6 +541,47 @@ Unimplemented
510
541
  --------------------
511
542
 
512
543
 
544
+ ### requestConsentInfo(...)
545
+
546
+ ```typescript
547
+ requestConsentInfo(options?: AdmobConsentRequestOptions) => Promise<AdmobConsentInfo>
548
+ ```
549
+
550
+ Request user consent information
551
+
552
+ | Param | Type | Description |
553
+ | ------------- | --------------------------------------------------------------------------------- | --------------------- |
554
+ | **`options`** | <code><a href="#admobconsentrequestoptions">AdmobConsentRequestOptions</a></code> | ConsentRequestOptions |
555
+
556
+ **Returns:** <code>Promise&lt;<a href="#admobconsentinfo">AdmobConsentInfo</a>&gt;</code>
557
+
558
+ --------------------
559
+
560
+
561
+ ### showConsentForm()
562
+
563
+ ```typescript
564
+ showConsentForm() => Promise<AdmobConsentInfo>
565
+ ```
566
+
567
+ Shows a google user consent form (rendered from your GDPR message config).
568
+
569
+ **Returns:** <code>Promise&lt;<a href="#admobconsentinfo">AdmobConsentInfo</a>&gt;</code>
570
+
571
+ --------------------
572
+
573
+
574
+ ### resetConsentInfo()
575
+
576
+ ```typescript
577
+ resetConsentInfo() => Promise<void>
578
+ ```
579
+
580
+ Resets the UMP SDK state. Call requestConsentInfo function again to allow user modify their consent
581
+
582
+ --------------------
583
+
584
+
513
585
  ### prepareInterstitial(...)
514
586
 
515
587
  ```typescript
@@ -818,6 +890,23 @@ https://developers.google.com/android/reference/com/google/android/gms/ads/AdErr
818
890
  | **`message`** | <code>string</code> | Gets the message describing the error. |
819
891
 
820
892
 
893
+ #### AdmobConsentInfo
894
+
895
+ | Prop | Type | Description |
896
+ | ---------------------------- | ----------------------------------------------------------------- | ----------------------------------------------------- |
897
+ | **`status`** | <code><a href="#admobconsentstatus">AdmobConsentStatus</a></code> | The consent status of the user. |
898
+ | **`isConsentFormAvailable`** | <code>boolean</code> | If `true` a consent form is available and vice versa. |
899
+
900
+
901
+ #### AdmobConsentRequestOptions
902
+
903
+ | Prop | Type | Description |
904
+ | ----------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
905
+ | **`debugGeography`** | <code><a href="#admobconsentdebuggeography">AdmobConsentDebugGeography</a></code> | Sets the debug geography to test the consent locally. |
906
+ | **`testDeviceIdentifiers`** | <code>string[]</code> | An array of test device IDs to allow. Note: On iOS, the ID may renew if you uninstall and reinstall the app. |
907
+ | **`tagForUnderAgeOfConsent`** | <code>boolean</code> | Set to `true` to provide the option for the user to accept being shown personalized ads. |
908
+
909
+
821
910
  #### AdLoadInfo
822
911
 
823
912
  | Prop | Type |
@@ -915,6 +1004,25 @@ From T, pick a set of properties whose keys are in the union K
915
1004
  | **`AdImpression`** | <code>"bannerAdImpression"</code> | Similarly, this method should be called when an impression is recorded for the ad by the mediated SDK. |
916
1005
 
917
1006
 
1007
+ #### AdmobConsentStatus
1008
+
1009
+ | Members | Value | Description |
1010
+ | ------------------ | --------------------------- | ------------------------------------------------------------------------------------- |
1011
+ | **`NOT_REQUIRED`** | <code>'NOT_REQUIRED'</code> | User consent not required. |
1012
+ | **`OBTAINED`** | <code>'OBTAINED'</code> | User consent already obtained. |
1013
+ | **`REQUIRED`** | <code>'REQUIRED'</code> | User consent required but not yet obtained. |
1014
+ | **`UNKNOWN`** | <code>'UNKNOWN'</code> | Unknown consent status, AdsConsent.requestInfoUpdate needs to be called to update it. |
1015
+
1016
+
1017
+ #### AdmobConsentDebugGeography
1018
+
1019
+ | Members | Value | Description |
1020
+ | -------------- | -------------- | -------------------------------------------------- |
1021
+ | **`DISABLED`** | <code>0</code> | Debug geography disabled. |
1022
+ | **`EEA`** | <code>1</code> | Geography appears as in EEA for debug devices. |
1023
+ | **`NOT_EEA`** | <code>2</code> | Geography appears as not in EEA for debug devices. |
1024
+
1025
+
918
1026
  #### InterstitialAdPluginEvents
919
1027
 
920
1028
  | Members | Value | Description |
@@ -46,6 +46,9 @@ android {
46
46
  sourceCompatibility JavaVersion.VERSION_17
47
47
  targetCompatibility JavaVersion.VERSION_17
48
48
  }
49
+ kotlinOptions {
50
+ jvmTarget = JavaVersion.VERSION_17
51
+ }
49
52
  }
50
53
 
51
54
  repositories {
@@ -9,6 +9,7 @@ import com.getcapacitor.PluginMethod;
9
9
  import com.getcapacitor.annotation.CapacitorPlugin;
10
10
  import com.getcapacitor.annotation.Permission;
11
11
  import com.getcapacitor.community.admob.banner.BannerExecutor;
12
+ import com.getcapacitor.community.admob.consent.AdConsentExecutor;
12
13
  import com.getcapacitor.community.admob.helpers.AuthorizationStatusEnum;
13
14
  import com.getcapacitor.community.admob.interstitial.AdInterstitialExecutor;
14
15
  import com.getcapacitor.community.admob.interstitial.InterstitialAdCallbackAndListeners;
@@ -46,6 +47,13 @@ public class AdMob extends Plugin {
46
47
  InterstitialAdCallbackAndListeners.INSTANCE
47
48
  );
48
49
 
50
+ private final AdConsentExecutor adConsentExecutor = new AdConsentExecutor(
51
+ this::getContext,
52
+ this::getActivity,
53
+ this::notifyListeners,
54
+ getLogTag()
55
+ );
56
+
49
57
  // Initialize AdMob with appId
50
58
  @PluginMethod
51
59
  public void initialize(final PluginCall call) {
@@ -73,6 +81,22 @@ public class AdMob extends Plugin {
73
81
  call.resolve(response);
74
82
  }
75
83
 
84
+ // User Consent
85
+ @PluginMethod
86
+ public void requestConsentInfo(final PluginCall call) {
87
+ adConsentExecutor.requestConsentInfo(call, this::notifyListeners);
88
+ }
89
+
90
+ @PluginMethod
91
+ public void showConsentForm(final PluginCall call) {
92
+ adConsentExecutor.showConsentForm(call, this::notifyListeners);
93
+ }
94
+
95
+ @PluginMethod
96
+ public void resetConsentInfo(final PluginCall call) {
97
+ adConsentExecutor.resetConsentInfo(call, this::notifyListeners);
98
+ }
99
+
76
100
  @PluginMethod
77
101
  public void setApplicationMuted(final PluginCall call) {
78
102
  Boolean muted = call.getBoolean("muted");
@@ -2,10 +2,12 @@ package com.getcapacitor.community.admob.banner;
2
2
 
3
3
  import android.app.Activity;
4
4
  import android.content.Context;
5
+ import android.util.DisplayMetrics;
5
6
  import android.util.Log;
6
7
  import android.view.Gravity;
7
8
  import android.view.View;
8
9
  import android.view.ViewGroup;
10
+ import android.view.WindowManager;
9
11
  import android.widget.RelativeLayout;
10
12
  import androidx.annotation.NonNull;
11
13
  import androidx.coordinatorlayout.widget.CoordinatorLayout;
@@ -46,9 +48,19 @@ public class BannerExecutor extends Executor {
46
48
 
47
49
  public void showBanner(final PluginCall call) {
48
50
  final AdOptions adOptions = AdOptions.getFactory().createBannerOptions(call);
49
- float widthPixels = (int) contextSupplier.get().getResources().getDisplayMetrics().widthPixels;
50
51
  float density = contextSupplier.get().getResources().getDisplayMetrics().density;
51
52
 
53
+ int defaultWidthPixels = contextSupplier.get().getResources().getDisplayMetrics().widthPixels;
54
+
55
+ DisplayMetrics metrics = new DisplayMetrics();
56
+ activitySupplier.get().getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
57
+ int realWidthPixels = metrics.widthPixels;
58
+
59
+ boolean fullscreen = false;
60
+ if ((activitySupplier.get().getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0) {
61
+ fullscreen = true;
62
+ }
63
+
52
64
  if (mAdView != null) {
53
65
  updateExistingAdView(adOptions);
54
66
  return;
@@ -63,7 +75,7 @@ public class BannerExecutor extends Executor {
63
75
  } else {
64
76
  // ADAPTIVE BANNER
65
77
  mAdView.setAdSize(
66
- AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(contextSupplier.get(), (int) (widthPixels / density))
78
+ AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(contextSupplier.get(), (int) (defaultWidthPixels / density))
67
79
  );
68
80
  }
69
81
 
@@ -96,11 +108,18 @@ public class BannerExecutor extends Executor {
96
108
 
97
109
  // Center Banner Ads
98
110
  int adWidth = (int) (adOptions.adSize.getSize().getWidth() * density);
99
- int sideMargin = ((int) widthPixels - adWidth) / 2;
100
111
 
101
112
  if (adWidth <= 0 || adOptions.adSize.toString().equals("ADAPTIVE_BANNER")) {
102
- mAdViewLayoutParams.setMargins(0, densityMargin, 0, densityMargin);
113
+ int margin = 0;
114
+ if (fullscreen) {
115
+ margin = (realWidthPixels - defaultWidthPixels) / 2;
116
+ }
117
+ mAdViewLayoutParams.setMargins(margin, densityMargin, margin, densityMargin);
103
118
  } else {
119
+ int sideMargin = ((int) defaultWidthPixels - adWidth) / 2;
120
+ if (fullscreen) {
121
+ sideMargin = (realWidthPixels - adWidth) / 2;
122
+ }
104
123
  mAdViewLayoutParams.setMargins(sideMargin, densityMargin, sideMargin, densityMargin);
105
124
  }
106
125
 
@@ -0,0 +1,145 @@
1
+ package com.getcapacitor.community.admob.consent;
2
+
3
+ import android.app.Activity;
4
+ import android.content.Context;
5
+ import android.content.SharedPreferences;
6
+ import android.preference.PreferenceManager;
7
+ import androidx.core.util.Supplier;
8
+ import com.getcapacitor.JSArray;
9
+ import com.getcapacitor.JSObject;
10
+ import com.getcapacitor.PluginCall;
11
+ import com.getcapacitor.PluginMethod;
12
+ import com.getcapacitor.community.admob.models.Executor;
13
+ import com.google.android.gms.common.util.BiConsumer;
14
+ import com.google.android.ump.ConsentDebugSettings;
15
+ import com.google.android.ump.ConsentForm;
16
+ import com.google.android.ump.ConsentInformation;
17
+ import com.google.android.ump.ConsentRequestParameters;
18
+ import com.google.android.ump.FormError;
19
+ import com.google.android.ump.UserMessagingPlatform;
20
+
21
+ public class AdConsentExecutor extends Executor {
22
+
23
+ private ConsentInformation consentInformation;
24
+
25
+ public AdConsentExecutor(
26
+ Supplier<Context> contextSupplier,
27
+ Supplier<Activity> activitySupplier,
28
+ BiConsumer<String, JSObject> notifyListenersFunction,
29
+ String pluginLogTag
30
+ ) {
31
+ super(contextSupplier, activitySupplier, notifyListenersFunction, pluginLogTag, "AdConsentExecutor");
32
+ }
33
+
34
+ @PluginMethod
35
+ public void requestConsentInfo(final PluginCall call, BiConsumer<String, JSObject> notifyListenersFunction) {
36
+ try {
37
+ ensureConsentInfo();
38
+
39
+ ConsentRequestParameters.Builder paramsBuilder = new ConsentRequestParameters.Builder();
40
+ ConsentDebugSettings.Builder debugSettingsBuilder = new ConsentDebugSettings.Builder(contextSupplier.get());
41
+
42
+ if (call.getData().has("testDeviceIdentifiers")) {
43
+ JSArray devices = call.getArray("testDeviceIdentifiers");
44
+
45
+ for (int i = 0; i < devices.length(); i++) {
46
+ debugSettingsBuilder.addTestDeviceHashedId(devices.getString(i));
47
+ }
48
+ }
49
+
50
+ if (call.getData().has("debugGeography")) {
51
+ debugSettingsBuilder.setDebugGeography(call.getInt("debugGeography"));
52
+ }
53
+
54
+ paramsBuilder.setConsentDebugSettings(debugSettingsBuilder.build());
55
+
56
+ if (call.getData().has("tagForUnderAgeOfConsent")) {
57
+ paramsBuilder.setTagForUnderAgeOfConsent(call.getBoolean("tagForUnderAgeOfConsent"));
58
+ }
59
+
60
+ ConsentRequestParameters consentRequestParameters = paramsBuilder.build();
61
+
62
+ if (activitySupplier.get() == null) {
63
+ call.reject("Trying to request consent info but the Activity is null");
64
+ return;
65
+ }
66
+
67
+ consentInformation.requestConsentInfoUpdate(
68
+ activitySupplier.get(),
69
+ consentRequestParameters,
70
+ () -> {
71
+ JSObject consentInfo = new JSObject();
72
+ consentInfo.put("status", getConsentStatusString(consentInformation.getConsentStatus()));
73
+ consentInfo.put("isConsentFormAvailable", consentInformation.isConsentFormAvailable());
74
+ call.resolve(consentInfo);
75
+ },
76
+ formError -> call.reject(formError.getMessage())
77
+ );
78
+ } catch (Exception ex) {
79
+ call.reject(ex.getLocalizedMessage(), ex);
80
+ }
81
+ }
82
+
83
+ @PluginMethod
84
+ public void showConsentForm(final PluginCall call, BiConsumer<String, JSObject> notifyListenersFunction) {
85
+ try {
86
+ if (activitySupplier.get() == null) {
87
+ call.reject("Trying to show the consent form but the Activity is null");
88
+ return;
89
+ }
90
+ ensureConsentInfo();
91
+ activitySupplier
92
+ .get()
93
+ .runOnUiThread(
94
+ () ->
95
+ UserMessagingPlatform.loadConsentForm(
96
+ contextSupplier.get(),
97
+ consentForm ->
98
+ consentForm.show(
99
+ activitySupplier.get(),
100
+ formError -> {
101
+ if (formError != null) {
102
+ call.reject("Error when show consent form", formError.getMessage());
103
+ } else {
104
+ JSObject consentFormInfo = new JSObject();
105
+ consentFormInfo.put("status", getConsentStatusString(consentInformation.getConsentStatus()));
106
+
107
+ call.resolve(consentFormInfo);
108
+ }
109
+ }
110
+ ),
111
+ formError -> call.reject("Error when show consent form", formError.getMessage())
112
+ )
113
+ );
114
+ } catch (Exception ex) {
115
+ call.reject(ex.getLocalizedMessage(), ex);
116
+ }
117
+ }
118
+
119
+ @PluginMethod
120
+ public void resetConsentInfo(final PluginCall call, BiConsumer<String, JSObject> notifyListenersFunction) {
121
+ ensureConsentInfo();
122
+ consentInformation.reset();
123
+ call.resolve();
124
+ }
125
+
126
+ private String getConsentStatusString(int consentConstant) {
127
+ switch (consentConstant) {
128
+ case ConsentInformation.ConsentStatus.REQUIRED:
129
+ return "REQUIRED";
130
+ case ConsentInformation.ConsentStatus.NOT_REQUIRED:
131
+ return "NOT_REQUIRED";
132
+ case ConsentInformation.ConsentStatus.OBTAINED:
133
+ return "OBTAINED";
134
+ case ConsentInformation.ConsentStatus.UNKNOWN:
135
+ default:
136
+ return "UNKNOWN";
137
+ }
138
+ }
139
+
140
+ private void ensureConsentInfo() {
141
+ if (consentInformation == null) {
142
+ consentInformation = UserMessagingPlatform.getConsentInformation(contextSupplier.get());
143
+ }
144
+ }
145
+ }
@@ -71,7 +71,6 @@ public class AdRewardExecutor extends Executor {
71
71
  activitySupplier.get(),
72
72
  RewardedAdCallbackAndListeners.INSTANCE.getOnUserEarnedRewardListener(call, notifyListenersFunction)
73
73
  );
74
- call.resolve();
75
74
  }
76
75
  );
77
76
  } catch (Exception ex) {