cordova-plugin-admob-nextgen 1.0.0 → 1.0.2

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 SwapLab Engine
3
+ Copyright (c) 2024-2026 SwapLab Engine
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,9 +1,14 @@
1
1
  # Cordova AdMob Next-Gen Plugin
2
2
 
3
3
  [![Android](https://img.shields.io/badge/Platform-Android-green?logo=android)](https://www.android.com)
4
+ [![iOS](https://img.shields.io/badge/Platform-iOS-lightgrey?logo=apple)](https://www.apple.com/ios)
4
5
  [![AdMob Next Gen](https://img.shields.io/badge/SDK-Google%20Mobile%20Ads%20Next--Gen-blue)](https://ads-developers.googleblog.com/2026/01/announcing-google-mobile-ads-next-gen.html)
5
6
  [![License](https://img.shields.io/badge/License-MIT-yellow)](LICENSE)
6
7
 
8
+ [![NPM version](https://img.shields.io/npm/v/cordova-plugin-admob-nextgen.svg)](https://www.npmjs.com/package/cordova-plugin-admob-nextgen)
9
+ [![Downloads](https://img.shields.io/npm/dm/cordova-plugin-admob-nextgen.svg)](https://www.npmjs.com/package/cordova-plugin-admob-nextgen)
10
+ [![License](https://img.shields.io/npm/l/cordova-plugin-admob-nextgen.svg)](https://github.com/swaplab-engine/cordova-plugin-admob-nextgen/blob/main/LICENSE)
11
+
7
12
  **The Ultimate AdMob Monetization Solution for Cordova/Capacitor/Framework7.**
8
13
 
9
14
  This plugin is a complete **rewrite and re-architecture** of the classic AdMob integration, built specifically for the **[Google Mobile Ads Next Generation SDK](https://ads-developers.googleblog.com/2026/01/announcing-google-mobile-ads-next-gen.html)**. It moves away from legacy implementations to modern `SurfaceControl`, optimized layouts, and background threading, ensuring maximum performance, stability, and revenue.
@@ -65,15 +70,16 @@ We prioritize the safety of your AdMob account and the stability of your app.
65
70
  ### Option A: Via CLI
66
71
  Install the plugin directly using the Cordova CLI. You must provide your AdMob App ID.
67
72
 
68
- cordova plugin add cordova-plugin-admob-nextgen --save --variable APP_ID_ANDROID="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"
73
+ cordova plugin add cordova-plugin-admob-nextgen --save --variable APP_ID_ANDROID="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy" --variable APP_ID_IOS="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"
69
74
 
70
75
  ### Option B: Via config.xml
71
76
  Add this to your `config.xml` to restore the plugin automatically.
72
77
 
73
78
  <plugin name="cordova-plugin-admob-nextgen" spec="latest">
74
79
  <variable name="APP_ID_ANDROID" value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy" />
80
+ <variable name="APP_ID_IOS" value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy" />
75
81
 
76
- <variable name="NEXT_GEN_SDK_VERSION" value="0.23.0-beta01" />
82
+ <variable name="NEXT_GEN_SDK_VERSION" value="0.25.0-beta01" />
77
83
  <variable name="UMP_VERSION" value="4.0.0" />
78
84
  </plugin>
79
85
 
@@ -149,7 +155,30 @@ Add this to your `config.xml` to restore the plugin automatically.
149
155
  });
150
156
 
151
157
 
152
-
158
+ ### App Tracking Transparency (ATT / IDFA) - iOS Only
159
+ For iOS 14+, Apple requires you to prompt the user before tracking their IDFA.
160
+ The plugin provides manual control over this prompt so you can display it at the right time in your app's lifecycle.
161
+
162
+ ```
163
+ function checkAppTracking() {
164
+ admobNextGen.requestTrackingAuthorization(
165
+ function(status) {
166
+ console.log("ATT Status: " + status);
167
+ // Returns: 'AUTHORIZED', 'DENIED', 'NOT_DETERMINED', 'RESTRICTED'
168
+
169
+ // Regardless of the ATT choice, initialize the SDK
170
+ startSdk();
171
+ },
172
+ function(err) {
173
+ console.warn("ATT Request Failed", err);
174
+ startSdk();
175
+ }
176
+ );
177
+ }
178
+
179
+ // You can also silently check the status anytime:
180
+ // admobNextGen.getTrackingAuthorizationStatus(success, error);
181
+ ```
153
182
 
154
183
  ### Step 3: Check Consent Status (Smart Analysis)
155
184
  You can check if the user has granted permission for Personalized Ads without parsing complex IAB strings manually.
@@ -8,9 +8,12 @@ const configPath = fs.existsSync(path.join(rootPath, 'capacitor.config.ts'))
8
8
 
9
9
  const manifestPath = path.join(rootPath, 'android/app/src/main/AndroidManifest.xml');
10
10
  const gradlePath = path.join(rootPath, 'android/app/build.gradle');
11
+ const iosPlistPath = path.join(rootPath, 'ios/App/App/Info.plist');
11
12
 
12
13
  /**
13
- * Updates AndroidManifest.xml with the AdMob App ID
14
+ * ---------------------------------------------------------
15
+ * ANDROID HOOKS
16
+ * ---------------------------------------------------------
14
17
  */
15
18
  function updateAndroidManifest(appId) {
16
19
  if (!fs.existsSync(manifestPath)) return;
@@ -24,12 +27,9 @@ function updateAndroidManifest(appId) {
24
27
  content = content.replace('</application>', ` ${newTag}\n </application>`);
25
28
  }
26
29
  fs.writeFileSync(manifestPath, content, 'utf8');
27
- console.log(`[AdMob Hook] Success: Updated App ID to ${appId}`);
30
+ console.log(`[AdMob Hook] Success: Updated Android App ID to ${appId}`);
28
31
  }
29
32
 
30
- /**
31
- * Updates build.gradle with specific SDK and UMP versions
32
- */
33
33
  function updateGradleDependencies(nextGenVersion, umpVersion) {
34
34
  if (!fs.existsSync(gradlePath)) return;
35
35
  let content = fs.readFileSync(gradlePath, 'utf8');
@@ -44,34 +44,104 @@ function updateGradleDependencies(nextGenVersion, umpVersion) {
44
44
  if (umpRegex.test(content)) content = content.replace(umpRegex, newUmp);
45
45
 
46
46
  fs.writeFileSync(gradlePath, content, 'utf8');
47
- console.log(`[AdMob Hook] Success: Updated Next Gen SDK to ${nextGenVersion} and UMP to ${umpVersion}`);
47
+ console.log(`[AdMob Hook] Success: Updated Android Next Gen SDK to ${nextGenVersion} and UMP to ${umpVersion}`);
48
48
  }
49
49
 
50
50
  function injectExclusionRules() {
51
51
  if (!fs.existsSync(gradlePath)) return;
52
52
  let content = fs.readFileSync(gradlePath, 'utf8');
53
53
 
54
- if (content.includes('exclude group: "com.google.android.gms", module: "play-services-ads"')) {
55
- return;
56
- }
54
+ if (content.includes('exclude group: "com.google.android.gms", module: "play-services-ads"')) return;
57
55
 
58
56
  const exclusionBlock = `
59
57
  // [AdMob Next Gen] Exclude Legacy SDK to prevent duplicates
60
58
  configurations.configureEach {
61
- exclude group: "com.google.android.gms", module: "play-services-ads"
62
- exclude group: "com.google.android.gms", module: "play-services-ads-lite"
59
+ exclude group: "com.google.android.gms", module: "play-services-ads"
60
+ exclude group: "com.google.android.gms", module: "play-services-ads-lite"
63
61
  }
64
62
  `;
65
-
66
63
  content += exclusionBlock;
67
-
68
64
  fs.writeFileSync(gradlePath, content, 'utf8');
69
65
  console.log('[AdMob Hook] Success: Injected legacy SDK exclusion rules into build.gradle');
70
66
  }
71
67
 
68
+ /**
69
+ * ---------------------------------------------------------
70
+ * IOS HOOKS (THE NEW SMART ENGINE)
71
+ * ---------------------------------------------------------
72
+ */
73
+ function updateIosInfoPlist(appIdIos) {
74
+ if (!fs.existsSync(iosPlistPath)) {
75
+ console.warn('[AdMob Hook] Warning: ios/App/App/Info.plist not found. Run "npx cap add ios" first.');
76
+ return;
77
+ }
78
+
79
+ let content = fs.readFileSync(iosPlistPath, 'utf8');
80
+
81
+ function setStringKey(key, value) {
82
+ const regex = new RegExp(`<key>${key}</key>\\s*<string>.*?</string>`, 's');
83
+ const replacement = `<key>${key}</key>\n\t<string>${value}</string>`;
84
+ if (regex.test(content)) {
85
+ content = content.replace(regex, replacement);
86
+ } else {
87
+ content = content.replace('</dict>\n</plist>', `\t${replacement}\n</dict>\n</plist>`);
88
+ }
89
+ }
90
+
91
+ function setBoolKey(key, value) {
92
+ const boolStr = value ? '<true/>' : '<false/>';
93
+ const regex = new RegExp(`<key>${key}</key>\\s*<(true|false)\\/>`, 's');
94
+ const replacement = `<key>${key}</key>\n\t${boolStr}`;
95
+ if (regex.test(content)) {
96
+ content = content.replace(regex, replacement);
97
+ } else {
98
+ content = content.replace('</dict>\n</plist>', `\t${replacement}\n</dict>\n</plist>`);
99
+ }
100
+ }
101
+
102
+ setStringKey('GADApplicationIdentifier', appIdIos);
103
+
104
+ setStringKey('NSUserTrackingUsageDescription', 'This identifier will be used to deliver personalized ads to you.');
105
+
106
+ setBoolKey('GADDelayAppMeasurementInit', true);
107
+
108
+ if (!content.includes('<key>SKAdNetworkItems</key>')) {
109
+ const skAdNetworks = [
110
+ 'cstr6suwn9.skadnetwork', '4fzdc2evr5.skadnetwork', '2fnua5tdw4.skadnetwork', 'ydx93a7ass.skadnetwork',
111
+ 'p78axxw29g.skadnetwork', 'v72qych5uu.skadnetwork', 'ludvb6z3bs.skadnetwork', 'cp8zw746q7.skadnetwork',
112
+ '3sh42y64q3.skadnetwork', 'c6k4g5qg8m.skadnetwork', 's39g8k73mm.skadnetwork', 'wg4vff78zm.skadnetwork',
113
+ '3qy4746246.skadnetwork', 'f38h382jlk.skadnetwork', 'hs6bdukanm.skadnetwork', 'mlmmfzh3r3.skadnetwork',
114
+ 'v4nxqhlyqp.skadnetwork', 'wzmmz9fp6w.skadnetwork', 'su67r6k2v3.skadnetwork', 'yclnxrl5pm.skadnetwork',
115
+ 't38b2kh725.skadnetwork', '7ug5zh24hu.skadnetwork', 'gta9lk7p23.skadnetwork', 'vutu7akeur.skadnetwork',
116
+ 'y5ghdn5j9k.skadnetwork', 'v9wttpbfk9.skadnetwork', 'n38lu8286q.skadnetwork', '47vhws6wlr.skadnetwork',
117
+ 'kbd757ywx3.skadnetwork', '9t245vhmpl.skadnetwork', 'a2p9lx4jpn.skadnetwork', '22mmun2rn5.skadnetwork',
118
+ '44jx6755aq.skadnetwork', 'k674qkevps.skadnetwork', '4468km3ulz.skadnetwork', '2u9pt9hc89.skadnetwork',
119
+ '8s468mfl3y.skadnetwork', 'klf5c3l5u5.skadnetwork', 'ppxm28t8ap.skadnetwork', 'uw77j35x4d.skadnetwork',
120
+ '578prtvx9j.skadnetwork', '4dzt52r2t5.skadnetwork', 'tl55sbb4fm.skadnetwork', 'e5fvkxwrpn.skadnetwork',
121
+ '8c4e2ghe7u.skadnetwork', '3rd42ekr43.skadnetwork', '3qcr597p9d.skadnetwork'
122
+ ];
123
+
124
+ let dicts = skAdNetworks.map(id => `\t\t<dict>\n\t\t\t<key>SKAdNetworkIdentifier</key>\n\t\t\t<string>${id}</string>\n\t\t</dict>`).join('\n');
125
+ let arrayBlock = `\t<key>SKAdNetworkItems</key>\n\t<array>\n${dicts}\n\t</array>`;
126
+
127
+ content = content.replace('</dict>\n</plist>', `${arrayBlock}\n</dict>\n</plist>`);
128
+ }
129
+
130
+ fs.writeFileSync(iosPlistPath, content, 'utf8');
131
+ console.log(`[AdMob Hook] Success: Updated iOS Info.plist with App ID (${appIdIos}), ATT prompt, and SKAdNetworks.`);
132
+ }
133
+
134
+ /**
135
+ * ---------------------------------------------------------
136
+ * MAIN RUNNER
137
+ * ---------------------------------------------------------
138
+ */
72
139
  function run() {
73
140
  try {
74
- if (!fs.existsSync(configPath)) return;
141
+ if (!fs.existsSync(configPath)) {
142
+ console.warn('[AdMob Hook] capacitor.config not found. Skipping auto-injection.');
143
+ return;
144
+ }
75
145
 
76
146
  const configContent = fs.readFileSync(configPath, 'utf8');
77
147
  let admob;
@@ -79,28 +149,33 @@ function run() {
79
149
  if (configPath.endsWith('.json')) {
80
150
  admob = JSON.parse(configContent).plugins?.AdMob;
81
151
  } else {
82
- // Extracting values from .ts file using regex
83
- const appId = configContent.match(/APP_ID_ANDROID:\s*['"](.*?)['"]/);
152
+ // Extract from .ts
153
+ const appIdAndroid = configContent.match(/APP_ID_ANDROID:\s*['"](.*?)['"]/);
154
+ const appIdIos = configContent.match(/APP_ID_IOS:\s*['"](.*?)['"]/);
84
155
  const sdk = configContent.match(/NEXT_GEN_SDK_VERSION:\s*['"](.*?)['"]/);
85
156
  const ump = configContent.match(/UMP_VERSION:\s*['"](.*?)['"]/);
157
+
86
158
  admob = {
87
- APP_ID_ANDROID: appId ? appId[1] : null,
88
- NEXT_GEN_SDK_VERSION: sdk ? sdk[1] : "0.23.0-beta01",
159
+ APP_ID_ANDROID: appIdAndroid ? appIdAndroid[1] : "ca-app-pub-3940256099942544~3347511713",
160
+ APP_ID_IOS: appIdIos ? appIdIos[1] : "ca-app-pub-3940256099942544~1458002511",
161
+ NEXT_GEN_SDK_VERSION: sdk ? sdk[1] : "0.25.0-beta01",
89
162
  UMP_VERSION: ump ? ump[1] : "4.0.0"
90
163
  };
91
164
  }
92
165
 
93
166
  if (admob?.APP_ID_ANDROID) updateAndroidManifest(admob.APP_ID_ANDROID);
94
-
95
167
  injectExclusionRules();
96
-
97
168
  if (admob?.NEXT_GEN_SDK_VERSION || admob?.UMP_VERSION) {
98
169
  updateGradleDependencies(
99
- admob.NEXT_GEN_SDK_VERSION || "0.23.0-beta01",
170
+ admob.NEXT_GEN_SDK_VERSION || "0.25.0-beta01",
100
171
  admob.UMP_VERSION || "4.0.0"
101
172
  );
102
173
  }
103
174
 
175
+ if (admob?.APP_ID_IOS) {
176
+ updateIosInfoPlist(admob.APP_ID_IOS);
177
+ }
178
+
104
179
  } catch (err) {
105
180
  console.error('[AdMob Hook] Error:', err.message);
106
181
  }
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "cordova-plugin-admob-nextgen",
3
- "version": "1.0.0",
4
- "description": "Google Mobile Ads Next Gen SDK for Cordova. High performance and modular architecture.",
3
+ "version": "1.0.2",
4
+ "description": "Google Mobile Ads Next Gen SDK for Cordova. High performance and modular architecture. ",
5
5
  "cordova": {
6
6
  "id": "cordova-plugin-admob-nextgen",
7
7
  "platforms": [
8
- "android"
8
+ "android",
9
+ "ios"
9
10
  ]
10
11
  },
11
12
  "repository": {
package/plugin.xml CHANGED
@@ -1,10 +1,11 @@
1
1
  <?xml version='1.0' encoding='utf-8'?>
2
- <plugin id="cordova-plugin-admob-nextgen" version="1.0.0"
2
+ <plugin id="cordova-plugin-admob-nextgen"
3
+ version="1.0.2"
3
4
  xmlns="http://apache.org/cordova/ns/plugins/1.0"
4
5
  xmlns:android="http://schemas.android.com/apk/res/android">
5
6
 
6
7
  <name>AdMob Next Gen</name>
7
- <description>Google Mobile Ads Next Gen SDK for Cordova</description>
8
+ <description>Google Mobile Ads Next Gen SDK for Cordova including capacitors</description>
8
9
  <author>EMI INDO</author>
9
10
  <license>MIT</license>
10
11
 
@@ -46,8 +47,110 @@
46
47
 
47
48
  </platform>
48
49
 
49
- <preference name="NEXT_GEN_SDK_VERSION" default="0.23.0-beta01" />
50
+ <preference name="NEXT_GEN_SDK_VERSION" default="0.25.0-beta01" />
50
51
  <preference name="UMP_VERSION" default="4.0.0" />
51
52
  <preference name="APP_ID_ANDROID" default="ca-app-pub-3940256099942544~3347511713" />
52
53
 
54
+ <platform name="ios">
55
+ <config-file target="config.xml" parent="/*">
56
+ <feature name="AdMobNextGen">
57
+ <param name="ios-package" value="AdMobNextGen" />
58
+ <param name="onload" value="true" />
59
+ </feature>
60
+ </config-file>
61
+
62
+ <config-file target="*-Info.plist" parent="GADApplicationIdentifier">
63
+ <string>$APP_ID_IOS</string>
64
+ </config-file>
65
+
66
+ <config-file target="*-Info.plist" parent="NSUserTrackingUsageDescription">
67
+ <string>This identifier will be used to deliver personalized ads to you.</string>
68
+ </config-file>
69
+
70
+ <config-file target="*-Info.plist" parent="SKAdNetworkItems">
71
+ <array>
72
+ <dict><key>SKAdNetworkIdentifier</key><string>cstr6suwn9.skadnetwork</string></dict>
73
+ <dict><key>SKAdNetworkIdentifier</key><string>4fzdc2evr5.skadnetwork</string></dict>
74
+ <dict><key>SKAdNetworkIdentifier</key><string>2fnua5tdw4.skadnetwork</string></dict>
75
+ <dict><key>SKAdNetworkIdentifier</key><string>ydx93a7ass.skadnetwork</string></dict>
76
+ <dict><key>SKAdNetworkIdentifier</key><string>p78axxw29g.skadnetwork</string></dict>
77
+ <dict><key>SKAdNetworkIdentifier</key><string>v72qych5uu.skadnetwork</string></dict>
78
+ <dict><key>SKAdNetworkIdentifier</key><string>ludvb6z3bs.skadnetwork</string></dict>
79
+ <dict><key>SKAdNetworkIdentifier</key><string>cp8zw746q7.skadnetwork</string></dict>
80
+ <dict><key>SKAdNetworkIdentifier</key><string>3sh42y64q3.skadnetwork</string></dict>
81
+ <dict><key>SKAdNetworkIdentifier</key><string>c6k4g5qg8m.skadnetwork</string></dict>
82
+ <dict><key>SKAdNetworkIdentifier</key><string>s39g8k73mm.skadnetwork</string></dict>
83
+ <dict><key>SKAdNetworkIdentifier</key><string>wg4vff78zm.skadnetwork</string></dict>
84
+ <dict><key>SKAdNetworkIdentifier</key><string>3qy4746246.skadnetwork</string></dict>
85
+ <dict><key>SKAdNetworkIdentifier</key><string>f38h382jlk.skadnetwork</string></dict>
86
+ <dict><key>SKAdNetworkIdentifier</key><string>hs6bdukanm.skadnetwork</string></dict>
87
+ <dict><key>SKAdNetworkIdentifier</key><string>mlmmfzh3r3.skadnetwork</string></dict>
88
+ <dict><key>SKAdNetworkIdentifier</key><string>v4nxqhlyqp.skadnetwork</string></dict>
89
+ <dict><key>SKAdNetworkIdentifier</key><string>wzmmz9fp6w.skadnetwork</string></dict>
90
+ <dict><key>SKAdNetworkIdentifier</key><string>su67r6k2v3.skadnetwork</string></dict>
91
+ <dict><key>SKAdNetworkIdentifier</key><string>yclnxrl5pm.skadnetwork</string></dict>
92
+ <dict><key>SKAdNetworkIdentifier</key><string>t38b2kh725.skadnetwork</string></dict>
93
+ <dict><key>SKAdNetworkIdentifier</key><string>7ug5zh24hu.skadnetwork</string></dict>
94
+ <dict><key>SKAdNetworkIdentifier</key><string>gta9lk7p23.skadnetwork</string></dict>
95
+ <dict><key>SKAdNetworkIdentifier</key><string>vutu7akeur.skadnetwork</string></dict>
96
+ <dict><key>SKAdNetworkIdentifier</key><string>y5ghdn5j9k.skadnetwork</string></dict>
97
+ <dict><key>SKAdNetworkIdentifier</key><string>v9wttpbfk9.skadnetwork</string></dict>
98
+ <dict><key>SKAdNetworkIdentifier</key><string>n38lu8286q.skadnetwork</string></dict>
99
+ <dict><key>SKAdNetworkIdentifier</key><string>47vhws6wlr.skadnetwork</string></dict>
100
+ <dict><key>SKAdNetworkIdentifier</key><string>kbd757ywx3.skadnetwork</string></dict>
101
+ <dict><key>SKAdNetworkIdentifier</key><string>9t245vhmpl.skadnetwork</string></dict>
102
+ <dict><key>SKAdNetworkIdentifier</key><string>a2p9lx4jpn.skadnetwork</string></dict>
103
+ <dict><key>SKAdNetworkIdentifier</key><string>22mmun2rn5.skadnetwork</string></dict>
104
+ <dict><key>SKAdNetworkIdentifier</key><string>44jx6755aq.skadnetwork</string></dict>
105
+ <dict><key>SKAdNetworkIdentifier</key><string>k674qkevps.skadnetwork</string></dict>
106
+ <dict><key>SKAdNetworkIdentifier</key><string>4468km3ulz.skadnetwork</string></dict>
107
+ <dict><key>SKAdNetworkIdentifier</key><string>2u9pt9hc89.skadnetwork</string></dict>
108
+ <dict><key>SKAdNetworkIdentifier</key><string>8s468mfl3y.skadnetwork</string></dict>
109
+ <dict><key>SKAdNetworkIdentifier</key><string>klf5c3l5u5.skadnetwork</string></dict>
110
+ <dict><key>SKAdNetworkIdentifier</key><string>ppxm28t8ap.skadnetwork</string></dict>
111
+ <dict><key>SKAdNetworkIdentifier</key><string>kbmxgpxpgc.skadnetwork</string></dict>
112
+ <dict><key>SKAdNetworkIdentifier</key><string>uw77j35x4d.skadnetwork</string></dict>
113
+ <dict><key>SKAdNetworkIdentifier</key><string>578prtvx9j.skadnetwork</string></dict>
114
+ <dict><key>SKAdNetworkIdentifier</key><string>4dzt52r2t5.skadnetwork</string></dict>
115
+ <dict><key>SKAdNetworkIdentifier</key><string>tl55sbb4fm.skadnetwork</string></dict>
116
+ <dict><key>SKAdNetworkIdentifier</key><string>c3frkrj4fj.skadnetwork</string></dict>
117
+ <dict><key>SKAdNetworkIdentifier</key><string>e5fvkxwrpn.skadnetwork</string></dict>
118
+ <dict><key>SKAdNetworkIdentifier</key><string>8c4e2ghe7u.skadnetwork</string></dict>
119
+ <dict><key>SKAdNetworkIdentifier</key><string>3rd42ekr43.skadnetwork</string></dict>
120
+ <dict><key>SKAdNetworkIdentifier</key><string>97r2b46745.skadnetwork</string></dict>
121
+ <dict><key>SKAdNetworkIdentifier</key><string>3qcr597p9d.skadnetwork</string></dict>
122
+ </array>
123
+ </config-file>
124
+
125
+ <framework src="AdSupport.framework" weak="true" />
126
+ <framework src="AppTrackingTransparency.framework" weak="true" />
127
+
128
+ <podspec>
129
+ <config>
130
+ <source url="https://cdn.cocoapods.org/"/>
131
+ </config>
132
+ <pods use-frameworks="true">
133
+ <pod name="GoogleUserMessagingPlatform" spec="~> 3.1.0" />
134
+ <pod name="Google-Mobile-Ads-SDK" spec="~> 13.1.0" />
135
+ </pods>
136
+ </podspec>
137
+
138
+ <header-file src="src/ios/AdMobNextGen.h" />
139
+ <source-file src="src/ios/AdMobNextGen.m" />
140
+ <header-file src="src/ios/ConsentExecutor.h" />
141
+ <source-file src="src/ios/ConsentExecutor.m" />
142
+ <header-file src="src/ios/AppOpenAdExecutor.h" />
143
+ <source-file src="src/ios/AppOpenAdExecutor.m" />
144
+ <header-file src="src/ios/BannerExecutor.h" />
145
+ <source-file src="src/ios/BannerExecutor.m" />
146
+ <header-file src="src/ios/InterstitialExecutor.h" />
147
+ <source-file src="src/ios/InterstitialExecutor.m" />
148
+ <header-file src="src/ios/RewardedExecutor.h" />
149
+ <source-file src="src/ios/RewardedExecutor.m" />
150
+ <header-file src="src/ios/RewardedInterstitialExecutor.h" />
151
+ <source-file src="src/ios/RewardedInterstitialExecutor.m" />
152
+ </platform>
153
+
154
+ <preference name="APP_ID_IOS" default="ca-app-pub-3940256099942544~1458002511" />
155
+
53
156
  </plugin>
@@ -53,6 +53,9 @@ public class BannerExecutor {
53
53
 
54
54
  private int lastAdHeight = 0;
55
55
 
56
+ private int systemSafeTop = 0;
57
+ private int systemSafeBottom = 0;
58
+
56
59
  private long lastLoadTime = 0;
57
60
  private long minLoadInterval = 5000;
58
61
 
@@ -301,20 +304,30 @@ public class BannerExecutor {
301
304
 
302
305
  if (adLayout == null) {
303
306
  adLayout = new RelativeLayout(cordova.getActivity());
307
+
304
308
  RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
305
309
  RelativeLayout.LayoutParams.MATCH_PARENT,
306
- RelativeLayout.LayoutParams.MATCH_PARENT);
310
+ RelativeLayout.LayoutParams.WRAP_CONTENT);
311
+
312
+ if ("top".equalsIgnoreCase(currentPosition)) {
313
+ params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
314
+ } else {
315
+ params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
316
+ }
317
+
307
318
  adLayout.setClickable(false);
308
319
  adLayout.setFocusable(false);
309
320
  cordova.getActivity().addContentView(adLayout, params);
310
321
  }
311
322
 
323
+ isBannerVisible = true;
312
324
  updateBannerLayout();
313
325
 
314
326
  adLayout.bringToFront();
315
327
  adLayout.setVisibility(View.VISIBLE);
328
+ adView.setVisibility(View.VISIBLE);
329
+
316
330
  updateWebViewMargins();
317
- isBannerVisible = true;
318
331
  }
319
332
 
320
333
  private void updateBannerLayout() {
@@ -340,12 +353,37 @@ public class BannerExecutor {
340
353
  } else {
341
354
  adView.setLayoutParams(bannerParams);
342
355
  }
343
- }
344
356
 
345
- private void hideBannerView() {
346
- if (adLayout != null) adLayout.setVisibility(View.GONE);
347
- resetWebViewMargins();
348
- isBannerVisible = false;
357
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
358
+ adLayout.setOnApplyWindowInsetsListener((v, insets) -> {
359
+
360
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
361
+ systemSafeTop = insets.getInsets(android.view.WindowInsets.Type.systemBars()).top;
362
+ systemSafeBottom = insets.getInsets(android.view.WindowInsets.Type.systemBars()).bottom;
363
+ } else {
364
+ systemSafeTop = insets.getSystemWindowInsetTop();
365
+ systemSafeBottom = insets.getSystemWindowInsetBottom();
366
+ }
367
+
368
+ if (adView != null && adView.getLayoutParams() instanceof RelativeLayout.LayoutParams) {
369
+ RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) adView.getLayoutParams();
370
+ if ("top".equalsIgnoreCase(currentPosition)) {
371
+ params.topMargin = systemSafeTop;
372
+ params.bottomMargin = 0;
373
+ } else {
374
+ params.bottomMargin = systemSafeBottom;
375
+ params.topMargin = 0;
376
+ }
377
+ adView.setLayoutParams(params);
378
+ }
379
+
380
+ updateWebViewMargins();
381
+
382
+ return insets;
383
+ });
384
+ adLayout.requestApplyInsets();
385
+ }
386
+
349
387
  }
350
388
 
351
389
  private void updateWebViewMargins() {
@@ -357,31 +395,49 @@ public class BannerExecutor {
357
395
  if (lp instanceof ViewGroup.MarginLayoutParams) {
358
396
  ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) lp;
359
397
 
360
- if (isOverlapping) {
398
+ if ("top".equalsIgnoreCase(currentPosition)) {
399
+
361
400
  params.setMargins(0, 0, 0, 0);
362
- } else {
363
- if ("top".equalsIgnoreCase(currentPosition)) {
364
- params.setMargins(0, lastAdHeight, 0, 0);
401
+
402
+ if (isBannerVisible && !isOverlapping) {
403
+ float shift = (float) (lastAdHeight + systemSafeTop);
404
+ webViewView.setTranslationY(shift);
405
+
365
406
  } else {
366
- params.setMargins(0, 0, 0, lastAdHeight);
407
+ webViewView.setTranslationY(0);
408
+
367
409
  }
368
410
  }
411
+
412
+ else {
413
+
414
+ webViewView.setTranslationY(0);
415
+
416
+ if (!isBannerVisible || isOverlapping) {
417
+ params.setMargins(0, 0, 0, 0);
418
+ } else {
419
+
420
+ int finalBottom = lastAdHeight + systemSafeBottom;
421
+ params.setMargins(0, 0, 0, finalBottom);
422
+
423
+ }
424
+ }
425
+
369
426
  webViewView.setLayoutParams(params);
370
427
  webViewView.requestLayout();
371
428
  }
372
429
  }
373
430
 
374
- private void resetWebViewMargins() {
375
- if (webView == null || webView.getView() == null) return;
376
- View webViewView = webView.getView();
377
- ViewGroup.LayoutParams lp = webViewView.getLayoutParams();
431
+ private void hideBannerView() {
432
+ if (adLayout == null || adView == null) return;
433
+
434
+ isBannerVisible = false;
435
+
436
+ adView.setVisibility(View.GONE);
437
+ adLayout.setVisibility(View.GONE);
438
+
439
+ updateWebViewMargins();
378
440
 
379
- if (lp instanceof ViewGroup.MarginLayoutParams) {
380
- ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) lp;
381
- params.setMargins(0, 0, 0, 0);
382
- webViewView.setLayoutParams(params);
383
- webViewView.requestLayout();
384
- }
385
441
  }
386
442
 
387
443
  public void hideBanner(CallbackContext callbackContext) {
@@ -404,7 +460,9 @@ public class BannerExecutor {
404
460
 
405
461
  private void destroyBannerInternal() {
406
462
  if (adView != null) {
407
- resetWebViewMargins();
463
+ isBannerVisible = false;
464
+ updateWebViewMargins();
465
+
408
466
  if (adView.getParent() != null) {
409
467
  ((ViewGroup) adView.getParent()).removeView(adView);
410
468
  }
@@ -0,0 +1,34 @@
1
+ #import <Cordova/CDV.h>
2
+ #import <GoogleMobileAds/GoogleMobileAds.h>
3
+
4
+ @interface AdMobNextGen : CDVPlugin
5
+
6
+ - (void)initialize:(CDVInvokedUrlCommand*)command;
7
+
8
+ - (void)requestConsentInfo:(CDVInvokedUrlCommand*)command;
9
+ - (void)showPrivacyOptionsForm:(CDVInvokedUrlCommand*)command;
10
+ - (void)getTCData:(CDVInvokedUrlCommand*)command;
11
+ - (void)canRequestAds:(CDVInvokedUrlCommand*)command;
12
+ - (void)requestTrackingAuthorization:(CDVInvokedUrlCommand*)command;
13
+ - (void)getTrackingAuthorizationStatus:(CDVInvokedUrlCommand*)command;
14
+
15
+ - (void)createBanner:(CDVInvokedUrlCommand*)command;
16
+ - (void)showBanner:(CDVInvokedUrlCommand*)command;
17
+ - (void)hideBanner:(CDVInvokedUrlCommand*)command;
18
+ - (void)removeBanner:(CDVInvokedUrlCommand*)command;
19
+
20
+ - (void)createInterstitial:(CDVInvokedUrlCommand*)command;
21
+ - (void)showInterstitial:(CDVInvokedUrlCommand*)command;
22
+
23
+ - (void)createRewarded:(CDVInvokedUrlCommand*)command;
24
+ - (void)showRewarded:(CDVInvokedUrlCommand*)command;
25
+
26
+ - (void)loadAppOpenAd:(CDVInvokedUrlCommand*)command;
27
+ - (void)showAppOpenAd:(CDVInvokedUrlCommand*)command;
28
+
29
+ - (void)createRewardedInterstitial:(CDVInvokedUrlCommand*)command;
30
+ - (void)showRewardedInterstitial:(CDVInvokedUrlCommand*)command;
31
+
32
+ - (void)fireEvent:(NSString *)obj event:(NSString *)eventName withData:(NSString *)jsonStr;
33
+
34
+ @end