From a399554e5832aaf0a56bbdec903fd463ee9802f1 Mon Sep 17 00:00:00 2001 From: zeng Date: Fri, 11 Jul 2025 17:43:00 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0applovin=E5=B9=BF=E5=91=8A?= =?UTF-8?q?=EF=BC=8C=E5=B9=BF=E5=91=8A=E6=B5=81=E7=A8=8B=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ThimraTV/AppDelegate/SceneDelegate.swift | 2 +- ThimraTV/Base/Networking/API/SPAdAPI.swift | 10 ++- .../SPWebViewController+ScriptMessage.swift | 6 ++ .../Controller/SPMineViewController.swift | 7 ++- .../ViewModel/SPPlayerListViewModel.swift | 6 ++ .../AppOpenAd/SPAppOpenAdManager.swift | 5 +- .../Libs/AdManager/BannerAd/SPBannerAd.swift | 6 +- .../SPRewardedAdManager+Admob.swift | 2 +- .../SPRewardedAdManager+AppLovin.swift | 63 +++++++++---------- .../RewardedAd/SPRewardedAdManager.swift | 21 +++++-- ThimraTV/Libs/AdManager/SPAdInfo.swift | 1 + ThimraTV/Libs/AdManager/SPAdManager.swift | 52 ++++++++++++--- ThimraTV/Libs/User/SPUserInfo.swift | 27 ++++---- 13 files changed, 138 insertions(+), 70 deletions(-) diff --git a/ThimraTV/AppDelegate/SceneDelegate.swift b/ThimraTV/AppDelegate/SceneDelegate.swift index 601c861..8b73b19 100644 --- a/ThimraTV/AppDelegate/SceneDelegate.swift +++ b/ThimraTV/AppDelegate/SceneDelegate.swift @@ -122,7 +122,7 @@ extension SceneDelegate { window?.rootViewController = guideVc window?.makeKeyAndVisible() - } else if !SPAPPTool.isAppOpen, hasOpenApp == true, SPNetworkReachabilityManager.manager.isReachable == true { //开屏广告 + } else if !SPAPPTool.isAppOpen, hasOpenApp == true, SPNetworkReachabilityManager.manager.isReachable == true, SPLoginManager.manager.userInfo?.user_level == .ad { //开屏广告 let openAdVC = SPAppOpenAdViewController() openAdVC.didEndBlock = { [weak self] in self?.handleOpenApp() diff --git a/ThimraTV/Base/Networking/API/SPAdAPI.swift b/ThimraTV/Base/Networking/API/SPAdAPI.swift index b89fb3b..c514125 100644 --- a/ThimraTV/Base/Networking/API/SPAdAPI.swift +++ b/ThimraTV/Base/Networking/API/SPAdAPI.swift @@ -15,7 +15,15 @@ class SPAdAPI { param.method = .get SPNetwork.request(parameters: param) { (response: SPNetworkResponse) in - completer?(response.data?.ad) + if response.code != SPNetworkCodeSucceed || response.data?.ad?.platform_key == nil { + let adInfo = SPAdInfo() + adInfo.platform_key = .google + adInfo.ads_id = SPAdManager.manager.admob_rewardedAdUnitID + completer?(adInfo) + } else { + completer?(response.data?.ad) + } + } } diff --git a/ThimraTV/Base/WebView/SPWebViewController+ScriptMessage.swift b/ThimraTV/Base/WebView/SPWebViewController+ScriptMessage.swift index 179ca7d..3e29c4e 100644 --- a/ThimraTV/Base/WebView/SPWebViewController+ScriptMessage.swift +++ b/ThimraTV/Base/WebView/SPWebViewController+ScriptMessage.swift @@ -77,6 +77,12 @@ extension SPWebViewController { } } else if name == WebMessageOpenCheckSignIn { //点击点到 + + guard SPRewardedAdManager.manager.isAdAvailable() else { + SPRewardedAdManager.manager.showToast() + return + } + self.needAutoRefresh = false let manager = SPRewardedAdManager.manager manager.statScene = .reward diff --git a/ThimraTV/Class/Mine/Controller/SPMineViewController.swift b/ThimraTV/Class/Mine/Controller/SPMineViewController.swift index f0517a1..5df9dd0 100644 --- a/ThimraTV/Class/Mine/Controller/SPMineViewController.swift +++ b/ThimraTV/Class/Mine/Controller/SPMineViewController.swift @@ -118,11 +118,14 @@ extension SPMineViewController { guard SPLoginManager.manager.userInfo?.user_level == .ad else { return } guard needShowRewardedAd else { return } needShowRewardedAd = false - guard SPRewardedAdManager.manager.isEnable else { return } + guard SPRewardedAdManager.manager.isAdAvailable() else { + return + } let manager = SPRewardedAdManager.manager + manager.delegate = nil manager.statScene = .me - manager.loadAndShowRewardedAd() + manager.loadAndShowRewardedAd(isShowToast: false) } } diff --git a/ThimraTV/Class/Player/ViewModel/SPPlayerListViewModel.swift b/ThimraTV/Class/Player/ViewModel/SPPlayerListViewModel.swift index ad23d45..431e2c1 100644 --- a/ThimraTV/Class/Player/ViewModel/SPPlayerListViewModel.swift +++ b/ThimraTV/Class/Player/ViewModel/SPPlayerListViewModel.swift @@ -142,6 +142,12 @@ extension SPPlayerListViewModel { } func adUnlockVideo(finish: (() -> Void)?) { + + guard SPRewardedAdManager.manager.isAdAvailable() else { + SPRewardedAdManager.manager.showToast() + return + } + let manager = SPRewardedAdManager.manager manager.delegate = self manager.videoInfo = self.currentPlayer?.videoInfo diff --git a/ThimraTV/Libs/AdManager/AppOpenAd/SPAppOpenAdManager.swift b/ThimraTV/Libs/AdManager/AppOpenAd/SPAppOpenAdManager.swift index 57e7a9b..7903be5 100644 --- a/ThimraTV/Libs/AdManager/AppOpenAd/SPAppOpenAdManager.swift +++ b/ThimraTV/Libs/AdManager/AppOpenAd/SPAppOpenAdManager.swift @@ -25,9 +25,8 @@ class SPAppOpenAdManager: NSObject { weak var delegate: SPAppOpenAdManagerDelegate? -#if DEBUG - let adUnitID = "ca-app-pub-3940256099942544/5575463023" -#endif + let adUnitID = SPAdManager.manager.appOpenAdUnitID + private var appOpenAd: AppOpenAd? private(set) var isLoadingAd = false diff --git a/ThimraTV/Libs/AdManager/BannerAd/SPBannerAd.swift b/ThimraTV/Libs/AdManager/BannerAd/SPBannerAd.swift index cce665b..93ac466 100644 --- a/ThimraTV/Libs/AdManager/BannerAd/SPBannerAd.swift +++ b/ThimraTV/Libs/AdManager/BannerAd/SPBannerAd.swift @@ -22,9 +22,7 @@ import GoogleMobileAds class SPBannerAd: NSObject { -#if DEBUG - let adUnitID = "ca-app-pub-3940256099942544/2435281174" -#endif + let adUnitID = SPAdManager.manager.bannerAdUnitID let size = CGSize.init(width: kSPScreenWidth, height: 59) @@ -97,7 +95,7 @@ extension SPBannerAd { model.ads_id = adUnitID model.ad_platform_key = .google model.error_msg = errorMsg - model.scene = .splash + model.scene = .banner SPStatAPI.requestStatAd(model: model) } diff --git a/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager+Admob.swift b/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager+Admob.swift index ceaa76f..363da0e 100644 --- a/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager+Admob.swift +++ b/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager+Admob.swift @@ -66,7 +66,7 @@ extension SPRewardedAdManager { guard !self.admob_isLoadingRewardedAd else { return } #if DEBUG - adInfo.ads_id = "ca-app-pub-3940256099942544/1712485313" + adInfo.ads_id = SPAdManager.manager.admob_rewardedAdUnitID #endif let adUnitID = adInfo.ads_id ?? "" diff --git a/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager+AppLovin.swift b/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager+AppLovin.swift index ae5b0b2..23842d9 100644 --- a/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager+AppLovin.swift +++ b/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager+AppLovin.swift @@ -20,7 +20,6 @@ extension SPRewardedAdManager { static var appLovin_rewardedAd: Int? static var appLovin_needShowRewardedAd: Int? static var appLovin_isLoadingRewardedAd: Int? - static var appLovin_retryAttempt: Int? } #if canImport(AppLovinSDK) @@ -33,15 +32,6 @@ extension SPRewardedAdManager { } } - private var appLovin_retryAttempt: CGFloat { - set { - objc_setAssociatedObject(self, &AssociatedKeys.appLovin_retryAttempt, newValue, .OBJC_ASSOCIATION_ASSIGN) - } - get { - return (objc_getAssociatedObject(self, &AssociatedKeys.appLovin_retryAttempt) as? CGFloat) ?? 0 - } - } - ///是否需要展示广告,true广告加载完成会直接展示广告 private var appLovin_needShowRewardedAd: Bool { set { @@ -63,13 +53,22 @@ extension SPRewardedAdManager { } #endif + func appLovin_isReady() -> Bool { +#if canImport(AppLovinSDK) + return appLovin_rewardedAd?.isReady ?? false +#else + return false +#endif + } + ///加载激励广告 - func appLovin_loadRewardedAd() { + func appLovin_loadRewardedAd(adInfo: SPAdInfo) { + #if canImport(AppLovinSDK) if !appLovin_isLoadingRewardedAd { self.appLovin_isLoadingRewardedAd = true - appLovin_rewardedAd = MARewardedAd.shared(withAdUnitIdentifier: appLovin_adUnitID) + appLovin_rewardedAd = MARewardedAd.shared(withAdUnitIdentifier: adInfo.ads_id ?? "") appLovin_rewardedAd?.delegate = self appLovin_rewardedAd?.load() } @@ -77,14 +76,14 @@ extension SPRewardedAdManager { } ///加载并展示广告 - func appLovin_loadAndShowRewardedAd() { + func appLovin_loadAndShowRewardedAd(adInfo: SPAdInfo) { #if canImport(AppLovinSDK) self.appLovin_needShowRewardedAd = true if appLovin_rewardedAd?.isReady == true { self.appLovin_show() } else { - appLovin_loadRewardedAd() + appLovin_loadRewardedAd(adInfo: adInfo) } #endif } @@ -104,55 +103,55 @@ extension SPRewardedAdManager { } #if canImport(AppLovinSDK) +//MARK: -------------- MARewardedAdDelegate -------------- extension SPRewardedAdManager: MARewardedAdDelegate { func didLoad(_ ad: MAAd) { self.appLovin_isLoadingRewardedAd = false - // Rewarded ad is ready to show. '[self.rewardedAd isReady]' now returns 'YES'. - // Reset retry attempt - appLovin_retryAttempt = 0 + loadFinishHandler() appLovin_show() + } func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) { - // Rewarded ad failed to load - // AppLovin recommends that you retry with exponentially higher delays up to a maximum delay (in this case 64 seconds). + self.appLovin_isLoadingRewardedAd = false - appLovin_retryAttempt += 1 - let delaySec = pow(2.0, min(6.0, appLovin_retryAttempt)) - - DispatchQueue.main.asyncAfter(deadline: .now() + delaySec) { - self.appLovin_rewardedAd?.load() - } + let nsError = NSError(domain: error.message, code: error.code.rawValue) + loadFailHandler(error: nsError) } - func didDisplay(_ ad: MAAd) {} + func didDisplay(_ ad: MAAd) { + self.didShowHandler() + } - func didClick(_ ad: MAAd) {} + func didClick(_ ad: MAAd) { + self.didClickHandler() + } func didHide(_ ad: MAAd) { - // Rewarded ad is hidden. Pre-load the next ad - self.appLovin_isLoadingRewardedAd = false - appLovin_loadRewardedAd() + self.didDismissHandler() } func didFail(toDisplay ad: MAAd, withError error: MAError) { // Rewarded ad failed to display. AppLovin recommends that you load the next ad. self.appLovin_isLoadingRewardedAd = false - appLovin_loadRewardedAd() +// appLovin_loadRewardedAd() + + let nsError = NSError(domain: error.message, code: error.code.rawValue) + displayFailHandler(error: nsError) } - // MARK: MARewardedAdDelegate Protocol func didRewardUser(for ad: MAAd, with reward: MAReward) { // Rewarded ad was displayed and user should receive the reward + self.userDidEarnRewardHandler() } diff --git a/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager.swift b/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager.swift index 72a105c..8b993cf 100644 --- a/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager.swift +++ b/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager.swift @@ -63,16 +63,18 @@ class SPRewardedAdManager: NSObject { guard let adInfo = adInfo else { return false } if adInfo.platform_key == .google { return admob_rewardedAd != nil ? true : false + } else if adInfo.platform_key == .applovin { + return appLovin_isReady() } return false } ///加载并展示激励广告 - func loadAndShowRewardedAd(isShowLoading: Bool = true, isShowToast: Bool = true) { + func loadAndShowRewardedAd(isShowLoading: Bool = false, isShowToast: Bool = true) { guard isEnable else { let text = "movia_no_ads_tip".localized if isShowToast { - SPToast.show(text: text) + self.showToast(text: text) } self.isShowToast = false self.isShowLoading = false @@ -91,6 +93,8 @@ class SPRewardedAdManager: NSObject { if let adInfo = adInfo {//已有广告 if adInfo.platform_key == .google { self.admob_loadAndShowRewardedAd(adInfo: adInfo) + } else if adInfo.platform_key == .applovin { + self.appLovin_loadAndShowRewardedAd(adInfo: adInfo) } } else { @@ -108,6 +112,8 @@ class SPRewardedAdManager: NSObject { 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 } @@ -135,6 +141,8 @@ class SPRewardedAdManager: NSObject { 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.adInfo = nil } @@ -186,7 +194,7 @@ extension SPRewardedAdManager { SPHUD.dismiss() } if isShowToast { - SPToast.show(text: "movia_no_ads_tip".localized) + self.showToast() } self.isLoadingRewardedAd = false self.delegate?.rewardedAdManager?(manager: self, didLoadFail: error) @@ -214,7 +222,7 @@ extension SPRewardedAdManager { SPHUD.dismiss() } if isShowToast { - SPToast.show(text: "movia_no_ads_tip".localized) + self.showToast() } self.delegate?.rewardedAdManager?(manager: self, didDisplayFail: error) self.requestStatAd(type: "show_failed", errorMsg: error.localizedDescription) @@ -263,7 +271,6 @@ extension SPRewardedAdManager { } -//MARK: -------------- 统计 -------------- extension SPRewardedAdManager { private func requestStatAd(type: String, seconds: Int = 0, errorMsg: String?, completer: (() -> Void)? = nil) { @@ -288,4 +295,8 @@ extension SPRewardedAdManager { self.requestStatAd(type: "Interrupt", seconds: 0, errorMsg: nil) } + + func showToast(text: String? = "movia_no_ads_tip".localized) { + SPToast.show(text: text) + } } diff --git a/ThimraTV/Libs/AdManager/SPAdInfo.swift b/ThimraTV/Libs/AdManager/SPAdInfo.swift index 83d7aab..488dadd 100644 --- a/ThimraTV/Libs/AdManager/SPAdInfo.swift +++ b/ThimraTV/Libs/AdManager/SPAdInfo.swift @@ -11,6 +11,7 @@ import SmartCodable enum SPAdPlatformKey: String, SmartCaseDefaultable { case google = "google" + case applovin = "applovin" } class SPAdDataModel: SPModel, SmartCodable { diff --git a/ThimraTV/Libs/AdManager/SPAdManager.swift b/ThimraTV/Libs/AdManager/SPAdManager.swift index 95b6030..90fb18a 100644 --- a/ThimraTV/Libs/AdManager/SPAdManager.swift +++ b/ThimraTV/Libs/AdManager/SPAdManager.swift @@ -24,22 +24,56 @@ class SPAdManager: NSObject { #if canImport(AppLovinSDK) //初始化 -// let initConfig = ALSdkInitializationConfiguration(sdkKey: "«SDK-key»") { builder in -// builder.mediationProvider = ALMediationProviderMAX -// } -// -// // Initialize the SDK with the configuration -// ALSdk.shared().initialize(with: initConfig) { sdkConfig in -// // Start loading ads -// } + 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 -// SPRewardedAdManager.manager.preloadRewardedAd() } } +//MARK: -------------- 单元ID -------------- +extension SPAdManager { + + ///谷歌激励广告单元ID + var admob_rewardedAdUnitID: String { +#if DEBUG + return "ca-app-pub-3940256099942544/1712485313" +#else + return "" +#endif + } + + ///开屏广告的单元ID + var appOpenAdUnitID: String { +#if DEBUG + return "ca-app-pub-3940256099942544/5575463023" +#else + return "" +#endif + } + ///横幅广告单元ID + var bannerAdUnitID: String { +#if DEBUG + return "ca-app-pub-3940256099942544/2435281174" +#else + return "" +#endif + } + + +} + diff --git a/ThimraTV/Libs/User/SPUserInfo.swift b/ThimraTV/Libs/User/SPUserInfo.swift index 3ad5cea..bb2a2aa 100644 --- a/ThimraTV/Libs/User/SPUserInfo.swift +++ b/ThimraTV/Libs/User/SPUserInfo.swift @@ -51,23 +51,26 @@ class SPUserInfo: SPModel, SmartCodable, NSSecureCoding { func encode(with coder: NSCoder) { -// coder.encode(id, forKey: "id") -// coder.encode(phone, forKey: "phone") -// coder.encode(userToken, forKey: "userToken") -// coder.encode(ipAddress, forKey: "ipAddress") -// coder.encode(audioNum, forKey: "audioNum") -// coder.encode(audioSeconds, forKey: "audioSeconds") + coder.encode(id, forKey: "id") + coder.encode(customer_id, forKey: "customer_id") + coder.encode(user_level?.rawValue, forKey: "user_level") + coder.encode(is_vip, forKey: "is_vip") + coder.encode(family_name, forKey: "family_name") + coder.encode(giving_name, forKey: "giving_name") } required init?(coder: NSCoder) { super.init() -// id = coder.decodeObject(of: NSString.self, forKey: "id") as? String -// phone = coder.decodeObject(of: NSString.self, forKey: "phone") as? String -// userToken = coder.decodeObject(of: NSString.self, forKey: "userToken") as? String -// ipAddress = coder.decodeObject(of: NSString.self, forKey: "ipAddress") as? String -// audioNum = coder.decodeObject(of: NSNumber.self, forKey: "audioNum")?.intValue -// audioSeconds = coder.decodeObject(of: NSNumber.self, forKey: "audioSeconds")?.intValue + id = coder.decodeObject(of: NSString.self, forKey: "id") as? String + customer_id = coder.decodeObject(of: NSString.self, forKey: "customer_id") as? String + if let user_level = coder.decodeObject(of: NSString.self, forKey: "user_level") as? String { + self.user_level = UserLevel(rawValue: user_level) + } + is_vip = coder.decodeBool(forKey: "is_vip") + family_name = coder.decodeObject(of: NSString.self, forKey: "family_name") as? String + giving_name = coder.decodeObject(of: NSString.self, forKey: "giving_name") as? String + } }