@capgo/capacitor-admob 7.1.1 → 7.4.4

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.
@@ -1,26 +1,239 @@
1
1
  import Capacitor
2
2
  import Foundation
3
+ import GoogleMobileAds
4
+ import AppTrackingTransparency
3
5
 
4
6
  @objc(AdmobPlusPlugin)
5
7
  public class AdmobPlusPlugin: CAPPlugin, CAPBridgedPlugin {
6
- private let PLUGIN_VERSION: String = "7.1.1"
8
+ private let pluginVersion: String = "7.4.4"
7
9
  public let identifier = "AdmobPlusPlugin"
8
10
  public let jsName = "AdMobPlus"
9
11
  public let pluginMethods: [CAPPluginMethod] = [
10
- CAPPluginMethod(name: "echo", returnType: CAPPluginReturnPromise),
12
+ CAPPluginMethod(name: "start", returnType: CAPPluginReturnPromise),
13
+ CAPPluginMethod(name: "configure", returnType: CAPPluginReturnPromise),
14
+ CAPPluginMethod(name: "configRequest", returnType: CAPPluginReturnPromise),
15
+ CAPPluginMethod(name: "adCreate", returnType: CAPPluginReturnPromise),
16
+ CAPPluginMethod(name: "adIsLoaded", returnType: CAPPluginReturnPromise),
17
+ CAPPluginMethod(name: "adLoad", returnType: CAPPluginReturnPromise),
18
+ CAPPluginMethod(name: "adShow", returnType: CAPPluginReturnPromise),
19
+ CAPPluginMethod(name: "adHide", returnType: CAPPluginReturnPromise),
20
+ CAPPluginMethod(name: "trackingAuthorizationStatus", returnType: CAPPluginReturnPromise),
21
+ CAPPluginMethod(name: "requestTrackingAuthorization", returnType: CAPPluginReturnPromise),
11
22
  CAPPluginMethod(name: "getPluginVersion", returnType: CAPPluginReturnPromise)
12
23
  ]
13
- private let implementation = AdmobPlus()
14
24
 
15
- @objc func echo(_ call: CAPPluginCall) {
16
- let value = call.getString("value") ?? ""
17
- call.resolve([
18
- "value": implementation.echo(value)
19
- ])
25
+ private var nextAdId = 1
26
+ private let adManager = AdManager.shared
27
+
28
+ @objc func start(_ call: CAPPluginCall) {
29
+ DispatchQueue.main.async {
30
+ GADMobileAds.sharedInstance().start { _ in
31
+ call.resolve()
32
+ }
33
+ }
20
34
  }
21
35
 
22
- @objc func getPluginVersion(_ call: CAPPluginCall) {
23
- call.resolve(["version": self.PLUGIN_VERSION])
36
+ @objc func configure(_ call: CAPPluginCall) {
37
+ let appMuted = call.getBool("appMuted")
38
+ let appVolume = call.getFloat("appVolume")
39
+
40
+ if let muted = appMuted {
41
+ GADMobileAds.sharedInstance().applicationMuted = muted
42
+ }
43
+
44
+ if let volume = appVolume {
45
+ GADMobileAds.sharedInstance().applicationVolume = volume
46
+ }
47
+
48
+ call.resolve()
49
+ }
50
+
51
+ @objc func configRequest(_ call: CAPPluginCall) {
52
+ let requestConfiguration = GADMobileAds.sharedInstance().requestConfiguration
53
+
54
+ if let maxAdContentRating = call.getString("maxAdContentRating") {
55
+ switch maxAdContentRating {
56
+ case "G":
57
+ requestConfiguration.maxAdContentRating = .general
58
+ case "PG":
59
+ requestConfiguration.maxAdContentRating = .parentalGuidance
60
+ case "T":
61
+ requestConfiguration.maxAdContentRating = .teen
62
+ case "MA":
63
+ requestConfiguration.maxAdContentRating = .matureAudience
64
+ default:
65
+ break
66
+ }
67
+ }
68
+
69
+ if let tagForChildDirectedTreatment = call.getBool("tagForChildDirectedTreatment") {
70
+ requestConfiguration.tagForChildDirectedTreatment = NSNumber(value: tagForChildDirectedTreatment)
71
+ }
72
+
73
+ if let tagForUnderAgeOfConsent = call.getBool("tagForUnderAgeOfConsent") {
74
+ requestConfiguration.tagForUnderAgeOfConsent = NSNumber(value: tagForUnderAgeOfConsent)
75
+ }
76
+
77
+ if let testDeviceIds = call.getArray("testDeviceIds", String.self) {
78
+ requestConfiguration.testDeviceIdentifiers = testDeviceIds
79
+ }
80
+
81
+ call.resolve()
24
82
  }
25
83
 
84
+ @objc func adCreate(_ call: CAPPluginCall) {
85
+ guard let adUnitId = call.getString("adUnitId") else {
86
+ call.reject("adUnitId is required")
87
+ return
88
+ }
89
+
90
+ guard let adClass = call.getString("cls") else {
91
+ call.reject("cls (ad class) is required")
92
+ return
93
+ }
94
+
95
+ let adId = call.getInt("id") ?? nextAdId
96
+ nextAdId = adId + 1
97
+
98
+ let position = call.getString("position") ?? "bottom"
99
+
100
+ DispatchQueue.main.async { [weak self] in
101
+ guard let self = self else {
102
+ call.reject("Plugin instance not available")
103
+ return
104
+ }
105
+
106
+ let ad: Ad?
107
+ switch adClass {
108
+ case "BannerAd":
109
+ ad = BannerAd(id: adId, adUnitId: adUnitId, position: position, plugin: self)
110
+ case "InterstitialAd":
111
+ ad = InterstitialAd(id: adId, adUnitId: adUnitId, plugin: self)
112
+ case "RewardedAd":
113
+ ad = RewardedAd(id: adId, adUnitId: adUnitId, plugin: self)
114
+ case "RewardedInterstitialAd":
115
+ ad = RewardedInterstitialAd(id: adId, adUnitId: adUnitId, plugin: self)
116
+ default:
117
+ call.reject("Unsupported ad class: \(adClass)")
118
+ return
119
+ }
120
+
121
+ if let ad = ad {
122
+ self.adManager.addAd(ad, withId: adId)
123
+ call.resolve(["id": adId])
124
+ } else {
125
+ call.reject("Failed to create ad")
126
+ }
127
+ }
128
+ }
129
+
130
+ @objc func adIsLoaded(_ call: CAPPluginCall) {
131
+ guard let adId = call.getInt("id") else {
132
+ call.reject("id is required")
133
+ return
134
+ }
135
+
136
+ DispatchQueue.main.async { [weak self] in
137
+ guard let ad = self?.adManager.getAd(adId) else {
138
+ call.resolve(["value": false])
139
+ return
140
+ }
141
+
142
+ call.resolve(["value": ad.isLoaded])
143
+ }
144
+ }
145
+
146
+ @objc func adLoad(_ call: CAPPluginCall) {
147
+ guard let adId = call.getInt("id") else {
148
+ call.reject("id is required")
149
+ return
150
+ }
151
+
152
+ DispatchQueue.main.async { [weak self] in
153
+ guard let ad = self?.adManager.getAd(adId) else {
154
+ call.reject("Ad not found")
155
+ return
156
+ }
157
+
158
+ ad.load { error in
159
+ if let error = error {
160
+ call.reject("Failed to load ad: \(error.localizedDescription)")
161
+ } else {
162
+ call.resolve()
163
+ }
164
+ }
165
+ }
166
+ }
167
+
168
+ @objc func adShow(_ call: CAPPluginCall) {
169
+ guard let adId = call.getInt("id") else {
170
+ call.reject("id is required")
171
+ return
172
+ }
173
+
174
+ DispatchQueue.main.async { [weak self] in
175
+ guard let ad = self?.adManager.getAd(adId) else {
176
+ call.reject("Ad not found")
177
+ return
178
+ }
179
+
180
+ if !ad.isLoaded {
181
+ call.reject("Ad is not loaded")
182
+ return
183
+ }
184
+
185
+ ad.show { error in
186
+ if let error = error {
187
+ call.reject("Failed to show ad: \(error.localizedDescription)")
188
+ } else {
189
+ call.resolve()
190
+ }
191
+ }
192
+ }
193
+ }
194
+
195
+ @objc func adHide(_ call: CAPPluginCall) {
196
+ guard let adId = call.getInt("id") else {
197
+ call.reject("id is required")
198
+ return
199
+ }
200
+
201
+ DispatchQueue.main.async { [weak self] in
202
+ guard let ad = self?.adManager.getAd(adId) else {
203
+ call.reject("Ad not found")
204
+ return
205
+ }
206
+
207
+ ad.hide { error in
208
+ if let error = error {
209
+ call.reject("Failed to hide ad: \(error.localizedDescription)")
210
+ } else {
211
+ call.resolve()
212
+ }
213
+ }
214
+ }
215
+ }
216
+
217
+ @objc func trackingAuthorizationStatus(_ call: CAPPluginCall) {
218
+ if #available(iOS 14, *) {
219
+ let status = ATTrackingManager.trackingAuthorizationStatus
220
+ call.resolve(["status": status.rawValue])
221
+ } else {
222
+ call.resolve(["status": false])
223
+ }
224
+ }
225
+
226
+ @objc func requestTrackingAuthorization(_ call: CAPPluginCall) {
227
+ if #available(iOS 14, *) {
228
+ ATTrackingManager.requestTrackingAuthorization { status in
229
+ call.resolve(["status": status.rawValue])
230
+ }
231
+ } else {
232
+ call.resolve(["status": false])
233
+ }
234
+ }
235
+
236
+ @objc func getPluginVersion(_ call: CAPPluginCall) {
237
+ call.resolve(["version": self.pluginVersion])
238
+ }
26
239
  }
@@ -0,0 +1,143 @@
1
+ import Foundation
2
+ import UIKit
3
+ import GoogleMobileAds
4
+ import Capacitor
5
+
6
+ class BannerAd: NSObject, Ad {
7
+ let id: Int
8
+ let adUnitId: String
9
+ private var bannerView: GADBannerView?
10
+ private weak var plugin: AdmobPlusPlugin?
11
+ private let position: String
12
+ private var bannerContainer: UIView?
13
+
14
+ var isLoaded: Bool {
15
+ return bannerView != nil
16
+ }
17
+
18
+ init(id: Int, adUnitId: String, position: String, plugin: AdmobPlusPlugin) {
19
+ self.id = id
20
+ self.adUnitId = adUnitId
21
+ self.position = position
22
+ self.plugin = plugin
23
+ super.init()
24
+ }
25
+
26
+ func load(completion: @escaping (Error?) -> Void) {
27
+ DispatchQueue.main.async { [weak self] in
28
+ guard let self = self else { return }
29
+
30
+ if self.bannerView == nil {
31
+ let banner = GADBannerView(adSize: GADAdSizeBanner)
32
+ banner.adUnitID = self.adUnitId
33
+ banner.delegate = self
34
+ banner.rootViewController = self.plugin?.bridge?.viewController
35
+ self.bannerView = banner
36
+ }
37
+
38
+ let request = AdMobHelper.buildAdRequest()
39
+ self.bannerView?.load(request)
40
+ completion(nil)
41
+ }
42
+ }
43
+
44
+ func show(completion: @escaping (Error?) -> Void) {
45
+ DispatchQueue.main.async { [weak self] in
46
+ guard let self = self, let banner = self.bannerView else {
47
+ completion(AdMobError.adNotLoaded)
48
+ return
49
+ }
50
+
51
+ guard let webView = self.plugin?.bridge?.webView,
52
+ let viewController = self.plugin?.bridge?.viewController else {
53
+ completion(AdMobError.unknown("Unable to access view hierarchy"))
54
+ return
55
+ }
56
+
57
+ // Remove existing container if any
58
+ self.bannerContainer?.removeFromSuperview()
59
+
60
+ // Create a new container
61
+ let container = UIView()
62
+ container.translatesAutoresizingMaskIntoConstraints = false
63
+ banner.translatesAutoresizingMaskIntoConstraints = false
64
+
65
+ container.addSubview(banner)
66
+
67
+ // Add container to the view hierarchy
68
+ viewController.view.addSubview(container)
69
+
70
+ // Setup constraints
71
+ NSLayoutConstraint.activate([
72
+ container.leadingAnchor.constraint(equalTo: viewController.view.leadingAnchor),
73
+ container.trailingAnchor.constraint(equalTo: viewController.view.trailingAnchor),
74
+ container.heightAnchor.constraint(equalToConstant: 50),
75
+
76
+ banner.centerXAnchor.constraint(equalTo: container.centerXAnchor),
77
+ banner.centerYAnchor.constraint(equalTo: container.centerYAnchor)
78
+ ])
79
+
80
+ if self.position == "top" {
81
+ NSLayoutConstraint.activate([
82
+ container.topAnchor.constraint(equalTo: viewController.view.safeAreaLayoutGuide.topAnchor)
83
+ ])
84
+ } else {
85
+ NSLayoutConstraint.activate([
86
+ container.bottomAnchor.constraint(equalTo: viewController.view.safeAreaLayoutGuide.bottomAnchor)
87
+ ])
88
+ }
89
+
90
+ self.bannerContainer = container
91
+ container.isHidden = false
92
+ banner.isHidden = false
93
+
94
+ completion(nil)
95
+ }
96
+ }
97
+
98
+ func hide(completion: @escaping (Error?) -> Void) {
99
+ DispatchQueue.main.async { [weak self] in
100
+ self?.bannerContainer?.isHidden = true
101
+ self?.bannerView?.isHidden = true
102
+ completion(nil)
103
+ }
104
+ }
105
+
106
+ func destroy() {
107
+ DispatchQueue.main.async { [weak self] in
108
+ self?.bannerContainer?.removeFromSuperview()
109
+ self?.bannerView?.removeFromSuperview()
110
+ self?.bannerView = nil
111
+ self?.bannerContainer = nil
112
+ }
113
+ }
114
+ }
115
+
116
+ extension BannerAd: GADBannerViewDelegate {
117
+ func bannerViewDidReceiveAd(_ bannerView: GADBannerView) {
118
+ plugin?.notifyListeners(Events.bannerLoad, data: ["id": id])
119
+ }
120
+
121
+ func bannerView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: Error) {
122
+ plugin?.notifyListeners(Events.bannerLoadFail, data: [
123
+ "id": id,
124
+ "error": error.localizedDescription
125
+ ])
126
+ }
127
+
128
+ func bannerViewDidRecordImpression(_ bannerView: GADBannerView) {
129
+ plugin?.notifyListeners(Events.bannerImpression, data: ["id": id])
130
+ }
131
+
132
+ func bannerViewWillPresentScreen(_ bannerView: GADBannerView) {
133
+ plugin?.notifyListeners(Events.bannerOpen, data: ["id": id])
134
+ }
135
+
136
+ func bannerViewWillDismissScreen(_ bannerView: GADBannerView) {
137
+ plugin?.notifyListeners(Events.bannerClose, data: ["id": id])
138
+ }
139
+
140
+ func bannerViewDidRecordClick(_ bannerView: GADBannerView) {
141
+ plugin?.notifyListeners(Events.bannerClick, data: ["id": id])
142
+ }
143
+ }
@@ -0,0 +1,40 @@
1
+ // THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2
+ import Foundation
3
+
4
+ struct Events {
5
+ static let adClick = "ad.click"
6
+ static let adDismiss = "ad.dismiss"
7
+ static let adImpression = "ad.impression"
8
+ static let adLoad = "ad.load"
9
+ static let adLoadFail = "ad.loadfail"
10
+ static let adReward = "ad.reward"
11
+ static let adShow = "ad.show"
12
+ static let adShowFail = "ad.showfail"
13
+ static let bannerClick = "banner.click"
14
+ static let bannerClose = "banner.close"
15
+ static let bannerImpression = "banner.impression"
16
+ static let bannerLoad = "banner.load"
17
+ static let bannerLoadFail = "banner.loadfail"
18
+ static let bannerOpen = "banner.open"
19
+ static let bannerSizeChange = "banner.sizechange"
20
+ static let interstitialDismiss = "interstitial.dismiss"
21
+ static let interstitialImpression = "interstitial.impression"
22
+ static let interstitialLoad = "interstitial.load"
23
+ static let interstitialLoadFail = "interstitial.loadfail"
24
+ static let interstitialShow = "interstitial.show"
25
+ static let interstitialShowFail = "interstitial.showfail"
26
+ static let rewardedDismiss = "rewarded.dismiss"
27
+ static let rewardedImpression = "rewarded.impression"
28
+ static let rewardedInterstitialDismiss = "rewardedi.dismiss"
29
+ static let rewardedInterstitialImpression = "rewardedi.impression"
30
+ static let rewardedInterstitialLoad = "rewardedi.load"
31
+ static let rewardedInterstitialLoadFail = "rewardedi.loadfail"
32
+ static let rewardedInterstitialReward = "rewardedi.reward"
33
+ static let rewardedInterstitialShow = "rewardedi.show"
34
+ static let rewardedInterstitialShowFail = "rewardedi.showfail"
35
+ static let rewardedLoad = "rewarded.load"
36
+ static let rewardedLoadFail = "rewarded.loadfail"
37
+ static let rewardedReward = "rewarded.reward"
38
+ static let rewardedShow = "rewarded.show"
39
+ static let rewardedShowFail = "rewarded.showfail"
40
+ }
@@ -0,0 +1,68 @@
1
+ import Foundation
2
+ import GoogleMobileAds
3
+
4
+ class AdManager {
5
+ static let shared = AdManager()
6
+ private var ads: [Int: Ad] = [:]
7
+
8
+ private init() {}
9
+
10
+ func addAd(_ ad: Ad, withId id: Int) {
11
+ ads[id] = ad
12
+ }
13
+
14
+ func getAd(_ id: Int) -> Ad? {
15
+ return ads[id]
16
+ }
17
+
18
+ func removeAd(_ id: Int) {
19
+ ads.removeValue(forKey: id)
20
+ }
21
+ }
22
+
23
+ protocol Ad {
24
+ var id: Int { get }
25
+ var adUnitId: String { get }
26
+ var isLoaded: Bool { get }
27
+
28
+ func load(completion: @escaping (Error?) -> Void)
29
+ func show(completion: @escaping (Error?) -> Void)
30
+ func hide(completion: @escaping (Error?) -> Void)
31
+ func destroy()
32
+ }
33
+
34
+ extension Ad {
35
+ func hide(completion: @escaping (Error?) -> Void) {
36
+ completion(NSError(domain: "AdMobPlus", code: -1, userInfo: [NSLocalizedDescriptionKey: "Hide not supported for this ad type"]))
37
+ }
38
+ }
39
+
40
+ class AdMobHelper {
41
+ static func buildAdRequest() -> GADRequest {
42
+ let request = GADRequest()
43
+ return request
44
+ }
45
+ }
46
+
47
+ enum AdMobError: Error {
48
+ case adNotFound
49
+ case adNotLoaded
50
+ case adAlreadyExists
51
+ case invalidAdType
52
+ case unknown(String)
53
+
54
+ var localizedDescription: String {
55
+ switch self {
56
+ case .adNotFound:
57
+ return "Ad not found"
58
+ case .adNotLoaded:
59
+ return "Ad is not loaded"
60
+ case .adAlreadyExists:
61
+ return "Ad already exists"
62
+ case .invalidAdType:
63
+ return "Invalid ad type"
64
+ case .unknown(let message):
65
+ return message
66
+ }
67
+ }
68
+ }
@@ -0,0 +1,92 @@
1
+ import Foundation
2
+ import UIKit
3
+ import GoogleMobileAds
4
+ import Capacitor
5
+
6
+ class InterstitialAd: NSObject, Ad {
7
+ let id: Int
8
+ let adUnitId: String
9
+ private var interstitial: GADInterstitialAd?
10
+ private weak var plugin: AdmobPlusPlugin?
11
+
12
+ var isLoaded: Bool {
13
+ return interstitial != nil
14
+ }
15
+
16
+ init(id: Int, adUnitId: String, plugin: AdmobPlusPlugin) {
17
+ self.id = id
18
+ self.adUnitId = adUnitId
19
+ self.plugin = plugin
20
+ super.init()
21
+ }
22
+
23
+ func load(completion: @escaping (Error?) -> Void) {
24
+ let request = AdMobHelper.buildAdRequest()
25
+
26
+ GADInterstitialAd.load(withAdUnitID: adUnitId, request: request) { [weak self] ad, error in
27
+ guard let self = self else { return }
28
+
29
+ if let error = error {
30
+ self.plugin?.notifyListeners(Events.interstitialLoadFail, data: [
31
+ "id": self.id,
32
+ "error": error.localizedDescription
33
+ ])
34
+ completion(error)
35
+ return
36
+ }
37
+
38
+ self.interstitial = ad
39
+ self.interstitial?.fullScreenContentDelegate = self
40
+
41
+ self.plugin?.notifyListeners(Events.interstitialLoad, data: ["id": self.id])
42
+ completion(nil)
43
+ }
44
+ }
45
+
46
+ func show(completion: @escaping (Error?) -> Void) {
47
+ DispatchQueue.main.async { [weak self] in
48
+ guard let self = self, let interstitial = self.interstitial else {
49
+ completion(AdMobError.adNotLoaded)
50
+ return
51
+ }
52
+
53
+ guard let viewController = self.plugin?.bridge?.viewController else {
54
+ completion(AdMobError.unknown("Unable to access view controller"))
55
+ return
56
+ }
57
+
58
+ interstitial.present(fromRootViewController: viewController)
59
+ completion(nil)
60
+ }
61
+ }
62
+
63
+ func destroy() {
64
+ interstitial = nil
65
+ }
66
+ }
67
+
68
+ extension InterstitialAd: GADFullScreenContentDelegate {
69
+ func adDidRecordImpression(_ ad: GADFullScreenPresentingAd) {
70
+ plugin?.notifyListeners(Events.interstitialImpression, data: ["id": id])
71
+ }
72
+
73
+ func adDidRecordClick(_ ad: GADFullScreenPresentingAd) {
74
+ plugin?.notifyListeners(Events.adClick, data: ["id": id])
75
+ }
76
+
77
+ func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
78
+ plugin?.notifyListeners(Events.interstitialShowFail, data: [
79
+ "id": id,
80
+ "error": error.localizedDescription
81
+ ])
82
+ }
83
+
84
+ func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
85
+ plugin?.notifyListeners(Events.interstitialShow, data: ["id": id])
86
+ }
87
+
88
+ func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
89
+ plugin?.notifyListeners(Events.interstitialDismiss, data: ["id": id])
90
+ interstitial = nil
91
+ }
92
+ }
@@ -0,0 +1,102 @@
1
+ import Foundation
2
+ import UIKit
3
+ import GoogleMobileAds
4
+ import Capacitor
5
+
6
+ class RewardedAd: NSObject, Ad {
7
+ let id: Int
8
+ let adUnitId: String
9
+ private var rewardedAd: GADRewardedAd?
10
+ private weak var plugin: AdmobPlusPlugin?
11
+
12
+ var isLoaded: Bool {
13
+ return rewardedAd != nil
14
+ }
15
+
16
+ init(id: Int, adUnitId: String, plugin: AdmobPlusPlugin) {
17
+ self.id = id
18
+ self.adUnitId = adUnitId
19
+ self.plugin = plugin
20
+ super.init()
21
+ }
22
+
23
+ func load(completion: @escaping (Error?) -> Void) {
24
+ let request = AdMobHelper.buildAdRequest()
25
+
26
+ GADRewardedAd.load(withAdUnitID: adUnitId, request: request) { [weak self] ad, error in
27
+ guard let self = self else { return }
28
+
29
+ if let error = error {
30
+ self.plugin?.notifyListeners(Events.rewardedLoadFail, data: [
31
+ "id": self.id,
32
+ "error": error.localizedDescription
33
+ ])
34
+ completion(error)
35
+ return
36
+ }
37
+
38
+ self.rewardedAd = ad
39
+ self.rewardedAd?.fullScreenContentDelegate = self
40
+
41
+ self.plugin?.notifyListeners(Events.rewardedLoad, data: ["id": self.id])
42
+ completion(nil)
43
+ }
44
+ }
45
+
46
+ func show(completion: @escaping (Error?) -> Void) {
47
+ DispatchQueue.main.async { [weak self] in
48
+ guard let self = self, let rewardedAd = self.rewardedAd else {
49
+ completion(AdMobError.adNotLoaded)
50
+ return
51
+ }
52
+
53
+ guard let viewController = self.plugin?.bridge?.viewController else {
54
+ completion(AdMobError.unknown("Unable to access view controller"))
55
+ return
56
+ }
57
+
58
+ rewardedAd.present(fromRootViewController: viewController) { [weak self] in
59
+ guard let self = self else { return }
60
+ let reward = rewardedAd.adReward
61
+ self.plugin?.notifyListeners(Events.rewardedReward, data: [
62
+ "id": self.id,
63
+ "reward": [
64
+ "amount": reward.amount.intValue,
65
+ "type": reward.type
66
+ ]
67
+ ])
68
+ }
69
+ completion(nil)
70
+ }
71
+ }
72
+
73
+ func destroy() {
74
+ rewardedAd = nil
75
+ }
76
+ }
77
+
78
+ extension RewardedAd: GADFullScreenContentDelegate {
79
+ func adDidRecordImpression(_ ad: GADFullScreenPresentingAd) {
80
+ plugin?.notifyListeners(Events.rewardedImpression, data: ["id": id])
81
+ }
82
+
83
+ func adDidRecordClick(_ ad: GADFullScreenPresentingAd) {
84
+ plugin?.notifyListeners(Events.adClick, data: ["id": id])
85
+ }
86
+
87
+ func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
88
+ plugin?.notifyListeners(Events.rewardedShowFail, data: [
89
+ "id": id,
90
+ "error": error.localizedDescription
91
+ ])
92
+ }
93
+
94
+ func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
95
+ plugin?.notifyListeners(Events.rewardedShow, data: ["id": id])
96
+ }
97
+
98
+ func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
99
+ plugin?.notifyListeners(Events.rewardedDismiss, data: ["id": id])
100
+ rewardedAd = nil
101
+ }
102
+ }