@ququplay/admob 7.0.2 → 7.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.
Files changed (42) hide show
  1. package/Package.swift +4 -2
  2. package/QuquplayAdmob.podspec +2 -1
  3. package/README.md +90 -39
  4. package/android/build.gradle +15 -14
  5. package/android/src/main/java/com/getcapacitor/community/admob/AdMob.java +5 -0
  6. package/android/src/main/java/com/getcapacitor/community/admob/banner/BannerExecutor.java +19 -0
  7. package/android/src/main/java/com/getcapacitor/community/admob/consent/AdConsentExecutor.java +92 -23
  8. package/android/src/main/java/com/getcapacitor/community/admob/interstitial/AdInterstitialExecutor.java +1 -1
  9. package/android/src/main/java/com/getcapacitor/community/admob/interstitial/InterstitialAdCallbackAndListeners.kt +2 -0
  10. package/android/src/main/java/com/getcapacitor/community/admob/rewarded/AdRewardExecutor.java +1 -1
  11. package/android/src/main/java/com/getcapacitor/community/admob/rewarded/RewardedAdCallbackAndListeners.kt +3 -0
  12. package/android/src/main/java/com/getcapacitor/community/admob/rewardedinterstitial/AdRewardInterstitialExecutor.java +1 -1
  13. package/dist/docs.json +422 -101
  14. package/dist/esm/consent/consent-debug-geography.enum.d.ts +10 -1
  15. package/dist/esm/consent/consent-debug-geography.enum.js +9 -0
  16. package/dist/esm/consent/consent-debug-geography.enum.js.map +1 -1
  17. package/dist/esm/consent/consent-definition.interface.d.ts +7 -0
  18. package/dist/esm/consent/consent-info.interface.d.ts +11 -0
  19. package/dist/esm/consent/privacy-options-requirement-status.enum.d.ts +19 -0
  20. package/dist/esm/consent/privacy-options-requirement-status.enum.js +21 -0
  21. package/dist/esm/consent/privacy-options-requirement-status.enum.js.map +1 -0
  22. package/dist/esm/definitions.d.ts +0 -1
  23. package/dist/esm/definitions.js.map +1 -1
  24. package/dist/esm/shared/ad-options.interface.d.ts +11 -0
  25. package/dist/esm/web.d.ts +1 -0
  26. package/dist/esm/web.js +8 -0
  27. package/dist/esm/web.js.map +1 -1
  28. package/dist/plugin.cjs.js +37 -0
  29. package/dist/plugin.cjs.js.map +1 -1
  30. package/dist/plugin.js +37 -0
  31. package/dist/plugin.js.map +1 -1
  32. package/ios/Sources/AdMobPlugin/AdMobPlugin.swift +23 -14
  33. package/ios/Sources/AdMobPlugin/Banner/BannerExecutor.swift +45 -46
  34. package/ios/Sources/AdMobPlugin/Consent/ConsentExecutor.swift +101 -43
  35. package/ios/Sources/AdMobPlugin/Interstitial/AdInterstitialExecutor.swift +9 -9
  36. package/ios/Sources/AdMobPlugin/Rewarded/AdRewardExecutor.swift +11 -11
  37. package/ios/Sources/AdMobPlugin/RewardedInterstitial/AdRewardInterstitialExecutor.swift +11 -11
  38. package/package.json +3 -3
  39. package/android/src/main/res/layout/bridge_layout_main.xml +0 -15
  40. package/android/src/main/res/values/colors.xml +0 -3
  41. package/android/src/main/res/values/strings.xml +0 -2
  42. package/android/src/main/res/values/styles.xml +0 -3
@@ -13,6 +13,7 @@ public class AdMobPlugin: CAPPlugin, CAPBridgedPlugin {
13
13
  CAPPluginMethod(name: "initialize", returnType: CAPPluginReturnPromise),
14
14
  CAPPluginMethod(name: "trackingAuthorizationStatus", returnType: CAPPluginReturnPromise),
15
15
  CAPPluginMethod(name: "requestConsentInfo", returnType: CAPPluginReturnPromise),
16
+ CAPPluginMethod(name: "showPrivacyOptionsForm", returnType: CAPPluginReturnPromise),
16
17
  CAPPluginMethod(name: "requestTrackingAuthorization", returnType: CAPPluginReturnPromise),
17
18
  CAPPluginMethod(name: "showConsentForm", returnType: CAPPluginReturnPromise),
18
19
  CAPPluginMethod(name: "resetConsentInfo", returnType: CAPPluginReturnPromise),
@@ -25,7 +26,9 @@ public class AdMobPlugin: CAPPlugin, CAPBridgedPlugin {
25
26
  CAPPluginMethod(name: "prepareInterstitial", returnType: CAPPluginReturnPromise),
26
27
  CAPPluginMethod(name: "showInterstitial", returnType: CAPPluginReturnPromise),
27
28
  CAPPluginMethod(name: "prepareRewardVideoAd", returnType: CAPPluginReturnPromise),
28
- CAPPluginMethod(name: "showRewardVideoAd", returnType: CAPPluginReturnPromise)
29
+ CAPPluginMethod(name: "showRewardVideoAd", returnType: CAPPluginReturnPromise),
30
+ CAPPluginMethod(name: "prepareRewardInterstitialAd", returnType: CAPPluginReturnPromise),
31
+ CAPPluginMethod(name: "showRewardInterstitialAd", returnType: CAPPluginReturnPromise)
29
32
  ]
30
33
 
31
34
  var testingDevices: [String] = []
@@ -49,7 +52,7 @@ public class AdMobPlugin: CAPPlugin, CAPBridgedPlugin {
49
52
  self.consentExecutor.plugin = self
50
53
  self.setRequestConfiguration(call)
51
54
 
52
- GADMobileAds.sharedInstance().start(completionHandler: nil)
55
+ MobileAds.shared.start(completionHandler: nil)
53
56
  call.resolve([:])
54
57
  }
55
58
 
@@ -72,7 +75,7 @@ public class AdMobPlugin: CAPPlugin, CAPBridgedPlugin {
72
75
 
73
76
  @objc func setApplicationMuted(_ call: CAPPluginCall) {
74
77
  if let shouldMute = call.getBool("muted") {
75
- GADMobileAds.sharedInstance().applicationMuted = shouldMute
78
+ MobileAds.shared.isApplicationMuted = shouldMute
76
79
  call.resolve([:])
77
80
  } else {
78
81
  call.reject("muted property cannot be null")
@@ -85,7 +88,7 @@ public class AdMobPlugin: CAPPlugin, CAPBridgedPlugin {
85
88
  // Clamp volumes.
86
89
  if volume < 0.0 {volume = 0.0} else if volume > 1.0 {volume = 1.0}
87
90
 
88
- GADMobileAds.sharedInstance().applicationVolume = volume
91
+ MobileAds.shared.applicationVolume = volume
89
92
 
90
93
  call.resolve([:])
91
94
  } else {
@@ -237,6 +240,12 @@ public class AdMobPlugin: CAPPlugin, CAPBridgedPlugin {
237
240
  }
238
241
  }
239
242
 
243
+ @objc func showPrivacyOptionsForm(_ call: CAPPluginCall) {
244
+ DispatchQueue.main.async {
245
+ self.consentExecutor.showPrivacyOptionsForm(call)
246
+ }
247
+ }
248
+
240
249
  @objc func resetConsentInfo(_ call: CAPPluginCall) {
241
250
  DispatchQueue.main.async {
242
251
  self.consentExecutor.resetConsentInfo(call)
@@ -252,11 +261,11 @@ public class AdMobPlugin: CAPPlugin, CAPBridgedPlugin {
252
261
  return adUnitID
253
262
  }
254
263
 
255
- private func GADRequestWithOption(_ npa: Bool) -> GADRequest {
256
- let request = GADRequest()
264
+ private func GADRequestWithOption(_ npa: Bool) -> Request {
265
+ let request = Request()
257
266
 
258
267
  if npa {
259
- let extras = GADExtras()
268
+ let extras = Extras()
260
269
  extras.additionalParameters = ["npa": "1"]
261
270
  request.register(extras)
262
271
  }
@@ -270,30 +279,30 @@ public class AdMobPlugin: CAPPlugin, CAPBridgedPlugin {
270
279
  private func setRequestConfiguration(_ call: CAPPluginCall) {
271
280
 
272
281
  if call.getBool("initializeForTesting") ?? false {
273
- GADMobileAds.sharedInstance().requestConfiguration.testDeviceIdentifiers = call.getArray("testingDevices", String.self) ?? []
282
+ MobileAds.shared.requestConfiguration.testDeviceIdentifiers = call.getArray("testingDevices", String.self) ?? []
274
283
  }
275
284
 
276
285
  if call.getBool("tagForChildDirectedTreatment") == true {
277
- GADMobileAds.sharedInstance().requestConfiguration.tagForChildDirectedTreatment = true
286
+ MobileAds.shared.requestConfiguration.tagForChildDirectedTreatment = true
278
287
  }
279
288
 
280
289
  if call.getBool("tagForUnderAgeOfConsent") == true {
281
- GADMobileAds.sharedInstance().requestConfiguration.tagForUnderAgeOfConsent = true
290
+ MobileAds.shared.requestConfiguration.tagForUnderAgeOfConsent = true
282
291
  }
283
292
 
284
293
  if call.getString("maxAdContentRating") != nil {
285
294
  switch call.getString("maxAdContentRating") {
286
295
  case "General":
287
- GADMobileAds.sharedInstance().requestConfiguration.maxAdContentRating =
296
+ MobileAds.shared.requestConfiguration.maxAdContentRating =
288
297
  GADMaxAdContentRating.general
289
298
  case "ParentalGuidance":
290
- GADMobileAds.sharedInstance().requestConfiguration.maxAdContentRating =
299
+ MobileAds.shared.requestConfiguration.maxAdContentRating =
291
300
  GADMaxAdContentRating.parentalGuidance
292
301
  case "Teen":
293
- GADMobileAds.sharedInstance().requestConfiguration.maxAdContentRating =
302
+ MobileAds.shared.requestConfiguration.maxAdContentRating =
294
303
  GADMaxAdContentRating.teen
295
304
  case "MatureAudience":
296
- GADMobileAds.sharedInstance().requestConfiguration.maxAdContentRating =
305
+ MobileAds.shared.requestConfiguration.maxAdContentRating =
297
306
  GADMaxAdContentRating.matureAudience
298
307
  default:
299
308
  print("maxAdContentRating can't find value")
@@ -2,34 +2,36 @@ import Foundation
2
2
  import Capacitor
3
3
  import GoogleMobileAds
4
4
 
5
- class BannerExecutor: NSObject, GADBannerViewDelegate {
5
+ class BannerExecutor: NSObject, BannerViewDelegate {
6
6
  weak var plugin: AdMobPlugin?
7
- var bannerView: GADBannerView!
7
+ var bannerView: BannerView!
8
+ var adPosition: String = ""
9
+ var Margin: Int = 0
8
10
 
9
- func showBanner(_ call: CAPPluginCall, _ request: GADRequest, _ adUnitID: String) {
11
+ func showBanner(_ call: CAPPluginCall, _ request: Request, _ adUnitID: String) {
10
12
  if let rootViewController = plugin?.getRootVC() {
11
13
 
12
14
  let adSize = call.getString("adSize") ?? "ADAPTIVE_BANNER"
13
15
  let adPosition = call.getString("position") ?? "BOTTOM_CENTER"
14
16
  let adMargin = call.getInt("margin") ?? 0
15
17
 
16
- var bannerSize: GADAdSize
18
+ var bannerSize: AdSize
17
19
 
18
20
  switch adSize {
19
21
  case "BANNER":
20
- bannerSize = GADAdSizeBanner
22
+ bannerSize = AdSizeBanner
21
23
  break
22
24
  case "LARGE_BANNER":
23
- bannerSize = GADAdSizeLargeBanner
25
+ bannerSize = AdSizeLargeBanner
24
26
  break
25
27
  case "FULL_BANNER":
26
- bannerSize = GADAdSizeFullBanner
28
+ bannerSize = AdSizeFullBanner
27
29
  break
28
30
  case "LEADERBOARD":
29
- bannerSize = GADAdSizeLeaderboard
31
+ bannerSize = AdSizeLeaderboard
30
32
  break
31
33
  case "MEDIUM_RECTANGLE":
32
- bannerSize = GADAdSizeMediumRectangle
34
+ bannerSize = AdSizeMediumRectangle
33
35
  break
34
36
  case "SMART_BANNER":
35
37
  bannerSize = kGADAdSizeSmartBannerPortrait
@@ -38,18 +40,14 @@ class BannerExecutor: NSObject, GADBannerViewDelegate {
38
40
  let frame = { () -> CGRect in
39
41
  // Here safe area is taken into account, hence the view frame is used
40
42
  // after the view has been laid out.
41
- if #available(iOS 11.0, *) {
42
- return rootViewController.view.frame.inset(by: rootViewController.view.safeAreaInsets)
43
- } else {
44
- return rootViewController.view.frame
45
- }
43
+ return rootViewController.view.frame.inset(by: rootViewController.view.safeAreaInsets)
46
44
  }()
47
45
  let viewWidth = frame.size.width
48
- bannerSize = GADCurrentOrientationAnchoredAdaptiveBannerAdSizeWithWidth(viewWidth)
46
+ bannerSize = currentOrientationAnchoredAdaptiveBanner(width: viewWidth)
49
47
  break
50
48
  }
51
49
 
52
- self.bannerView = GADBannerView(adSize: bannerSize)
50
+ self.bannerView = BannerView(adSize: bannerSize)
53
51
  self.addBannerViewToView(self.bannerView, adPosition, adMargin)
54
52
  self.bannerView.translatesAutoresizingMaskIntoConstraints = false
55
53
  self.bannerView.adUnitID = adUnitID
@@ -107,21 +105,37 @@ class BannerExecutor: NSObject, GADBannerViewDelegate {
107
105
  call.resolve([:])
108
106
  }
109
107
 
110
- private func addBannerViewToView(_ bannerView: GADBannerView, _ adPosition: String, _ Margin: Int) {
108
+ private func addBannerViewToView(_ bannerView: BannerView, _ adPosition: String, _ Margin: Int) {
111
109
  removeBannerViewToView()
110
+ bannerView.translatesAutoresizingMaskIntoConstraints = false
111
+ bannerView.tag = 2743243288699 // rand
112
+ self.Margin = Margin
113
+ self.adPosition = adPosition
114
+ }
115
+
116
+ private func removeBannerViewToView() {
112
117
  if let rootViewController = plugin?.getRootVC() {
118
+ if let subView = rootViewController.view.viewWithTag(2743243288699) {
119
+ bannerView.delegate = nil
120
+ NSLog("AdMob: find subView")
121
+ subView.removeFromSuperview()
122
+ }
123
+ }
124
+ }
113
125
 
114
- bannerView.translatesAutoresizingMaskIntoConstraints = false
115
- bannerView.tag = 2743243288699 // rand
126
+ /// Tells the delegate an ad request loaded an ad.
127
+ func bannerViewDidReceiveAd(_ bannerView: BannerView) {
128
+ NSLog("bannerViewDidReceiveAd")
129
+ if let rootViewController = plugin?.getRootVC() {
116
130
  rootViewController.view.addSubview(bannerView)
117
131
  rootViewController.view.addConstraints(
118
132
  [NSLayoutConstraint(item: bannerView,
119
- attribute: adPosition == "TOP_CENTER" ? .top : .bottom,
133
+ attribute: self.adPosition == "TOP_CENTER" ? .top : .bottom,
120
134
  relatedBy: .equal,
121
135
  toItem: rootViewController.view.safeAreaLayoutGuide,
122
- attribute: adPosition == "TOP_CENTER" ? .top : .bottom,
136
+ attribute: self.adPosition == "TOP_CENTER" ? .top : .bottom,
123
137
  multiplier: 1,
124
- constant: CGFloat(Int(Margin) * -1)),
138
+ constant: CGFloat(Int(self.Margin) * -1)),
125
139
  NSLayoutConstraint(item: bannerView,
126
140
  attribute: .centerX,
127
141
  relatedBy: .equal,
@@ -130,32 +144,17 @@ class BannerExecutor: NSObject, GADBannerViewDelegate {
130
144
  multiplier: 1,
131
145
  constant: 0)
132
146
  ])
133
- }
134
- }
147
+ self.plugin?.notifyListeners(BannerAdPluginEvents.SizeChanged.rawValue, data: [
148
+ "width": bannerView.frame.width,
149
+ "height": bannerView.frame.height
150
+ ])
151
+ self.plugin?.notifyListeners(BannerAdPluginEvents.Loaded.rawValue, data: [:])
135
152
 
136
- private func removeBannerViewToView() {
137
- if let rootViewController = plugin?.getRootVC() {
138
- if let subView = rootViewController.view.viewWithTag(2743243288699) {
139
- bannerView.delegate = nil
140
- NSLog("AdMob: find subView")
141
- subView.removeFromSuperview()
142
- }
143
153
  }
144
154
  }
145
155
 
146
- /// Tells the delegate an ad request loaded an ad.
147
- func bannerViewDidReceiveAd(_ bannerView: GADBannerView) {
148
- NSLog("bannerViewDidReceiveAd")
149
-
150
- self.plugin?.notifyListeners(BannerAdPluginEvents.SizeChanged.rawValue, data: [
151
- "width": bannerView.frame.width,
152
- "height": bannerView.frame.height
153
- ])
154
- self.plugin?.notifyListeners(BannerAdPluginEvents.Loaded.rawValue, data: [:])
155
- }
156
-
157
156
  /// Tells the delegate an ad request failed.
158
- func bannerView(_ bannerView: GADBannerView,
157
+ func bannerView(_ bannerView: BannerView,
159
158
  didFailToReceiveAdWithError error: Error) {
160
159
  NSLog("bannerView:didFailToReceiveAdWithError: \(error.localizedDescription)")
161
160
  self.removeBannerViewToView()
@@ -169,18 +168,18 @@ class BannerExecutor: NSObject, GADBannerViewDelegate {
169
168
  ])
170
169
  }
171
170
 
172
- func bannerViewDidRecordImpression(_ bannerView: GADBannerView) {
171
+ func bannerViewDidRecordImpression(_ bannerView: BannerView) {
173
172
  self.plugin?.notifyListeners(BannerAdPluginEvents.AdImpression.rawValue, data: [:])
174
173
  }
175
174
 
176
175
  /// Tells the delegate that a full-screen view will be presented in response
177
176
  /// to the user clicking on an ad.
178
- func bannerViewWillPresentScreen(_ bannerView: GADBannerView) {
177
+ func bannerViewWillPresentScreen(_ bannerView: BannerView) {
179
178
  self.plugin?.notifyListeners(BannerAdPluginEvents.Opened.rawValue, data: [:])
180
179
  }
181
180
 
182
181
  /// Tells the delegate that the full-screen view will be dismissed.
183
- func bannerViewWillDismissScreen(_ bannerView: GADBannerView) {
182
+ func bannerViewWillDismissScreen(_ bannerView: BannerView) {
184
183
  self.plugin?.notifyListeners(BannerAdPluginEvents.Closed.rawValue, data: [:])
185
184
  }
186
185
  }
@@ -7,76 +7,88 @@ class ConsentExecutor: NSObject {
7
7
  weak var plugin: AdMobPlugin?
8
8
 
9
9
  func requestConsentInfo(_ call: CAPPluginCall, _ debugGeography: Int, _ testDeviceIdentifiers: [String], _ tagForUnderAgeOfConsent: Bool) {
10
- let parameters = UMPRequestParameters()
11
- let debugSettings = UMPDebugSettings()
10
+ let parameters = RequestParameters()
11
+ let debugSettings = DebugSettings()
12
12
 
13
- debugSettings.geography = UMPDebugGeography(rawValue: debugGeography) ?? UMPDebugGeography.disabled
13
+ debugSettings.geography = DebugGeography(rawValue: debugGeography) ?? DebugGeography.disabled
14
14
  debugSettings.testDeviceIdentifiers = testDeviceIdentifiers
15
15
 
16
16
  parameters.debugSettings = debugSettings
17
- parameters.tagForUnderAgeOfConsent = tagForUnderAgeOfConsent
17
+ parameters.isTaggedForUnderAgeOfConsent = tagForUnderAgeOfConsent
18
18
 
19
19
  // Request an update to the consent information.
20
- UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(
20
+ ConsentInformation.shared.requestConsentInfoUpdate(
21
21
  with: parameters,
22
22
  completionHandler: { error in
23
23
  if error != nil {
24
24
  call.reject("Request consent info failed")
25
25
  } else {
26
- call.resolve([
27
- "status": self.getConsentStatusString(UMPConsentInformation.sharedInstance.consentStatus),
28
- "isConsentFormAvailable": UMPConsentInformation.sharedInstance.formStatus == UMPFormStatus.available,
29
- "canShowAds": self.canShowAds(),
30
- "canShowPersonalizedAds": self.canShowPersonalizedAds()
31
- ])
26
+ call.resolve(self.getConsentInfoDictionary())
32
27
  }
33
28
  })
34
29
  }
35
30
 
31
+ @MainActor
32
+ func showPrivacyOptionsForm(_ call: CAPPluginCall) {
33
+ guard let rootViewController = plugin?.getRootVC() else {
34
+ return call.reject("No ViewController")
35
+ }
36
+
37
+ Task {
38
+ do {
39
+ try await ConsentForm.presentPrivacyOptionsForm(from: rootViewController)
40
+ call.resolve()
41
+ } catch {
42
+ call.reject("Failed to show privacy options form: \(error.localizedDescription)")
43
+ }
44
+ }
45
+ }
46
+
47
+ @MainActor
36
48
  func showConsentForm(_ call: CAPPluginCall) {
37
- if let rootViewController = plugin?.getRootVC() {
38
- let formStatus = UMPConsentInformation.sharedInstance.formStatus
39
-
40
- if formStatus == UMPFormStatus.available {
41
- UMPConsentForm.load(completionHandler: {form, loadError in
42
- if loadError != nil {
43
- call.reject(loadError?.localizedDescription ?? "Load consent form error")
44
- return
45
- }
46
-
47
- form?.present(from: rootViewController, completionHandler: { dismissError in
48
- if dismissError != nil {
49
- call.reject(dismissError?.localizedDescription ?? "Consent dismiss error")
50
- return
51
- }
52
-
53
- call.resolve([
54
- "status": self.getConsentStatusString(UMPConsentInformation.sharedInstance.consentStatus),
55
- "canShowAds": self.canShowAds(),
56
- "canShowPersonalizedAds": self.canShowPersonalizedAds()
57
- ])
58
- })
59
- })
60
- } else {
61
- call.reject("Consent Form not available")
49
+ guard let rootViewController = plugin?.getRootVC() else {
50
+ return call.reject("No ViewController")
51
+ }
52
+
53
+ guard ConsentInformation.shared.formStatus == FormStatus.available else {
54
+ return call.reject("Consent Form not available")
55
+ }
56
+
57
+ Task {
58
+ do {
59
+ let form = try await ConsentForm.load()
60
+ try await form.present(from: rootViewController)
61
+ call.resolve(getConsentInfoDictionary())
62
+ } catch {
63
+ call.reject("Request consent info failed")
62
64
  }
63
- } else {
64
- call.reject("No ViewController")
65
65
  }
66
66
  }
67
67
 
68
68
  func resetConsentInfo(_ call: CAPPluginCall) {
69
- UMPConsentInformation.sharedInstance.reset()
69
+ ConsentInformation.shared.reset()
70
70
  call.resolve()
71
71
  }
72
72
 
73
- func getConsentStatusString(_ consentStatus: UMPConsentStatus) -> String {
73
+ private func getConsentInfoDictionary() -> [String: Any] {
74
+ return [
75
+ "status": getConsentStatusString(ConsentInformation.shared.consentStatus),
76
+ "isConsentFormAvailable": ConsentInformation.shared.formStatus == FormStatus.available,
77
+ "canRequestAds": ConsentInformation.shared.canRequestAds,
78
+ "privacyOptionsRequirementStatus": getPrivacyOptionsRequirementStatus(ConsentInformation.shared.privacyOptionsRequirementStatus),
79
+ "canShowAds": canShowAds(),
80
+ "canShowPersonalizedAds": canShowPersonalizedAds(),
81
+ "isConsentOutdated": isConsentOutdated()
82
+ ]
83
+ }
84
+
85
+ func getConsentStatusString(_ consentStatus: ConsentStatus) -> String {
74
86
  switch consentStatus {
75
- case UMPConsentStatus.required:
87
+ case ConsentStatus.required:
76
88
  return "REQUIRED"
77
- case UMPConsentStatus.notRequired:
89
+ case ConsentStatus.notRequired:
78
90
  return "NOT_REQUIRED"
79
- case UMPConsentStatus.obtained:
91
+ case ConsentStatus.obtained:
80
92
  return "OBTAINED"
81
93
  default:
82
94
  return "UNKNOWN"
@@ -147,4 +159,50 @@ class ConsentExecutor: NSObject {
147
159
  return hasConsentFor([1,3,4], purposeConsent, hasGoogleVendorConsent)
148
160
  && hasConsentOrLegitimateInterestFor([2,7,9,10], purposeConsent, purposeLI, hasGoogleVendorConsent, hasGoogleVendorLI)
149
161
  }
162
+
163
+ private func isConsentOutdated() -> Bool {
164
+ let settings = UserDefaults.standard
165
+ guard let tcString = settings.string(forKey: "IABTCF_TCString"), !tcString.isEmpty else {
166
+ return false
167
+ }
168
+
169
+ // base64 alphabet used to store data in IABTCF string
170
+ let base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
171
+
172
+ // date is stored in digits 1..7 of the IABTCF string
173
+ let dateSubstring = String(tcString[tcString.index(tcString.startIndex, offsetBy: 1)..<tcString.index(tcString.startIndex, offsetBy: 7)])
174
+
175
+ // interpret date substring as base64-encoded integer value
176
+ var timestamp: Int64 = 0
177
+
178
+ for char in dateSubstring {
179
+ if let value = base64.firstIndex(of: char) {
180
+ timestamp = timestamp * 64 + Int64(value.utf16Offset(in: base64))
181
+ }
182
+ }
183
+
184
+ // timestamp is given in deci-seconds, convert to milliseconds
185
+ timestamp *= 100
186
+
187
+ // compare with current timestamp to get age in days
188
+ let daysAgo = (Int64(Date().timeIntervalSince1970 * 1000) - timestamp) / (1000 * 60 * 60 * 24)
189
+
190
+ // delete TC string if age is over a year
191
+ if daysAgo > 365 {
192
+ settings.removeObject(forKey: "IABTCF_TCString")
193
+ return true
194
+ }
195
+
196
+ return false
197
+ }
198
+ func getPrivacyOptionsRequirementStatus(_ requirementStatus: PrivacyOptionsRequirementStatus) -> String {
199
+ switch requirementStatus {
200
+ case PrivacyOptionsRequirementStatus.required:
201
+ return "REQUIRED"
202
+ case PrivacyOptionsRequirementStatus.notRequired:
203
+ return "NOT_REQUIRED"
204
+ default:
205
+ return "UNKNOWN"
206
+ }
207
+ }
150
208
  }
@@ -2,13 +2,13 @@ import Foundation
2
2
  import Capacitor
3
3
  import GoogleMobileAds
4
4
 
5
- class AdInterstitialExecutor: NSObject, GADFullScreenContentDelegate {
5
+ class AdInterstitialExecutor: NSObject, FullScreenContentDelegate {
6
6
  weak var plugin: AdMobPlugin?
7
- var interstitial: GADInterstitialAd!
7
+ var interstitial: InterstitialAd!
8
8
 
9
- func prepareInterstitial(_ call: CAPPluginCall, _ request: GADRequest, _ adUnitID: String) {
10
- GADInterstitialAd.load(
11
- withAdUnitID: adUnitID,
9
+ func prepareInterstitial(_ call: CAPPluginCall, _ request: Request, _ adUnitID: String) {
10
+ InterstitialAd.load(
11
+ with: adUnitID,
12
12
  request: request,
13
13
  completionHandler: { (ad, error) in
14
14
  if let error = error {
@@ -36,7 +36,7 @@ class AdInterstitialExecutor: NSObject, GADFullScreenContentDelegate {
36
36
  func showInterstitial(_ call: CAPPluginCall) {
37
37
  if let rootViewController = plugin?.getRootVC() {
38
38
  if let ad = self.interstitial {
39
- ad.present(fromRootViewController: rootViewController)
39
+ ad.present(from: rootViewController)
40
40
  call.resolve([:])
41
41
  } else {
42
42
  NSLog("Ad wasn't ready")
@@ -45,7 +45,7 @@ class AdInterstitialExecutor: NSObject, GADFullScreenContentDelegate {
45
45
  }
46
46
  }
47
47
 
48
- func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
48
+ func ad(_ ad: FullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
49
49
  NSLog("InterstitialFullScreenDelegate Ad failed to present full screen content with error \(error.localizedDescription).")
50
50
  self.plugin?.notifyListeners(InterstitialAdPluginEvents.FailedToShow.rawValue, data: [
51
51
  "code": 0,
@@ -53,12 +53,12 @@ class AdInterstitialExecutor: NSObject, GADFullScreenContentDelegate {
53
53
  ])
54
54
  }
55
55
 
56
- func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
56
+ func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) {
57
57
  NSLog("InterstitialFullScreenDelegate Ad did present full screen content.")
58
58
  self.plugin?.notifyListeners(InterstitialAdPluginEvents.Showed.rawValue, data: [:])
59
59
  }
60
60
 
61
- func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
61
+ func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) {
62
62
  NSLog("InterstitialFullScreenDelegate Ad did dismiss full screen content.")
63
63
  self.plugin?.notifyListeners(InterstitialAdPluginEvents.Dismissed.rawValue, data: [:])
64
64
  }
@@ -2,13 +2,13 @@ import Foundation
2
2
  import Capacitor
3
3
  import GoogleMobileAds
4
4
 
5
- class AdRewardExecutor: NSObject, GADFullScreenContentDelegate {
5
+ class AdRewardExecutor: NSObject, FullScreenContentDelegate {
6
6
  weak var plugin: AdMobPlugin?
7
- var rewardedAd: GADRewardedAd!
7
+ var rewardedAd: RewardedAd!
8
8
 
9
- func prepareRewardVideoAd(_ call: CAPPluginCall, _ request: GADRequest, _ adUnitID: String) {
10
- GADRewardedAd.load(
11
- withAdUnitID: adUnitID,
9
+ func prepareRewardVideoAd(_ call: CAPPluginCall, _ request: Request, _ adUnitID: String) {
10
+ RewardedAd.load(
11
+ with: adUnitID,
12
12
  request: request,
13
13
  completionHandler: { (ad, error) in
14
14
  if let error = error {
@@ -24,11 +24,11 @@ class AdRewardExecutor: NSObject, GADFullScreenContentDelegate {
24
24
  self.rewardedAd = ad
25
25
 
26
26
  if let providedOptions = call.getObject("ssv") {
27
- let ssvOptions = GADServerSideVerificationOptions()
27
+ let ssvOptions = ServerSideVerificationOptions()
28
28
 
29
29
  if let customData = providedOptions["customData"] as? String {
30
30
  NSLog("Sending Custom Data: \(customData) to SSV callback")
31
- ssvOptions.customRewardString = customData
31
+ ssvOptions.customRewardText = customData
32
32
  }
33
33
 
34
34
  if let userId = providedOptions["userId"] as? String {
@@ -53,7 +53,7 @@ class AdRewardExecutor: NSObject, GADFullScreenContentDelegate {
53
53
  func showRewardVideoAd(_ call: CAPPluginCall) {
54
54
  if let rootViewController = plugin?.getRootVC() {
55
55
  if let ad = self.rewardedAd {
56
- ad.present(fromRootViewController: rootViewController,
56
+ ad.present(from: rootViewController,
57
57
  userDidEarnRewardHandler: {
58
58
  let reward = ad.adReward
59
59
  self.plugin?.notifyListeners(RewardAdPluginEvents.Rewarded.rawValue, data: ["type": reward.type, "amount": reward.amount])
@@ -66,7 +66,7 @@ class AdRewardExecutor: NSObject, GADFullScreenContentDelegate {
66
66
  }
67
67
  }
68
68
 
69
- func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
69
+ func ad(_ ad: FullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
70
70
  NSLog("RewardFullScreenDelegate Ad failed to present full screen content with error \(error.localizedDescription).")
71
71
  self.plugin?.notifyListeners(RewardAdPluginEvents.FailedToShow.rawValue, data: [
72
72
  "code": 0,
@@ -74,12 +74,12 @@ class AdRewardExecutor: NSObject, GADFullScreenContentDelegate {
74
74
  ])
75
75
  }
76
76
 
77
- func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
77
+ func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) {
78
78
  NSLog("RewardFullScreenDelegate Ad did present full screen content.")
79
79
  self.plugin?.notifyListeners(RewardAdPluginEvents.Showed.rawValue, data: [:])
80
80
  }
81
81
 
82
- func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
82
+ func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) {
83
83
  NSLog("RewardFullScreenDelegate Ad did dismiss full screen content.")
84
84
  self.plugin?.notifyListeners(RewardAdPluginEvents.Dismissed.rawValue, data: [:])
85
85
  }
@@ -2,13 +2,13 @@ import Foundation
2
2
  import Capacitor
3
3
  import GoogleMobileAds
4
4
 
5
- class AdRewardInterstitialExecutor: NSObject, GADFullScreenContentDelegate {
5
+ class AdRewardInterstitialExecutor: NSObject, FullScreenContentDelegate {
6
6
  weak var plugin: AdMobPlugin?
7
- var rewardedInterstitialAd: GADRewardedInterstitialAd!
7
+ var rewardedInterstitialAd: RewardedInterstitialAd!
8
8
 
9
- func prepareRewardInterstitialAd(_ call: CAPPluginCall, _ request: GADRequest, _ adUnitID: String) {
10
- GADRewardedInterstitialAd.load(
11
- withAdUnitID: adUnitID,
9
+ func prepareRewardInterstitialAd(_ call: CAPPluginCall, _ request: Request, _ adUnitID: String) {
10
+ RewardedInterstitialAd.load(
11
+ with: adUnitID,
12
12
  request: request,
13
13
  completionHandler: { (ad, error) in
14
14
  if let error = error {
@@ -24,11 +24,11 @@ class AdRewardInterstitialExecutor: NSObject, GADFullScreenContentDelegate {
24
24
  self.rewardedInterstitialAd = ad
25
25
 
26
26
  if let providedOptions = call.getObject("ssv") {
27
- let ssvOptions = GADServerSideVerificationOptions()
27
+ let ssvOptions = ServerSideVerificationOptions()
28
28
 
29
29
  if let customData = providedOptions["customData"] as? String {
30
30
  NSLog("Sending Custom Data: \(customData) to SSV callback")
31
- ssvOptions.customRewardString = customData
31
+ ssvOptions.customRewardText = customData
32
32
  }
33
33
 
34
34
  if let userId = providedOptions["userId"] as? String {
@@ -53,7 +53,7 @@ class AdRewardInterstitialExecutor: NSObject, GADFullScreenContentDelegate {
53
53
  func showRewardInterstitialAd(_ call: CAPPluginCall) {
54
54
  if let rootViewController = plugin?.getRootVC() {
55
55
  if let ad = self.rewardedInterstitialAd {
56
- ad.present(fromRootViewController: rootViewController,
56
+ ad.present(from: rootViewController,
57
57
  userDidEarnRewardHandler: {
58
58
  let reward = ad.adReward
59
59
  self.plugin?.notifyListeners(RewardInterstitialAdPluginEvents.Rewarded.rawValue, data: ["type": reward.type, "amount": reward.amount])
@@ -66,7 +66,7 @@ class AdRewardInterstitialExecutor: NSObject, GADFullScreenContentDelegate {
66
66
  }
67
67
  }
68
68
 
69
- func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
69
+ func ad(_ ad: FullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
70
70
  NSLog("RewardFullScreenDelegate Ad failed to present full screen content with error \(error.localizedDescription).")
71
71
  self.plugin?.notifyListeners(RewardInterstitialAdPluginEvents.FailedToShow.rawValue, data: [
72
72
  "code": 0,
@@ -74,12 +74,12 @@ class AdRewardInterstitialExecutor: NSObject, GADFullScreenContentDelegate {
74
74
  ])
75
75
  }
76
76
 
77
- func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
77
+ func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) {
78
78
  NSLog("RewardFullScreenDelegate Ad did present full screen content.")
79
79
  self.plugin?.notifyListeners(RewardInterstitialAdPluginEvents.Showed.rawValue, data: [:])
80
80
  }
81
81
 
82
- func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
82
+ func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) {
83
83
  NSLog("RewardFullScreenDelegate Ad did dismiss full screen content.")
84
84
  self.plugin?.notifyListeners(RewardInterstitialAdPluginEvents.Dismissed.rawValue, data: [:])
85
85
  }