@capgo/capacitor-admob 8.1.21 → 8.2.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 (44) hide show
  1. package/CapgoCapacitorAdmob.podspec +1 -0
  2. package/Package.swift +4 -2
  3. package/README.md +327 -8
  4. package/android/build.gradle +3 -2
  5. package/android/src/main/kotlin/admob/plus/capacitor/AdMobPlusPlugin.kt +121 -0
  6. package/android/src/main/kotlin/admob/plus/capacitor/ConsentHelper.kt +140 -0
  7. package/android/src/main/kotlin/admob/plus/capacitor/Generated.kt +7 -0
  8. package/android/src/main/kotlin/admob/plus/capacitor/feed/FeedAdManager.kt +512 -0
  9. package/android/src/main/kotlin/admob/plus/core/Ad.kt +2 -4
  10. package/android/src/main/kotlin/admob/plus/core/Helper.kt +18 -1
  11. package/dist/docs.json +543 -5
  12. package/dist/esm/definitions.d.ts +284 -1
  13. package/dist/esm/definitions.js +55 -0
  14. package/dist/esm/definitions.js.map +1 -1
  15. package/dist/esm/events.d.ts +127 -0
  16. package/dist/esm/events.js +50 -0
  17. package/dist/esm/events.js.map +1 -0
  18. package/dist/esm/feed-ad.d.ts +32 -0
  19. package/dist/esm/feed-ad.js +133 -0
  20. package/dist/esm/feed-ad.js.map +1 -0
  21. package/dist/esm/index.d.ts +4 -2
  22. package/dist/esm/index.js +4 -32
  23. package/dist/esm/index.js.map +1 -1
  24. package/dist/esm/plugin-instance.d.ts +3 -0
  25. package/dist/esm/plugin-instance.js +35 -0
  26. package/dist/esm/plugin-instance.js.map +1 -0
  27. package/dist/esm/web.d.ts +11 -1
  28. package/dist/esm/web.js +40 -0
  29. package/dist/esm/web.js.map +1 -1
  30. package/dist/plugin.cjs.js +313 -31
  31. package/dist/plugin.cjs.js.map +1 -1
  32. package/dist/plugin.js +313 -31
  33. package/dist/plugin.js.map +1 -1
  34. package/ios/Sources/AdmobPlusPlugin/AdmobPlusPlugin.swift +131 -1
  35. package/ios/Sources/AdmobPlusPlugin/BannerAd.swift +6 -9
  36. package/ios/Sources/AdmobPlusPlugin/ConsentExecutor.swift +100 -0
  37. package/ios/Sources/AdmobPlusPlugin/FeedAdManager.swift +435 -0
  38. package/ios/Sources/AdmobPlusPlugin/Generated.swift +7 -0
  39. package/ios/Sources/AdmobPlusPlugin/Helper.swift +29 -0
  40. package/ios/Sources/AdmobPlusPlugin/InterstitialAd.swift +7 -13
  41. package/ios/Sources/AdmobPlusPlugin/RewardedAd.swift +13 -20
  42. package/ios/Sources/AdmobPlusPlugin/RewardedInterstitialAd.swift +13 -20
  43. package/ios/Tests/AdmobPlusPluginTests/AdmobPlusPluginTests.swift +3 -6
  44. package/package.json +2 -2
@@ -5,18 +5,27 @@ import AppTrackingTransparency
5
5
 
6
6
  @objc(AdmobPlusPlugin)
7
7
  public class AdmobPlusPlugin: CAPPlugin, CAPBridgedPlugin {
8
- private let pluginVersion: String = "8.1.21"
8
+ private let pluginVersion: String = "8.2.0"
9
9
  public let identifier = "AdmobPlusPlugin"
10
10
  public let jsName = "AdMobPlus"
11
11
  public let pluginMethods: [CAPPluginMethod] = [
12
12
  CAPPluginMethod(name: "start", returnType: CAPPluginReturnPromise),
13
13
  CAPPluginMethod(name: "configure", returnType: CAPPluginReturnPromise),
14
14
  CAPPluginMethod(name: "configRequest", returnType: CAPPluginReturnPromise),
15
+ CAPPluginMethod(name: "requestConsentInfo", returnType: CAPPluginReturnPromise),
16
+ CAPPluginMethod(name: "showConsentForm", returnType: CAPPluginReturnPromise),
17
+ CAPPluginMethod(name: "showPrivacyOptionsForm", returnType: CAPPluginReturnPromise),
15
18
  CAPPluginMethod(name: "adCreate", returnType: CAPPluginReturnPromise),
16
19
  CAPPluginMethod(name: "adIsLoaded", returnType: CAPPluginReturnPromise),
17
20
  CAPPluginMethod(name: "adLoad", returnType: CAPPluginReturnPromise),
18
21
  CAPPluginMethod(name: "adShow", returnType: CAPPluginReturnPromise),
19
22
  CAPPluginMethod(name: "adHide", returnType: CAPPluginReturnPromise),
23
+ CAPPluginMethod(name: "feedAdCreate", returnType: CAPPluginReturnPromise),
24
+ CAPPluginMethod(name: "feedAdDestroy", returnType: CAPPluginReturnPromise),
25
+ CAPPluginMethod(name: "feedAdLoad", returnType: CAPPluginReturnPromise),
26
+ CAPPluginMethod(name: "feedAdIsLoaded", returnType: CAPPluginReturnPromise),
27
+ CAPPluginMethod(name: "feedAdUpdateBounds", returnType: CAPPluginReturnPromise),
28
+ CAPPluginMethod(name: "feedAdSetAutoRefresh", returnType: CAPPluginReturnPromise),
20
29
  CAPPluginMethod(name: "trackingAuthorizationStatus", returnType: CAPPluginReturnPromise),
21
30
  CAPPluginMethod(name: "requestTrackingAuthorization", returnType: CAPPluginReturnPromise),
22
31
  CAPPluginMethod(name: "getPluginVersion", returnType: CAPPluginReturnPromise)
@@ -24,6 +33,11 @@ public class AdmobPlusPlugin: CAPPlugin, CAPBridgedPlugin {
24
33
 
25
34
  private var nextAdId = 1
26
35
  private let adManager = AdManager.shared
36
+ private lazy var consentExecutor: ConsentExecutor = {
37
+ let executor = ConsentExecutor()
38
+ executor.plugin = self
39
+ return executor
40
+ }()
27
41
 
28
42
  @objc func start(_ call: CAPPluginCall) {
29
43
  DispatchQueue.main.async {
@@ -48,6 +62,33 @@ public class AdmobPlusPlugin: CAPPlugin, CAPBridgedPlugin {
48
62
  call.resolve()
49
63
  }
50
64
 
65
+ @objc func requestConsentInfo(_ call: CAPPluginCall) {
66
+ let debugGeography = call.getInt("debugGeography") ?? 0
67
+ let testDeviceIdentifiers = call.getArray("testDeviceIdentifiers", String.self) ?? []
68
+ let tagForUnderAgeOfConsent = call.getBool("tagForUnderAgeOfConsent") ?? false
69
+
70
+ DispatchQueue.main.async {
71
+ self.consentExecutor.requestConsentInfo(
72
+ call,
73
+ debugGeography: debugGeography,
74
+ testDeviceIdentifiers: testDeviceIdentifiers,
75
+ tagForUnderAgeOfConsent: tagForUnderAgeOfConsent
76
+ )
77
+ }
78
+ }
79
+
80
+ @objc func showConsentForm(_ call: CAPPluginCall) {
81
+ DispatchQueue.main.async {
82
+ self.consentExecutor.showConsentForm(call)
83
+ }
84
+ }
85
+
86
+ @objc func showPrivacyOptionsForm(_ call: CAPPluginCall) {
87
+ DispatchQueue.main.async {
88
+ self.consentExecutor.showPrivacyOptionsForm(call)
89
+ }
90
+ }
91
+
51
92
  @objc func configRequest(_ call: CAPPluginCall) {
52
93
  let requestConfiguration = MobileAds.shared.requestConfiguration
53
94
 
@@ -193,6 +234,95 @@ public class AdmobPlusPlugin: CAPPlugin, CAPBridgedPlugin {
193
234
  }
194
235
  }
195
236
 
237
+ @objc func feedAdCreate(_ call: CAPPluginCall) {
238
+ guard let adUnitId = call.getString("adUnitId") else {
239
+ call.reject("adUnitId is required")
240
+ return
241
+ }
242
+ guard let format = call.getString("format") else {
243
+ call.reject("format is required")
244
+ return
245
+ }
246
+ let positionKey = call.getString("positionKey")
247
+ let autoRefreshMs = call.getInt("autoRefreshMs")
248
+ var nativeStyle: [String: String] = [:]
249
+ if let styleObj = call.getObject("nativeStyle") {
250
+ for (key, value) in styleObj {
251
+ if let str = value as? String {
252
+ nativeStyle[key] = str
253
+ }
254
+ }
255
+ }
256
+ DispatchQueue.main.async {
257
+ let id = FeedAdManager.shared.create(
258
+ format: format,
259
+ adUnitId: adUnitId,
260
+ positionKey: positionKey,
261
+ autoRefreshMs: autoRefreshMs,
262
+ nativeStyle: nativeStyle,
263
+ plugin: self
264
+ )
265
+ call.resolve(["id": id])
266
+ }
267
+ }
268
+
269
+ @objc func feedAdDestroy(_ call: CAPPluginCall) {
270
+ guard let id = call.getInt("id") else {
271
+ call.reject("id is required")
272
+ return
273
+ }
274
+ DispatchQueue.main.async {
275
+ FeedAdManager.shared.destroy(id: id)
276
+ call.resolve()
277
+ }
278
+ }
279
+
280
+ @objc func feedAdLoad(_ call: CAPPluginCall) {
281
+ guard let id = call.getInt("id") else {
282
+ call.reject("id is required")
283
+ return
284
+ }
285
+ FeedAdManager.shared.load(id: id) { error in
286
+ if let error = error {
287
+ call.reject("Failed to load feed ad: \(error.localizedDescription)")
288
+ } else {
289
+ call.resolve()
290
+ }
291
+ }
292
+ }
293
+
294
+ @objc func feedAdIsLoaded(_ call: CAPPluginCall) {
295
+ guard let id = call.getInt("id") else {
296
+ call.reject("id is required")
297
+ return
298
+ }
299
+ call.resolve(["value": FeedAdManager.shared.isLoaded(id: id)])
300
+ }
301
+
302
+ @objc func feedAdUpdateBounds(_ call: CAPPluginCall) {
303
+ guard let id = call.getInt("id") else {
304
+ call.reject("id is required")
305
+ return
306
+ }
307
+ let x = call.getDouble("x") ?? 0
308
+ let y = call.getDouble("y") ?? 0
309
+ let width = call.getDouble("width") ?? 0
310
+ let height = call.getDouble("height") ?? 0
311
+ let visible = call.getBool("visible") ?? false
312
+ FeedAdManager.shared.updateBounds(id: id, x: x, y: y, width: width, height: height, visible: visible)
313
+ call.resolve()
314
+ }
315
+
316
+ @objc func feedAdSetAutoRefresh(_ call: CAPPluginCall) {
317
+ guard let id = call.getInt("id") else {
318
+ call.reject("id is required")
319
+ return
320
+ }
321
+ let autoRefreshMs = call.getInt("autoRefreshMs")
322
+ FeedAdManager.shared.setAutoRefresh(id: id, autoRefreshMs: autoRefreshMs)
323
+ call.resolve()
324
+ }
325
+
196
326
  @objc func adHide(_ call: CAPPluginCall) {
197
327
  guard let adId = call.getInt("id") else {
198
328
  call.reject("id is required")
@@ -115,29 +115,26 @@ class BannerAd: NSObject, Ad {
115
115
 
116
116
  extension BannerAd: BannerViewDelegate {
117
117
  func bannerViewDidReceiveAd(_ bannerView: BannerView) {
118
- plugin?.notifyListeners(Events.bannerLoad, data: ["id": id])
118
+ plugin?.notifyAdListeners(Events.bannerLoad, adId: id)
119
119
  }
120
120
 
121
121
  func bannerView(_ bannerView: BannerView, didFailToReceiveAdWithError error: Error) {
122
- plugin?.notifyListeners(Events.bannerLoadFail, data: [
123
- "id": id,
124
- "error": error.localizedDescription
125
- ])
122
+ plugin?.notifyAdFailureListeners(Events.bannerLoadFail, adId: id, error: error)
126
123
  }
127
124
 
128
125
  func bannerViewDidRecordImpression(_ bannerView: BannerView) {
129
- plugin?.notifyListeners(Events.bannerImpression, data: ["id": id])
126
+ plugin?.notifyAdListeners(Events.bannerImpression, adId: id)
130
127
  }
131
128
 
132
129
  func bannerViewWillPresentScreen(_ bannerView: BannerView) {
133
- plugin?.notifyListeners(Events.bannerOpen, data: ["id": id])
130
+ plugin?.notifyAdListeners(Events.bannerOpen, adId: id)
134
131
  }
135
132
 
136
133
  func bannerViewWillDismissScreen(_ bannerView: BannerView) {
137
- plugin?.notifyListeners(Events.bannerClose, data: ["id": id])
134
+ plugin?.notifyAdListeners(Events.bannerClose, adId: id)
138
135
  }
139
136
 
140
137
  func bannerViewDidRecordClick(_ bannerView: BannerView) {
141
- plugin?.notifyListeners(Events.bannerClick, data: ["id": id])
138
+ plugin?.notifyAdListeners(Events.bannerClick, adId: id)
142
139
  }
143
140
  }
@@ -0,0 +1,100 @@
1
+ import Foundation
2
+ import Capacitor
3
+ import GoogleMobileAds
4
+ import UserMessagingPlatform
5
+
6
+ class ConsentExecutor: NSObject {
7
+ weak var plugin: AdmobPlusPlugin?
8
+
9
+ func requestConsentInfo(_ call: CAPPluginCall, debugGeography: Int, testDeviceIdentifiers: [String], tagForUnderAgeOfConsent: Bool) {
10
+ let parameters = RequestParameters()
11
+ let debugSettings = DebugSettings()
12
+
13
+ debugSettings.geography = DebugGeography(rawValue: debugGeography) ?? DebugGeography.disabled
14
+ debugSettings.testDeviceIdentifiers = testDeviceIdentifiers
15
+
16
+ parameters.debugSettings = debugSettings
17
+ parameters.isTaggedForUnderAgeOfConsent = tagForUnderAgeOfConsent
18
+
19
+ ConsentInformation.shared.requestConsentInfoUpdate(with: parameters) { error in
20
+ if let error = error {
21
+ call.reject(error.localizedDescription)
22
+ } else {
23
+ call.resolve(self.buildConsentInfo(includeFormAvailability: true))
24
+ }
25
+ }
26
+ }
27
+
28
+ @MainActor
29
+ func showPrivacyOptionsForm(_ call: CAPPluginCall) {
30
+ guard let rootViewController = plugin?.bridge?.viewController else {
31
+ call.reject("No ViewController")
32
+ return
33
+ }
34
+
35
+ Task {
36
+ do {
37
+ try await ConsentForm.presentPrivacyOptionsForm(from: rootViewController)
38
+ call.resolve()
39
+ } catch {
40
+ call.reject("Failed to show privacy options form: \(error.localizedDescription)")
41
+ }
42
+ }
43
+ }
44
+
45
+ func showConsentForm(_ call: CAPPluginCall) {
46
+ guard let rootViewController = plugin?.bridge?.viewController else {
47
+ call.reject("No ViewController")
48
+ return
49
+ }
50
+
51
+ Task { @MainActor in
52
+ do {
53
+ try await ConsentForm.loadAndPresentIfRequired(from: rootViewController)
54
+ call.resolve(self.buildConsentInfo(includeFormAvailability: false))
55
+ } catch {
56
+ call.reject("Error when show consent form: \(error.localizedDescription)")
57
+ }
58
+ }
59
+ }
60
+
61
+ private func buildConsentInfo(includeFormAvailability: Bool) -> [String: Any] {
62
+ var result: [String: Any] = [
63
+ "status": getConsentStatusString(ConsentInformation.shared.consentStatus),
64
+ "canRequestAds": ConsentInformation.shared.canRequestAds,
65
+ "privacyOptionsRequirementStatus": getPrivacyOptionsRequirementStatus(
66
+ ConsentInformation.shared.privacyOptionsRequirementStatus
67
+ ),
68
+ ]
69
+
70
+ if includeFormAvailability {
71
+ result["isConsentFormAvailable"] = ConsentInformation.shared.formStatus == FormStatus.available
72
+ }
73
+
74
+ return result
75
+ }
76
+
77
+ private func getConsentStatusString(_ consentStatus: ConsentStatus) -> String {
78
+ switch consentStatus {
79
+ case ConsentStatus.required:
80
+ return "REQUIRED"
81
+ case ConsentStatus.notRequired:
82
+ return "NOT_REQUIRED"
83
+ case ConsentStatus.obtained:
84
+ return "OBTAINED"
85
+ default:
86
+ return "UNKNOWN"
87
+ }
88
+ }
89
+
90
+ private func getPrivacyOptionsRequirementStatus(_ requirementStatus: PrivacyOptionsRequirementStatus) -> String {
91
+ switch requirementStatus {
92
+ case PrivacyOptionsRequirementStatus.required:
93
+ return "REQUIRED"
94
+ case PrivacyOptionsRequirementStatus.notRequired:
95
+ return "NOT_REQUIRED"
96
+ default:
97
+ return "UNKNOWN"
98
+ }
99
+ }
100
+ }