ThimraTV/ThimraTV/Libs/AdManager/AppOpenAd/SPAppOpenAdManager.swift
2025-07-15 15:42:15 +08:00

157 lines
4.8 KiB
Swift

//
// SPAppOpenAdManager.swift
// ThimraTV
//
// Created by on 2025/7/10.
//
import UIKit
import GoogleMobileAds
@objc protocol SPAppOpenAdManagerDelegate: NSObjectProtocol {
///广
@objc optional func appOpenAdManager(manager: SPAppOpenAdManager, didLoadFail error: Error)
///广
@objc optional func appOpenAdManagerDidLoadFinish(manager: SPAppOpenAdManager)
///广
@objc optional func appOpenAdManager(manager: SPAppOpenAdManager, didDisplayFail error: Error)
///广
@objc optional func appOpenAdManagerDidShow(manager: SPAppOpenAdManager)
///广
@objc optional func appOpenAdManagerDidDismiss(manager: SPAppOpenAdManager)
}
class SPAppOpenAdManager: NSObject {
weak var delegate: SPAppOpenAdManagerDelegate?
let adUnitID = SPAdManager.manager.appOpenAdUnitID
private var appOpenAd: AppOpenAd?
private(set) var isLoadingAd = false
private(set) var isShowingAd = false
private var isNeedShow = false
static let manager = SPAppOpenAdManager()
deinit {
NotificationCenter.default.removeObserver(self)
}
override init() {
super.init()
NotificationCenter.default.addObserver(self, selector: #selector(didEnterBackgroundNotification), name: UIApplication.didEnterBackgroundNotification, object: nil)
}
private func loadAd() {
// Do not load ad if there is an unused ad or one is already loading.
if isLoadingAd || isAdAvailable() {
return
}
isLoadingAd = true
AppOpenAd.load(with: adUnitID, request: Request()) { [weak self] appOpenAd, error in
guard let self = self else { return }
self.isLoadingAd = false
self.appOpenAd = appOpenAd
self.appOpenAd?.fullScreenContentDelegate = self
if appOpenAd != nil, self.isNeedShow {
self.showAdIfAvailable()
}
if let error = error {
self.requestStatAd(type: "load_failed", errorMsg: error.localizedDescription)
self.delegate?.appOpenAdManager?(manager: self, didLoadFail: error)
} else {
self.delegate?.appOpenAdManagerDidLoadFinish?(manager: self)
}
}
}
func showAdIfAvailable() {
// If the app open ad is already showing, do not show the ad again.
guard !isShowingAd else { return }
self.isNeedShow = true
// If the app open ad is not available yet but is supposed to show, load
// a new ad.
if !isAdAvailable() {
self.loadAd()
return
}
if let ad = appOpenAd {
self.isNeedShow = false
isShowingAd = true
ad.present(from: nil)
}
}
private func isAdAvailable() -> Bool {
// Check if ad exists and can be shown.
return appOpenAd != nil
}
}
extension SPAppOpenAdManager: FullScreenContentDelegate {
func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) {
self.requestStatAd(type: "start", errorMsg: nil)
print("App open ad will be presented.")
self.delegate?.appOpenAdManagerDidShow?(manager: self)
}
func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) {
self.requestStatAd(type: "close", errorMsg: nil)
appOpenAd = nil
isShowingAd = false
// Reload an ad.
// self.loadAd()
self.delegate?.appOpenAdManagerDidDismiss?(manager: self)
}
func ad(_ ad: FullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
self.requestStatAd(type: "show_failed", errorMsg: error.localizedDescription)
appOpenAd = nil
isShowingAd = false
// Reload an ad.
// self.loadAd()
self.delegate?.appOpenAdManager?(manager: self, didDisplayFail: error)
}
func adDidRecordClick(_ ad: any FullScreenPresentingAd) {
self.requestStatAd(type: "click", errorMsg: nil)
}
}
//MARK: -------------- --------------
extension SPAppOpenAdManager {
private func requestStatAd(type: String, errorMsg: String?) {
let model = SPStatAdModel()
model.type = type
model.ads_id = adUnitID
model.ad_platform_key = .google
model.error_msg = errorMsg
model.scene = .splash
SPStatAPI.requestStatAd(model: model)
}
@objc private func didEnterBackgroundNotification() {
guard appOpenAd != nil else { return }
self.requestStatAd(type: "Interrupt", errorMsg: nil)
}
}