diff --git a/ThimraTV.xcodeproj/project.pbxproj b/ThimraTV.xcodeproj/project.pbxproj index 93ef0ea..5e38fac 100644 --- a/ThimraTV.xcodeproj/project.pbxproj +++ b/ThimraTV.xcodeproj/project.pbxproj @@ -282,7 +282,11 @@ 1BF513112E1FA138009750EA /* SPStatAdModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BF513102E1FA138009750EA /* SPStatAdModel.swift */; }; 1BF513142E1FB8C1009750EA /* SPAppOpenAdManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BF513132E1FB8C1009750EA /* SPAppOpenAdManager.swift */; }; 1BF513162E20ADB4009750EA /* SPAppOpenAdViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BF513152E20ADB4009750EA /* SPAppOpenAdViewController.swift */; }; - 1BF513192E20DC85009750EA /* SPBannerAd.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BF513182E20DC85009750EA /* SPBannerAd.swift */; }; + 1BF513192E20DC85009750EA /* SPBannerAdManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BF513182E20DC85009750EA /* SPBannerAdManager.swift */; }; + 1BF5131B2E265880009750EA /* SPAdmobAppOpenAd.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BF5131A2E265880009750EA /* SPAdmobAppOpenAd.swift */; }; + 1BF5131D2E265A80009750EA /* SPApplovinAppOpenAd.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BF5131C2E265A80009750EA /* SPApplovinAppOpenAd.swift */; }; + 1BF513212E2662DC009750EA /* SPAdmobBannerAd.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BF513202E2662DC009750EA /* SPAdmobBannerAd.swift */; }; + 1BF513232E273482009750EA /* SPApplovinBannerAd.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BF513222E273479009750EA /* SPApplovinBannerAd.swift */; }; C3D1CE788CA03A1878493356 /* Pods_ThimraTV.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B64805795B479324EB764157 /* Pods_ThimraTV.framework */; }; /* End PBXBuildFile section */ @@ -596,7 +600,11 @@ 1BF513102E1FA138009750EA /* SPStatAdModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPStatAdModel.swift; sourceTree = ""; }; 1BF513132E1FB8C1009750EA /* SPAppOpenAdManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPAppOpenAdManager.swift; sourceTree = ""; }; 1BF513152E20ADB4009750EA /* SPAppOpenAdViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPAppOpenAdViewController.swift; sourceTree = ""; }; - 1BF513182E20DC85009750EA /* SPBannerAd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPBannerAd.swift; sourceTree = ""; }; + 1BF513182E20DC85009750EA /* SPBannerAdManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPBannerAdManager.swift; sourceTree = ""; }; + 1BF5131A2E265880009750EA /* SPAdmobAppOpenAd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPAdmobAppOpenAd.swift; sourceTree = ""; }; + 1BF5131C2E265A80009750EA /* SPApplovinAppOpenAd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPApplovinAppOpenAd.swift; sourceTree = ""; }; + 1BF513202E2662DC009750EA /* SPAdmobBannerAd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPAdmobBannerAd.swift; sourceTree = ""; }; + 1BF513222E273479009750EA /* SPApplovinBannerAd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPApplovinBannerAd.swift; sourceTree = ""; }; 1DBC40592DA4EDFC0093FCB0 /* ThimraTV.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ThimraTV.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1F666DE0B12C863F26BE5027 /* Pods-MoviaBox.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MoviaBox.debug.xcconfig"; path = "Target Support Files/Pods-MoviaBox/Pods-MoviaBox.debug.xcconfig"; sourceTree = ""; }; A1174E10BCF2C606F7818792 /* Pods-ThimraTV.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ThimraTV.release.xcconfig"; path = "Target Support Files/Pods-ThimraTV/Pods-ThimraTV.release.xcconfig"; sourceTree = ""; }; @@ -1511,6 +1519,8 @@ isa = PBXGroup; children = ( 1BF513132E1FB8C1009750EA /* SPAppOpenAdManager.swift */, + 1BF5131A2E265880009750EA /* SPAdmobAppOpenAd.swift */, + 1BF5131C2E265A80009750EA /* SPApplovinAppOpenAd.swift */, ); path = AppOpenAd; sourceTree = ""; @@ -1518,7 +1528,9 @@ 1BF513172E20DC63009750EA /* BannerAd */ = { isa = PBXGroup; children = ( - 1BF513182E20DC85009750EA /* SPBannerAd.swift */, + 1BF513182E20DC85009750EA /* SPBannerAdManager.swift */, + 1BF513202E2662DC009750EA /* SPAdmobBannerAd.swift */, + 1BF513222E273479009750EA /* SPApplovinBannerAd.swift */, ); path = BannerAd; sourceTree = ""; @@ -1743,6 +1755,7 @@ 1BB91D132E04FD6A00A2C715 /* AppDelegate+OpenApp.swift in Sources */, 1BB91D142E04FD6A00A2C715 /* AppDelegate+Thirdparty.swift in Sources */, 1BB91D152E04FD6A00A2C715 /* SceneDelegate.swift in Sources */, + 1BF5131D2E265A80009750EA /* SPApplovinAppOpenAd.swift in Sources */, 1BB91D162E04FD6A00A2C715 /* SPNavigationController.swift in Sources */, 1BB91D172E04FD6A00A2C715 /* SPTabBarController.swift in Sources */, 1BB91D182E04FD6A00A2C715 /* SPViewController.swift in Sources */, @@ -1776,6 +1789,7 @@ 1BC1F0D72E0A35EF00B579A4 /* SPVideoRevolutionManager.swift in Sources */, 1BB91D342E04FD6A00A2C715 /* SPSettingAPI.swift in Sources */, 1BB91D352E04FD6A00A2C715 /* SPStatAPI.swift in Sources */, + 1BF5131B2E265880009750EA /* SPAdmobAppOpenAd.swift in Sources */, 1BB91D362E04FD6A00A2C715 /* SPUserAPI.swift in Sources */, 1BB91D372E04FD6A00A2C715 /* SPVideoAPI.swift in Sources */, 1BB91D382E04FD6A00A2C715 /* SPWalletAPI.swift in Sources */, @@ -1817,6 +1831,7 @@ 1BB91D5A2E04FD6A00A2C715 /* SPHomePageController.swift in Sources */, 1BB91D5B2E04FD6A00A2C715 /* SPHomeV2ViewController.swift in Sources */, 1BDE201E2E1E3D3E00C2C2B5 /* SPRewardedAdManager+Admob.swift in Sources */, + 1BF513212E2662DC009750EA /* SPAdmobBannerAd.swift in Sources */, 1BB91D5C2E04FD6A00A2C715 /* SPHomeViewController.swift in Sources */, 1BB91D5D2E04FD6A00A2C715 /* SPSearchViewController.swift in Sources */, 1BB91D5E2E04FD6A00A2C715 /* SPHomeCategoryModel.swift in Sources */, @@ -1842,7 +1857,7 @@ 1BF5130C2E1F4660009750EA /* SPRewardedAdManager+AppLovin.swift in Sources */, 1BB91D712E04FD6A00A2C715 /* SPHomeHotView.swift in Sources */, 1BB91D722E04FD6A00A2C715 /* SPHomeNineSquareContentCell.swift in Sources */, - 1BF513192E20DC85009750EA /* SPBannerAd.swift in Sources */, + 1BF513192E20DC85009750EA /* SPBannerAdManager.swift in Sources */, 1BB91D732E04FD6A00A2C715 /* SPHomePlayHistoricalView.swift in Sources */, 1BDE20172E1E164600C2C2B5 /* SPAdAPI.swift in Sources */, 1BB91D742E04FD6A00A2C715 /* SPHomePlayHistoryCell.swift in Sources */, @@ -1964,6 +1979,7 @@ 1BB91DE42E04FD6A00A2C715 /* SPTokenModel.swift in Sources */, 1BB91DE52E04FD6A00A2C715 /* SPPlayer.swift in Sources */, 1BB91DE62E04FD6A00A2C715 /* SPIAPManager.swift in Sources */, + 1BF513232E273482009750EA /* SPApplovinBannerAd.swift in Sources */, 1BB91DE72E04FD6A00A2C715 /* SPIAPOrderModel.swift in Sources */, 1BB91DE82E04FD6A00A2C715 /* SPIAPVerifyModel.swift in Sources */, 1BB91DE92E04FD6A00A2C715 /* SPWaitRestoreModel.swift in Sources */, @@ -2098,7 +2114,7 @@ CODE_SIGN_ENTITLEMENTS = ThimraTV/ThimraTV.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 5; DEVELOPMENT_TEAM = TWDZ3MP9DV; ENABLE_USER_SCRIPT_SANDBOXING = NO; GENERATE_INFOPLIST_FILE = YES; @@ -2146,7 +2162,7 @@ CODE_SIGN_ENTITLEMENTS = ThimraTV/ThimraTV.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 5; DEVELOPMENT_TEAM = TWDZ3MP9DV; ENABLE_USER_SCRIPT_SANDBOXING = NO; GENERATE_INFOPLIST_FILE = YES; diff --git a/ThimraTV/AppDelegate/AppDelegate+APNS.swift b/ThimraTV/AppDelegate/AppDelegate+APNS.swift index acc9d18..24805bd 100644 --- a/ThimraTV/AppDelegate/AppDelegate+APNS.swift +++ b/ThimraTV/AppDelegate/AppDelegate+APNS.swift @@ -12,8 +12,13 @@ import FirebaseCore extension AppDelegate { ///是否展示过通知提示 static var haveBeenShownAPNS = false + ///是否申请过权限 + static var isRequestAuthorization = false func registerAPNS() { + guard !Self.isRequestAuthorization else { return } + Self.isRequestAuthorization = true + FirebaseApp.configure() Messaging.messaging().delegate = self diff --git a/ThimraTV/AppDelegate/AppDelegate.swift b/ThimraTV/AppDelegate/AppDelegate.swift index 8374de3..c625803 100644 --- a/ThimraTV/AppDelegate/AppDelegate.swift +++ b/ThimraTV/AppDelegate/AppDelegate.swift @@ -30,7 +30,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // SPLoginManager.manager.requestVisitorLogin(completer: nil) SPLoginManager.manager.updateUserInfo(completer: nil) ///注册消息通知 - registerAPNS() +// registerAPNS() return true } diff --git a/ThimraTV/AppDelegate/SceneDelegate.swift b/ThimraTV/AppDelegate/SceneDelegate.swift index 96fdea0..7642c9b 100644 --- a/ThimraTV/AppDelegate/SceneDelegate.swift +++ b/ThimraTV/AppDelegate/SceneDelegate.swift @@ -122,16 +122,20 @@ extension SceneDelegate { window?.rootViewController = guideVc window?.makeKeyAndVisible() + SPAPPTool.appDelegate?.registerAPNS() + } else if SPLoginManager.manager.userInfo?.user_level == .ad, !SPAPPTool.isAppOpen, hasOpenApp == true, SPNetworkReachabilityManager.manager.isReachable == true { //开屏广告 let openAdVC = SPAppOpenAdViewController() openAdVC.didEndBlock = { [weak self] in self?.handleOpenApp() + SPAPPTool.appDelegate?.registerAPNS() } window?.rootViewController = openAdVC window?.makeKeyAndVisible() } else { handleOpenApp() + SPAPPTool.appDelegate?.registerAPNS() } } diff --git a/ThimraTV/Class/Guide/Controller/SPAppOpenAdViewController.swift b/ThimraTV/Class/Guide/Controller/SPAppOpenAdViewController.swift index c71aba5..28b61a4 100644 --- a/ThimraTV/Class/Guide/Controller/SPAppOpenAdViewController.swift +++ b/ThimraTV/Class/Guide/Controller/SPAppOpenAdViewController.swift @@ -30,7 +30,12 @@ class SPAppOpenAdViewController: SPViewController { } + + private func openApp() { + self.didEndBlock?() + NotificationCenter.default.post(name: SPGuideViewController.didOpenAppNotification, object: nil, userInfo: nil) + } } @@ -38,14 +43,17 @@ extension SPAppOpenAdViewController: SPAppOpenAdManagerDelegate { ///广告加载失败 func appOpenAdManager(manager: SPAppOpenAdManager, didLoadFail error: Error) { - self.didEndBlock?() + openApp() } ///广告展示失败 func appOpenAdManager(manager: SPAppOpenAdManager, didDisplayFail error: Error) { - self.didEndBlock?() + openApp() } ///广告被关闭 func appOpenAdManagerDidDismiss(manager: SPAppOpenAdManager) { - self.didEndBlock?() + openApp() + } + func appOpenAdManager(manager: SPAppOpenAdManager, didOtherFail error: any Error) { + openApp() } } diff --git a/ThimraTV/Class/Mine/Model/SPVersionUpdateModel.swift b/ThimraTV/Class/Mine/Model/SPVersionUpdateModel.swift index 2541c0b..92bab5e 100644 --- a/ThimraTV/Class/Mine/Model/SPVersionUpdateModel.swift +++ b/ThimraTV/Class/Mine/Model/SPVersionUpdateModel.swift @@ -17,9 +17,18 @@ class SPVersionUpdateModel: SPModel, SmartCodable { func canUpdate() -> Bool { - let currentCode = NSNumber(string: kSPAPPBundleVersion)?.intValue ?? 0 - let serverCode = NSNumber(string: version_code ?? "0")?.intValue ?? 0 - return serverCode > currentCode +// let currentCode = NSNumber(string: kSPAPPBundleVersion)?.intValue ?? 0 +// let serverCode = NSNumber(string: version_code ?? "0")?.intValue ?? 0 +// return serverCode > currentCode + + guard let versionName = version_name else { return false } + + let result = kSPAPPVersion.compare(versionName, options: .numeric) + if result == .orderedAscending { + return true + } else { + return false + } } diff --git a/ThimraTV/Class/Player/View/SPPlayerDetailRecommandView.swift b/ThimraTV/Class/Player/View/SPPlayerDetailRecommandView.swift index e47f623..70c568a 100644 --- a/ThimraTV/Class/Player/View/SPPlayerDetailRecommandView.swift +++ b/ThimraTV/Class/Player/View/SPPlayerDetailRecommandView.swift @@ -28,8 +28,8 @@ class SPPlayerDetailRecommandView: HWPanModalContentView { } } - private lazy var bannerAd: SPBannerAd = { - let ad = SPBannerAd() + private lazy var bannerAd: SPBannerAdManager = { + let ad = SPBannerAdManager() return ad }() @@ -213,6 +213,7 @@ extension SPPlayerDetailRecommandView { bannerAd.view.snp.makeConstraints { make in make.centerX.equalToSuperview() make.bottom.equalToSuperview().offset(-kSPTabbarSafeBottomMargin) + make.size.equalTo(bannerAd.size) } } diff --git a/ThimraTV/Class/Player/ViewModel/SPPlayerListViewModel.swift b/ThimraTV/Class/Player/ViewModel/SPPlayerListViewModel.swift index 5698955..3d00127 100644 --- a/ThimraTV/Class/Player/ViewModel/SPPlayerListViewModel.swift +++ b/ThimraTV/Class/Player/ViewModel/SPPlayerListViewModel.swift @@ -128,11 +128,12 @@ extension SPPlayerListViewModel { completer?(false) case .success: - videoInfo?.is_lock = false - completer?(true) //更新用户信息 - SPLoginManager.manager.updateUserInfo(completer: nil) + SPLoginManager.manager.updateUserInfo { + videoInfo?.is_lock = false + completer?(true) + } default: completer?(false) diff --git a/ThimraTV/Libs/AdManager/AppOpenAd/SPAdmobAppOpenAd.swift b/ThimraTV/Libs/AdManager/AppOpenAd/SPAdmobAppOpenAd.swift new file mode 100644 index 0000000..3d02f0f --- /dev/null +++ b/ThimraTV/Libs/AdManager/AppOpenAd/SPAdmobAppOpenAd.swift @@ -0,0 +1,67 @@ +// +// SPAdmobAppOpenAd.swift +// ThimraTV +// +// Created by 长沙佳儿 on 2025/7/15. +// + +import UIKit +import GoogleMobileAds + +class SPAdmobAppOpenAd: NSObject, SPAppOpenAd { + + private var appOpenAd: AppOpenAd? + + var delegate: (any SPAppOpenAdDelegate)? + + var adPlatformKey: String { + return SPAdPlatformKey.google.rawValue + } + + var adUnitID: String { + return SPAdManager.manager.admob_appOpenAdUnitID + } + + var isReady: Bool { + return appOpenAd != nil + } + + func loadAd() { + AppOpenAd.load(with: adUnitID, request: Request()) { [weak self] appOpenAd, error in + guard let self = self else { return } + + self.appOpenAd = appOpenAd + self.appOpenAd?.fullScreenContentDelegate = self + + if let error = error { + self.delegate?.appOpenAd?(ad: self, didLoadFail: error) + } else { + self.delegate?.appOpenAdDidLoadFinish?(ad: self) + } + } + } + + func showAd() { + appOpenAd?.present(from: nil) + } + +} + +extension SPAdmobAppOpenAd: FullScreenContentDelegate { + func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) { + self.delegate?.appOpenAdDidShow?(ad: self) + } + + func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) { + self.delegate?.appOpenAdDidDismiss?(ad: self) + } + + func ad(_ ad: FullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) { + self.delegate?.appOpenAd?(ad: self, didDisplayFail: error) + } + + func adDidRecordClick(_ ad: any FullScreenPresentingAd) { + self.delegate?.appOpenAdDidClick?(ad: self) + } + +} diff --git a/ThimraTV/Libs/AdManager/AppOpenAd/SPAppOpenAdManager.swift b/ThimraTV/Libs/AdManager/AppOpenAd/SPAppOpenAdManager.swift index 124f112..ba3896d 100644 --- a/ThimraTV/Libs/AdManager/AppOpenAd/SPAppOpenAdManager.swift +++ b/ThimraTV/Libs/AdManager/AppOpenAd/SPAppOpenAdManager.swift @@ -6,7 +6,6 @@ // import UIKit -import GoogleMobileAds @objc protocol SPAppOpenAdManagerDelegate: NSObjectProtocol { ///广告加载失败 @@ -19,21 +18,60 @@ import GoogleMobileAds @objc optional func appOpenAdManagerDidShow(manager: SPAppOpenAdManager) ///广告被关闭 @objc optional func appOpenAdManagerDidDismiss(manager: SPAppOpenAdManager) + + ///其它错误 + @objc optional func appOpenAdManager(manager: SPAppOpenAdManager, didOtherFail error: Error) +} + +@objc protocol SPAppOpenAdDelegate: NSObjectProtocol { + + ///广告加载失败 + @objc optional func appOpenAd(ad: SPAppOpenAd, didLoadFail error: Error) + ///广告加载成功 + @objc optional func appOpenAdDidLoadFinish(ad: SPAppOpenAd) + ///广告展示失败 + @objc optional func appOpenAd(ad: SPAppOpenAd, didDisplayFail error: Error) + ///广告被展示 + @objc optional func appOpenAdDidShow(ad: SPAppOpenAd) + ///广告被关闭 + @objc optional func appOpenAdDidDismiss(ad: SPAppOpenAd) + ///广告被点击 + @objc optional func appOpenAdDidClick(ad: SPAppOpenAd) +} + + +@objc protocol SPAppOpenAd: NSObjectProtocol { + + weak var delegate: SPAppOpenAdDelegate? { get set } + + var adPlatformKey: String { get } + + var adUnitID: String { get } + + var isReady: Bool { get } + + func loadAd() + func showAd() + } class SPAppOpenAdManager: NSObject { + static let manager = SPAppOpenAdManager() weak var delegate: SPAppOpenAdManagerDelegate? - let adUnitID = SPAdManager.manager.appOpenAdUnitID + let adUnitID = SPAdManager.manager.admob_appOpenAdUnitID - private var appOpenAd: AppOpenAd? + private var appOpenAd: SPAppOpenAd? + + private(set) var isLoadingAd = false private(set) var isShowingAd = false private var isNeedShow = false - static let manager = SPAppOpenAdManager() + private var timeOutTimer: Timer? + deinit { NotificationCenter.default.removeObserver(self) @@ -51,26 +89,17 @@ class SPAppOpenAdManager: NSObject { } 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) - } + appOpenAd = SPAdmobAppOpenAd() + appOpenAd?.delegate = self + appOpenAd?.loadAd() + } + + func showAd() { + if let ad = appOpenAd { + self.isNeedShow = false + isShowingAd = true + ad.showAd() } - - - } func showAdIfAvailable() { @@ -79,6 +108,8 @@ class SPAppOpenAdManager: NSObject { self.isNeedShow = true + self.timeOutTimer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(handleTimeOutTimer), userInfo: nil, repeats: false) + // If the app open ad is not available yet but is supposed to show, load // a new ad. if !isAdAvailable() { @@ -86,48 +117,80 @@ class SPAppOpenAdManager: NSObject { return } - if let ad = appOpenAd { - self.isNeedShow = false - isShowingAd = true - ad.present(from: nil) - } + showAd() } + private func isAdAvailable() -> Bool { - // Check if ad exists and can be shown. - return appOpenAd != nil + return appOpenAd?.isReady ?? false } + + @objc private func handleTimeOutTimer() { + self.isNeedShow = false + self.timeOutTimer?.invalidate() + self.timeOutTimer = nil + clearTimer() + + let error = NSError(domain: "time-out", code: -1) + self.delegate?.appOpenAdManager?(manager: self, didOtherFail: error) + } + + private func clearTimer() { + self.timeOutTimer?.invalidate() + self.timeOutTimer = 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) - } +//MARK: -------------- SPAppOpenAdDelegate -------------- +extension SPAppOpenAdManager: SPAppOpenAdDelegate { - func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) { - self.requestStatAd(type: "close", errorMsg: nil) + ///广告加载失败 + func appOpenAd(ad: SPAppOpenAd, didLoadFail error: Error) { + self.requestStatAd(type: "load_failed", errorMsg: error.localizedDescription) + isLoadingAd = false + clearTimer() - appOpenAd = nil - isShowingAd = false - // Reload an ad. -// self.loadAd() - self.delegate?.appOpenAdManagerDidDismiss?(manager: self) + self.delegate?.appOpenAdManager?(manager: self, didLoadFail: error) } - - func ad(_ ad: FullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) { + ///广告加载成功 + func appOpenAdDidLoadFinish(ad: SPAppOpenAd) { + isLoadingAd = false + clearTimer() + self.delegate?.appOpenAdManagerDidLoadFinish?(manager: self) + + if isNeedShow { + self.showAd() + } + + } + ///广告展示失败 + func appOpenAd(ad: SPAppOpenAd, didDisplayFail error: Error) { + self.requestStatAd(type: "show_failed", errorMsg: error.localizedDescription) appOpenAd = nil isShowingAd = false - // Reload an ad. -// self.loadAd() + clearTimer() self.delegate?.appOpenAdManager?(manager: self, didDisplayFail: error) } - - func adDidRecordClick(_ ad: any FullScreenPresentingAd) { + ///广告被展示 + func appOpenAdDidShow(ad: SPAppOpenAd) { + self.requestStatAd(type: "start", errorMsg: nil) + self.delegate?.appOpenAdManagerDidShow?(manager: self) + } + ///广告被关闭 + func appOpenAdDidDismiss(ad: SPAppOpenAd) { + self.requestStatAd(type: "close", errorMsg: nil) + + appOpenAd = nil + isShowingAd = false + + self.delegate?.appOpenAdManagerDidDismiss?(manager: self) + } + ///广告被点击 + func appOpenAdDidClick(ad: SPAppOpenAd) { self.requestStatAd(type: "click", errorMsg: nil) } @@ -137,10 +200,12 @@ extension SPAppOpenAdManager: FullScreenContentDelegate { extension SPAppOpenAdManager { private func requestStatAd(type: String, errorMsg: String?) { + guard let appOpenAd = appOpenAd else { return } + let model = SPStatAdModel() model.type = type - model.ads_id = adUnitID - model.ad_platform_key = .google + model.ads_id = appOpenAd.adUnitID + model.ad_platform_key = SPAdPlatformKey(rawValue: appOpenAd.adPlatformKey) model.error_msg = errorMsg model.scene = .splash @@ -149,7 +214,7 @@ extension SPAppOpenAdManager { @objc private func didEnterBackgroundNotification() { - guard appOpenAd != nil else { return } + if !self.isShowingAd { return } self.requestStatAd(type: "Interrupt", errorMsg: nil) } diff --git a/ThimraTV/Libs/AdManager/AppOpenAd/SPApplovinAppOpenAd.swift b/ThimraTV/Libs/AdManager/AppOpenAd/SPApplovinAppOpenAd.swift new file mode 100644 index 0000000..7989799 --- /dev/null +++ b/ThimraTV/Libs/AdManager/AppOpenAd/SPApplovinAppOpenAd.swift @@ -0,0 +1,79 @@ +// +// SPApplovinAppOpenAd.swift +// ThimraTV +// +// Created by 长沙佳儿 on 2025/7/15. +// + +import UIKit +import AppLovinSDK + +class SPApplovinAppOpenAd: NSObject, SPAppOpenAd { + + private lazy var appOpenAd = MAAppOpenAd(adUnitIdentifier: adUnitID) + + var delegate: (any SPAppOpenAdDelegate)? + + var adPlatformKey: String { + return SPAdPlatformKey.applovin.rawValue + } + + var adUnitID: String { + return SPAdManager.manager.applovin_appOpenAdUnitID + } + + var isReady: Bool { + if ALSdk.shared().isInitialized && appOpenAd.isReady { + return true + } else { + return false + } + } + + func loadAd() { + SPAdManager.manager.initialize_applovinSdk { [weak self] in + guard let self = self else { return } + appOpenAd.delegate = self + appOpenAd.load() + } + } + + func showAd() { + guard isReady else { return } + appOpenAd.show() + } + + + + +} + +//MARK: -------------- MAAdDelegate -------------- +extension SPApplovinAppOpenAd: MAAdDelegate { + func didLoad(_ ad: MAAd) { + self.delegate?.appOpenAdDidLoadFinish?(ad: self) + } + + func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) { + let nsError = NSError(domain: error.message, code: error.code.rawValue) + self.delegate?.appOpenAd?(ad: self, didLoadFail: nsError) + } + + func didDisplay(_ ad: MAAd) { + self.delegate?.appOpenAdDidShow?(ad: self) + } + + func didHide(_ ad: MAAd) { + self.delegate?.appOpenAdDidDismiss?(ad: self) + } + + func didClick(_ ad: MAAd) { + self.delegate?.appOpenAdDidClick?(ad: self) + } + + func didFail(toDisplay ad: MAAd, withError error: MAError) { + let nsError = NSError(domain: error.message, code: error.code.rawValue) + self.delegate?.appOpenAd?(ad: self, didDisplayFail: nsError) + } + +} diff --git a/ThimraTV/Libs/AdManager/BannerAd/SPAdmobBannerAd.swift b/ThimraTV/Libs/AdManager/BannerAd/SPAdmobBannerAd.swift new file mode 100644 index 0000000..da27311 --- /dev/null +++ b/ThimraTV/Libs/AdManager/BannerAd/SPAdmobBannerAd.swift @@ -0,0 +1,75 @@ +// +// SPAdmobBannerAd.swift +// ThimraTV +// +// Created by 长沙佳儿 on 2025/7/15. +// + +import UIKit +import GoogleMobileAds + +class SPAdmobBannerAd: NSObject, SPBannerAd { + + + var delegate: (any SPBannerAdDelegate)? + + + let size = CGSize.init(width: kSPScreenWidth, height: 59) + + private lazy var _adView: BannerView = { + let view = BannerView() + view.adUnitID = self.adUnitID + view.adSize = inlineAdaptiveBanner(width: size.width, maxHeight:size.height) + view.delegate = self + return view + }() + + var adView: UIView { + return _adView + } + + var adPlatformKey: String { + return SPAdPlatformKey.google.rawValue + } + + var adUnitID: String { + return SPAdManager.manager.admob_bannerAdUnitID + } + + + + func loadAd() { + _adView.load(Request()) + } + +} + +//MARK: -------------- BannerViewDelegate -------------- +extension SPAdmobBannerAd: BannerViewDelegate { + + func bannerViewDidReceiveAd(_ bannerView: BannerView) { + self.delegate?.bannerAdDidLoadFinish?(bannerAd: self) + } + + func bannerView(_ bannerView: BannerView, didFailToReceiveAdWithError error: Error) { + self.delegate?.bannerAd?(bannerAd: self, didLoadFail: error) + } + + func bannerViewDidRecordClick(_ bannerView: BannerView) { + self.delegate?.bannerAdDidClick?(ad: self) + } + + func bannerViewDidRecordImpression(_ bannerView: BannerView) { + } + + func bannerViewWillPresentScreen(_ bannerView: BannerView) { + self.delegate?.bannerAdDidShow?(bannerAd: self) + } + + func bannerViewWillDismissScreen(_ bannerView: BannerView) { + } + + func bannerViewDidDismissScreen(_ bannerView: BannerView) { + self.delegate?.bannerAdDidDismiss?(bannerAd: self) + } +} diff --git a/ThimraTV/Libs/AdManager/BannerAd/SPApplovinBannerAd.swift b/ThimraTV/Libs/AdManager/BannerAd/SPApplovinBannerAd.swift new file mode 100644 index 0000000..2eeca84 --- /dev/null +++ b/ThimraTV/Libs/AdManager/BannerAd/SPApplovinBannerAd.swift @@ -0,0 +1,82 @@ +// +// SPApplovinBannerAd.swift +// ThimraTV +// +// Created by 长沙佳儿 on 2025/7/16. +// + +import UIKit +import AppLovinSDK + +class SPApplovinBannerAd: NSObject, SPBannerAd { + + let size = CGSize.init(width: kSPScreenWidth, height: 59) + + var delegate: (any SPBannerAdDelegate)? + + private(set) lazy var _adView: MAAdView = { + let view = MAAdView(adUnitIdentifier: adUnitID) + view.frame = .init(x: 0, y: 0, width: size.width, height: size.height) + view.delegate = self + return view + }() + + var adView: UIView { + return _adView + } + + var adPlatformKey: String { + return SPAdPlatformKey.applovin.rawValue + } + + var adUnitID: String { + return SPAdManager.manager.applovin_bannerAdUnitID + } + + func loadAd() { + _adView.loadAd() + } + + + + +} + +//MARK: -------------- MAAdViewAdDelegate -------------- +extension SPApplovinBannerAd: MAAdViewAdDelegate { + func didExpand(_ ad: MAAd) { + + } + + func didCollapse(_ ad: MAAd) { + + } + + func didLoad(_ ad: MAAd) { + self.delegate?.bannerAdDidLoadFinish?(bannerAd: self) + } + + func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) { + let nsError = NSError(domain: error.message, code: error.code.rawValue) + self.delegate?.bannerAd?(bannerAd: self, didLoadFail: nsError) + } + + func didDisplay(_ ad: MAAd) { + self.delegate?.bannerAdDidShow?(bannerAd: self) + } + + func didHide(_ ad: MAAd) { + self.delegate?.bannerAdDidDismiss?(bannerAd: self) + } + + func didClick(_ ad: MAAd) { + self.delegate?.bannerAdDidClick?(ad: self) + } + + func didFail(toDisplay ad: MAAd, withError error: MAError) { + + } + + + +} diff --git a/ThimraTV/Libs/AdManager/BannerAd/SPBannerAd.swift b/ThimraTV/Libs/AdManager/BannerAd/SPBannerAd.swift deleted file mode 100644 index 31d52c7..0000000 --- a/ThimraTV/Libs/AdManager/BannerAd/SPBannerAd.swift +++ /dev/null @@ -1,111 +0,0 @@ -// -// SPBannerAd.swift -// ThimraTV -// -// Created by 长沙佳儿 on 2025/7/11. -// - -import UIKit -import GoogleMobileAds - - -@objc protocol SPBannerAdDelegate: NSObjectProtocol { - ///广告加载失败 - @objc optional func bannerAd(bannerAd: SPBannerAd, didLoadFail error: Error) - ///广告加载成功 - @objc optional func bannerAdDidLoadFinish(bannerAd: SPBannerAd) - ///广告被展示 - @objc optional func bannerAdDidShow(bannerAd: SPBannerAd) - ///广告被关闭 - @objc optional func bannerAdDidDismiss(bannerAd: SPBannerAd) -} - -class SPBannerAd: NSObject { - - let adUnitID = SPAdManager.manager.bannerAdUnitID - - let size = CGSize.init(width: kSPScreenWidth, height: 59) - - weak var delegate: SPBannerAdDelegate? - - private(set) lazy var view: BannerView = { - let view = BannerView() - view.adUnitID = self.adUnitID - view.adSize = inlineAdaptiveBanner(width: size.width, maxHeight:size.height) -// view.adSize = adSizeFor(cgSize: size) - view.delegate = self - return view - }() - - - deinit { - NotificationCenter.default.removeObserver(self) - } - - override init() { - super.init() - NotificationCenter.default.addObserver(self, selector: #selector(didEnterBackgroundNotification), name: UIApplication.didEnterBackgroundNotification, object: nil) - - view.load(Request()) - } - -} - -//MARK: -------------- BannerViewDelegate -------------- -extension SPBannerAd: BannerViewDelegate { - func bannerViewDidReceiveAd(_ bannerView: BannerView) { - self.requestStatAd(type: "start", errorMsg: nil) - self.delegate?.bannerAdDidLoadFinish?(bannerAd: self) - } - - func bannerView(_ bannerView: BannerView, didFailToReceiveAdWithError error: Error) { - self.requestStatAd(type: "load_failed", errorMsg: error.localizedDescription) - self.delegate?.bannerAd?(bannerAd: self, didLoadFail: error) - } - - func bannerViewDidRecordClick(_ bannerView: BannerView) { - print(#function) - self.requestStatAd(type: "click", errorMsg: nil) - } - - func bannerViewDidRecordImpression(_ bannerView: BannerView) { - print(#function) - } - - func bannerViewWillPresentScreen(_ bannerView: BannerView) { - self.delegate?.bannerAdDidShow?(bannerAd: self) - } - - func bannerViewWillDismissScreen(_ bannerView: BannerView) { - print(#function) - } - - func bannerViewDidDismissScreen(_ bannerView: BannerView) { - self.requestStatAd(type: "close", errorMsg: nil) - self.delegate?.bannerAdDidDismiss?(bannerAd: self) - } -} - -//MARK: -------------- 统计 -------------- -extension SPBannerAd { - - func requestStatAd(type: String, errorMsg: String?) { - guard self.view.superview != nil else { return } - - let model = SPStatAdModel() - model.type = type - model.ads_id = adUnitID - model.ad_platform_key = .google - model.error_msg = errorMsg - model.scene = .banner - - SPStatAPI.requestStatAd(model: model) - } - - - @objc private func didEnterBackgroundNotification() { - - self.requestStatAd(type: "Interrupt", errorMsg: nil) - } -} - diff --git a/ThimraTV/Libs/AdManager/BannerAd/SPBannerAdManager.swift b/ThimraTV/Libs/AdManager/BannerAd/SPBannerAdManager.swift new file mode 100644 index 0000000..1e80723 --- /dev/null +++ b/ThimraTV/Libs/AdManager/BannerAd/SPBannerAdManager.swift @@ -0,0 +1,135 @@ +// +// SPBannerAdManager.swift +// ThimraTV +// +// Created by 长沙佳儿 on 2025/7/11. +// + +import UIKit +import GoogleMobileAds + + + +@objc protocol SPBannerAdManagerDelegate: NSObjectProtocol { + ///广告加载失败 + @objc optional func bannerAdManager(adManager: SPBannerAdManager, didLoadFail error: Error) + ///广告加载成功 + @objc optional func bannerAdManagerDidLoadFinish(adManager: SPBannerAdManager) + ///广告被展示 + @objc optional func bannerAdManagerDidShow(adManager: SPBannerAdManager) + ///广告被关闭 + @objc optional func bannerAdManagerDidDismiss(adManager: SPBannerAdManager) +} + + +@objc protocol SPBannerAdDelegate: NSObjectProtocol { + ///广告加载失败 + @objc optional func bannerAd(bannerAd: SPBannerAd, didLoadFail error: Error) + ///广告加载成功 + @objc optional func bannerAdDidLoadFinish(bannerAd: SPBannerAd) + ///广告被展示 + @objc optional func bannerAdDidShow(bannerAd: SPBannerAd) + ///广告被关闭 + @objc optional func bannerAdDidDismiss(bannerAd: SPBannerAd) + ///广告被点击 + @objc optional func bannerAdDidClick(ad: SPBannerAd) +} + +@objc protocol SPBannerAd: NSObjectProtocol { + + weak var delegate: SPBannerAdDelegate? { get set } + + var adView: UIView { get } + + var adPlatformKey: String { get } + + var adUnitID: String { get } + + func loadAd() + +} + +class SPBannerAdManager: NSObject { + + let adUnitID = SPAdManager.manager.admob_bannerAdUnitID + + let size = CGSize.init(width: kSPScreenWidth, height: 59) + + weak var delegate: SPBannerAdManagerDelegate? + + private lazy var bannerAd: SPBannerAd = { + let ad = SPAdmobBannerAd() + ad.delegate = self + return ad + }() + + var view: UIView { + return bannerAd.adView + } + + + deinit { + NotificationCenter.default.removeObserver(self) + } + + override init() { + super.init() + NotificationCenter.default.addObserver(self, selector: #selector(didEnterBackgroundNotification), name: UIApplication.didEnterBackgroundNotification, object: nil) + + bannerAd.loadAd() + } + +} + +//MARK: -------------- SPBannerAdDelegate -------------- +extension SPBannerAdManager: SPBannerAdDelegate { + + ///广告加载失败 + func bannerAd(bannerAd: SPBannerAd, didLoadFail error: Error) { + self.requestStatAd(type: "load_failed", errorMsg: error.localizedDescription) + self.delegate?.bannerAdManager?(adManager: self, didLoadFail: error) + } + ///广告加载成功 + func bannerAdDidLoadFinish(bannerAd: SPBannerAd) { + self.requestStatAd(type: "start", errorMsg: nil) + self.delegate?.bannerAdManagerDidLoadFinish?(adManager: self) + } + ///广告被展示 + func bannerAdDidShow(bannerAd: SPBannerAd) { + self.delegate?.bannerAdManagerDidShow?(adManager: self) + } + ///广告被关闭 + func bannerAdDidDismiss(bannerAd: SPBannerAd) { + self.requestStatAd(type: "close", errorMsg: nil) + self.delegate?.bannerAdManagerDidDismiss?(adManager: self) + } + + func bannerAdDidClick(ad: any SPBannerAd) { + self.requestStatAd(type: "click", errorMsg: nil) + } +} + + +//MARK: -------------- 统计 -------------- +extension SPBannerAdManager { + + func requestStatAd(type: String, errorMsg: String?) { + guard self.view.superview != nil else { return } + + let model = SPStatAdModel() + model.type = type + model.ads_id = adUnitID + model.ad_platform_key = SPAdPlatformKey(rawValue: bannerAd.adPlatformKey) + model.error_msg = errorMsg + model.scene = .banner + + SPStatAPI.requestStatAd(model: model) + } + + + @objc private func didEnterBackgroundNotification() { + + self.requestStatAd(type: "Interrupt", errorMsg: nil) + } +} + diff --git a/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager+Admob.swift b/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager+Admob.swift index 363da0e..6cf0efc 100644 --- a/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager+Admob.swift +++ b/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager+Admob.swift @@ -43,7 +43,10 @@ extension SPRewardedAdManager { return (objc_getAssociatedObject(self, &AssociatedKeys.admob_needShowRewardedAd) as? Bool) ?? false } } - + + func admob_isReady() -> Bool { + return admob_rewardedAd != nil ? true : false + } ///加载并展示广告 func admob_loadAndShowRewardedAd(adInfo: SPAdInfo) { @@ -75,7 +78,6 @@ extension SPRewardedAdManager { let request = Request() self.admob_isLoadingRewardedAd = true - spLog(message: "====Ad 加载广告") RewardedAd.load(with: adUnitID, request: request) { [weak self] rewardedAd, error in guard let self = self else { return } self.admob_isLoadingRewardedAd = false @@ -83,7 +85,6 @@ extension SPRewardedAdManager { if let error = error { self.admob_needShowRewardedAd = false self.loadFailHandler(error: error) - spLog(message: "====Ad 广告加载失败") return } self.loadFinishHandler() @@ -94,7 +95,6 @@ extension SPRewardedAdManager { if self.admob_needShowRewardedAd { self.admob_show() } - spLog(message: "====Ad 广告加载成功") } } @@ -102,14 +102,12 @@ extension SPRewardedAdManager { ///展示广告 private func admob_show() { guard let rewardedAd = admob_rewardedAd, self.admob_needShowRewardedAd else { - return print("====Ad wasn't ready.") + return } self.admob_needShowRewardedAd = false // The UIViewController parameter is an optional. rewardedAd.present(from: nil) { [weak self] in - let reward = rewardedAd.adReward - print("Reward received with currency \(reward.amount), amount \(reward.amount.doubleValue)") self?.userDidEarnRewardHandler() // TODO: Reward the user. } @@ -127,13 +125,11 @@ extension SPRewardedAdManager: FullScreenContentDelegate { /// Tells the delegate that the ad will present full screen content. func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) { - print("====Ad will present full screen content.") self.didShowHandler() } /// Tells the delegate that the ad dismissed full screen content. func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) { - print("====Ad did dismiss full screen content.") self.admob_rewardedAd = nil self.didDismissHandler() diff --git a/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager+AppLovin.swift b/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager+AppLovin.swift index 7235302..6ecbe94 100644 --- a/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager+AppLovin.swift +++ b/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager+AppLovin.swift @@ -61,13 +61,13 @@ extension SPRewardedAdManager { func appLovin_loadRewardedAd(adInfo: SPAdInfo) { #if canImport(AppLovinSDK) - if !appLovin_isLoadingRewardedAd { - self.appLovin_isLoadingRewardedAd = true - - appLovin_rewardedAd = MARewardedAd.shared(withAdUnitIdentifier: adInfo.ads_id ?? "") - appLovin_rewardedAd?.delegate = self - appLovin_rewardedAd?.load() - } + if self.appLovin_isLoadingRewardedAd { return } + self.appLovin_isLoadingRewardedAd = true + + + self.appLovin_rewardedAd = MARewardedAd.shared(withAdUnitIdentifier: adInfo.ads_id ?? "") + self.appLovin_rewardedAd?.delegate = self + self.appLovin_rewardedAd?.load() #endif } diff --git a/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager.swift b/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager.swift index 9585cf2..7f76d0f 100644 --- a/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager.swift +++ b/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager.swift @@ -62,7 +62,7 @@ class SPRewardedAdManager: NSObject { func isAdAvailable() -> Bool { guard let adInfo = adInfo else { return false } if adInfo.platform_key == .google { - return admob_rewardedAd != nil ? true : false + return admob_isReady() } else if adInfo.platform_key == .applovin { return appLovin_isReady() } @@ -90,33 +90,21 @@ class SPRewardedAdManager: NSObject { SPHUD.show() } - if let adInfo = adInfo {//已有广告 + guard !isLoadingRewardedAd else { return } + if !isAdAvailable() { + self.isLoadingRewardedAd = true + } + + self.requestAdInfo { [weak self] adInfo in + guard let self = self else { return } + if adInfo.platform_key == .google { self.admob_loadAndShowRewardedAd(adInfo: adInfo) } else if adInfo.platform_key == .applovin { self.appLovin_loadAndShowRewardedAd(adInfo: adInfo) - } - - } else { - guard !isLoadingRewardedAd else { return } - self.isLoadingRewardedAd = true - - SPAdAPI.requestShowAdInfo { [weak self] adInfo in - guard let self = self else { return } - guard let adInfo = adInfo else { - let text = "movia_no_ads_tip".localized - let error = NSError(domain: text.localized, code: -1) - loadFailHandler(isStat: false, error: error) - return - } - self.adInfo = adInfo - if adInfo.platform_key == .google { - self.admob_loadAndShowRewardedAd(adInfo: adInfo) - } else if adInfo.platform_key == .applovin { - self.appLovin_loadAndShowRewardedAd(adInfo: adInfo) - } else { - self.adInfo = nil - } + } else { + self.isLoadingRewardedAd = false + self.adInfo = nil } } } @@ -125,25 +113,20 @@ class SPRewardedAdManager: NSObject { func preloadRewardedAd() { guard isEnable else { return } guard !isLoadingRewardedAd else { return } - guard self.adInfo == nil else { return } isShowLoading = false isShowToast = false self.isLoadingRewardedAd = true - SPAdAPI.requestShowAdInfo { [weak self] adInfo in + self.requestAdInfo { [weak self] adInfo in guard let self = self else { return } - guard let adInfo = adInfo else { - self.isLoadingRewardedAd = false - return - } - self.adInfo = adInfo if adInfo.platform_key == .google { self.admob_loadRewardedAd(adInfo: adInfo) } else if adInfo.platform_key == .applovin { self.appLovin_loadRewardedAd(adInfo: adInfo) } else { + self.isLoadingRewardedAd = false self.adInfo = nil } } @@ -169,7 +152,6 @@ class SPRewardedAdManager: NSObject { } private func clean() { - self.adInfo = nil self.statScene = nil self.videoInfo = nil } @@ -256,6 +238,7 @@ extension SPRewardedAdManager { } ///广告被关闭 func didDismissHandler() { + let adInfo = self.adInfo var seconds = 0 if let adsDate = self.adsDate { @@ -264,13 +247,13 @@ extension SPRewardedAdManager { self.requestStatAd(type: "close", seconds: seconds, errorMsg: nil) { [weak self] in guard let self = self else { return } - if let adInfo = self.adInfo { + if let adInfo = adInfo { self.delegate?.rewardedAdManager?(manager: self, didDismiss: adInfo) } - self.clean() - self.preloadRewardedAd() } + self.clean() + self.preloadRewardedAd() } @@ -314,4 +297,25 @@ extension SPRewardedAdManager { func showToast(text: String? = "movia_no_ads_tip".localized) { SPToast.show(text: text) } + + + private func requestAdInfo(completer: ((_ adInfo: SPAdInfo) -> Void)?) { + + if let adInfo = self.adInfo { + completer?(adInfo) + return + } + SPAdAPI.requestShowAdInfo { [weak self] adInfo in + guard let self = self else { return } + + if let adInfo = adInfo { + self.adInfo = adInfo + } else { + self.adInfo = SPAdInfo() + self.adInfo?.platform_key = .google + self.adInfo?.ads_id = SPAdManager.manager.admob_rewardedAdUnitID + } + completer?(self.adInfo!) + } + } } diff --git a/ThimraTV/Libs/AdManager/SPAdManager.swift b/ThimraTV/Libs/AdManager/SPAdManager.swift index 90fb18a..ad904be 100644 --- a/ThimraTV/Libs/AdManager/SPAdManager.swift +++ b/ThimraTV/Libs/AdManager/SPAdManager.swift @@ -17,29 +17,41 @@ class SPAdManager: NSObject { static let manager = SPAdManager() + /// AppLovinSDK 初始化完成回调 + private var appLovininitializeCompleter: (() -> Void)? + func start() { //初始化admob MobileAds.shared.start() -#if canImport(AppLovinSDK) - //初始化 - let initConfig = ALSdkInitializationConfiguration(sdkKey: "XW2aulJv9urKD4MIIFT1xcSCuyTHaDZ9qUbDqygnTLS04GkdX7WMQJviGP5vDRWGsk4OJJIyLGRV3mbLqOWx0W") { builder in - builder.mediationProvider = ALMediationProviderMAX -#if DEBUG - builder.testDeviceAdvertisingIdentifiers = [JXUUID.idfa()] -#endif - } - - // Initialize the SDK with the configuration - ALSdk.shared().initialize(with: initConfig) { sdkConfig in - // Start loading ads - } -#endif - + initialize_applovinSdk(completer: nil) } - + ///初始化AppLovinSDK + func initialize_applovinSdk(completer: (() -> Void)? = nil) { + if completer != nil { + self.appLovininitializeCompleter = completer + } +#if canImport(AppLovinSDK) + if !ALSdk.shared().isInitialized { + //初始化 + let initConfig = ALSdkInitializationConfiguration(sdkKey: "XW2aulJv9urKD4MIIFT1xcSCuyTHaDZ9qUbDqygnTLS04GkdX7WMQJviGP5vDRWGsk4OJJIyLGRV3mbLqOWx0W") { builder in + builder.mediationProvider = ALMediationProviderMAX +//#if DEBUG +// builder.testDeviceAdvertisingIdentifiers = [JXUUID.idfa()] +//#endif + } + + ALSdk.shared().initialize(with: initConfig) { sdkConfig in + // Start loading ads + self.appLovininitializeCompleter?() + } + } else { + self.appLovininitializeCompleter?() + } +#endif + } } @@ -48,31 +60,38 @@ extension SPAdManager { ///谷歌激励广告单元ID var admob_rewardedAdUnitID: String { -#if DEBUG - return "ca-app-pub-3940256099942544/1712485313" -#else - return "" -#endif +//#if DEBUG +// return "ca-app-pub-3940256099942544/1712485313" +//#else +//#endif + return "ca-app-pub-5209443898911659/3535954087" } ///开屏广告的单元ID - var appOpenAdUnitID: String { -#if DEBUG - return "ca-app-pub-3940256099942544/5575463023" -#else - return "" -#endif + var admob_appOpenAdUnitID: String { +//#if DEBUG +// return "ca-app-pub-3940256099942544/5575463023" +//#else +//#endif + return "ca-app-pub-5209443898911659/3886651330" } ///横幅广告单元ID - var bannerAdUnitID: String { -#if DEBUG - return "ca-app-pub-3940256099942544/2435281174" -#else - return "" -#endif + var admob_bannerAdUnitID: String { +//#if DEBUG +// return "ca-app-pub-3940256099942544/2435281174" +//#else +//#endif + return "ca-app-pub-5209443898911659/8858726666" } - + ///开屏广告的单元ID + var applovin_appOpenAdUnitID: String { + return "" + } + ///横幅广告单元ID + var applovin_bannerAdUnitID: String { + return "" + } } diff --git a/ThimraTV/Source/Info.plist b/ThimraTV/Source/Info.plist index be9551c..6e92c3c 100644 --- a/ThimraTV/Source/Info.plist +++ b/ThimraTV/Source/Info.plist @@ -30,7 +30,7 @@ FirebaseAppDelegateProxyEnabled GADApplicationIdentifier - ca-app-pub-3940256099942544~1458002511 + ca-app-pub-5209443898911659~1849745003 LSApplicationQueriesSchemes fbapi @@ -38,618 +38,618 @@ SKAdNetworkItems - - SKAdNetworkIdentifier - 22mmun2rn5.skadnetwork - - - SKAdNetworkIdentifier - 238da6jt44.skadnetwork - - - SKAdNetworkIdentifier - 24t9a8vw3c.skadnetwork - - - SKAdNetworkIdentifier - 24zw6aqk47.skadnetwork - - - SKAdNetworkIdentifier - 252b5q8x7y.skadnetwork - - - SKAdNetworkIdentifier - 275upjj5gd.skadnetwork - - - SKAdNetworkIdentifier - 294l99pt4k.skadnetwork - - - SKAdNetworkIdentifier - 2fnua5tdw4.skadnetwork - - - SKAdNetworkIdentifier - 2u9pt9hc89.skadnetwork - - - SKAdNetworkIdentifier - 32z4fx6l9h.skadnetwork - - - SKAdNetworkIdentifier - 3l6bd9hu43.skadnetwork - - - SKAdNetworkIdentifier - 3qcr597p9d.skadnetwork - - - SKAdNetworkIdentifier - 3qy4746246.skadnetwork - - - SKAdNetworkIdentifier - 3rd42ekr43.skadnetwork - - - SKAdNetworkIdentifier - 3sh42y64q3.skadnetwork - - - SKAdNetworkIdentifier - 424m5254lk.skadnetwork - - - SKAdNetworkIdentifier - 4468km3ulz.skadnetwork - - - SKAdNetworkIdentifier - 44jx6755aq.skadnetwork - - - SKAdNetworkIdentifier - 44n7hlldy6.skadnetwork - - - SKAdNetworkIdentifier - 47vhws6wlr.skadnetwork - - - SKAdNetworkIdentifier - 488r3q3dtq.skadnetwork - - - SKAdNetworkIdentifier - 4dzt52r2t5.skadnetwork - - - SKAdNetworkIdentifier - 4fzdc2evr5.skadnetwork - - - SKAdNetworkIdentifier - 4mn522wn87.skadnetwork - - - SKAdNetworkIdentifier - 4pfyvq9l8r.skadnetwork - - - SKAdNetworkIdentifier - 4w7y6s5ca2.skadnetwork - - - SKAdNetworkIdentifier - 523jb4fst2.skadnetwork - - - SKAdNetworkIdentifier - 52fl2v3hgk.skadnetwork - - - SKAdNetworkIdentifier - 54nzkqm89y.skadnetwork - - - SKAdNetworkIdentifier - 578prtvx9j.skadnetwork - - - SKAdNetworkIdentifier - 5a6flpkh64.skadnetwork - - - SKAdNetworkIdentifier - 5l3tpt7t6e.skadnetwork - - - SKAdNetworkIdentifier - 5lm9lj6jb7.skadnetwork - - - SKAdNetworkIdentifier - 5tjdwbrq8w.skadnetwork - - - SKAdNetworkIdentifier - 6964rsfnh4.skadnetwork - - - SKAdNetworkIdentifier - 6g9af3uyq4.skadnetwork - - - SKAdNetworkIdentifier - 6p4ks3rnbw.skadnetwork - - - SKAdNetworkIdentifier - 6v7lgmsu45.skadnetwork - - - SKAdNetworkIdentifier - 6xzpu9s2p8.skadnetwork - - - SKAdNetworkIdentifier - 737z793b9f.skadnetwork - - - SKAdNetworkIdentifier - 74b6s63p6l.skadnetwork - - - SKAdNetworkIdentifier - 79pbpufp6p.skadnetwork - - - SKAdNetworkIdentifier - 7fmhfwg9en.skadnetwork - - - SKAdNetworkIdentifier - 7rz58n8ntl.skadnetwork - - - SKAdNetworkIdentifier - 7ug5zh24hu.skadnetwork - - - SKAdNetworkIdentifier - 84993kbrcf.skadnetwork - - - SKAdNetworkIdentifier - 89z7zv988g.skadnetwork - - - SKAdNetworkIdentifier - 8c4e2ghe7u.skadnetwork - - - SKAdNetworkIdentifier - 8m87ys6875.skadnetwork - - - SKAdNetworkIdentifier - 8r8llnkz5a.skadnetwork - - - SKAdNetworkIdentifier - 8s468mfl3y.skadnetwork - - - SKAdNetworkIdentifier - 97r2b46745.skadnetwork - - - SKAdNetworkIdentifier - 9b89h5y424.skadnetwork - - - SKAdNetworkIdentifier - 9nlqeag3gk.skadnetwork - - - SKAdNetworkIdentifier - 9rd848q2bz.skadnetwork - - - SKAdNetworkIdentifier - 9t245vhmpl.skadnetwork - - - SKAdNetworkIdentifier - 9vvzujtq5s.skadnetwork - - - SKAdNetworkIdentifier - 9yg77x724h.skadnetwork - - - SKAdNetworkIdentifier - a2p9lx4jpn.skadnetwork - - - SKAdNetworkIdentifier - a7xqa6mtl2.skadnetwork - - - SKAdNetworkIdentifier - a8cz6cu7e5.skadnetwork - - - SKAdNetworkIdentifier - av6w8kgt66.skadnetwork - - - SKAdNetworkIdentifier - b9bk5wbcq9.skadnetwork - - - SKAdNetworkIdentifier - bxvub5ada5.skadnetwork - - - SKAdNetworkIdentifier - c3frkrj4fj.skadnetwork - - - SKAdNetworkIdentifier - c6k4g5qg8m.skadnetwork - - - SKAdNetworkIdentifier - cg4yq2srnc.skadnetwork - - - SKAdNetworkIdentifier - cj5566h2ga.skadnetwork - - - SKAdNetworkIdentifier - cp8zw746q7.skadnetwork - - - SKAdNetworkIdentifier - cs644xg564.skadnetwork - - - SKAdNetworkIdentifier - cstr6suwn9.skadnetwork - - - SKAdNetworkIdentifier - dbu4b84rxf.skadnetwork - - - SKAdNetworkIdentifier - dkc879ngq3.skadnetwork - - - SKAdNetworkIdentifier - dzg6xy7pwj.skadnetwork - - - SKAdNetworkIdentifier - e5fvkxwrpn.skadnetwork - - - SKAdNetworkIdentifier - ecpz2srf59.skadnetwork - - - SKAdNetworkIdentifier - eh6m2bh4zr.skadnetwork - - - SKAdNetworkIdentifier - ejvt5qm6ak.skadnetwork - - - SKAdNetworkIdentifier - f38h382jlk.skadnetwork - - - SKAdNetworkIdentifier - f73kdq92p3.skadnetwork - - - SKAdNetworkIdentifier - f7s53z58qe.skadnetwork - - - SKAdNetworkIdentifier - feyaarzu9v.skadnetwork - - - SKAdNetworkIdentifier - g28c52eehv.skadnetwork - - - SKAdNetworkIdentifier - g2y4y55b64.skadnetwork - - - SKAdNetworkIdentifier - g6gcrrvk4p.skadnetwork - - - SKAdNetworkIdentifier - ggvn48r87g.skadnetwork - - - SKAdNetworkIdentifier - glqzh8vgby.skadnetwork - - - SKAdNetworkIdentifier - gta8lk7p23.skadnetwork - - - SKAdNetworkIdentifier - gta9lk7p23.skadnetwork - - - SKAdNetworkIdentifier - hb56zgv37p.skadnetwork - - - SKAdNetworkIdentifier - hdw39hrw9y.skadnetwork - - - SKAdNetworkIdentifier - hs6bdukanm.skadnetwork - - - SKAdNetworkIdentifier - k674qkevps.skadnetwork - - - SKAdNetworkIdentifier - kbd757ywx3.skadnetwork - - - SKAdNetworkIdentifier - kbmxgpxpgc.skadnetwork - - - SKAdNetworkIdentifier - klf5c3l5u5.skadnetwork - - - SKAdNetworkIdentifier - krvm3zuq6h.skadnetwork - - - SKAdNetworkIdentifier - lr83yxwka7.skadnetwork - - - SKAdNetworkIdentifier - ludvb6z3bs.skadnetwork - - - SKAdNetworkIdentifier - m297p6643m.skadnetwork - - - SKAdNetworkIdentifier - m5mvw97r93.skadnetwork - - - SKAdNetworkIdentifier - m8dbw4sv7c.skadnetwork - - - SKAdNetworkIdentifier - mj797d8u6f.skadnetwork - - - SKAdNetworkIdentifier - mlmmfzh3r3.skadnetwork - - - SKAdNetworkIdentifier - mls7yz5dvl.skadnetwork - - - SKAdNetworkIdentifier - mp6xlyr22a.skadnetwork - - - SKAdNetworkIdentifier - mqn7fxpca7.skadnetwork - - - SKAdNetworkIdentifier - mtkv5xtk9e.skadnetwork - - - SKAdNetworkIdentifier - n38lu8286q.skadnetwork - - - SKAdNetworkIdentifier - n66cz3y3bx.skadnetwork - - - SKAdNetworkIdentifier - n6fk4nfna4.skadnetwork - - - SKAdNetworkIdentifier - n9x2a789qt.skadnetwork - - - SKAdNetworkIdentifier - ns5j362hk7.skadnetwork - - - SKAdNetworkIdentifier - nzq8sh4pbs.skadnetwork - - - SKAdNetworkIdentifier - p78axxw29g.skadnetwork - - - SKAdNetworkIdentifier - ppxm28t8ap.skadnetwork - - - SKAdNetworkIdentifier - prcb7njmu6.skadnetwork - - - SKAdNetworkIdentifier - pwa73g5rt2.skadnetwork - - - SKAdNetworkIdentifier - pwdxu55a5a.skadnetwork - - - SKAdNetworkIdentifier - qqp299437r.skadnetwork - - - SKAdNetworkIdentifier - qu637u8glc.skadnetwork - - - SKAdNetworkIdentifier - r45fhb6rf7.skadnetwork - - - SKAdNetworkIdentifier - rvh3l7un93.skadnetwork - - - SKAdNetworkIdentifier - rx5hdcabgc.skadnetwork - - - SKAdNetworkIdentifier - s39g8k73mm.skadnetwork - - - SKAdNetworkIdentifier - s69wq72ugq.skadnetwork - - - SKAdNetworkIdentifier - su67r6k2v3.skadnetwork - - - SKAdNetworkIdentifier - t38b2kh725.skadnetwork - - - SKAdNetworkIdentifier - tl55sbb4fm.skadnetwork - - - SKAdNetworkIdentifier - u679fj5vs4.skadnetwork - - - SKAdNetworkIdentifier - uw77j35x4d.skadnetwork - - - SKAdNetworkIdentifier - v4nxqhlyqp.skadnetwork - - - SKAdNetworkIdentifier - v72qych5uu.skadnetwork - - - SKAdNetworkIdentifier - v79kvwwj4g.skadnetwork - - - SKAdNetworkIdentifier - v9wttpbfk9.skadnetwork - - - SKAdNetworkIdentifier - vcra2ehyfk.skadnetwork - - - SKAdNetworkIdentifier - vhf287vqwu.skadnetwork - - - SKAdNetworkIdentifier - vutu7akeur.skadnetwork - - - SKAdNetworkIdentifier - w9q455wk68.skadnetwork - - - SKAdNetworkIdentifier - wg4vff78zm.skadnetwork - - - SKAdNetworkIdentifier - wzmmz9fp6w.skadnetwork - - - SKAdNetworkIdentifier - x44k69ngh6.skadnetwork - - - SKAdNetworkIdentifier - x5l83yy675.skadnetwork - - - SKAdNetworkIdentifier - x8jxxk4ff5.skadnetwork - - - SKAdNetworkIdentifier - x8uqf25wch.skadnetwork - - - SKAdNetworkIdentifier - xga6mpmplv.skadnetwork - - - SKAdNetworkIdentifier - xy9t38ct57.skadnetwork - - - SKAdNetworkIdentifier - y45688jllp.skadnetwork - - - SKAdNetworkIdentifier - y5ghdn5j9k.skadnetwork - - - SKAdNetworkIdentifier - yclnxrl5pm.skadnetwork - - - SKAdNetworkIdentifier - ydx93a7ass.skadnetwork - - - SKAdNetworkIdentifier - zmvfpc5aq8.skadnetwork - - - SKAdNetworkIdentifier - zq492l623r.skadnetwork - + + SKAdNetworkIdentifier + 22mmun2rn5.skadnetwork + + + SKAdNetworkIdentifier + 238da6jt44.skadnetwork + + + SKAdNetworkIdentifier + 24t9a8vw3c.skadnetwork + + + SKAdNetworkIdentifier + 24zw6aqk47.skadnetwork + + + SKAdNetworkIdentifier + 252b5q8x7y.skadnetwork + + + SKAdNetworkIdentifier + 275upjj5gd.skadnetwork + + + SKAdNetworkIdentifier + 294l99pt4k.skadnetwork + + + SKAdNetworkIdentifier + 2fnua5tdw4.skadnetwork + + + SKAdNetworkIdentifier + 2u9pt9hc89.skadnetwork + + + SKAdNetworkIdentifier + 32z4fx6l9h.skadnetwork + + + SKAdNetworkIdentifier + 3l6bd9hu43.skadnetwork + + + SKAdNetworkIdentifier + 3qcr597p9d.skadnetwork + + + SKAdNetworkIdentifier + 3qy4746246.skadnetwork + + + SKAdNetworkIdentifier + 3rd42ekr43.skadnetwork + + + SKAdNetworkIdentifier + 3sh42y64q3.skadnetwork + + + SKAdNetworkIdentifier + 424m5254lk.skadnetwork + + + SKAdNetworkIdentifier + 4468km3ulz.skadnetwork + + + SKAdNetworkIdentifier + 44jx6755aq.skadnetwork + + + SKAdNetworkIdentifier + 44n7hlldy6.skadnetwork + + + SKAdNetworkIdentifier + 47vhws6wlr.skadnetwork + + + SKAdNetworkIdentifier + 488r3q3dtq.skadnetwork + + + SKAdNetworkIdentifier + 4dzt52r2t5.skadnetwork + + + SKAdNetworkIdentifier + 4fzdc2evr5.skadnetwork + + + SKAdNetworkIdentifier + 4mn522wn87.skadnetwork + + + SKAdNetworkIdentifier + 4pfyvq9l8r.skadnetwork + + + SKAdNetworkIdentifier + 4w7y6s5ca2.skadnetwork + + + SKAdNetworkIdentifier + 523jb4fst2.skadnetwork + + + SKAdNetworkIdentifier + 52fl2v3hgk.skadnetwork + + + SKAdNetworkIdentifier + 54nzkqm89y.skadnetwork + + + SKAdNetworkIdentifier + 578prtvx9j.skadnetwork + + + SKAdNetworkIdentifier + 5a6flpkh64.skadnetwork + + + SKAdNetworkIdentifier + 5l3tpt7t6e.skadnetwork + + + SKAdNetworkIdentifier + 5lm9lj6jb7.skadnetwork + + + SKAdNetworkIdentifier + 5tjdwbrq8w.skadnetwork + + + SKAdNetworkIdentifier + 6964rsfnh4.skadnetwork + + + SKAdNetworkIdentifier + 6g9af3uyq4.skadnetwork + + + SKAdNetworkIdentifier + 6p4ks3rnbw.skadnetwork + + + SKAdNetworkIdentifier + 6v7lgmsu45.skadnetwork + + + SKAdNetworkIdentifier + 6xzpu9s2p8.skadnetwork + + + SKAdNetworkIdentifier + 737z793b9f.skadnetwork + + + SKAdNetworkIdentifier + 74b6s63p6l.skadnetwork + + + SKAdNetworkIdentifier + 79pbpufp6p.skadnetwork + + + SKAdNetworkIdentifier + 7fmhfwg9en.skadnetwork + + + SKAdNetworkIdentifier + 7rz58n8ntl.skadnetwork + + + SKAdNetworkIdentifier + 7ug5zh24hu.skadnetwork + + + SKAdNetworkIdentifier + 84993kbrcf.skadnetwork + + + SKAdNetworkIdentifier + 89z7zv988g.skadnetwork + + + SKAdNetworkIdentifier + 8c4e2ghe7u.skadnetwork + + + SKAdNetworkIdentifier + 8m87ys6875.skadnetwork + + + SKAdNetworkIdentifier + 8r8llnkz5a.skadnetwork + + + SKAdNetworkIdentifier + 8s468mfl3y.skadnetwork + + + SKAdNetworkIdentifier + 97r2b46745.skadnetwork + + + SKAdNetworkIdentifier + 9b89h5y424.skadnetwork + + + SKAdNetworkIdentifier + 9nlqeag3gk.skadnetwork + + + SKAdNetworkIdentifier + 9rd848q2bz.skadnetwork + + + SKAdNetworkIdentifier + 9t245vhmpl.skadnetwork + + + SKAdNetworkIdentifier + 9vvzujtq5s.skadnetwork + + + SKAdNetworkIdentifier + 9yg77x724h.skadnetwork + + + SKAdNetworkIdentifier + a2p9lx4jpn.skadnetwork + + + SKAdNetworkIdentifier + a7xqa6mtl2.skadnetwork + + + SKAdNetworkIdentifier + a8cz6cu7e5.skadnetwork + + + SKAdNetworkIdentifier + av6w8kgt66.skadnetwork + + + SKAdNetworkIdentifier + b9bk5wbcq9.skadnetwork + + + SKAdNetworkIdentifier + bxvub5ada5.skadnetwork + + + SKAdNetworkIdentifier + c3frkrj4fj.skadnetwork + + + SKAdNetworkIdentifier + c6k4g5qg8m.skadnetwork + + + SKAdNetworkIdentifier + cg4yq2srnc.skadnetwork + + + SKAdNetworkIdentifier + cj5566h2ga.skadnetwork + + + SKAdNetworkIdentifier + cp8zw746q7.skadnetwork + + + SKAdNetworkIdentifier + cs644xg564.skadnetwork + + + SKAdNetworkIdentifier + cstr6suwn9.skadnetwork + + + SKAdNetworkIdentifier + dbu4b84rxf.skadnetwork + + + SKAdNetworkIdentifier + dkc879ngq3.skadnetwork + + + SKAdNetworkIdentifier + dzg6xy7pwj.skadnetwork + + + SKAdNetworkIdentifier + e5fvkxwrpn.skadnetwork + + + SKAdNetworkIdentifier + ecpz2srf59.skadnetwork + + + SKAdNetworkIdentifier + eh6m2bh4zr.skadnetwork + + + SKAdNetworkIdentifier + ejvt5qm6ak.skadnetwork + + + SKAdNetworkIdentifier + f38h382jlk.skadnetwork + + + SKAdNetworkIdentifier + f73kdq92p3.skadnetwork + + + SKAdNetworkIdentifier + f7s53z58qe.skadnetwork + + + SKAdNetworkIdentifier + feyaarzu9v.skadnetwork + + + SKAdNetworkIdentifier + g28c52eehv.skadnetwork + + + SKAdNetworkIdentifier + g2y4y55b64.skadnetwork + + + SKAdNetworkIdentifier + g6gcrrvk4p.skadnetwork + + + SKAdNetworkIdentifier + ggvn48r87g.skadnetwork + + + SKAdNetworkIdentifier + glqzh8vgby.skadnetwork + + + SKAdNetworkIdentifier + gta8lk7p23.skadnetwork + + + SKAdNetworkIdentifier + gta9lk7p23.skadnetwork + + + SKAdNetworkIdentifier + hb56zgv37p.skadnetwork + + + SKAdNetworkIdentifier + hdw39hrw9y.skadnetwork + + + SKAdNetworkIdentifier + hs6bdukanm.skadnetwork + + + SKAdNetworkIdentifier + k674qkevps.skadnetwork + + + SKAdNetworkIdentifier + kbd757ywx3.skadnetwork + + + SKAdNetworkIdentifier + kbmxgpxpgc.skadnetwork + + + SKAdNetworkIdentifier + klf5c3l5u5.skadnetwork + + + SKAdNetworkIdentifier + krvm3zuq6h.skadnetwork + + + SKAdNetworkIdentifier + lr83yxwka7.skadnetwork + + + SKAdNetworkIdentifier + ludvb6z3bs.skadnetwork + + + SKAdNetworkIdentifier + m297p6643m.skadnetwork + + + SKAdNetworkIdentifier + m5mvw97r93.skadnetwork + + + SKAdNetworkIdentifier + m8dbw4sv7c.skadnetwork + + + SKAdNetworkIdentifier + mj797d8u6f.skadnetwork + + + SKAdNetworkIdentifier + mlmmfzh3r3.skadnetwork + + + SKAdNetworkIdentifier + mls7yz5dvl.skadnetwork + + + SKAdNetworkIdentifier + mp6xlyr22a.skadnetwork + + + SKAdNetworkIdentifier + mqn7fxpca7.skadnetwork + + + SKAdNetworkIdentifier + mtkv5xtk9e.skadnetwork + + + SKAdNetworkIdentifier + n38lu8286q.skadnetwork + + + SKAdNetworkIdentifier + n66cz3y3bx.skadnetwork + + + SKAdNetworkIdentifier + n6fk4nfna4.skadnetwork + + + SKAdNetworkIdentifier + n9x2a789qt.skadnetwork + + + SKAdNetworkIdentifier + ns5j362hk7.skadnetwork + + + SKAdNetworkIdentifier + nzq8sh4pbs.skadnetwork + + + SKAdNetworkIdentifier + p78axxw29g.skadnetwork + + + SKAdNetworkIdentifier + ppxm28t8ap.skadnetwork + + + SKAdNetworkIdentifier + prcb7njmu6.skadnetwork + + + SKAdNetworkIdentifier + pwa73g5rt2.skadnetwork + + + SKAdNetworkIdentifier + pwdxu55a5a.skadnetwork + + + SKAdNetworkIdentifier + qqp299437r.skadnetwork + + + SKAdNetworkIdentifier + qu637u8glc.skadnetwork + + + SKAdNetworkIdentifier + r45fhb6rf7.skadnetwork + + + SKAdNetworkIdentifier + rvh3l7un93.skadnetwork + + + SKAdNetworkIdentifier + rx5hdcabgc.skadnetwork + + + SKAdNetworkIdentifier + s39g8k73mm.skadnetwork + + + SKAdNetworkIdentifier + s69wq72ugq.skadnetwork + + + SKAdNetworkIdentifier + su67r6k2v3.skadnetwork + + + SKAdNetworkIdentifier + t38b2kh725.skadnetwork + + + SKAdNetworkIdentifier + tl55sbb4fm.skadnetwork + + + SKAdNetworkIdentifier + u679fj5vs4.skadnetwork + + + SKAdNetworkIdentifier + uw77j35x4d.skadnetwork + + + SKAdNetworkIdentifier + v4nxqhlyqp.skadnetwork + + + SKAdNetworkIdentifier + v72qych5uu.skadnetwork + + + SKAdNetworkIdentifier + v79kvwwj4g.skadnetwork + + + SKAdNetworkIdentifier + v9wttpbfk9.skadnetwork + + + SKAdNetworkIdentifier + vcra2ehyfk.skadnetwork + + + SKAdNetworkIdentifier + vhf287vqwu.skadnetwork + + + SKAdNetworkIdentifier + vutu7akeur.skadnetwork + + + SKAdNetworkIdentifier + w9q455wk68.skadnetwork + + + SKAdNetworkIdentifier + wg4vff78zm.skadnetwork + + + SKAdNetworkIdentifier + wzmmz9fp6w.skadnetwork + + + SKAdNetworkIdentifier + x44k69ngh6.skadnetwork + + + SKAdNetworkIdentifier + x5l83yy675.skadnetwork + + + SKAdNetworkIdentifier + x8jxxk4ff5.skadnetwork + + + SKAdNetworkIdentifier + x8uqf25wch.skadnetwork + + + SKAdNetworkIdentifier + xga6mpmplv.skadnetwork + + + SKAdNetworkIdentifier + xy9t38ct57.skadnetwork + + + SKAdNetworkIdentifier + y45688jllp.skadnetwork + + + SKAdNetworkIdentifier + y5ghdn5j9k.skadnetwork + + + SKAdNetworkIdentifier + yclnxrl5pm.skadnetwork + + + SKAdNetworkIdentifier + ydx93a7ass.skadnetwork + + + SKAdNetworkIdentifier + zmvfpc5aq8.skadnetwork + + + SKAdNetworkIdentifier + zq492l623r.skadnetwork + UIAppFonts