From 5d8529dd9588fb1fcb318a67a0b4fc6ffae0c8fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B9=96=E5=8C=97=E7=A7=A6=E4=B9=9D?= Date: Thu, 12 Feb 2026 09:09:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=80=E5=B1=8F=E5=B9=BF=E5=91=8A=E7=BB=9F?= =?UTF-8?q?=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AdManager/Banner/FABannerAdManager.swift | 6 ++ .../Object/Libs/AdManager/FAAdManager.swift | 1 + .../AdManager/FAUploadAdsPriceModel.swift | 2 +- .../Libs/AdManager/Open/FAOpenAdManager.swift | 99 +++++++++++++++---- .../AdManager/Open/FATradPlusOpenAd.swift | 9 +- .../Rewarded/FARewardedAdManager.swift | 4 +- 6 files changed, 97 insertions(+), 24 deletions(-) diff --git a/Fableon/Object/Libs/AdManager/Banner/FABannerAdManager.swift b/Fableon/Object/Libs/AdManager/Banner/FABannerAdManager.swift index 2f32f48..010b2a4 100644 --- a/Fableon/Object/Libs/AdManager/Banner/FABannerAdManager.swift +++ b/Fableon/Object/Libs/AdManager/Banner/FABannerAdManager.swift @@ -143,4 +143,10 @@ extension FABannerAdManager: FABannerAdDelegate { +} + +extension FABannerAdManager { + + + } diff --git a/Fableon/Object/Libs/AdManager/FAAdManager.swift b/Fableon/Object/Libs/AdManager/FAAdManager.swift index 0e923a0..cd09698 100644 --- a/Fableon/Object/Libs/AdManager/FAAdManager.swift +++ b/Fableon/Object/Libs/AdManager/FAAdManager.swift @@ -22,6 +22,7 @@ class FAAdManager: NSObject { case reward = "reward" case splash = "splash" case banner = "banner" + case open = "open" } static func initSdk() { diff --git a/Fableon/Object/Libs/AdManager/FAUploadAdsPriceModel.swift b/Fableon/Object/Libs/AdManager/FAUploadAdsPriceModel.swift index 2771b38..0536f26 100644 --- a/Fableon/Object/Libs/AdManager/FAUploadAdsPriceModel.swift +++ b/Fableon/Object/Libs/AdManager/FAUploadAdsPriceModel.swift @@ -20,6 +20,6 @@ class FAUploadAdsPriceModel: NSObject, SmartCodable { var alliance_name: String? var money: String? var scene: FAAdManager.BusinessScene? - + var currency: String = "USD" } diff --git a/Fableon/Object/Libs/AdManager/Open/FAOpenAdManager.swift b/Fableon/Object/Libs/AdManager/Open/FAOpenAdManager.swift index 225d5aa..4003f27 100644 --- a/Fableon/Object/Libs/AdManager/Open/FAOpenAdManager.swift +++ b/Fableon/Object/Libs/AdManager/Open/FAOpenAdManager.swift @@ -23,10 +23,12 @@ import UIKit } protocol FAOpenAdDelegate: NSObjectProtocol { - func fa_openAd(ad: FAOpenAd, didLoadFail error: Error) + + func fa_openAdDidStartLoad(ad: FAOpenAd) func fa_openAdDidLoadFinish(ad: FAOpenAd) + func fa_openAd(ad: FAOpenAd, didLoadFail error: Error) func fa_openAd(ad: FAOpenAd, didDisplayFail error: Error) - func fa_openAdDidShow(ad: FAOpenAd) + func fa_openAdDidShow(ad: FAOpenAd, adInfo: [AnyHashable : Any]) func fa_openAdDidDismiss(ad: FAOpenAd) func fa_openAdDidClick(ad: FAOpenAd) } @@ -36,6 +38,7 @@ protocol FAOpenAd: NSObjectProtocol { var adPlatform: FAAdPlatform { get } var adType: FAAdType { get } var adUnitID: String { get } + var networkName: String { get set } var isReady: Bool { get } func loadAd() @@ -67,6 +70,10 @@ class FAOpenAdManager: NSObject { private(set) var isWaitingToShow = false private var timeOutTimer: Timer? + private var startShowDate: Date? + private var startLoadDate: Date? + private var endLoadDate: Date? + var isAdAvailable: Bool { return appOpenAd?.isReady ?? false } @@ -128,6 +135,8 @@ class FAOpenAdManager: NSObject { showAd() return } + self.startLoadDate = nil + self.endLoadDate = nil // 2. 如果没有就绪,标记等待并开始加载,同时开启超时保护 isWaitingToShow = true @@ -168,17 +177,25 @@ class FAOpenAdManager: NSObject { // MARK: - BRAppOpenAdDelegate extension FAOpenAdManager: FAOpenAdDelegate { + func fa_openAdDidStartLoad(ad: any FAOpenAd) { + self.startLoadDate = Date() + self.uploadAdsHistory(ad: ad, type: "startLoad") + } + func fa_openAd(ad: FAOpenAd, didLoadFail error: Error) { + self.endLoadDate = Date() isLoadingAd = false isWaitingToShow = false appOpenAd = nil clearTimer() - requestStatAd(type: "load_failed", errorMsg: error.localizedDescription) + uploadAdsHistory(ad: ad, type: "load_failed", errorMsg: error.localizedDescription) delegate?.fa_openAdManager?(manager: self, didLoadFail: error) } func fa_openAdDidLoadFinish(ad: FAOpenAd) { + self.endLoadDate = Date() isLoadingAd = false + self.uploadAdsHistory(ad: ad, type: "endLoad") delegate?.fa_openAdManagerDidLoadFinish?(manager: self) // 如果之前处于等待展示状态,现在立即展示 @@ -193,18 +210,26 @@ extension FAOpenAdManager: FAOpenAdDelegate { isWaitingToShow = false appOpenAd = nil clearTimer() - requestStatAd(type: "show_failed", errorMsg: error.localizedDescription) + uploadAdsHistory(ad: ad, type: "show_failed", errorMsg: error.localizedDescription) delegate?.fa_openAdManager?(manager: self, didDisplayFail: error) } - func fa_openAdDidShow(ad: FAOpenAd) { - requestStatAd(type: "start", errorMsg: nil) + func fa_openAdDidShow(ad: any FAOpenAd, adInfo: [AnyHashable : Any]) { + self.startShowDate = Date() + self.uploadAdsHistory(ad: ad, type: "start", viewSeconds: 0) + self.requestUploadAdsPrice(ad: ad, adInfo: adInfo) delegate?.fa_openAdManagerDidShow?(manager: self) } func fa_openAdDidDismiss(ad: FAOpenAd) { isShowingAd = false appOpenAd = nil + var viewSeconds: Int? = nil + if let startShowDate = self.startShowDate { + viewSeconds = Int(Date().timeIntervalSince(startShowDate)) + } + self.uploadAdsHistory(ad: ad, type: "close", viewSeconds: viewSeconds) + delegate?.fa_openAdManagerDidDismiss?(manager: self) // 关闭后自动预加载下一条,5秒后开始加载 DispatchQueue.main.asyncAfter(deadline: .now() + 10) { [weak self] in @@ -214,30 +239,27 @@ extension FAOpenAdManager: FAOpenAdDelegate { } func fa_openAdDidClick(ad: FAOpenAd) { - requestStatAd(type: "click", errorMsg: nil) + var viewSeconds: Int? = nil + if let startShowDate = self.startShowDate { + viewSeconds = Int(Date().timeIntervalSince(startShowDate)) + } + self.uploadAdsHistory(ad: ad, type: "click", viewSeconds: viewSeconds) } } // MARK: - Statistics extension FAOpenAdManager { - private func requestStatAd(type: String, errorMsg: String?) { - guard let appOpenAd = appOpenAd else { return } - - // let model = SPStatAdModel() - // model.type = type - // model.ads_id = appOpenAd.adUnitID - // model.ad_platform_key = SPAdPlatformKey(rawValue: appOpenAd.adPlatformKey) - // model.error_msg = errorMsg - // model.scene = .splash - // - // SPStatAPI.requestStatAd(model: model) - } @objc private func didEnterBackgroundNotification() { if !self.isShowingAd { return } + guard let ad = self.appOpenAd else { return } - self.requestStatAd(type: "Interrupt", errorMsg: nil) + var viewSeconds: Int? = nil + if let startShowDate = self.startShowDate { + viewSeconds = Int(Date().timeIntervalSince(startShowDate)) + } + self.uploadAdsHistory(ad: ad, type: "Interrupt", viewSeconds: viewSeconds) } @objc private func didBecomeActiveNotification() { @@ -246,4 +268,41 @@ extension FAOpenAdManager { self.showAd() } } + + func uploadAdsHistory(ad: any FAOpenAd, type: String, viewSeconds: Int? = nil, errorMsg: String? = nil) { + var loadTime: Int? + if let startDate = self.startLoadDate, let endDate = self.endLoadDate { + loadTime = Int(endDate.timeIntervalSince(startDate)) + } + + let model = FAAdStatModel() + model.scene = .open + if let loadTime = loadTime { + model.loading_time = max(0, loadTime) + } + model.view_seconds = viewSeconds + 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 FAOpenAd, 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_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 = .open + + FAStatAPI.requestUploadAdsPrice(model: model) + } } diff --git a/Fableon/Object/Libs/AdManager/Open/FATradPlusOpenAd.swift b/Fableon/Object/Libs/AdManager/Open/FATradPlusOpenAd.swift index 4d54fac..56672c8 100644 --- a/Fableon/Object/Libs/AdManager/Open/FATradPlusOpenAd.swift +++ b/Fableon/Object/Libs/AdManager/Open/FATradPlusOpenAd.swift @@ -29,6 +29,8 @@ class FATradPlusOpenAd: NSObject, FAOpenAd { var adUnitID: String { return self.adPlatform.openUnitId } + + var networkName: String = "" var isReady: Bool { #if canImport(TradPlusAds) @@ -78,7 +80,12 @@ class FATradPlusOpenAd: NSObject, FAOpenAd { // MARK: - TradPlusADSplashDelegate extension FATradPlusOpenAd: TradPlusADSplashDelegate { + func tpSplashAdStartLoad(_ adInfo: [AnyHashable : Any]) { + self.delegate?.fa_openAdDidStartLoad(ad: self) + } + func tpSplashAdLoaded(_ adInfo: [AnyHashable : Any]) { + self.networkName = (adInfo["adNetworkName"] as? String) ?? "unknown" self.delegate?.fa_openAdDidLoadFinish(ad: self) } @@ -88,7 +95,7 @@ extension FATradPlusOpenAd: TradPlusADSplashDelegate { } func tpSplashAdImpression(_ adInfo: [AnyHashable : Any]) { - self.delegate?.fa_openAdDidShow(ad: self) + self.delegate?.fa_openAdDidShow(ad: self, adInfo: adInfo) } func tpSplashAdShow(_ adInfo: [AnyHashable : Any], didFailWithError error: Error) { diff --git a/Fableon/Object/Libs/AdManager/Rewarded/FARewardedAdManager.swift b/Fableon/Object/Libs/AdManager/Rewarded/FARewardedAdManager.swift index e317fd9..395c2a3 100644 --- a/Fableon/Object/Libs/AdManager/Rewarded/FARewardedAdManager.swift +++ b/Fableon/Object/Libs/AdManager/Rewarded/FARewardedAdManager.swift @@ -112,6 +112,8 @@ class FARewardedAdManager: NSObject { } if self.isAdAvailable { return } if self.isLoadingAd { return } + self.startLoadDate = nil + self.endLoadDate = nil self.isLoadingAd = true @@ -144,7 +146,6 @@ extension FARewardedAdManager: FARewardedAdDelegate { self.isLoadingAd = false self.uploadAdsHistory(ad: ad, type: "load_failed", errorMsg: error.localizedDescription) self.delegate?.fa_rewardedAdManager?(adManager: self, didLoadFail: error) - self.endLoadDate = nil } func fa_rewardedAd(ad: any FARewardedAd, didDisplayFail error: any Error) { @@ -164,7 +165,6 @@ extension FARewardedAdManager: FARewardedAdDelegate { self.endLoadDate = Date() self.uploadAdsHistory(ad: ad, type: "endLoad") self.delegate?.fa_rewardedAdManagerDidLoadFinish?(adManager: self) - self.endLoadDate = nil } func fa_rewardedAdDidShow(ad: any FARewardedAd, adInfo: [AnyHashable : Any]) {