ToneSnap_FSX_Flutter/lib/ads/interstitial_ad_manager.dart
fengshengxiong 063e3d7c91 1.添加通知栏媒体控制
2.下一首上一首增加防抖
3.集成fb
4.首页单曲增加下载
5.增加后台播放(iOS仍有问题)
6.修改系统状态栏颜色
2024-08-19 13:51:10 +08:00

259 lines
9.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Author: fengshengxiong
// Date: 2024/6/25
// Description: 插页广告
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:get/get.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:tone_snap/data/enum/ad_scenes.dart';
import 'package:tone_snap/data/models/ad_config_model.dart';
import 'package:tone_snap/data/storage/music_box.dart';
import 'package:tone_snap/firebase/firebase_analytics_manager.dart';
import 'package:tone_snap/modules/launch/launch_controller.dart';
import 'package:tone_snap/modules/sideb/controllers/music_player_controller.dart';
import 'package:tone_snap/utils/log_util.dart';
import 'package:tone_snap/utils/obj_util.dart';
class InterstitialAdManager {
InterstitialAdManager._();
static final InterstitialAdManager _instance = InterstitialAdManager._();
factory InterstitialAdManager() => _instance;
/// 广告对象Map
final Map<String, InterstitialAd?> _interstitialAdMap = {};
/// 加载和显示广告之间允许的最长持续时间
final Duration _maxCacheDuration = const Duration(minutes: 50);
/// 跟踪加载时间,这样我们就不会显示过期的广告
final Map<String, DateTime?> _appOpenLoadTimeMap = {};
/// 记录关闭时的时间,用于下一次展示时计算时间差
DateTime? _closeDateTime;
/// 是否显示
bool isShowingAd = false;
/// 广告显示前的,音乐是否在播放
bool showAdFrontIsPlaying = false;
/// 加载所有插页广告位
void loadAdAll() {
AdConfigModel adConfigModel = MusicBox().getAdConfig();
_loadSingleAd(adConfigModel.coldLoading, AdScenes.coldLoading.name);
_loadSingleAd(adConfigModel.hotLoading, AdScenes.hotLoading.name);
_loadSingleAd(adConfigModel.play, AdScenes.play.name);
_loadSingleAd(adConfigModel.download, AdScenes.download.name);
_loadSingleAd(adConfigModel.list, AdScenes.list.name);
_loadSingleAd(adConfigModel.playCut, AdScenes.playCut.name);
_loadSingleAd(adConfigModel.search, AdScenes.search.name);
}
/// 加载单个广告位
void _loadSingleAd(List<AdModel>? adList, String adScenes) {
if (adList != null && adList.isNotEmpty) {
var adModel = adList.reduce((value, element) => element.level! < value.level! ? element : value);
loadAd(adModel.identifier, adScenes);
}
}
/// 加载广告
void loadAd(String? adUnitId, String adScenes) async {
final List<ConnectivityResult> connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult.contains(ConnectivityResult.none)) {
LogUtil.d('当前无网络,不加载广告');
return;
}
if (ObjUtil.isEmpty(adUnitId)) {
return;
}
InterstitialAd.load(
adUnitId: adUnitId!,
request: const AdRequest(),
adLoadCallback: InterstitialAdLoadCallback(
onAdLoaded: (ad) {
LogUtil.d('$adScenes:${ad.adUnitId}插页广告加载完成');
_interstitialAdMap[adScenes] = ad;
_appOpenLoadTimeMap[adScenes] = DateTime.now();
if (adScenes == AdScenes.coldLoading.name) {
if (Get.isRegistered<LaunchController>()) {
LaunchController.to.editChangeValue();
}
}
},
onAdFailedToLoad: (LoadAdError error) {
LogUtil.d('$adScenes:$adUnitId插页广告加载失败: $error');
_loadFailHandle(adUnitId, adScenes);
FirebaseAnalyticsManager.logPlayAdsLoadFailure(error.message);
},
),
);
}
/// 加载失败处理
void _loadFailHandle(String adUnitId, String adScenes) {
int interval = 0;
if (adScenes != AdScenes.coldLoading.name && adScenes != AdScenes.hotLoading.name) {
interval = 15;
}
Future.delayed(Duration(seconds: interval), () {
AdConfigModel adConfigModel = MusicBox().getAdConfig();
var adList = _getAdList(adScenes);
if (adList != null) {
var currentItem = adList.firstWhereOrNull((e) => e.identifier == adUnitId);
if (currentItem != null) {
var nextItem = adList.firstWhereOrNull((e) => e.level == currentItem.level! + 1);
if (nextItem != null) {
// 当前id加载失败加载下一个id
loadAd(nextItem.identifier, adScenes);
} else {
// 对应场景id都加载失败加载全局id
_loadSingleAd(adConfigModel.backup, adScenes);
}
} else {
var currentItem = adConfigModel.backup?.firstWhereOrNull((e) => e.identifier == adUnitId);
if (currentItem != null) {
var nextItem = adConfigModel.backup?.firstWhereOrNull((e) => e.level == currentItem.level! + 1);
if (nextItem != null) {
loadAd(nextItem.identifier, adScenes);
} else {
if (adList.isNotEmpty) {
_loadSingleAd(adList, adScenes);
}
}
}
}
}
});
}
List<AdModel>? _getAdList(String adScenes) {
AdConfigModel adConfigModel = MusicBox().getAdConfig();
if (adScenes == AdScenes.coldLoading.name) {
return adConfigModel.coldLoading;
} else if (adScenes == AdScenes.hotLoading.name) {
return adConfigModel.hotLoading;
} else if (adScenes == AdScenes.play.name) {
return adConfigModel.play;
} else if (adScenes == AdScenes.download.name) {
return adConfigModel.download;
} else if (adScenes == AdScenes.list.name) {
return adConfigModel.list;
} else if (adScenes == AdScenes.playCut.name) {
return adConfigModel.playCut;
} else if (adScenes == AdScenes.search.name) {
return adConfigModel.search;
} else if (adScenes == AdScenes.backup.name) {
return adConfigModel.backup;
}
return null;
}
/// 是否可以播放广告
bool isAdAvailable(String adScenes) {
return _interstitialAdMap[adScenes] != null;
}
/// 显示广告(如果存在且尚未显示)
/// 如果先前缓存的广告已过期,则只加载并缓存新广告
void showAdIfAvailable(String adScenes, {Function()? onTap}) {
if (!isAdAvailable(adScenes)) {
LogUtil.d('尝试在可用之前显示广告');
if(onTap != null) onTap();
return;
}
if (isShowingAd) {
LogUtil.d('尝试在已显示广告的情况下显示广告');
if(onTap != null) onTap();
return;
}
if (DateTime.now().subtract(_maxCacheDuration).isAfter(_appOpenLoadTimeMap[adScenes]!)) {
LogUtil.d('超过了最大缓存持续时间。正在加载另一个广告');
_interstitialAdMap[adScenes]!.dispose();
loadAd(_interstitialAdMap[adScenes]?.adUnitId, adScenes);
_interstitialAdMap[adScenes] = null;
_interstitialAdMap.remove(adScenes);
if(onTap != null) onTap();
return;
}
if (_closeDateTime != null) {
// 计算时间差
Duration timeDifference = DateTime.now().difference(_closeDateTime!);
int seconds;
if (adScenes == AdScenes.hotLoading.name) {
seconds = MusicBox().getOpenAppEventDuration();
} else {
seconds = MusicBox().getInterstitialEventDuration();
}
if (timeDifference < Duration(seconds: seconds)) {
LogUtil.d('距离上次广告展示未达到插页广告事件间隔时长');
if(onTap != null) onTap();
return;
}
}
FirebaseAnalyticsManager.logPlayAdsChanceAction();
// 设置 fullScreenContentCallback 并显示广告
_interstitialAdMap[adScenes]!.fullScreenContentCallback = FullScreenContentCallback(
// 暂停应用程序中的活动或记录广告展示的时间
onAdShowedFullScreenContent: (ad) {
LogUtil.d('$ad onAdShowedFullScreenContent');
isShowingAd = true;
showAdFrontIsPlaying = MusicPlayerController.to.isPlaying.value;
if (showAdFrontIsPlaying) {
MusicPlayerController.to.pause();
}
},
// 更适合用于跟踪广告展示的次数和效果,以及执行与广告展示相关的操作
onAdImpression: (ad) {
LogUtil.d('$ad onAdImpression');
FirebaseAnalyticsManager.logPlayAdsShowSuccess(ad);
},
onAdFailedToShowFullScreenContent: (ad, error) {
LogUtil.d('$ad onAdFailedToShowFullScreenContent: $error');
isShowingAd = false;
ad.dispose();
loadAd(_interstitialAdMap[adScenes]?.adUnitId, adScenes);
_interstitialAdMap[adScenes] = null;
_interstitialAdMap.remove(adScenes);
FirebaseAnalyticsManager.logPlayAdsLoadFailure(error.message);
if(onTap != null) onTap();
},
onAdDismissedFullScreenContent: (ad) {
LogUtil.d('$ad onAdDismissedFullScreenContent');
isShowingAd = false;
if (showAdFrontIsPlaying) {
MusicPlayerController.to.play();
}
_closeDateTime = DateTime.now();
ad.dispose();
int interval = 0;
if (adScenes != AdScenes.coldLoading.name && adScenes != AdScenes.hotLoading.name) {
interval = 15;
}
Future.delayed(Duration(seconds: interval), () {
loadAd(_interstitialAdMap[adScenes]?.adUnitId, adScenes);
_interstitialAdMap[adScenes] = null;
_interstitialAdMap.remove(adScenes);
});
if(onTap != null) onTap();
},
onAdClicked: (ad) {
LogUtil.d('$ad onAdClicked');
},
);
_interstitialAdMap[adScenes]!.show();
}
}