877 lines
36 KiB
Swift
877 lines
36 KiB
Swift
//
|
||
// MP_AppLovinManager.swift
|
||
// relax.offline.mp3.music
|
||
//
|
||
// Created by Mr.Zhou on 2024/9/18.
|
||
//
|
||
|
||
import UIKit
|
||
import AppLovinSDK
|
||
///AppLovin管理器
|
||
class MP_AppLovinManager: NSObject {
|
||
static let shared = MP_AppLovinManager()
|
||
///广告总开关
|
||
private var openAdStatus:Bool = MP_ADSimpleManager.shared.openAdStatus
|
||
///内部使用广告开光
|
||
private var internalAdStatus:Bool = MP_ADSimpleManager.shared.internalAdStatus
|
||
//AppLovin的SDk密钥
|
||
private var SDKKey:String {
|
||
return "1z4AGzagANHydAtmbNQmAcrt1O5_HtPpt4iNTNW5Bb0RQhaXVByUEQTq5cMcR0l9NnfDtuobQqhSQE0kfEWwAC"
|
||
}
|
||
///广告过期时间(50分钟)
|
||
private let expirationTime:TimeInterval = 3000
|
||
|
||
//检测广告是否过期
|
||
private func wasAdexpirationTime(_ date:Date?) -> Bool {
|
||
guard let loadTime = date else { return false }
|
||
// Check if ad was loaded more than four hours ago.
|
||
return Date().timeIntervalSince(loadTime) < expirationTime
|
||
}
|
||
//MARK: - 插页广告总设置
|
||
///插页广告总开关
|
||
private var interstitialSwitch:Bool = false{
|
||
didSet{
|
||
DispatchQueue.main.async {
|
||
[weak self] in
|
||
MPSideA_MediaCenterManager.shared.isAdLate = self?.interstitialSwitch
|
||
}
|
||
}
|
||
}
|
||
///插页广告显示时间
|
||
var interstitialDate:Date?
|
||
///插页广告间隔秒数(默认40秒)
|
||
private var interstitialDuration:TimeInterval{
|
||
get{
|
||
if let times = UserDefaults.standard.object(forKey: "InterstitialDuration") as? TimeInterval {
|
||
return times
|
||
}else {
|
||
return 40
|
||
}
|
||
}
|
||
}
|
||
///中介间隔秒数
|
||
private var intermediaryDuration:TimeInterval{
|
||
get{
|
||
if let times = UserDefaults.standard.object(forKey: "IntermediaryDuration") as? TimeInterval {
|
||
return times
|
||
}else {
|
||
return 40
|
||
}
|
||
}
|
||
}
|
||
///设置插页总开关
|
||
func setInterstitialSwitch(_ status:Bool) {
|
||
interstitialSwitch = status
|
||
}
|
||
///获得插页开关的状态
|
||
func getInterstitialSwitch() -> Bool {
|
||
return interstitialSwitch
|
||
}
|
||
///开屏中介记录时间值
|
||
private var intermediaryOpenShowTime:Date?
|
||
///插页中介记录时间值
|
||
private var intermediaryInterstitialShowTime:Date?
|
||
///检索与插页广告之间的中介间隔时长是否达标
|
||
private func retrieveIntermediaryInterstitial() -> Bool {
|
||
//判断插页中介记录时间值是否存在
|
||
guard let date = intermediaryInterstitialShowTime else {return true}
|
||
return Date().timeIntervalSince(date) > intermediaryDuration
|
||
}
|
||
///检索与开屏广告之间的中介间隔时长是否达标
|
||
private func retrieveIntermediaryOpen() -> Bool {
|
||
//判断插页中介记录时间值是否存在
|
||
guard let date = intermediaryOpenShowTime else {return true}
|
||
return Date().timeIntervalSince(date) > intermediaryDuration
|
||
}
|
||
///是否达到插页间隔时长(达到即可继续展示插页广告)
|
||
private func isShowInterstitialADAvailable(_ date:Date) -> Bool {
|
||
return Date().timeIntervalSince(date) > interstitialDuration
|
||
}
|
||
override init() {
|
||
super.init()
|
||
reloadAppLovinIDs()
|
||
//对开屏广告完成处理闭包
|
||
completeOpenAdBlock = {
|
||
[weak self] in
|
||
guard let self = self, interstitialSwitch == true else {return}
|
||
//销毁现在的开屏广告实例
|
||
appOpenAd = nil
|
||
isShowingOpenAd = false
|
||
loadOpenAdTime = nil
|
||
//关闭插页广告开关
|
||
interstitialSwitch = false
|
||
//更新开屏广告中介间隔时间
|
||
intermediaryOpenShowTime = Date()
|
||
//重新加载后续的开屏广告
|
||
DispatchQueue.main.asyncAfter(deadline: .now() + 4) {
|
||
[weak self] in
|
||
self?.loadOpenAd{ status in
|
||
if status == true {
|
||
print("新的开屏广告加载成功")
|
||
}else {
|
||
print("开屏广告加载失败了")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//搜索插页广告完成处理闭包
|
||
completeSearchInterstitialAdBlock = {
|
||
[weak self] in
|
||
guard let self = self, interstitialSwitch == true else {return}
|
||
//销毁现在的搜索插页广告实例
|
||
searchInterstitialAd = nil
|
||
isShowingSearchInterstitialAd = false
|
||
loadSearchInterstitialAdTime = nil
|
||
//关闭插页广告开关
|
||
interstitialSwitch = false
|
||
//更新插页广告中介间隔时长
|
||
intermediaryInterstitialShowTime = Date()
|
||
//重新加载后续的搜索插页广告
|
||
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
|
||
[weak self] in
|
||
self?.loadSearchInterstitialAd { status in
|
||
if status {
|
||
print("成功加载搜索插页广告")
|
||
}else {
|
||
print("搜索插页广告加载失败")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//播放插页广告完成处理闭包
|
||
completePlayInterstitialAdBlock = {
|
||
[weak self] in
|
||
guard let self = self, interstitialSwitch == true else {return}
|
||
//销毁现在的播放插页广告实例
|
||
playInterstitialAd = nil
|
||
isShowingPlayInterstitialAd = false
|
||
loadPlayInterstitialAdTime = nil
|
||
//关闭插页广告开关
|
||
interstitialSwitch = false
|
||
//更新插页广告中介间隔时长
|
||
intermediaryInterstitialShowTime = Date()
|
||
//重新加载后续的播放插页广告
|
||
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
|
||
[weak self] in
|
||
self?.loadPlayInterstitialAd { status in
|
||
if status {
|
||
print("成功加载播放插页广告")
|
||
}else {
|
||
print("播放插页广告加载失败")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//曲库插页广告完成处理闭包
|
||
completeLibraryInterstitialAdBlock = {
|
||
[weak self] in
|
||
guard let self = self, interstitialSwitch == true else {return}
|
||
//销毁现在的曲库插页广告实例
|
||
libraryInterstitialAd = nil
|
||
isShowingLibraryInterstitialAd = false
|
||
loadLibraryInterstitialAdTime = nil
|
||
//关闭插页广告开关
|
||
interstitialSwitch = false
|
||
//更新插页广告中介间隔时长
|
||
intermediaryInterstitialShowTime = Date()
|
||
//重新加载后续的曲库插页广告
|
||
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
|
||
[weak self] in
|
||
self?.loadLibraryInterstitialAd { status in
|
||
if status {
|
||
print("成功加载曲库插页广告")
|
||
}else {
|
||
print("曲库插页广告加载失败")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
///初始化
|
||
func startConfig() {
|
||
//AppLovin初始化配置
|
||
let initConfig = ALSdkInitializationConfiguration(sdkKey: SDKKey) { builder in
|
||
builder.mediationProvider = ALMediationProviderMAX
|
||
}
|
||
// //设置全部静音
|
||
// ALSdk.shared().settings.isMuted = true
|
||
ALSdk.shared().settings.userIdentifier = app_UUID
|
||
//AppLovin初始化
|
||
ALSdk.shared().initialize(with: initConfig)
|
||
}
|
||
///更新广告ID
|
||
func reloadAppLovinIDs() {
|
||
//更新要用到的广告信息
|
||
if let data = UserDefaults.standard.object(forKey: "Max_OpenICEIDs") as? Data, let array = jsonforCoreAdModel(data) {
|
||
print("成功提取ID")
|
||
OpenIDs = array.sorted(by: {$0.level > $1.level})
|
||
}
|
||
if let data = UserDefaults.standard.object(forKey: "Max_SearchINSERTIDs") as? Data, let array = jsonforCoreAdModel(data) {
|
||
SearchINSERTIDs = array.sorted(by: {$0.level > $1.level})
|
||
}
|
||
if let data = UserDefaults.standard.object(forKey: "Max_PlayerINSERTIDs") as? Data, let array = jsonforCoreAdModel(data) {
|
||
PlayerINSERTIDs = array.sorted(by: {$0.level > $1.level})
|
||
}
|
||
if let data = UserDefaults.standard.object(forKey: "Max_LibraryNATIVEIDs") as? Data, let array = jsonforCoreAdModel(data) {
|
||
LibraryINSERTIDs = array.sorted(by: {$0.level > $1.level})
|
||
}
|
||
}
|
||
///加载广告
|
||
func loadMoreAds(){
|
||
loadPlayInterstitialAd{status in
|
||
if status {
|
||
print("成功加载播放插页广告")
|
||
}else {
|
||
print("播放插页广告加载失败")
|
||
}
|
||
}
|
||
loadSearchInterstitialAd { status in
|
||
if status {
|
||
print("成功加载搜索插页广告")
|
||
}else {
|
||
print("搜索插页广告加载失败")
|
||
}
|
||
}
|
||
loadLibraryInterstitialAd { status in
|
||
if status {
|
||
print("成功加载曲库插页广告")
|
||
}else {
|
||
print("曲库插页广告加载失败")
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
//MARK: - 开屏广告
|
||
///开屏广告ID组
|
||
private var OpenIDs:[MPPositive_AdItemModel] = []
|
||
///开屏广告
|
||
var appOpenAd:MAInterstitialAd?
|
||
///是否正在加载开屏广告
|
||
private var isLoadingOpenAd:Bool = false
|
||
///是否正在展示开屏广告
|
||
var isShowingOpenAd:Bool = false
|
||
//开屏广告加载时间
|
||
private var loadOpenAdTime:Date?
|
||
//开屏广告回调传值闭包
|
||
private var loadStatuOpenAdBlock:((Bool) -> Void)?
|
||
//开屏广告加载完成处理闭包
|
||
var completeOpenAdBlock:(() -> Void)?
|
||
//当前加载的ID数组Level阶级(从0开始,越低等级越高)
|
||
private var openLevel:Int = 0
|
||
//开屏广告时间间隔(默认10秒)
|
||
private var openAppDuration:TimeInterval{
|
||
get{
|
||
if let times = UserDefaults.standard.object(forKey: "OpenAppDuration") as? TimeInterval {
|
||
return times
|
||
}else {
|
||
return 10
|
||
}
|
||
}
|
||
}
|
||
//设置开屏广告时间间隔
|
||
func setOpenAppDuration(_ duration:TimeInterval) {
|
||
UserDefaults.standard.set(duration, forKey: "OpenAppDuration")
|
||
}
|
||
//获取开屏广告时间间隔
|
||
func getOpenAppDuration() -> TimeInterval {
|
||
return self.openAppDuration
|
||
}
|
||
///加载开屏广告
|
||
func loadOpenAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
||
guard openAdStatus, internalAdStatus else {return}
|
||
// 检测当前是否有广告或者有广告正在加载
|
||
if isLoadingOpenAd || isOpenAdAvailable() {
|
||
// 有广告或有广告在加载
|
||
completion(false)
|
||
return
|
||
}
|
||
//检索是否超过了对应的id组的阶级数量
|
||
guard OpenIDs.isEmpty == false else {
|
||
//冷启动无数据
|
||
MP_AnalyticsManager.shared.max_lunch_showFailureAction("No IDs")
|
||
//重新获取数据
|
||
reloadAppLovinIDs()
|
||
completion(false)
|
||
return
|
||
}
|
||
guard level < (OpenIDs.count) else {
|
||
print("开屏广告组已经全部加载失败,停止继续加载")
|
||
MP_AnalyticsManager.shared.max_lunch_loadFailureAction("No Ads Fill")
|
||
completion(false)
|
||
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
||
[weak self] in
|
||
self?.loadOpenAd( completion: { status in
|
||
if status {
|
||
print("重新加载启动广告成功")
|
||
}else {
|
||
print("重新加载启动广告失败")
|
||
}
|
||
})
|
||
}
|
||
return
|
||
}
|
||
let item = OpenIDs[level]
|
||
openLevel = level
|
||
//重置闭包导向
|
||
loadStatuOpenAdBlock = completion
|
||
//根据ID生成广告
|
||
appOpenAd = MAInterstitialAd(adUnitIdentifier: item.identifier)
|
||
appOpenAd?.delegate = self
|
||
//加载开屏广告
|
||
appOpenAd?.load()
|
||
}
|
||
///展示加载广告
|
||
func showOpenAdIfAvailable(_ completion:((_ T:MAInterstitialAd) -> Void)?) {
|
||
guard openAdStatus, internalAdStatus else {return}
|
||
// 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。
|
||
guard !interstitialSwitch, !isShowingOpenAd, retrieveIntermediaryInterstitial() else { return }
|
||
// 如果应用开屏广告尚不可用但应该显示,则加载新广告。
|
||
if !isOpenAdAvailable() {
|
||
loadOpenAd{ [weak self] success in
|
||
guard let self = self else { return }
|
||
if success {
|
||
self.showOpenAdIfAvailable(completion)
|
||
}
|
||
}
|
||
return
|
||
}
|
||
MP_AnalyticsManager.shared.max_lunch_chanceAction()
|
||
if let ad = appOpenAd, ad.isReady {
|
||
//传递加载完成事件
|
||
if let block = completion {
|
||
block(ad)
|
||
}else {
|
||
isShowingOpenAd = true
|
||
interstitialSwitch = true
|
||
DispatchQueue.main.async {
|
||
[weak self] in
|
||
guard let self = self else {return}
|
||
//可以展示
|
||
ad.show()
|
||
}
|
||
}
|
||
}else {
|
||
print("开屏广告展示失败")
|
||
MP_AnalyticsManager.shared.max_lunch_showFailureAction("Ad loading failed")
|
||
}
|
||
}
|
||
///查询是否有开屏广告
|
||
func isOpenAdAvailable() -> Bool {
|
||
return (appOpenAd != nil) && wasAdexpirationTime(loadOpenAdTime)
|
||
}
|
||
//MARK: - 搜索
|
||
///搜索插页广告ID
|
||
private var SearchINSERTIDs:[MPPositive_AdItemModel] = []
|
||
///搜索插页广告
|
||
private var searchInterstitialAd:MAInterstitialAd?
|
||
///是否正在加载搜索插页广告
|
||
private var isLoadingSearchInterstitialAd:Bool = false
|
||
///是否正在展示搜索插页广告
|
||
var isShowingSearchInterstitialAd:Bool = false
|
||
///搜索插页加载时间
|
||
private var loadSearchInterstitialAdTime:Date?
|
||
///搜索广告处理闭包
|
||
var completeSearchInterstitialAdBlock:(() -> Void)?
|
||
//开屏广告回调传值闭包
|
||
private var loadStatuSearchAdBlock:((Bool) -> Void)?
|
||
//当前加载的ID数组Level阶级(从0开始,越低等级越高)
|
||
private var searchLevel:Int = 0
|
||
//异步加载搜索插页广告
|
||
func loadSearchInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
||
guard openAdStatus, internalAdStatus else {return}
|
||
if isLoadingSearchInterstitialAd || isSearchInterstitialAdAvailable() {
|
||
// 有广告或有广告在加载
|
||
completion(false)
|
||
return
|
||
}
|
||
guard SearchINSERTIDs.isEmpty == false else {
|
||
MP_AnalyticsManager.shared.max_search_showFailureAction("No IDs")
|
||
//重新获取数据
|
||
reloadAppLovinIDs()
|
||
completion(false)
|
||
return
|
||
}
|
||
guard level < (SearchINSERTIDs.count) else {
|
||
print("搜索插页广告组已经全部加载失败,停止继续加载")
|
||
MP_AnalyticsManager.shared.max_search_loadFailureAction("No Ads Fill")
|
||
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
|
||
[weak self] in
|
||
self?.loadSearchInterstitialAd { status in
|
||
if status {
|
||
print("重新加载搜索插页广告")
|
||
}else {
|
||
print("加载搜索插页广告失败")
|
||
}
|
||
}
|
||
}
|
||
return
|
||
}
|
||
isLoadingSearchInterstitialAd = true
|
||
searchLevel = level
|
||
//重置闭包导向
|
||
loadStatuSearchAdBlock = completion
|
||
let item = SearchINSERTIDs[level]
|
||
//根据ID生成广告
|
||
searchInterstitialAd = MAInterstitialAd(adUnitIdentifier: item.identifier)
|
||
searchInterstitialAd?.delegate = self
|
||
//加载开屏广告
|
||
searchInterstitialAd?.load()
|
||
}
|
||
///搜索插页广告展示
|
||
func showSearchInterstitialAdIfAvailable(_ completion:((MAInterstitialAd) -> Void)?) {
|
||
guard openAdStatus, internalAdStatus else {return}
|
||
// 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。
|
||
guard !interstitialSwitch, !isShowingSearchInterstitialAd, retrieveIntermediaryOpen() else { return }
|
||
//检索是否存在插页间隔时间
|
||
if let date = interstitialDate {
|
||
if isShowInterstitialADAvailable(date) == false {
|
||
//未超过插页间隔时长
|
||
print("距上一次展示插页广告时长未超过要求,此次插页广告展示滞后")
|
||
return
|
||
}
|
||
}
|
||
// 如果搜索广告尚不可用但应该显示,则加载新广告。
|
||
if !isSearchInterstitialAdAvailable() {
|
||
loadSearchInterstitialAd { [weak self] success in
|
||
guard let self = self else { return }
|
||
if success {
|
||
self.showSearchInterstitialAdIfAvailable(completion)
|
||
}
|
||
}
|
||
return
|
||
}
|
||
MP_AnalyticsManager.shared.max_search_chanceAction()
|
||
//当搜索插页广告确定有值后展示
|
||
if let ad = searchInterstitialAd, ad.isReady {
|
||
//传递加载完成事件
|
||
if let block = completion {
|
||
block(ad)
|
||
}else {
|
||
isShowingSearchInterstitialAd = true
|
||
interstitialSwitch = true
|
||
DispatchQueue.main.async {
|
||
[weak self] in
|
||
guard let self = self else {return}
|
||
//可以展示
|
||
ad.show()
|
||
}
|
||
}
|
||
}else {
|
||
MP_AnalyticsManager.shared.max_search_showFailureAction("Ad loading failed")
|
||
}
|
||
}
|
||
//查询是否有搜索插页广告
|
||
func isSearchInterstitialAdAvailable() -> Bool {
|
||
return searchInterstitialAd != nil && wasAdexpirationTime(loadSearchInterstitialAdTime)
|
||
}
|
||
//MARK: - 播放/切割插页广告位
|
||
///播放插页广告ID
|
||
private var PlayerINSERTIDs:[MPPositive_AdItemModel] = []
|
||
///播放插页广告
|
||
var playInterstitialAd:MAInterstitialAd?
|
||
///是否正在加载播放插页广告
|
||
private var isLoadingPlayInterstitialAd:Bool = false
|
||
///是否正在展示播放插页广告
|
||
var isShowingPlayInterstitialAd:Bool = false
|
||
///播放插页加载时间
|
||
private var loadPlayInterstitialAdTime:Date?
|
||
///播放广告处理闭包
|
||
var completePlayInterstitialAdBlock:(() -> Void)?
|
||
//开屏广告回调传值闭包
|
||
private var loadStatuPlayAdBlock:((Bool) -> Void)?
|
||
//当前加载的ID数组Level阶级(从0开始,越低等级越高)
|
||
private var playLevel:Int = 0
|
||
//异步加载播放插页广告
|
||
func loadPlayInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
||
guard openAdStatus, internalAdStatus else {
|
||
completion(false)
|
||
return
|
||
}
|
||
// 检测当前是否有广告或者有广告正在加载
|
||
if isLoadingPlayInterstitialAd || isPlayInterstitialAdAvailable() {
|
||
// 有广告或有广告在加载
|
||
completion(false)
|
||
return
|
||
}
|
||
guard PlayerINSERTIDs.isEmpty == false else {
|
||
MP_AnalyticsManager.shared.max_play_showFailureAction("No IDs")
|
||
//重新获取数据
|
||
reloadAppLovinIDs()
|
||
completion(false)
|
||
return
|
||
}
|
||
|
||
guard level < (PlayerINSERTIDs.count) else {
|
||
print("播放插页广告组已经全部加载失败,停止继续加载")
|
||
MP_AnalyticsManager.shared.max_play_loadFailureAction("No Ads Fill")
|
||
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
|
||
[weak self] in
|
||
self?.loadPlayInterstitialAd { status in
|
||
if status {
|
||
print("重新加载播放插页广告")
|
||
}else {
|
||
print("加载播放插页广告失败")
|
||
}
|
||
}
|
||
}
|
||
return
|
||
}
|
||
isLoadingPlayInterstitialAd = true
|
||
playLevel = level
|
||
//重置闭包导向
|
||
loadStatuPlayAdBlock = completion
|
||
let item = PlayerINSERTIDs[level]
|
||
//根据ID生成广告
|
||
playInterstitialAd = MAInterstitialAd(adUnitIdentifier: item.identifier)
|
||
playInterstitialAd?.delegate = self
|
||
//加载开屏广告
|
||
playInterstitialAd?.load()
|
||
}
|
||
///播放插页广告展示
|
||
func showPlayInterstitialAdIfAvailable(_ completion:((MAInterstitialAd?) -> Void)?) {
|
||
guard openAdStatus, internalAdStatus else {
|
||
completion?(nil)
|
||
return
|
||
}
|
||
guard MP_NetWorkManager.shared.netWorkStatu == .reachable else {
|
||
completion?(nil)
|
||
return
|
||
}
|
||
// 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。
|
||
guard !interstitialSwitch, !isShowingPlayInterstitialAd, retrieveIntermediaryOpen() else {
|
||
completion?(nil)
|
||
return
|
||
}
|
||
//检索是否存在插页间隔时间
|
||
if let date = interstitialDate {
|
||
if isShowInterstitialADAvailable(date) == false {
|
||
//未超过插页间隔时长
|
||
print("距上一次展示插页广告时长未超过要求,此次插页广告展示滞后")
|
||
completion?(nil)
|
||
return
|
||
}
|
||
}
|
||
// 如果播放插页广告尚不可用但应该显示,则加载新广告。
|
||
if !isPlayInterstitialAdAvailable() {
|
||
loadPlayInterstitialAd{ [weak self] success in
|
||
guard let self = self else { return }
|
||
if success {
|
||
print("播放广告已加载")
|
||
}
|
||
}
|
||
completion?(nil)
|
||
return
|
||
}
|
||
MP_AnalyticsManager.shared.max_play_chanceACtion()
|
||
//当播放插页广告确定有值后展示
|
||
if let ad = playInterstitialAd, ad.isReady {
|
||
//传递加载完成事件
|
||
if let block = completion {
|
||
block(ad)
|
||
}else {
|
||
isShowingPlayInterstitialAd = true
|
||
interstitialSwitch = true
|
||
DispatchQueue.main.async {
|
||
[weak self] in
|
||
guard let self = self else {return}
|
||
//可以展示
|
||
ad.show()
|
||
}
|
||
}
|
||
}else {
|
||
MP_AnalyticsManager.shared.max_play_showFailureAction("Ad loading failed")
|
||
completion?(nil)
|
||
}
|
||
}
|
||
//查询是否有播放插页广告
|
||
func isPlayInterstitialAdAvailable() -> Bool {
|
||
return playInterstitialAd != nil && wasAdexpirationTime(loadPlayInterstitialAdTime)
|
||
}
|
||
//MARK: - 曲库/下载插页广告位
|
||
///曲库插页ID
|
||
private var LibraryINSERTIDs:[MPPositive_AdItemModel] = []
|
||
///曲库插页广告
|
||
private var libraryInterstitialAd:MAInterstitialAd?
|
||
///是否正在加载曲库插页广告
|
||
private var isLoadingLibraryInterstitialAd:Bool = false
|
||
///是否正在展示曲库插页广告
|
||
var isShowingLibraryInterstitialAd:Bool = false
|
||
///曲库插页加载时间
|
||
private var loadLibraryInterstitialAdTime:Date?
|
||
///曲库广告处理闭包
|
||
var completeLibraryInterstitialAdBlock:(() -> Void)?
|
||
//开屏广告回调传值闭包
|
||
private var loadStatuLibraryAdBlock:((Bool) -> Void)?
|
||
//当前加载的ID数组Level阶级(从0开始,越低等级越高)
|
||
private var libraryLevel:Int = 0
|
||
//异步加载曲库插页广告
|
||
func loadLibraryInterstitialAd(_ level:Int = 0, completion: @escaping (Bool) -> Void) {
|
||
guard openAdStatus, internalAdStatus else {
|
||
completion(false)
|
||
return
|
||
}
|
||
// 检测当前是否有广告或者有广告正在加载
|
||
if isLoadingLibraryInterstitialAd || isLibraryInterstitialAdAvailable() {
|
||
// 有广告或有广告在加载
|
||
completion(false)
|
||
return
|
||
}
|
||
guard LibraryINSERTIDs.isEmpty == false else {
|
||
MP_AnalyticsManager.shared.max_library_showFailureAction("No IDs")
|
||
//重新获取数据
|
||
reloadAppLovinIDs()
|
||
completion(false)
|
||
return
|
||
}
|
||
guard level < (LibraryINSERTIDs.count) else {
|
||
print("曲库插页广告组已经全部加载失败,停止继续加载")
|
||
MP_AnalyticsManager.shared.max_library_loadFailureAction("No Ads Fill")
|
||
DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
|
||
[weak self] in
|
||
self?.loadLibraryInterstitialAd { status in
|
||
if status {
|
||
print("重新加载曲库插页广告")
|
||
}else {
|
||
print("加载曲库插页广告失败")
|
||
}
|
||
}
|
||
}
|
||
return
|
||
}
|
||
isLoadingLibraryInterstitialAd = true
|
||
libraryLevel = level
|
||
//重置闭包导向
|
||
loadStatuLibraryAdBlock = completion
|
||
let item = LibraryINSERTIDs[level]
|
||
//根据ID生成广告
|
||
libraryInterstitialAd = MAInterstitialAd(adUnitIdentifier: item.identifier)
|
||
libraryInterstitialAd?.delegate = self
|
||
//加载开屏广告
|
||
libraryInterstitialAd?.load()
|
||
}
|
||
///曲库插页广告展示
|
||
func showLibraryInterstitialAdIfAvailable(_ completion:((MAInterstitialAd) -> Void)?) {
|
||
// 如果应用插页广告或者开屏广告已经正在展示,则不再展示该广告。
|
||
guard !interstitialSwitch, !isShowingLibraryInterstitialAd, retrieveIntermediaryOpen() else { return }
|
||
//检索是否存在插页间隔时间
|
||
if let date = interstitialDate {
|
||
if isShowInterstitialADAvailable(date) == false {
|
||
//未超过插页间隔时长
|
||
print("距上一次展示插页广告时长未超过要求,此次插页广告展示滞后")
|
||
return
|
||
}
|
||
}
|
||
// 如果曲库广告尚不可用但应该显示,则加载新广告。
|
||
if !isLibraryInterstitialAdAvailable() {
|
||
loadLibraryInterstitialAd { [weak self] success in
|
||
guard let self = self else { return }
|
||
if success {
|
||
self.showLibraryInterstitialAdIfAvailable(completion)
|
||
}
|
||
}
|
||
return
|
||
}
|
||
MP_AnalyticsManager.shared.max_library_chanceAction()
|
||
//当曲库插页广告确定有值后展示
|
||
if let ad = libraryInterstitialAd, ad.isReady {
|
||
//传递加载完成事件
|
||
if let block = completion {
|
||
block(ad)
|
||
}else {
|
||
isShowingPlayInterstitialAd = true
|
||
interstitialSwitch = true
|
||
DispatchQueue.main.async {
|
||
[weak self] in
|
||
guard let self = self else {return}
|
||
//可以展示
|
||
ad.show()
|
||
}
|
||
}
|
||
}else {
|
||
MP_AnalyticsManager.shared.max_library_showFailureAction("Ad loading failed")
|
||
}
|
||
}
|
||
//查询是否有曲库插页广告
|
||
func isLibraryInterstitialAdAvailable() -> Bool {
|
||
return libraryInterstitialAd != nil && wasAdexpirationTime(loadLibraryInterstitialAdTime)
|
||
}
|
||
}
|
||
//MARK: - 插页广告代理实现
|
||
extension MP_AppLovinManager: MAAdDelegate {
|
||
//广告加载成功
|
||
func didLoad(_ ad: MAAd) {
|
||
let adUnitIdentifier = ad.adUnitIdentifier
|
||
//判断广告位
|
||
if adUnitIdentifier == appOpenAd?.adUnitIdentifier {
|
||
//是开屏广告,调整加载状态
|
||
isLoadingOpenAd = false
|
||
//更新开屏广告加载时间
|
||
loadOpenAdTime = Date()
|
||
//实现开屏广告回调闭包
|
||
if let block = loadStatuOpenAdBlock {
|
||
block(true)
|
||
}
|
||
}else if adUnitIdentifier == searchInterstitialAd?.adUnitIdentifier {
|
||
//是搜索插页广告,调整加载状态
|
||
isLoadingSearchInterstitialAd = false
|
||
//更新搜索插页广告加载时间
|
||
loadSearchInterstitialAdTime = Date()
|
||
//实现搜索插页广告回调闭包
|
||
if let block = loadStatuSearchAdBlock {
|
||
block(true)
|
||
}
|
||
}else if adUnitIdentifier == playInterstitialAd?.adUnitIdentifier {
|
||
//是播放插页广告
|
||
isLoadingPlayInterstitialAd = false
|
||
//更新播放插页广告加载时间
|
||
loadPlayInterstitialAdTime = Date()
|
||
//实现播放插页广告回调闭包
|
||
if let block = loadStatuPlayAdBlock {
|
||
block(true)
|
||
}
|
||
}else if adUnitIdentifier == libraryInterstitialAd?.adUnitIdentifier {
|
||
//是曲库插页广告
|
||
isLoadingLibraryInterstitialAd = false
|
||
//更新曲库插页广告加载时间
|
||
loadLibraryInterstitialAdTime = Date()
|
||
//实现曲库插页广告回调
|
||
if let block = loadStatuLibraryAdBlock {
|
||
block(true)
|
||
}
|
||
}
|
||
}
|
||
//广告加载失败
|
||
func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) {
|
||
//判断广告位
|
||
if adUnitIdentifier == appOpenAd?.adUnitIdentifier {
|
||
//是开屏广告,调整加载状态
|
||
isLoadingOpenAd = false
|
||
//开屏广告加载失败,销毁广告
|
||
appOpenAd = nil
|
||
MP_AnalyticsManager.shared.max_lunch_loadFailureAction(error.message)
|
||
if let block = loadStatuOpenAdBlock {
|
||
//重新加载广告
|
||
loadOpenAd(openLevel + 1, completion: block)
|
||
}
|
||
}else if adUnitIdentifier == searchInterstitialAd?.adUnitIdentifier {
|
||
//是搜索插页广告,调整加载状态
|
||
isLoadingSearchInterstitialAd = false
|
||
searchInterstitialAd = nil
|
||
MP_AnalyticsManager.shared.max_search_loadFailureAction(error.message)
|
||
if let block = loadStatuSearchAdBlock {
|
||
loadSearchInterstitialAd(searchLevel + 1, completion: block)
|
||
}
|
||
}else if adUnitIdentifier == playInterstitialAd?.adUnitIdentifier {
|
||
//是播放插页广告
|
||
isLoadingPlayInterstitialAd = false
|
||
playInterstitialAd = nil
|
||
MP_AnalyticsManager.shared.max_play_loadFailureAction(error.message)
|
||
if let block = loadStatuPlayAdBlock {
|
||
loadPlayInterstitialAd(playLevel + 1, completion: block)
|
||
}
|
||
}else if adUnitIdentifier == libraryInterstitialAd?.adUnitIdentifier {
|
||
//是曲库插页广告
|
||
isLoadingLibraryInterstitialAd = false
|
||
libraryInterstitialAd = nil
|
||
MP_AnalyticsManager.shared.max_library_loadFailureAction(error.message)
|
||
if let block = loadStatuLibraryAdBlock {
|
||
loadLibraryInterstitialAd(libraryLevel + 1, completion: block)
|
||
}
|
||
}
|
||
}
|
||
//广告展示
|
||
func didDisplay(_ ad: MAAd) {
|
||
let adUnitIdentifier = ad.adUnitIdentifier
|
||
//检索广告位
|
||
if adUnitIdentifier == appOpenAd?.adUnitIdentifier {
|
||
//开屏广告
|
||
print("当前展示的广告是开屏广告,广告ID--\(ad.adUnitIdentifier)")
|
||
//上传广告事件
|
||
}else if adUnitIdentifier == searchInterstitialAd?.adUnitIdentifier {
|
||
//搜索广告位
|
||
print("当前展示的广告是搜索插页广告,广告ID--\(ad.adUnitIdentifier)")
|
||
//上传广告事件
|
||
}else if adUnitIdentifier == playInterstitialAd?.adUnitIdentifier {
|
||
//播放广告位
|
||
print("当前展示的广告是播放插页广告,广告ID--\(ad.adUnitIdentifier)")
|
||
}else if adUnitIdentifier == libraryInterstitialAd?.adUnitIdentifier {
|
||
//曲库广告位
|
||
print("当前展示的广告是曲库插页广告,广告ID--\(ad.adUnitIdentifier)")
|
||
}
|
||
}
|
||
//广告关闭
|
||
func didHide(_ ad: MAAd) {
|
||
let adUnitIdentifier = ad.adUnitIdentifier
|
||
//更新插页广告展示时间
|
||
interstitialDate = Date()
|
||
if adUnitIdentifier == appOpenAd?.adUnitIdentifier {
|
||
print("当前消失的广告是开屏广告,广告ID--\(ad.adUnitIdentifier)")
|
||
if let block = completeOpenAdBlock {
|
||
block()
|
||
}
|
||
}else if adUnitIdentifier == searchInterstitialAd?.adUnitIdentifier {
|
||
//搜索广告位
|
||
print("当前消失的广告是搜索插页广告,广告ID--\(ad.adUnitIdentifier)")
|
||
if let block = completeSearchInterstitialAdBlock {
|
||
block()
|
||
}
|
||
}else if adUnitIdentifier == playInterstitialAd?.adUnitIdentifier {
|
||
//播放广告位
|
||
print("当前消失的广告是播放插页广告,广告ID--\(ad.adUnitIdentifier)")
|
||
if let block = completePlayInterstitialAdBlock {
|
||
block()
|
||
}
|
||
}else if adUnitIdentifier == libraryInterstitialAd?.adUnitIdentifier {
|
||
//曲库广告位
|
||
print("当前消失的广告是曲库插页广告,广告ID--\(ad.adUnitIdentifier)")
|
||
if let block = completeLibraryInterstitialAdBlock {
|
||
block()
|
||
}
|
||
}
|
||
DispatchQueue.main.asyncAfter(deadline: .now()+0.1) {
|
||
accessAppdelegate.setAudioActive()
|
||
}
|
||
}
|
||
//广告点击
|
||
func didClick(_ ad: MAAd) {
|
||
|
||
}
|
||
//广告展示失败
|
||
func didFail(toDisplay ad: MAAd, withError error: MAError) {
|
||
let adUnitIdentifier = ad.adUnitIdentifier
|
||
//更新插页广告展示时间
|
||
interstitialDate = Date()
|
||
if adUnitIdentifier == appOpenAd?.adUnitIdentifier {
|
||
print("开屏广告展示时出错,广告ID--\(ad.adUnitIdentifier),具体错误原因:\(error.message)")
|
||
MP_AnalyticsManager.shared.max_lunch_showFailureAction(error.message)
|
||
if let block = completeOpenAdBlock {
|
||
block()
|
||
}
|
||
}else if adUnitIdentifier == searchInterstitialAd?.adUnitIdentifier {
|
||
//搜索广告位
|
||
print("搜索插页广告展示时出错,广告ID--\(ad.adUnitIdentifier),具体错误原因:\(error.message)")
|
||
MP_AnalyticsManager.shared.max_search_showFailureAction(error.message)
|
||
if let block = completeSearchInterstitialAdBlock {
|
||
block()
|
||
}
|
||
}else if adUnitIdentifier == playInterstitialAd?.adUnitIdentifier {
|
||
//播放广告位
|
||
print("播放插页广告展示时出错,广告ID--\(ad.adUnitIdentifier),具体错误原因:\(error.message)")
|
||
MP_AnalyticsManager.shared.max_play_showFailureAction(error.message)
|
||
if let block = completePlayInterstitialAdBlock {
|
||
block()
|
||
}
|
||
}else if adUnitIdentifier == libraryInterstitialAd?.adUnitIdentifier {
|
||
//曲库广告位
|
||
print("曲库插页广告展示时出错,广告ID--\(ad.adUnitIdentifier),具体错误原因:\(error.message)")
|
||
MP_AnalyticsManager.shared.max_library_showFailureAction(error.message)
|
||
if let block = completeLibraryInterstitialAdBlock {
|
||
block()
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
}
|