Fableon/Fableon/Object/Libs/AdManager/Rewarded/FARewardedAdManager.swift
2026-02-28 09:35:05 +08:00

250 lines
8.5 KiB
Swift

//
// FARewardedAdManager.swift
// Fableon
//
// Created by on 2026/1/24.
//
import UIKit
@objc protocol FARewardedAdManagerDelegate: NSObjectProtocol {
///
// @objc optional func rewardedAdManager(adManager: BRRewardedAdManager, userDidEarnReward adInfo: VPAdInfo)
///广
@objc optional func fa_rewardedAdManagerDidLoadFinish(adManager: FARewardedAdManager)
///广
@objc optional func fa_rewardedAdManager(adManager: FARewardedAdManager, didLoadFail error: Error)
///广
@objc optional func fa_rewardedAdManager(adManager: FARewardedAdManager, didDisplayFail error: Error)
///广
@objc optional func fa_rewardedAdManagerDidShow(adManager: FARewardedAdManager)
///广
@objc optional func fa_rewardedAdManagerDidDismiss(adManager: FARewardedAdManager, platform: String, adUnitID: String)
///广
@objc optional func fa_rewardedAdManagerDidClick(adManager: FARewardedAdManager)
///
@objc optional func fa_rewardedAdManager(adManager: FARewardedAdManager, didOtherFail error: Error)
}
protocol FARewardedAdDelegate: NSObjectProtocol {
///
// func rewardedAd(ad: BRRewardedAd, userDidEarnReward adInfo: VPAdInfo)
///广
func fa_rewardedAd(ad: FARewardedAd, didLoadFail error: Error)
///
func fa_rewardedAdDidStartLoad(ad: FARewardedAd)
///广
func fa_rewardedAdDidLoadFinish(ad: FARewardedAd)
///广
func fa_rewardedAd(ad: FARewardedAd, didDisplayFail error: Error)
///广
func fa_rewardedAdDidShow(ad: FARewardedAd, adInfo: [AnyHashable : Any])
///广
func fa_rewardedAdDidDismiss(ad: FARewardedAd)
///广
func fa_rewardedAdDidClick(ad: FARewardedAd)
}
protocol FARewardedAd: NSObjectProtocol {
var delegate: FARewardedAdDelegate? { get set }
var adPlatform: FAAdPlatform { get }
var adType: FAAdType { get }
var adUnitID: String { get }
var networkName: String { get set }
var isReady: Bool { get }
func loadAd()
func showAd()
}
class FARewardedAdManager: NSObject {
static let manager = FARewardedAdManager()
weak var delegate: FARewardedAdManagerDelegate?
var rewardedAd: FARewardedAd? {
didSet {
oldValue?.delegate = nil
rewardedAd?.delegate = self
}
}
var isAdAvailable: Bool {
if FALogin.manager.userInfo?.user_level == .ad {
return rewardedAd?.isReady ?? false
} else {
return false
}
}
///广
private(set) var isLoadingAd = false
private var isPlaying = false
///
var businessScene: FAAdManager.BusinessScene = .main
var shortPlayId: String?
var shortPlayVideoId: String?
private var startShowDate: Date? = nil
private var startLoadDate: Date?
private var endLoadDate: Date?
override init() {
super.init()
NotificationCenter.default.addObserver(self, selector: #selector(didEnterBackgroundNotification), name: UIApplication.didEnterBackgroundNotification, object: nil)
}
func load() {
guard FALogin.manager.userInfo?.user_level == .ad else {
let error = NSError(domain: "非广告用户", code: -1)
self.delegate?.fa_rewardedAdManager?(adManager: self, didOtherFail: error)
return
}
if self.isAdAvailable { return }
if self.isLoadingAd { return }
self.startLoadDate = nil
self.endLoadDate = nil
self.startShowDate = nil
self.isLoadingAd = true
// self.businessScene = .main
self.rewardedAd = FATradPlusInterstitialAd()
self.rewardedAd?.loadAd()
}
func show() {
guard FALogin.manager.userInfo?.user_level == .ad else {
let error = NSError(domain: "非广告用户", code: -1)
self.delegate?.fa_rewardedAdManager?(adManager: self, didOtherFail: error)
return
}
guard self.isAdAvailable else { return }
self.rewardedAd?.showAd()
}
}
//MARK: FARewardedAdDelegate
extension FARewardedAdManager: FARewardedAdDelegate {
func fa_rewardedAd(ad: any FARewardedAd, didLoadFail error: any Error) {
self.rewardedAd = nil
self.endLoadDate = Date()
self.isLoadingAd = false
self.uploadAdsHistory(ad: ad, type: .loadFailed, errorMsg: error.localizedDescription)
self.delegate?.fa_rewardedAdManager?(adManager: self, didLoadFail: error)
}
func fa_rewardedAd(ad: any FARewardedAd, didDisplayFail error: any Error) {
self.isPlaying = false
self.rewardedAd = nil
self.uploadAdsHistory(ad: ad, type: .showFailed, errorMsg: error.localizedDescription)
self.delegate?.fa_rewardedAdManager?(adManager: self, didDisplayFail: error)
}
func fa_rewardedAdDidStartLoad(ad: any FARewardedAd) {
self.startLoadDate = Date()
self.uploadAdsHistory(ad: ad, type: .startLoad)
}
func fa_rewardedAdDidLoadFinish(ad: any FARewardedAd) {
self.isLoadingAd = false
self.endLoadDate = Date()
self.uploadAdsHistory(ad: ad, type: .endLoad)
self.delegate?.fa_rewardedAdManagerDidLoadFinish?(adManager: self)
}
func fa_rewardedAdDidShow(ad: any FARewardedAd, adInfo: [AnyHashable : Any]) {
self.isPlaying = true
self.startShowDate = Date()
self.uploadAdsHistory(ad: ad, type: .show, viewSeconds: 0)
self.requestUploadAdsPrice(ad: ad, adInfo: adInfo)
self.delegate?.fa_rewardedAdManagerDidShow?(adManager: self)
}
func fa_rewardedAdDidDismiss(ad: any FARewardedAd) {
self.isPlaying = false
self.rewardedAd = nil
self.uploadAdsHistory(ad: ad, type: .close)
self.delegate?.fa_rewardedAdManagerDidDismiss?(adManager: self, platform: ad.adPlatform.rawValue, adUnitID: ad.adUnitID)
//广
self.load()
}
func fa_rewardedAdDidClick(ad: any FARewardedAd) {
self.uploadAdsHistory(ad: ad, type: .click)
self.delegate?.fa_rewardedAdManagerDidClick?(adManager: self)
}
}
extension FARewardedAdManager {
@objc private func didEnterBackgroundNotification() {
guard let ad = self.rewardedAd, self.isPlaying else { return }
self.uploadAdsHistory(ad: ad, type: .interrupt)
}
}
extension FARewardedAdManager {
func uploadAdsHistory(ad: any FARewardedAd, type: FAAdManager.StatType, viewSeconds: Int? = nil, errorMsg: String? = nil) {
var loadTime: Int?
if let startDate = self.startLoadDate, let endDate = self.endLoadDate {
loadTime = Int(endDate.timeIntervalSince(startDate))
}
var showTime: Int? = viewSeconds
if showTime == nil && (type == .click || type == .interrupt || type == .close) {
if let startShowDate = self.startShowDate {
showTime = Int(Date().timeIntervalSince(startShowDate))
}
}
let model = FAAdStatModel()
model.short_play_id = self.shortPlayId
model.short_play_video_id = self.shortPlayVideoId
model.scene = self.businessScene
model.loading_time = loadTime
model.view_seconds = showTime
model.ad_type = ad.adType.rawValue
model.ads_id = ad.adUnitID
model.ad_platform_key = ad.adPlatform
model.type = type
model.ag_platform_name = ad.networkName
model.ad_platform_name = ad.adPlatform
FAStatAPI.requestUploadAdsHistory(model: model)
}
func requestUploadAdsPrice(ad: any FARewardedAd, adInfo: [AnyHashable : Any]) {
guard let ecpm = adInfo["ecpm"] as? String else { return }
let money = (NSNumber(string: ecpm)?.doubleValue ?? 0) / 1000
let model = FAUploadAdsPriceModel()
model.short_play_id = self.shortPlayId
model.short_play_video_id = self.shortPlayVideoId
model.short_play_launch_id = ad.adUnitID
model.type = ad.adType.rawValue
model.agent_name = ad.adPlatform.rawValue
model.alliance_name = ad.networkName
model.money = "\(money)"
model.scene = self.businessScene
FAStatAPI.requestUploadAdsPrice(model: model)
}
}