1.新增瀑布流插页广告

2.新增增埋点
This commit is contained in:
fengshengxiong 2024-08-14 13:56:43 +08:00
parent da21720c3c
commit caded892d9
49 changed files with 1551 additions and 285 deletions

View File

@ -1,5 +1,9 @@
plugins { plugins {
id "com.android.application" id "com.android.application"
// START: FlutterFire Configuration
id 'com.google.gms.google-services'
id 'com.google.firebase.crashlytics'
// END: FlutterFire Configuration
id "kotlin-android" id "kotlin-android"
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id "dev.flutter.flutter-gradle-plugin" id "dev.flutter.flutter-gradle-plugin"

View File

@ -0,0 +1,29 @@
{
"project_info": {
"project_number": "280378307504",
"project_id": "tonesnap-and",
"storage_bucket": "tonesnap-and.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:280378307504:android:bcee5d63088dcbb7ca5c75",
"android_client_info": {
"package_name": "com.tone.music.offline"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyCLEOFjenMfiZKdoKdGh9mylckpIpTn854"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}

View File

@ -48,7 +48,7 @@
<!--AdMob app ID--> <!--AdMob app ID-->
<meta-data <meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID" android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-5684307632319406~7113477061"/> android:value="ca-app-pub-5684307632319406~5753747604"/>
</application> </application>
<!-- Required to query activities that can process text, see: <!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and https://developer.android.com/training/package-visibility and

View File

@ -19,6 +19,10 @@ pluginManagement {
plugins { plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0" id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.3.0" apply false id "com.android.application" version "7.3.0" apply false
// START: FlutterFire Configuration
id "com.google.gms.google-services" version "4.3.15" apply false
id "com.google.firebase.crashlytics" version "2.8.1" apply false
// END: FlutterFire Configuration
// id "org.jetbrains.kotlin.android" version "1.7.10" apply false // id "org.jetbrains.kotlin.android" version "1.7.10" apply false
id "org.jetbrains.kotlin.android" version "1.9.20" apply false id "org.jetbrains.kotlin.android" version "1.9.20" apply false
} }

View File

@ -490,7 +490,7 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 12; CURRENT_PROJECT_VERSION = 15;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = UH427LWP22; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = UH427LWP22;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
@ -689,7 +689,7 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 12; CURRENT_PROJECT_VERSION = 15;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = UH427LWP22; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = UH427LWP22;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
@ -723,7 +723,7 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 12; CURRENT_PROJECT_VERSION = 15;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = UH427LWP22; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = UH427LWP22;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;

View File

@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<scenes> <scenes>
<!--Flutter View Controller--> <!--Flutter View Controller-->
@ -14,13 +16,14 @@
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides> </layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/> <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view> </view>
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="-16" y="-40"/>
</scene> </scene>
</scenes> </scenes>
</document> </document>

View File

@ -20,17 +20,17 @@ class AppOpenAdManager {
factory AppOpenAdManager() => _instance; factory AppOpenAdManager() => _instance;
AppOpenAd? _appOpenAd;
bool _isShowingAd = false;
/// 广 /// 广
final Duration maxCacheDuration = const Duration(hours: 4); final Duration _maxCacheDuration = const Duration(minutes: 50);
/// 广 /// 广
DateTime? _appOpenLoadTime; DateTime? _appOpenLoadTime;
AppOpenAd? _appOpenAd;
bool _isShowingAd = false;
/// ///
DateTime? closeDateTime; DateTime? _closeDateTime;
/// 广id /// 广id
final adUnitId = Platform.isAndroid final adUnitId = Platform.isAndroid
@ -41,6 +41,7 @@ class AppOpenAdManager {
Future<void> loadAd() async { Future<void> loadAd() async {
final List<ConnectivityResult> connectivityResult = await (Connectivity().checkConnectivity()); final List<ConnectivityResult> connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult.contains(ConnectivityResult.none)) { if (connectivityResult.contains(ConnectivityResult.none)) {
LogUtil.d('当前无网络,不加载广告');
return; return;
} }
if (isAdAvailable) { if (isAdAvailable) {
@ -87,7 +88,7 @@ class AppOpenAdManager {
if(onTap != null) onTap(); if(onTap != null) onTap();
return; return;
} }
if (DateTime.now().subtract(maxCacheDuration).isAfter(_appOpenLoadTime!)) { if (DateTime.now().subtract(_maxCacheDuration).isAfter(_appOpenLoadTime!)) {
LogUtil.d('超过了最大缓存持续时间。正在加载另一个广告'); LogUtil.d('超过了最大缓存持续时间。正在加载另一个广告');
_appOpenAd!.dispose(); _appOpenAd!.dispose();
_appOpenAd = null; _appOpenAd = null;
@ -95,9 +96,9 @@ class AppOpenAdManager {
if(onTap != null) onTap(); if(onTap != null) onTap();
return; return;
} }
if (closeDateTime != null) { if (_closeDateTime != null) {
// //
Duration timeDifference = DateTime.now().difference(closeDateTime!); Duration timeDifference = DateTime.now().difference(_closeDateTime!);
// openAppEventDuration // openAppEventDuration
int openAppEventDuration = MusicBox().getOpenAppEventDuration(); int openAppEventDuration = MusicBox().getOpenAppEventDuration();
// 10 // 10
@ -130,7 +131,7 @@ class AppOpenAdManager {
}, },
onAdDismissedFullScreenContent: (ad) { onAdDismissedFullScreenContent: (ad) {
LogUtil.d('$ad onAdDismissedFullScreenContent'); LogUtil.d('$ad onAdDismissedFullScreenContent');
closeDateTime = DateTime.now(); _closeDateTime = DateTime.now();
// 广 // 广
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: SystemUiOverlay.values); SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: SystemUiOverlay.values);

View File

@ -2,12 +2,16 @@
// Date: 2024/6/25 // Date: 2024/6/25
// Description: 广 // Description: 广
import 'dart:io' show Platform;
import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/foundation.dart'; import 'package:get/get.dart';
import 'package:google_mobile_ads/google_mobile_ads.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/utils/log_util.dart'; import 'package:tone_snap/utils/log_util.dart';
import 'package:tone_snap/utils/obj_util.dart';
class InterstitialAdManager { class InterstitialAdManager {
InterstitialAdManager._(); InterstitialAdManager._();
@ -16,97 +20,208 @@ class InterstitialAdManager {
factory InterstitialAdManager() => _instance; factory InterstitialAdManager() => _instance;
/// 广Map
final Map<String, InterstitialAd?> _interstitialAdMap = {};
/// 广 /// 广
final Duration maxCacheDuration = const Duration(hours: 4); final Duration _maxCacheDuration = const Duration(minutes: 50);
/// 广 /// 广
DateTime? _appOpenLoadTime; final Map<String, DateTime?> _appOpenLoadTimeMap = {};
InterstitialAd? _interstitialAd; ///
DateTime? _closeDateTime;
///
bool isShowingAd = false; bool isShowingAd = false;
/// 广id /// 广
final adUnitId = Platform.isAndroid void loadAdAll() {
? (kReleaseMode ? '' : 'ca-app-pub-3940256099942544/1033173712') AdConfigModel adConfigModel = MusicBox().getAdConfig();
: (kReleaseMode ? 'ca-app-pub-5684307632319406/2760767691' : 'ca-app-pub-3940256099942544/4411468910'); _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() async { void loadAd(String? adUnitId, String adScenes) async {
final List<ConnectivityResult> connectivityResult = await (Connectivity().checkConnectivity()); final List<ConnectivityResult> connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult.contains(ConnectivityResult.none)) { if (connectivityResult.contains(ConnectivityResult.none)) {
LogUtil.d('当前无网络,不加载广告');
return; return;
} }
if (isAdAvailable) { if (ObjUtil.isEmpty(adUnitId)) {
return; return;
} }
InterstitialAd.load( InterstitialAd.load(
adUnitId: adUnitId, adUnitId: adUnitId!,
request: const AdRequest(), request: const AdRequest(),
adLoadCallback: InterstitialAdLoadCallback( adLoadCallback: InterstitialAdLoadCallback(
onAdLoaded: (ad) { onAdLoaded: (ad) {
LogUtil.d('插页广告加载完成'); LogUtil.d('$adScenes:${ad.adUnitId}插页广告加载完成');
_interstitialAd = ad; _interstitialAdMap[adScenes] = ad;
_appOpenLoadTime = DateTime.now(); _appOpenLoadTimeMap[adScenes] = DateTime.now();
if (adScenes == AdScenes.coldLoading.name) {
if (Get.isRegistered<LaunchController>()) {
LaunchController.to.editChangeValue();
}
}
}, },
onAdFailedToLoad: (LoadAdError error) { onAdFailedToLoad: (LoadAdError error) {
LogUtil.d('插页广告加载失败: $error'); LogUtil.d('$adScenes:$adUnitId插页广告加载失败: $error');
_loadFailHandle(adUnitId, adScenes);
FirebaseAnalyticsManager.logPlayAdsLoadFailure(error.message);
}, },
), ),
); );
} }
///
void _loadFailHandle(String adUnitId, String adScenes) {
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 get isAdAvailable { bool isAdAvailable(String adScenes) {
return _interstitialAd != null; return _interstitialAdMap[adScenes] != null;
} }
/// 广 /// 广
/// 广广 /// 广广
void showAdIfAvailable({Function()? onTap}) { void showAdIfAvailable(String adScenes, {Function()? onTap}) {
if (!isAdAvailable) { if (!isAdAvailable(adScenes)) {
LogUtil.d('尝试在可用之前显示广告'); LogUtil.d('尝试在可用之前显示广告');
loadAd();
if(onTap != null) onTap(); if(onTap != null) onTap();
return; return;
} }
if (isShowingAd) { if (isShowingAd) {
LogUtil.d('尝试在已显示广告的情况下显示广告'); LogUtil.d('尝试在已显示广告的情况下显示广告');
if(onTap != null) onTap(); if(onTap != null) onTap();
return; return;
} }
if (DateTime.now().subtract(maxCacheDuration).isAfter(_appOpenLoadTime!)) { if (DateTime.now().subtract(_maxCacheDuration).isAfter(_appOpenLoadTimeMap[adScenes]!)) {
LogUtil.d('超过了最大缓存持续时间。正在加载另一个广告'); LogUtil.d('超过了最大缓存持续时间。正在加载另一个广告');
_interstitialAd!.dispose(); _interstitialAdMap[adScenes]!.dispose();
_interstitialAd = null; loadAd(_interstitialAdMap[adScenes]?.adUnitId, adScenes);
loadAd(); _interstitialAdMap[adScenes] = null;
_interstitialAdMap.remove(adScenes);
if(onTap != null) onTap(); if(onTap != null) onTap();
return; 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 广 // fullScreenContentCallback 广
_interstitialAd!.fullScreenContentCallback = FullScreenContentCallback( _interstitialAdMap[adScenes]!.fullScreenContentCallback = FullScreenContentCallback(
// 广 // 广
onAdShowedFullScreenContent: (ad) { onAdShowedFullScreenContent: (ad) {
isShowingAd = true;
LogUtil.d('$ad onAdShowedFullScreenContent'); LogUtil.d('$ad onAdShowedFullScreenContent');
isShowingAd = true;
}, },
// 广广 // 广广
onAdImpression: (ad) { onAdImpression: (ad) {
LogUtil.d('$ad onAdImpression'); LogUtil.d('$ad onAdImpression');
FirebaseAnalyticsManager.logPlayAdsShowSuccess(ad);
}, },
onAdFailedToShowFullScreenContent: (ad, error) { onAdFailedToShowFullScreenContent: (ad, error) {
LogUtil.d('$ad onAdFailedToShowFullScreenContent: $error'); LogUtil.d('$ad onAdFailedToShowFullScreenContent: $error');
isShowingAd = false; isShowingAd = false;
ad.dispose(); ad.dispose();
_interstitialAd = null; loadAd(_interstitialAdMap[adScenes]?.adUnitId, adScenes);
_interstitialAdMap[adScenes] = null;
_interstitialAdMap.remove(adScenes);
FirebaseAnalyticsManager.logPlayAdsLoadFailure(error.message);
if(onTap != null) onTap(); if(onTap != null) onTap();
}, },
onAdDismissedFullScreenContent: (ad) { onAdDismissedFullScreenContent: (ad) {
LogUtil.d('$ad onAdDismissedFullScreenContent'); LogUtil.d('$ad onAdDismissedFullScreenContent');
isShowingAd = false; isShowingAd = false;
_closeDateTime = DateTime.now();
ad.dispose(); ad.dispose();
_interstitialAd = null; loadAd(_interstitialAdMap[adScenes]?.adUnitId, adScenes);
loadAd(); _interstitialAdMap[adScenes] = null;
_interstitialAdMap.remove(adScenes);
if(onTap != null) onTap(); if(onTap != null) onTap();
}, },
@ -114,6 +229,6 @@ class InterstitialAdManager {
LogUtil.d('$ad onAdClicked'); LogUtil.d('$ad onAdClicked');
}, },
); );
_interstitialAd!.show(); _interstitialAdMap[adScenes]!.show();
} }
} }

View File

@ -0,0 +1,94 @@
// Author: fengshengxiong
// Date: 2024/6/25
// Description: 广
import 'package:flutter/material.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/res/themes/app_colors.dart';
import 'package:tone_snap/utils/log_util.dart';
import 'package:tone_snap/utils/obj_util.dart';
class LibraryNativeAdManager {
LibraryNativeAdManager._();
static final LibraryNativeAdManager _instance = LibraryNativeAdManager._();
factory LibraryNativeAdManager() => _instance;
/// 广
NativeAd? nativeAd;
/// 广
var nativeAdIsLoaded = false.obs;
/// 广
void loadNativeAd() {
AdConfigModel adConfigModel = MusicBox().getAdConfig();
if (adConfigModel.library != null && adConfigModel.library!.isNotEmpty) {
_loadAd(adConfigModel.library![0].identifier, AdScenes.library.name);
}
}
/// 广
void _loadAd(String? adUnitId, String adScenes) async {
if (ObjUtil.isEmpty(adUnitId)) {
return;
}
nativeAd = NativeAd(
adUnitId: adUnitId!,
request: const AdRequest(),
listener: NativeAdListener(
onAdLoaded: (ad) {
LogUtil.d('$adScenes:${ad.adUnitId}原生广告加载完成');
nativeAdIsLoaded.value = true;
},
onAdFailedToLoad: (ad, error) {
LogUtil.e('$adScenes:${ad.adUnitId}原生广告加载失败: $error');
nativeAdIsLoaded.value = false;
loadNativeAd();
ad.dispose();
},
onAdClicked: (ad) {},
onAdImpression: (ad) {
},
onAdClosed: (ad) {},
onAdOpened: (ad) {},
onAdWillDismissScreen: (ad) {},
onPaidEvent: (ad, valueMicros, precision, currencyCode) {
},
),
nativeTemplateStyle: NativeTemplateStyle(
templateType: TemplateType.medium,
mainBackgroundColor: scaffoldBgColor,
cornerRadius: 8.0,
callToActionTextStyle: NativeTemplateTextStyle(
backgroundColor: seedColor,
textColor: Colors.white,
style: NativeTemplateFontStyle.bold,
size: 16.0,
),
primaryTextStyle: NativeTemplateTextStyle(
textColor: seedColor,
style: NativeTemplateFontStyle.bold,
size: 14.0,
),
secondaryTextStyle: NativeTemplateTextStyle(
textColor: Colors.white,
style: NativeTemplateFontStyle.italic,
size: 12.0,
),
tertiaryTextStyle: NativeTemplateTextStyle(
textColor: seedColor,
style: NativeTemplateFontStyle.normal,
size: 14.0,
),
),
)..load();
}
}

View File

@ -20,6 +20,7 @@ class MusicApi {
String? visitorData, String? visitorData,
Map<String, dynamic>? queryParameters, Map<String, dynamic>? queryParameters,
T Function(Map<String, dynamic>)? formJson, T Function(Map<String, dynamic>)? formJson,
Function(BaseError baseError)? fail,
bool showLoading = false, bool showLoading = false,
bool showToast = false, bool showToast = false,
}) async { }) async {
@ -47,6 +48,7 @@ class MusicApi {
queryParameters: queryParameters, queryParameters: queryParameters,
formJson: formJson, formJson: formJson,
success: (data) => model = data, success: (data) => model = data,
fail: fail
); );
return model; return model;
} }
@ -173,6 +175,7 @@ class MusicApi {
static Future<T?> search<T>({ static Future<T?> search<T>({
Map<String, dynamic>? queryParameters, Map<String, dynamic>? queryParameters,
T Function(Map<String, dynamic>)? formJson, T Function(Map<String, dynamic>)? formJson,
Function(BaseError baseError)? fail,
bool showLoading = false, bool showLoading = false,
bool showToast = true, bool showToast = true,
}) async { }) async {
@ -199,6 +202,7 @@ class MusicApi {
queryParameters: queryParameters, queryParameters: queryParameters,
formJson: formJson, formJson: formJson,
success: (data) => model = data, success: (data) => model = data,
fail: fail,
); );
return model; return model;
} }

View File

@ -0,0 +1,15 @@
// Author: fengshengxiong
// Date: 2024/6/13
// Description: 广
enum AdFormat {
///
insert('Insert'),
///
native('Native');
const AdFormat(this.type);
final String type;
}

View File

@ -0,0 +1,39 @@
// Author: fengshengxiong
// Date: 2024/6/13
// Description: 广
enum AdScenes {
/// cold_loading(广)
coldLoading('coldLoading'),
/// hot_loading(广)
hotLoading('hotLoading'),
/// play(广)
play('play'),
/// download(广)
download('download'),
/// list(广)
list('list'),
/// library(广)
library('library'),
/// play_cut(广)
playCut('playCut'),
/// search(广)
search('search'),
/// search(广)
searchResult('searchResult'),
/// backup(广)
backup('backup');
const AdScenes(this.name);
final String name;
}

View File

@ -0,0 +1,93 @@
// Author: fengshengxiong
// Date: 2024/8/6
// Description: 广
import 'dart:convert';
class AdConfigModel {
List<AdModel>? coldLoading;
List<AdModel>? hotLoading;
List<AdModel>? play;
List<AdModel>? download;
List<AdModel>? list;
List<AdModel>? library;
List<AdModel>? playCut;
List<AdModel>? search;
List<AdModel>? searchResult;
List<AdModel>? backup;
AdConfigModel({
this.coldLoading,
this.hotLoading,
this.play,
this.download,
this.list,
this.library,
this.playCut,
this.search,
this.searchResult,
this.backup,
});
factory AdConfigModel.fromJson(String str) => AdConfigModel.fromMap(json.decode(str));
String toJson() => json.encode(toMap());
factory AdConfigModel.fromMap(Map<String, dynamic> json) => AdConfigModel(
coldLoading: json["coldLoading"] == null ? [] : List<AdModel>.from(json["coldLoading"]!.map((x) => AdModel.fromMap(x))),
hotLoading: json["hotLoading"] == null ? [] : List<AdModel>.from(json["hotLoading"]!.map((x) => AdModel.fromMap(x))),
play: json["play"] == null ? [] : List<AdModel>.from(json["play"]!.map((x) => AdModel.fromMap(x))),
download: json["download"] == null ? [] : List<AdModel>.from(json["download"]!.map((x) => AdModel.fromMap(x))),
list: json["list"] == null ? [] : List<AdModel>.from(json["list"]!.map((x) => AdModel.fromMap(x))),
library: json["library"] == null ? [] : List<AdModel>.from(json["library"]!.map((x) => AdModel.fromMap(x))),
playCut: json["playCut"] == null ? [] : List<AdModel>.from(json["playCut"]!.map((x) => AdModel.fromMap(x))),
search: json["search"] == null ? [] : List<AdModel>.from(json["search"]!.map((x) => AdModel.fromMap(x))),
searchResult: json["searchResult"] == null ? [] : List<AdModel>.from(json["searchResult"]!.map((x) => AdModel.fromMap(x))),
backup: json["backup"] == null ? [] : List<AdModel>.from(json["backup"]!.map((x) => AdModel.fromMap(x))),
);
Map<String, dynamic> toMap() => {
"coldLoading": coldLoading == null ? [] : List<dynamic>.from(coldLoading!.map((x) => x.toMap())),
"hotLoading": hotLoading == null ? [] : List<dynamic>.from(hotLoading!.map((x) => x.toMap())),
"play": play == null ? [] : List<dynamic>.from(play!.map((x) => x.toMap())),
"download": download == null ? [] : List<dynamic>.from(download!.map((x) => x.toMap())),
"list": list == null ? [] : List<dynamic>.from(list!.map((x) => x.toMap())),
"library": library == null ? [] : List<dynamic>.from(library!.map((x) => x.toMap())),
"playCut": playCut == null ? [] : List<dynamic>.from(playCut!.map((x) => x.toMap())),
"search": search == null ? [] : List<dynamic>.from(search!.map((x) => x.toMap())),
"searchResult": searchResult == null ? [] : List<dynamic>.from(searchResult!.map((x) => x.toMap())),
"backup": backup == null ? [] : List<dynamic>.from(backup!.map((x) => x.toMap())),
};
}
class AdModel {
int? level;
String? identifier;
String? ad;
String? type;
AdModel({
this.level,
this.identifier,
this.ad,
this.type,
});
factory AdModel.fromJson(String str) => AdModel.fromMap(json.decode(str));
String toJson() => json.encode(toMap());
factory AdModel.fromMap(Map<String, dynamic> json) => AdModel(
level: json["level"],
identifier: json["identifier"],
ad: json["ad"],
type: json["type"],
);
Map<String, dynamic> toMap() => {
"level": level,
"identifier": identifier,
"ad": ad,
"type": type,
};
}

View File

@ -3,10 +3,12 @@
// Description: // Description:
import 'dart:convert'; import 'dart:convert';
import 'dart:io';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:tone_snap/data/enum/play_mode.dart'; import 'package:tone_snap/data/enum/play_mode.dart';
import 'package:tone_snap/data/models/ad_config_model.dart';
import 'package:tone_snap/data/storage/hive_storage.dart'; import 'package:tone_snap/data/storage/hive_storage.dart';
import 'package:tone_snap/global/app_config.dart'; import 'package:tone_snap/global/app_config.dart';
import 'package:tone_snap/utils/log_util.dart'; import 'package:tone_snap/utils/log_util.dart';
@ -21,21 +23,24 @@ class MusicBox {
return _instance; return _instance;
} }
/// RemoteConfig openStatus
final _openStatusKey = 'openStatusKey';
/// RemoteConfig dataVersion
final _dataVersionKey = 'dataVersionKey';
/// B面 /// B面
final _isOpenedSideBKey = 'isOpenedSideBKey'; final _isOpenedSideBKey = 'isOpenedSideBKey';
/// openStatus
final _openStatusKey = 'openStatusKey';
/// dataVersion
final _dataVersionKey = 'dataVersionKey';
/// ///
final _openAppEventDurationKey = 'openAppEventDurationKey'; final _openAppEventDurationKey = 'openAppEventDurationKey';
/// 广 /// 广
final _interstitialEventDurationKey = 'interstitialEventDurationKey'; final _interstitialEventDurationKey = 'interstitialEventDurationKey';
/// 广
final _adMobLevelIDsKey = 'adMobLevelIDsKey';
/// ///
final _playModeKey = 'playModeKey'; final _playModeKey = 'playModeKey';
@ -46,6 +51,16 @@ class MusicBox {
/// , main函数中这个盒子已经打开, /// , main函数中这个盒子已经打开,
final _box = Hive.box(musicBox); final _box = Hive.box(musicBox);
/// B面
Future<void> putIsOpenedSideB(bool isOpen) async {
return await _box.put(_isOpenedSideBKey, isOpen);
}
/// B面
bool getIsOpenedSideB() {
return _box.get(_isOpenedSideBKey, defaultValue: false);
}
/// openStatus /// openStatus
Future<void> putOpenStatus(String openStatus) async { Future<void> putOpenStatus(String openStatus) async {
return await _box.put(_openStatusKey, openStatus); return await _box.put(_openStatusKey, openStatus);
@ -114,16 +129,6 @@ class MusicBox {
return AppConfig.playerVersion; return AppConfig.playerVersion;
} }
/// B面
Future<void> putIsOpenedSideB(bool isOpen) async {
return await _box.put(_isOpenedSideBKey, isOpen);
}
/// B面
bool getIsOpenedSideB() {
return _box.get(_isOpenedSideBKey, defaultValue: false);
}
/// ///
Future<void> putOpenAppEventDuration(int time) async { Future<void> putOpenAppEventDuration(int time) async {
return await _box.put(_openAppEventDurationKey, time); return await _box.put(_openAppEventDurationKey, time);
@ -144,6 +149,17 @@ class MusicBox {
return _box.get(_interstitialEventDurationKey, defaultValue: AppConfig.interstitialEventDuration); return _box.get(_interstitialEventDurationKey, defaultValue: AppConfig.interstitialEventDuration);
} }
/// 广
Future<void> putAdConfig(String adConfigStr) async {
return await _box.put(_adMobLevelIDsKey, adConfigStr);
}
/// 广
AdConfigModel getAdConfig() {
var configStr = _box.get(_adMobLevelIDsKey, defaultValue: Platform.isIOS ? AppConfig.adIOSDefaultConfig : AppConfig.adAndroidDefaultConfig);
return AdConfigModel.fromJson(configStr);
}
/// ///
Future<void> putPlayMode(PlayMode playMode) async { Future<void> putPlayMode(PlayMode playMode) async {
return await _box.put(_playModeKey, playMode); return await _box.put(_playModeKey, playMode);

View File

@ -9,6 +9,7 @@ import 'package:tone_snap/data/models/music_model.dart';
import 'package:tone_snap/data/models/playlist_model.dart'; import 'package:tone_snap/data/models/playlist_model.dart';
import 'package:tone_snap/data/storage/hive_storage.dart'; import 'package:tone_snap/data/storage/hive_storage.dart';
import 'package:tone_snap/utils/date_util.dart'; import 'package:tone_snap/utils/date_util.dart';
import 'package:tone_snap/utils/log_util.dart';
class PlaylistsBox { class PlaylistsBox {
PlaylistsBox._(); PlaylistsBox._();
@ -25,12 +26,13 @@ class PlaylistsBox {
/// ///
List<PlaylistModel> getList() { List<PlaylistModel> getList() {
return _box.values.toList(); var list = _box.values.toList();
} try {
list.sort((a, b) => b.milliseconds!.compareTo(a.milliseconds!));
/// } catch (e) {
List<PlaylistModel> getReversedList() { LogUtil.e(e.toString());
return _box.values.toList().reversed.toList(); }
return list;
} }
/// ///

View File

@ -3,17 +3,291 @@
// Description: firebase_analytics管理 // Description: firebase_analytics管理
import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:tone_snap/utils/log_util.dart';
import 'package:tone_snap/utils/obj_util.dart';
class FirebaseAnalyticsManager { class FirebaseAnalyticsManager {
static const homeApv = 'home_a_pv';
/// ///
/// name /// name
/// parameters /// parameters
static void logEvent(String eventName, {Map<String, Object>? parameters}) { static void logEvent(String eventName, {Map<String, Object>? parameters}) {
FirebaseAnalytics.instance.logEvent( try {
name: eventName, FirebaseAnalytics.instance.logEvent(
parameters: parameters, name: eventName,
parameters: parameters,
);
} catch (e) {
LogUtil.e(e.toString());
}
}
///
static void logLaunchPV() {
logEvent('launch_pv');
}
///
static void logJumpEvent(String? side, String? reason) {
logEvent('jump_event',
parameters: {
'side': ObjUtil.getStr(side),
'reason': ObjUtil.getStr(reason)
},
);
}
/// A面首页曝光
static void logHomeAPV() {
logEvent('home_a_pv');
}
/// B面首页曝光
static void logHomeBPV() {
logEvent('home_b_pv');
}
///
static void logHomeBModuleShowsuccesAction() {
logEvent('home_b_module_showsucces_action');
}
///
static void logHomeBModuleFailAction(String? failreason) {
logEvent('home_b_module_fail_action',
parameters: {
'failreason': ObjUtil.getStr(failreason)
},
);
}
///
static void logHomeBModuleClick(String? modulename) {
logEvent('home_b_module_click',
parameters: {
'modulename': ObjUtil.getStr(modulename)
},
);
}
/// B面我的曝光
static void logMeBPV() {
logEvent('me_b_pv');
}
///
static void logSongClick(String? songfrom) {
logEvent('song_click',
parameters: {
'songfrom': ObjUtil.getStr(songfrom)
},
);
}
/// B面歌曲曝光
static void logPlayerBpv(String? videoid, String? videoname, String? artistname) {
logEvent('player_b_pv',
parameters: {
'videoid': ObjUtil.getStr(videoid),
'videoname': ObjUtil.getStr(videoname),
'artistname': ObjUtil.getStr(artistname),
},
);
}
///
static void logPlayerBDelayAction(String? videoid, String? videoname, String? artistname, String? delay) {
logEvent('player_b_delay_action',
parameters: {
'videoid': ObjUtil.getStr(videoid),
'videoname': ObjUtil.getStr(videoname),
'artistname': ObjUtil.getStr(artistname),
'delay': ObjUtil.getStr(delay),
},
);
}
///
static void logPlayerBSuccessAction(String? videoid, String? videoname, String? artistname) {
logEvent('player_b_success_action',
parameters: {
'videoid': ObjUtil.getStr(videoid),
'videoname': ObjUtil.getStr(videoname),
'artistname': ObjUtil.getStr(artistname),
},
);
}
///
static void logPlayerBFailAction(String? failreason) {
logEvent('player_b_fail_action',
parameters: {
'failreason': ObjUtil.getStr(failreason)
},
);
}
///
static void logPlayerBLoveClick(String? videoid, String? videoname, String? artistname) {
logEvent('player_b_love_click',
parameters: {
'videoid': ObjUtil.getStr(videoid),
'videoname': ObjUtil.getStr(videoname),
'artistname': ObjUtil.getStr(artistname),
},
);
}
///
static void logPlayerBUnloveClick(String? videoid, String? videoname, String? artistname) {
logEvent('player_b_unlove_click',
parameters: {
'videoid': ObjUtil.getStr(videoid),
'videoname': ObjUtil.getStr(videoname),
'artistname': ObjUtil.getStr(artistname),
},
);
}
///
static void logPlayerBDownloadClick(String? videoid, String? videoname, String? artistname) {
logEvent('player_b_download_click',
parameters: {
'videoid': ObjUtil.getStr(videoid),
'videoname': ObjUtil.getStr(videoname),
'artistname': ObjUtil.getStr(artistname),
},
);
}
///
static void logPlayerBDownloadsuccessAction(String? videoid, String? videoname, String? artistname) {
logEvent('player_b_downloadsuccess_action',
parameters: {
'videoid': ObjUtil.getStr(videoid),
'videoname': ObjUtil.getStr(videoname),
'artistname': ObjUtil.getStr(artistname),
},
);
}
///
static void logPlayerBDownloadfailAction(String? failreason) {
logEvent('player_b_downloadfail_action',
parameters: {
'failreason': ObjUtil.getStr(failreason)
},
);
}
/// B面搜索曝光
static void logSearchPV() {
logEvent('search_pv');
}
/// SUG曝光
static void logSearchSugShow() {
logEvent('search_sug_show');
}
///
static void logSearchSugClick(String? sugname) {
logEvent('search_sug_click',
parameters: {
'sugname': ObjUtil.getStr(sugname)
},
);
}
///
static void logSearchResultPV() {
logEvent('search_result_pv');
}
///
static void logSearchResultsuccessAction() {
logEvent('search_resultsuccess_action');
}
///
static void logSearchResultfailAction(String? failreason) {
logEvent('search_resultfail_action',
parameters: {
'failreason': ObjUtil.getStr(failreason)
},
);
}
///
static void logSearchFromAction(String? searchfrom) {
logEvent('search_from_action',
parameters: {
'searchfrom': ObjUtil.getStr(searchfrom)
},
);
}
///
static void logPlayerBImp() {
logEvent('player_b_imp');
}
///
static void logPlayerBList() {
logEvent('player_b_list');
}
///
static void logCreateList() {
logEvent('create_list');
}
///
static void logLibraryClick(String? clickfrom, String? folderclick) {
logEvent('library_click',
parameters: {
'clickfrom': ObjUtil.getStr(clickfrom),
'folderclick': ObjUtil.getStr(folderclick)
},
);
}
/// 广
static void logPlayAdsChanceAction() {
logEvent('play_ads_chance');
}
/// 广
static void logPlayAdsLoadFailure(String? error) {
logEvent('play_ads_loadFailure',
parameters: {
'error': ObjUtil.getStr(error),
},
);
}
/// 广
static void logPlayAdsShowSuccess(Ad ad) {
var mediation = '';
if (ad.responseInfo != null && ad.responseInfo!.responseExtras.isNotEmpty) {
mediation = ad.responseInfo!.responseExtras['mediation_group_name'];
}
logEvent('play_ads_showSuccess',
parameters: {
'platform': ObjUtil.getStr(ad.responseInfo?.loadedAdapterResponseInfo?.adSourceName),
'source': ObjUtil.getStr(ad.responseInfo?.loadedAdapterResponseInfo?.adSourceInstanceName),
'unitName': ObjUtil.getStr(mediation),
},
);
}
/// 广
static void logPlayAdsShowFailure(String? error) {
logEvent('play_ads_showFailure',
parameters: {
'error': ObjUtil.getStr(error),
},
); );
} }
} }

View File

@ -23,8 +23,8 @@ class DefaultFirebaseOptions {
); );
} }
switch (defaultTargetPlatform) { switch (defaultTargetPlatform) {
// case TargetPlatform.android: case TargetPlatform.android:
// return android; return android;
case TargetPlatform.iOS: case TargetPlatform.iOS:
return ios; return ios;
case TargetPlatform.macOS: case TargetPlatform.macOS:
@ -49,13 +49,13 @@ class DefaultFirebaseOptions {
} }
} }
// static const FirebaseOptions android = FirebaseOptions( static const FirebaseOptions android = FirebaseOptions(
// apiKey: 'AIzaSyDP6CpkN3HMpCofXlToug-hadYpTLEgE0E', apiKey: 'AIzaSyCLEOFjenMfiZKdoKdGh9mylckpIpTn854',
// appId: '1:318284530945:android:c7dd2abf520a9840250700', appId: '1:280378307504:android:bcee5d63088dcbb7ca5c75',
// messagingSenderId: '318284530945', messagingSenderId: '280378307504',
// projectId: 'nowwallpaper', projectId: 'tonesnap-and',
// storageBucket: 'nowwallpaper.appspot.com', storageBucket: 'tonesnap-and.appspot.com',
// ); );
static const FirebaseOptions ios = FirebaseOptions( static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIzaSyADeT4ReAayii_M9tl0GHR6tUlyVTXAaSU', apiKey: 'AIzaSyADeT4ReAayii_M9tl0GHR6tUlyVTXAaSU',

View File

@ -60,6 +60,12 @@ class FirebaseRemoteConfigManager {
LogUtil.e(e.toString()); LogUtil.e(e.toString());
} }
} }
// adMobLevelIDs
var adMobLevelIDs = allData['adMobLevelIDs']?.asString();
if (ObjUtil.isNotEmpty(adMobLevelIDs)) {
await MusicBox().putAdConfig(adMobLevelIDs!);
}
} }
} catch (e) { } catch (e) {
LogUtil.e(e.toString()); LogUtil.e(e.toString());

View File

@ -24,5 +24,269 @@ class AppConfig {
/// ///
static String isoCode = 'HK'; static String isoCode = 'HK';
/// iOS广告场景默认配置level越小价值越高
static String adIOSDefaultConfig = '''{
"coldLoading": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/5757639118",
"ad": "AdMob",
"type": "Insert"
},
{
"level": 2,
"identifier": "ca-app-pub-5684307632319406/5852437064",
"ad": "AdMob",
"type": "Insert"
}
],
"hotLoading": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/3414045794",
"ad": "AdMob",
"type": "Insert"
},
{
"level": 2,
"identifier": "ca-app-pub-5684307632319406/9382223193",
"ad": "AdMob",
"type": "Insert"
}
],
"play": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/9827341094",
"ad": "AdMob",
"type": "Insert"
},
{
"level": 2,
"identifier": "ca-app-pub-5684307632319406/5270553952",
"ad": "AdMob",
"type": "Insert"
}
],
"download": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/2060531710",
"ad": "AdMob",
"type": "Insert"
},
{
"level": 2,
"identifier": "ca-app-pub-5684307632319406/1913192057",
"ad": "AdMob",
"type": "Insert"
}
],
"list": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/9600110380",
"ad": "AdMob",
"type": "Insert"
},
{
"level": 2,
"identifier": "ca-app-pub-5684307632319406/6079667773",
"ad": "AdMob",
"type": "Insert"
}
],
"library": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/7785036659",
"ad": "AdMob",
"type": "Native"
}
],
"playCut": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/8551323416",
"ad": "AdMob",
"type": "Insert"
},
{
"level": 2,
"identifier": "ca-app-pub-5684307632319406/2140422769",
"ad": "AdMob",
"type": "Insert"
}
],
"search": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/8434368376",
"ad": "AdMob",
"type": "Insert"
},
{
"level": 2,
"identifier": "ca-app-pub-5684307632319406/9505312439",
"ad": "AdMob",
"type": "Insert"
}
],
"searchResult": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/1645766617",
"ad": "AdMob",
"type": "Native"
}
],
"backup": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/5987502154",
"ad": "AdMob",
"type": "Insert"
},
{
"level": 2,
"identifier": "ca-app-pub-5684307632319406/5361482476",
"ad": "AdMob",
"type": "Insert"
}
]
}''';
/// Android广告场景默认配置level越小价值越高
static String adAndroidDefaultConfig = '''{
"coldLoading": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/2307556684",
"ad": "AdMob",
"type": "Insert"
},
{
"level": 2,
"identifier": "ca-app-pub-5684307632319406/3395973732",
"ad": "AdMob",
"type": "Insert"
}
],
"hotLoading": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/2527048534",
"ad": "AdMob",
"type": "Insert"
},
{
"level": 2,
"identifier": "ca-app-pub-5684307632319406/5763116779",
"ad": "AdMob",
"type": "Insert"
}
],
"play": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/4450035105",
"ad": "AdMob",
"type": "Insert"
},
{
"level": 2,
"identifier": "ca-app-pub-5684307632319406/4279113904",
"ad": "AdMob",
"type": "Insert"
}
],
"download": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/3136953430",
"ad": "AdMob",
"type": "Insert"
},
{
"level": 2,
"identifier": "ca-app-pub-5684307632319406/7368311678",
"ad": "AdMob",
"type": "Insert"
}
],
"list": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/1823871765",
"ad": "AdMob",
"type": "Insert"
},
{
"level": 2,
"identifier": "ca-app-pub-5684307632319406/2536557320",
"ad": "AdMob",
"type": "Insert"
}
],
"library": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/5438052836",
"ad": "AdMob",
"type": "Native"
}
],
"playCut": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/5727092792",
"ad": "AdMob",
"type": "Insert"
},
{
"level": 2,
"identifier": "ca-app-pub-5684307632319406/8197708422",
"ad": "AdMob",
"type": "Insert"
}
],
"search": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/4971148979",
"ad": "AdMob",
"type": "Insert"
},
{
"level": 2,
"identifier": "ca-app-pub-5684307632319406/8026787222",
"ad": "AdMob",
"type": "Insert"
}
],
"searchResult": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/6848602773",
"ad": "AdMob",
"type": "Native"
}
],
"backup": [
{
"level": 1,
"identifier": "ca-app-pub-5684307632319406/8718822297",
"ad": "AdMob",
"type": "Insert"
},
{
"level": 2,
"identifier": "ca-app-pub-5684307632319406/4517483713",
"ad": "AdMob",
"type": "Insert"
}
]
}''';
} }

View File

@ -3,8 +3,8 @@
// Description: // Description:
import 'package:google_mobile_ads/google_mobile_ads.dart'; import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:tone_snap/ads/app_open_ad_manager.dart';
import 'package:tone_snap/ads/interstitial_ad_manager.dart'; import 'package:tone_snap/ads/interstitial_ad_manager.dart';
import 'package:tone_snap/data/enum/ad_scenes.dart';
class AppLifecycleReactor { class AppLifecycleReactor {
AppLifecycleReactor._(); AppLifecycleReactor._();
@ -23,7 +23,7 @@ class AppLifecycleReactor {
void _onAppStateChanged(AppState appState) { void _onAppStateChanged(AppState appState) {
// 广 // 广
if (appState == AppState.foreground && !InterstitialAdManager().isShowingAd) { if (appState == AppState.foreground && !InterstitialAdManager().isShowingAd) {
AppOpenAdManager().showAdIfAvailable(); InterstitialAdManager().showAdIfAvailable(AdScenes.hotLoading.name);
} }
} }
} }

View File

@ -5,11 +5,14 @@
import 'package:background_downloader/background_downloader.dart'; import 'package:background_downloader/background_downloader.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/ads/interstitial_ad_manager.dart';
import 'package:tone_snap/components/base_easyloading.dart'; import 'package:tone_snap/components/base_easyloading.dart';
import 'package:tone_snap/data/api/music_api.dart'; import 'package:tone_snap/data/api/music_api.dart';
import 'package:tone_snap/data/enum/ad_scenes.dart';
import 'package:tone_snap/data/models/music_model.dart'; import 'package:tone_snap/data/models/music_model.dart';
import 'package:tone_snap/data/models/player_model.dart'; import 'package:tone_snap/data/models/player_model.dart';
import 'package:tone_snap/data/storage/offline_box.dart'; import 'package:tone_snap/data/storage/offline_box.dart';
import 'package:tone_snap/firebase/firebase_analytics_manager.dart';
import 'package:tone_snap/modules/sideb/offline/offline_controller.dart'; import 'package:tone_snap/modules/sideb/offline/offline_controller.dart';
import 'package:tone_snap/modules/sideb/personal_music_library/personal_music_library_controller.dart'; import 'package:tone_snap/modules/sideb/personal_music_library/personal_music_library_controller.dart';
import 'package:tone_snap/utils/date_util.dart'; import 'package:tone_snap/utils/date_util.dart';
@ -49,6 +52,11 @@ class DownloadManager extends GetxController {
break; break;
case TaskStatus.complete: case TaskStatus.complete:
LogUtil.d('音乐下载路径:${await update.task.filePath()}'); LogUtil.d('音乐下载路径:${await update.task.filePath()}');
FirebaseAnalyticsManager.logPlayerBDownloadsuccessAction(
musicModel.videoId,
musicModel.title,
musicModel.subtitle,
);
musicModel.localPath = await update.task.filePath(); musicModel.localPath = await update.task.filePath();
OfflineBox().add(musicModel); OfflineBox().add(musicModel);
downloadList.remove(musicModel); downloadList.remove(musicModel);
@ -63,14 +71,17 @@ class DownloadManager extends GetxController {
case TaskStatus.notFound: case TaskStatus.notFound:
BaseEasyLoading.toast('Download failed'); BaseEasyLoading.toast('Download failed');
downloadList.remove(musicModel); downloadList.remove(musicModel);
FirebaseAnalyticsManager.logPlayerBDownloadfailAction('404,找不到url');
break; break;
case TaskStatus.failed: case TaskStatus.failed:
BaseEasyLoading.toast('Download failed'); BaseEasyLoading.toast('Download failed');
downloadList.remove(musicModel); downloadList.remove(musicModel);
FirebaseAnalyticsManager.logPlayerBDownloadfailAction('下载失败');
break; break;
case TaskStatus.canceled: case TaskStatus.canceled:
BaseEasyLoading.toast('Download cancelled'); BaseEasyLoading.toast('Download cancelled');
downloadList.remove(musicModel); downloadList.remove(musicModel);
FirebaseAnalyticsManager.logPlayerBDownloadfailAction('取消下载');
break; break;
case TaskStatus.waitingToRetry: case TaskStatus.waitingToRetry:
break; break;
@ -89,37 +100,47 @@ class DownloadManager extends GetxController {
/// ///
void downloadMusic(MusicModel? m) { void downloadMusic(MusicModel? m) {
if (m == null) return; FirebaseAnalyticsManager.logPlayerBDownloadClick(
MusicModel musicModel = m.copyWith(); m?.videoId,
musicModel.taskStatus = TaskStatus.enqueued; m?.title,
musicModel.cancelToken = CancelToken(); m?.subtitle,
downloadList.add(musicModel); );
updateDownloadState(); InterstitialAdManager().showAdIfAvailable(
AdScenes.download.name,
onTap: () {
if (m == null) return;
MusicModel musicModel = m.copyWith();
musicModel.taskStatus = TaskStatus.enqueued;
musicModel.cancelToken = CancelToken();
downloadList.add(musicModel);
updateDownloadState();
_getMusicUrl(musicModel, (url, mimeType) async { _getMusicUrl(musicModel, (url, mimeType) async {
if (ObjUtil.isNotEmpty(url)) { if (ObjUtil.isNotEmpty(url)) {
String extension = mimeType ?? 'mp4'; String extension = mimeType ?? 'mp4';
if (ObjUtil.isNotEmpty(mimeType)) { if (ObjUtil.isNotEmpty(mimeType)) {
// mimeType // mimeType
String type = mimeType!.split(';')[0].trim(); String type = mimeType!.split(';')[0].trim();
// //
extension = type.split('/')[1]; extension = type.split('/')[1];
} }
final filename = '${musicModel.title}_${DateUtil.getNowTimestamp()}.$extension'; final filename = '${musicModel.title}_${DateUtil.getNowTimestamp()}.$extension';
final task = DownloadTask( final task = DownloadTask(
taskId: musicModel.videoId, taskId: musicModel.videoId,
url: url!, url: url!,
filename: filename, filename: filename,
directory: LocalPathUtil.getMusicDownloadDir(), directory: LocalPathUtil.getMusicDownloadDir(),
updates: Updates.statusAndProgress, updates: Updates.statusAndProgress,
requiresWiFi: false, requiresWiFi: false,
retries: 0, retries: 0,
allowPause: false, allowPause: false,
metaData: '', metaData: '',
); );
tq?.add(task); tq?.add(task);
} }
}); });
},
);
} }
Future<void> _getMusicUrl(MusicModel musicModel, Function(String? url, String? mimeType) onTap) async { Future<void> _getMusicUrl(MusicModel musicModel, Function(String? url, String? mimeType) onTap) async {
@ -134,6 +155,7 @@ class DownloadManager extends GetxController {
musicModel.taskStatus = TaskStatus.failed; musicModel.taskStatus = TaskStatus.failed;
musicModel.cancelToken = null; musicModel.cancelToken = null;
} }
FirebaseAnalyticsManager.logPlayerBDownloadfailAction('${baseError.code},${baseError.message}');
downloadList.remove(musicModel); downloadList.remove(musicModel);
updateDownloadState(); updateDownloadState();
} }

View File

@ -6,10 +6,9 @@ import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/ads/app_open_ad_manager.dart';
import 'package:tone_snap/ads/interstitial_ad_manager.dart'; import 'package:tone_snap/ads/interstitial_ad_manager.dart';
import 'package:tone_snap/ads/library_native_ad_manager.dart';
import 'package:tone_snap/firebase/firebase_remote_config_manager.dart'; import 'package:tone_snap/firebase/firebase_remote_config_manager.dart';
import 'package:tone_snap/modules/launch/launch_controller.dart';
import 'package:tone_snap/utils/log_util.dart'; import 'package:tone_snap/utils/log_util.dart';
class NetworkConnectivityService extends GetxService { class NetworkConnectivityService extends GetxService {
@ -22,18 +21,14 @@ class NetworkConnectivityService extends GetxService {
super.onInit(); super.onInit();
subscription = Connectivity().onConnectivityChanged.listen((List<ConnectivityResult> result) { subscription = Connectivity().onConnectivityChanged.listen((List<ConnectivityResult> result) {
LogUtil.d('当前网络连接类型:$result'); LogUtil.d('当前网络连接类型:$result');
if (result.contains(ConnectivityResult.wifi) || result.contains(ConnectivityResult.mobile)) { if (!result.contains(ConnectivityResult.none)) {
if (!isExecutedTask) { if (!isExecutedTask) {
isExecutedTask = true; isExecutedTask = true;
FirebaseRemoteConfigManager.getAll(); FirebaseRemoteConfigManager.getAll();
if (Get.isRegistered<LaunchController>()) { InterstitialAdManager().loadAdAll();
LaunchController.to.getIsoCode(); // LibraryNativeAdManager().loadNativeAd();
}
InterstitialAdManager().loadAd();
AppOpenAdManager().loadAd();
} }
} }
}); });

View File

@ -20,8 +20,6 @@ import 'package:tone_snap/modules/sideb/music_bar/music_bar_controller.dart';
import 'package:tone_snap/res/themes/app_themes.dart'; import 'package:tone_snap/res/themes/app_themes.dart';
import 'package:tone_snap/routes/app_pages.dart'; import 'package:tone_snap/routes/app_pages.dart';
import 'package:tone_snap/routes/app_routes.dart'; import 'package:tone_snap/routes/app_routes.dart';
import 'package:tone_snap/utils/file_util.dart';
import 'package:tone_snap/utils/local_path_util.dart';
import 'package:tone_snap/utils/log_util.dart'; import 'package:tone_snap/utils/log_util.dart';
void main() async { void main() async {
@ -38,7 +36,11 @@ void main() async {
} }
// 广 SDK // 广 SDK
MobileAds.instance.initialize(); try {
MobileAds.instance.initialize();
} catch (e) {
LogUtil.e("MobileAds initialization error: $e");
}
// Hive // Hive
await initHive(); await initHive();
@ -59,10 +61,6 @@ void main() async {
systemNavigationBarIconBrightness: Brightness.light, systemNavigationBarIconBrightness: Brightness.light,
)); ));
} }
//
FileUtil.deleteAllFilesInDirectory(await LocalPathUtil.getRecordingsDir());
FileUtil.deleteAllFilesInDirectory(await LocalPathUtil.getAssetsDir());
} }
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {
@ -75,7 +73,9 @@ class MyApp extends StatelessWidget {
navigatorObservers = [ navigatorObservers = [
GetObserver((_) { GetObserver((_) {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (Get.currentRoute == AppRoutes.playPage) { if (Get.currentRoute == AppRoutes.playPage
|| Get.currentRoute == AppRoutes.privacy
|| Get.currentRoute == AppRoutes.terms) {
MusicBar().hide(); MusicBar().hide();
} else { } else {
if (Get.isRegistered<MusicPlayerController>()) { if (Get.isRegistered<MusicPlayerController>()) {

View File

@ -2,14 +2,12 @@ import 'dart:async';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:tone_snap/ads/app_open_ad_manager.dart'; import 'package:tone_snap/ads/interstitial_ad_manager.dart';
import 'package:tone_snap/data/api/tikustok_api.dart'; import 'package:tone_snap/data/enum/ad_scenes.dart';
import 'package:tone_snap/data/enum/app_side_enum.dart'; import 'package:tone_snap/data/enum/app_side_enum.dart';
import 'package:tone_snap/data/models/base_model.dart';
import 'package:tone_snap/data/models/isocode_model.dart';
import 'package:tone_snap/data/storage/music_box.dart'; import 'package:tone_snap/data/storage/music_box.dart';
import 'package:tone_snap/firebase/firebase_analytics_manager.dart';
import 'package:tone_snap/global/app_config.dart'; import 'package:tone_snap/global/app_config.dart';
import 'package:tone_snap/global/app_lifecycle_reactor.dart';
import 'package:tone_snap/global/network_connectivity_service.dart'; import 'package:tone_snap/global/network_connectivity_service.dart';
import 'package:tone_snap/modules/sideb/controllers/main_controller.dart'; import 'package:tone_snap/modules/sideb/controllers/main_controller.dart';
import 'package:tone_snap/routes/app_routes.dart'; import 'package:tone_snap/routes/app_routes.dart';
@ -25,17 +23,12 @@ class LaunchController extends GetxController with GetSingleTickerProviderStateM
/// ///
var changeValue = 10; var changeValue = 10;
late AppLifecycleReactor _appLifecycleReactor;
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
_appLifecycleReactor = AppLifecycleReactor();
_appLifecycleReactor.listenToAppStateChanges();
Get.put(NetworkConnectivityService());
_startTimer(); _startTimer();
Get.put(NetworkConnectivityService());
FirebaseAnalyticsManager.logLaunchPV();
} }
@override @override
@ -46,14 +39,12 @@ class LaunchController extends GetxController with GetSingleTickerProviderStateM
/// ///
void _startTimer() { void _startTimer() {
_timer = Timer.periodic(Duration(milliseconds: changeValue), (Timer t) { _timer = Timer.periodic(const Duration(milliseconds: 10), (Timer t) {
if (currentProcess.value + changeValue >= timeTotal) { if (currentProcess.value + changeValue >= timeTotal) {
currentProcess.value = timeTotal; currentProcess.value = timeTotal;
if (currentProcess >= timeTotal) { _stopTimer();
_stopTimer(); _checkEnter();
_checkEnter(); return;
return;
}
} }
currentProcess.value += changeValue; currentProcess.value += changeValue;
}); });
@ -67,7 +58,7 @@ class LaunchController extends GetxController with GetSingleTickerProviderStateM
/// ///
void editChangeValue() { void editChangeValue() {
changeValue = 3000; changeValue = 200;
} }
/// A还是B /// A还是B
@ -75,18 +66,18 @@ class LaunchController extends GetxController with GetSingleTickerProviderStateM
bool isOpenedSideB = MusicBox().getIsOpenedSideB(); bool isOpenedSideB = MusicBox().getIsOpenedSideB();
if (isOpenedSideB) { if (isOpenedSideB) {
LogUtil.d('进入过B面'); LogUtil.d('进入过B面');
_openSideB(); _openSideB('进入过B面');
} else { } else {
bool enter = MusicBox().getEnter(); bool enter = MusicBox().getEnter();
String versionCode = await MusicBox().getVersionCode(); String versionCode = await MusicBox().getVersionCode();
final packageInfo = await PackageInfo.fromPlatform(); final packageInfo = await PackageInfo.fromPlatform();
if (versionCode != packageInfo.version) { if (versionCode != packageInfo.version) {
LogUtil.d('版本不相同进入B面'); LogUtil.d('版本不相同进入B面');
_openSideB(); _openSideB('版本不相同');
} else { } else {
if (enter) { if (enter) {
LogUtil.d('开关:打开'); LogUtil.d('开关:打开');
_openSideB(); _openSideB('版本相同, 开关打开');
} else { } else {
LogUtil.d('开关:关闭'); LogUtil.d('开关:关闭');
_openSideA(); _openSideA();
@ -96,26 +87,26 @@ class LaunchController extends GetxController with GetSingleTickerProviderStateM
} }
void _openSideA() { void _openSideA() {
AppOpenAdManager().showAdIfAvailable(onTap: () { InterstitialAdManager().showAdIfAvailable(
AppConfig.appSideEnum = AppSideEnum.sideA; AdScenes.coldLoading.name,
Get.offNamed(AppRoutes.initialA); onTap: () {
}); AppConfig.appSideEnum = AppSideEnum.sideA;
Get.offNamed(AppRoutes.initialA);
},
);
FirebaseAnalyticsManager.logJumpEvent('A', '版本相同,开关关闭');
} }
void _openSideB() { void _openSideB(String reason) {
AppOpenAdManager().showAdIfAvailable(onTap: () { InterstitialAdManager().showAdIfAvailable(
AppConfig.appSideEnum = AppSideEnum.sideB; AdScenes.coldLoading.name,
MainController.to.changeTheme(); onTap: () {
Get.offNamed(AppRoutes.initialB); AppConfig.appSideEnum = AppSideEnum.sideB;
MusicBox().putIsOpenedSideB(true); MainController.to.changeTheme();
}); Get.offNamed(AppRoutes.initialB);
} MusicBox().putIsOpenedSideB(true);
},
/// );
Future<void> getIsoCode() async { FirebaseAnalyticsManager.logJumpEvent('B', reason);
BaseModel<IsoCodeModel>? model = await TikUsTokApi.getIsoCode();
if (model != null && model.success && model.data?.isoCode != null) {
AppConfig.isoCode = model.data!.isoCode!;
}
} }
} }

View File

@ -4,7 +4,6 @@ import 'package:get/get.dart';
import 'package:step_progress_indicator/step_progress_indicator.dart'; import 'package:step_progress_indicator/step_progress_indicator.dart';
import 'package:tone_snap/generated/assets.dart'; import 'package:tone_snap/generated/assets.dart';
import 'package:tone_snap/modules/launch/launch_controller.dart'; import 'package:tone_snap/modules/launch/launch_controller.dart';
import 'package:tone_snap/res/themes/app_colors.dart';
class LaunchView extends StatelessWidget { class LaunchView extends StatelessWidget {
LaunchView({super.key}); LaunchView({super.key});

View File

@ -4,6 +4,7 @@ import 'package:ffmpeg_kit_flutter_audio/return_code.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/ads/interstitial_ad_manager.dart'; import 'package:tone_snap/ads/interstitial_ad_manager.dart';
import 'package:tone_snap/components/base_easyloading.dart'; import 'package:tone_snap/components/base_easyloading.dart';
import 'package:tone_snap/data/enum/ad_scenes.dart';
import 'package:tone_snap/data/models/voice_model.dart'; import 'package:tone_snap/data/models/voice_model.dart';
import 'package:tone_snap/data/storage/my_voice_box.dart'; import 'package:tone_snap/data/storage/my_voice_box.dart';
import 'package:tone_snap/generated/assets.dart'; import 'package:tone_snap/generated/assets.dart';
@ -46,8 +47,6 @@ class ChangeVoiceController extends GetxController {
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
InterstitialAdManager().loadAd();
filePath = Get.arguments; filePath = Get.arguments;
// playerController.setFilePath(filePath); // playerController.setFilePath(filePath);
} }
@ -104,9 +103,10 @@ class ChangeVoiceController extends GetxController {
/// ///
Future<void> save() async { Future<void> save() async {
// 广
InterstitialAdManager().showAdIfAvailable( InterstitialAdManager().showAdIfAvailable(
AdScenes.download.name,
onTap: () async { onTap: () async {
await playerController.startPlay();
// //
if (playerController.isPlaying.value) playerController.stopPlay(); if (playerController.isPlaying.value) playerController.stopPlay();
BaseEasyLoading.loading(); BaseEasyLoading.loading();

View File

@ -1,5 +1,7 @@
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/ads/interstitial_ad_manager.dart';
import 'package:tone_snap/components/base_easyloading.dart'; import 'package:tone_snap/components/base_easyloading.dart';
import 'package:tone_snap/data/enum/ad_scenes.dart';
import 'package:tone_snap/data/models/voice_model.dart'; import 'package:tone_snap/data/models/voice_model.dart';
import 'package:tone_snap/generated/assets.dart'; import 'package:tone_snap/generated/assets.dart';
import 'package:tone_snap/modules/sidea/controllers/player_controller.dart'; import 'package:tone_snap/modules/sidea/controllers/player_controller.dart';
@ -22,22 +24,32 @@ class HomeController extends GetxController {
]; ];
void onTapItem(VoiceModel item) { void onTapItem(VoiceModel item) {
InitialController.to.currentPlayVoiceModel.value = item; InterstitialAdManager().showAdIfAvailable(
Get.toNamed(AppRoutes.playSound, arguments: item); AdScenes.play.name,
onTap: () {
InitialController.to.currentPlayVoiceModel.value = item;
Get.toNamed(AppRoutes.playSound, arguments: item);
},
);
} }
Future<void> onTapPlayBarPlay(VoiceModel item) async { Future<void> onTapPlayBarPlay(VoiceModel item) async {
if (isPlayItem(item)) { if (isPlayItem(item)) {
await playerController.pausePlay(); await playerController.pausePlay();
} else { } else {
if (!identical(item, InitialController.to.currentPlayVoiceModel.value)) { InterstitialAdManager().showAdIfAvailable(
BaseEasyLoading.loading(); AdScenes.play.name,
await playerController.setFilePath(item.path); onTap: () async {
BaseEasyLoading.dismiss(); if (!identical(item, InitialController.to.currentPlayVoiceModel.value)) {
InitialController.to.currentPlayVoiceModel.value = item; BaseEasyLoading.loading();
InitialController.to.isFavourite.value = InitialController.to.getIsFavouriteModel() != null; await playerController.setFilePath(item.path);
} BaseEasyLoading.dismiss();
await playerController.startPlay(); InitialController.to.currentPlayVoiceModel.value = item;
InitialController.to.isFavourite.value = InitialController.to.getIsFavouriteModel() != null;
}
await playerController.startPlay();
},
);
} }
} }

View File

@ -4,6 +4,7 @@ import 'package:tone_snap/data/models/voice_model.dart';
import 'package:tone_snap/data/storage/favorite_box.dart'; import 'package:tone_snap/data/storage/favorite_box.dart';
import 'package:tone_snap/firebase/firebase_analytics_manager.dart'; import 'package:tone_snap/firebase/firebase_analytics_manager.dart';
import 'package:tone_snap/generated/assets.dart'; import 'package:tone_snap/generated/assets.dart';
import 'package:tone_snap/global/app_lifecycle_reactor.dart';
import 'package:tone_snap/global/app_tracking_transparency_manager.dart'; import 'package:tone_snap/global/app_tracking_transparency_manager.dart';
import 'package:tone_snap/modules/sidea/controllers/player_controller.dart'; import 'package:tone_snap/modules/sidea/controllers/player_controller.dart';
import 'package:tone_snap/modules/sidea/favourite/favourite_controller.dart'; import 'package:tone_snap/modules/sidea/favourite/favourite_controller.dart';
@ -12,6 +13,8 @@ import 'package:tone_snap/modules/sidea/me/me_view.dart';
import 'package:tone_snap/modules/sidea/my_voice/my_voice_controller.dart'; import 'package:tone_snap/modules/sidea/my_voice/my_voice_controller.dart';
import 'package:tone_snap/modules/sidea/settings/settings_view.dart'; import 'package:tone_snap/modules/sidea/settings/settings_view.dart';
import 'package:tone_snap/routes/app_routes.dart'; import 'package:tone_snap/routes/app_routes.dart';
import 'package:tone_snap/utils/file_util.dart';
import 'package:tone_snap/utils/local_path_util.dart';
class InitialController extends GetxController { class InitialController extends GetxController {
static InitialController get to => Get.find<InitialController>(); static InitialController get to => Get.find<InitialController>();
@ -29,17 +32,27 @@ class InitialController extends GetxController {
/// ///
var isFavourite = false.obs; var isFavourite = false.obs;
late AppLifecycleReactor _appLifecycleReactor;
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
AppTrackingTransparencyManager().requestATT(); AppTrackingTransparencyManager().requestATT();
_appLifecycleReactor = AppLifecycleReactor();
_appLifecycleReactor.listenToAppStateChanges();
pageController = PageController(initialPage: currentIndex.value); pageController = PageController(initialPage: currentIndex.value);
} }
@override @override
void onReady() async { void onReady() async {
super.onReady(); super.onReady();
_addEventLog(); //
FileUtil.deleteAllFilesInDirectory(await LocalPathUtil.getRecordingsDir());
FileUtil.deleteAllFilesInDirectory(await LocalPathUtil.getAssetsDir());
FirebaseAnalyticsManager.logHomeAPV();
} }
@override @override
@ -55,10 +68,10 @@ class InitialController extends GetxController {
} else { } else {
currentIndex.value = index; currentIndex.value = index;
pageController.jumpToPage(index); pageController.jumpToPage(index);
if (index == 0) {
_addEventLog();
}
if (index == 2) _refreshMe(); if (index == 2) _refreshMe();
if (index == 0) {
FirebaseAnalyticsManager.logHomeAPV();
}
} }
} }
@ -95,11 +108,6 @@ class InitialController extends GetxController {
if (Get.isRegistered<MyVoiceController>()) MyVoiceController.to.getData(); if (Get.isRegistered<MyVoiceController>()) MyVoiceController.to.getData();
if (Get.isRegistered<FavouriteController>()) FavouriteController.to.getData(); if (Get.isRegistered<FavouriteController>()) FavouriteController.to.getData();
} }
///
void _addEventLog() {
FirebaseAnalyticsManager.logEvent(FirebaseAnalyticsManager.homeApv);
}
} }
class PageItem { class PageItem {

View File

@ -1,4 +1,3 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/components/base_easyloading.dart'; import 'package:tone_snap/components/base_easyloading.dart';
import 'package:tone_snap/components/dialog/add_playlist_dialog.dart'; import 'package:tone_snap/components/dialog/add_playlist_dialog.dart';
@ -19,7 +18,7 @@ class AddToPlaylistBottomSheetController extends GetxController {
} }
void _getList() { void _getList() {
playlists.value = PlaylistsBox().getReversedList(); playlists.value = PlaylistsBox().getList();
} }
void setMusicModel(MusicModel musicModel) { void setMusicModel(MusicModel musicModel) {

View File

@ -1,12 +1,13 @@
import 'dart:ffi';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/ads/interstitial_ad_manager.dart';
import 'package:tone_snap/components/base_easyloading.dart'; import 'package:tone_snap/components/base_easyloading.dart';
import 'package:tone_snap/components/view_state_widget.dart'; import 'package:tone_snap/components/view_state_widget.dart';
import 'package:tone_snap/data/api/music_api.dart'; import 'package:tone_snap/data/api/music_api.dart';
import 'package:tone_snap/data/enum/ad_scenes.dart';
import 'package:tone_snap/data/models/browse_model.dart'; import 'package:tone_snap/data/models/browse_model.dart';
import 'package:tone_snap/data/models/music_model.dart'; import 'package:tone_snap/data/models/music_model.dart';
import 'package:tone_snap/data/storage/collect_playlists_box.dart'; import 'package:tone_snap/data/storage/collect_playlists_box.dart';
import 'package:tone_snap/firebase/firebase_analytics_manager.dart';
import 'package:tone_snap/modules/sideb/collect_playlists/collect_playlists_controller.dart'; import 'package:tone_snap/modules/sideb/collect_playlists/collect_playlists_controller.dart';
import 'package:tone_snap/modules/sideb/controllers/music_player_controller.dart'; import 'package:tone_snap/modules/sideb/controllers/music_player_controller.dart';
import 'package:tone_snap/routes/app_routes.dart'; import 'package:tone_snap/routes/app_routes.dart';
@ -103,6 +104,9 @@ class AlbumSongListController extends GetxController {
if (thumbnails != null && thumbnails.isNotEmpty) { if (thumbnails != null && thumbnails.isNotEmpty) {
musicModel.coverUrl = thumbnails.last.url; musicModel.coverUrl = thumbnails.last.url;
} }
if (ObjUtil.isEmpty(musicModel.coverUrl)) {
musicModel.coverUrl = coverUrl.value;
}
var flexColumns = o.musicResponsiveListItemRenderer?.flexColumns; var flexColumns = o.musicResponsiveListItemRenderer?.flexColumns;
if (flexColumns != null && flexColumns.isNotEmpty) { if (flexColumns != null && flexColumns.isNotEmpty) {
@ -142,21 +146,25 @@ class AlbumSongListController extends GetxController {
/// ///
Future<void> onTapPlayAll(bool isShuffle) async { Future<void> onTapPlayAll(bool isShuffle) async {
if (musicList.isNotEmpty) { if (musicList.isNotEmpty) {
int index = 0; InterstitialAdManager().showAdIfAvailable(
if (isShuffle && musicList.length > 1) { AdScenes.play.name,
final n = musicList.indexWhere((e) => e.videoId == musicPlayerController.getMusicModel()?.videoId); onTap: () {
if (n != -1) { int index = 0;
index = NumUtil.getRandomNumberExcludingCurrent(0, musicList.length, n); if (isShuffle && musicList.length > 1) {
} else { final n = musicList.indexWhere((e) => e.videoId == musicPlayerController.getMusicModel()?.videoId);
index = NumUtil.getRandomNumber(0, musicList.length); if (n != -1) {
} index = NumUtil.getRandomNumberExcludingCurrent(0, musicList.length, n);
} } else {
for (var o in musicList) { index = NumUtil.getRandomNumber(0, musicList.length);
if (ObjUtil.isEmpty(o.coverUrl)) { }
o.coverUrl = coverUrl.value; }
} Get.toNamed(AppRoutes.playPage, arguments: {
} 'videoId': musicList[index].videoId,
musicPlayerController.playMusic(musicList[index].videoId, playList: musicList); 'playList': musicList,
});
},
);
FirebaseAnalyticsManager.logSongClick('来自专辑/歌单');
} }
} }
@ -186,9 +194,15 @@ class AlbumSongListController extends GetxController {
/// ///
void onTapItem(MusicModel musicModel) { void onTapItem(MusicModel musicModel) {
Get.toNamed(AppRoutes.playPage, arguments: { InterstitialAdManager().showAdIfAvailable(
'videoId': musicModel.videoId, AdScenes.play.name,
'playlistId': musicModel.playlistId, onTap: () {
}); Get.toNamed(AppRoutes.playPage, arguments: {
'videoId': musicModel.videoId,
'playList': musicList,
});
},
);
FirebaseAnalyticsManager.logSongClick('来自专辑/歌单');
} }
} }

View File

@ -15,6 +15,7 @@ import 'package:tone_snap/data/models/music_model.dart';
import 'package:tone_snap/data/models/player_model.dart'; import 'package:tone_snap/data/models/player_model.dart';
import 'package:tone_snap/data/storage/music_box.dart'; import 'package:tone_snap/data/storage/music_box.dart';
import 'package:tone_snap/data/storage/offline_box.dart'; import 'package:tone_snap/data/storage/offline_box.dart';
import 'package:tone_snap/firebase/firebase_analytics_manager.dart';
import 'package:tone_snap/modules/sideb/music_bar/music_bar.dart'; import 'package:tone_snap/modules/sideb/music_bar/music_bar.dart';
import 'package:tone_snap/routes/app_routes.dart'; import 'package:tone_snap/routes/app_routes.dart';
import 'package:tone_snap/utils/audio_util.dart'; import 'package:tone_snap/utils/audio_util.dart';
@ -67,6 +68,9 @@ class MusicPlayerController extends GetxController {
/// ///
var currentIndex = 0.obs; var currentIndex = 0.obs;
/// videoId
String? _logVideoId;
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
@ -100,15 +104,18 @@ class MusicPlayerController extends GetxController {
/// ///
Future<void> _startPlay() async { Future<void> _startPlay() async {
if (playlist.isNotEmpty) { if (playlist.isNotEmpty) {
FirebaseAnalyticsManager.logPlayerBpv(getMusicModel()?.videoId, getMusicModel()?.title, getMusicModel()?.subtitle);
resetPlaybackStatus(); resetPlaybackStatus();
Get.currentRoute == AppRoutes.playPage ? MusicBar().hide() : MusicBar().show(); Get.currentRoute == AppRoutes.playPage ? MusicBar().hide() : MusicBar().show();
try { try {
DateTime startLoadDateTime = DateTime.now();
var model = OfflineBox().getList().firstWhereOrNull((e) => e.videoId == getMusicModel()?.videoId); var model = OfflineBox().getList().firstWhereOrNull((e) => e.videoId == getMusicModel()?.videoId);
if (model != null && ObjUtil.isNotEmpty(model.localPath)) { if (model != null && ObjUtil.isNotEmpty(model.localPath)) {
// //
LogUtil.d('读取下载路径=${model.localPath}'); LogUtil.d('读取下载路径=${model.localPath}');
if (!await File(model.localPath!).exists()) { if (!await File(model.localPath!).exists()) {
BaseEasyLoading.toast('file does not exist'); BaseEasyLoading.toast('file does not exist');
FirebaseAnalyticsManager.logPlayerBFailAction('本地文件不存在');
return; return;
} }
await _player.setFilePath(model.localPath!); await _player.setFilePath(model.localPath!);
@ -136,9 +143,20 @@ class MusicPlayerController extends GetxController {
_cancelListening(); _cancelListening();
_addListening(); _addListening();
_player.play(); _player.play();
DateTime endLoadDateTime = DateTime.now();
//
int millisecondsDifference = endLoadDateTime.difference(startLoadDateTime).inMilliseconds;
FirebaseAnalyticsManager.logPlayerBDelayAction(
getMusicModel()?.videoId,
getMusicModel()?.title,
getMusicModel()?.subtitle,
'${millisecondsDifference}ms',
);
} catch (e) { } catch (e) {
LogUtil.e('Play failed: $e'); LogUtil.e('Play failed: $e');
BaseEasyLoading.toast('Play failed'); BaseEasyLoading.toast('Play failed');
FirebaseAnalyticsManager.logPlayerBFailAction(e.toString());
} }
} }
} }
@ -200,6 +218,16 @@ class MusicPlayerController extends GetxController {
} }
break; break;
} }
if (isPlaying.value) {
if (_logVideoId != getMusicModel()?.videoId) {
_logVideoId = getMusicModel()?.videoId;
FirebaseAnalyticsManager.logPlayerBSuccessAction(
getMusicModel()?.videoId,
getMusicModel()?.title,
getMusicModel()?.subtitle,
);
}
}
}); });
} }

View File

@ -1,9 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/ads/interstitial_ad_manager.dart';
import 'package:tone_snap/components/view_state_widget.dart'; import 'package:tone_snap/components/view_state_widget.dart';
import 'package:tone_snap/data/enum/ad_scenes.dart';
import 'package:tone_snap/data/models/music_model.dart'; import 'package:tone_snap/data/models/music_model.dart';
import 'package:tone_snap/data/models/playlist_model.dart'; import 'package:tone_snap/data/models/playlist_model.dart';
import 'package:tone_snap/data/storage/playlists_box.dart'; import 'package:tone_snap/data/storage/playlists_box.dart';
import 'package:tone_snap/firebase/firebase_analytics_manager.dart';
import 'package:tone_snap/modules/sideb/controllers/music_player_controller.dart'; import 'package:tone_snap/modules/sideb/controllers/music_player_controller.dart';
import 'package:tone_snap/modules/sideb/more_playlist_bottom_sheet/more_playlist_bottom_sheet_view.dart'; import 'package:tone_snap/modules/sideb/more_playlist_bottom_sheet/more_playlist_bottom_sheet_view.dart';
import 'package:tone_snap/routes/app_routes.dart'; import 'package:tone_snap/routes/app_routes.dart';
@ -64,16 +67,25 @@ class CustomPlaylistController extends GetxController {
Future<void> onTapPlayAll(bool isShuffle) async { Future<void> onTapPlayAll(bool isShuffle) async {
if (musicList.isNotEmpty) { if (musicList.isNotEmpty) {
int index = 0; InterstitialAdManager().showAdIfAvailable(
if (isShuffle && musicList.length > 1) { AdScenes.play.name,
final n = musicList.indexWhere((e) => e.videoId == musicPlayerController.getMusicModel()?.videoId); onTap: () {
if (n != -1) { int index = 0;
index = NumUtil.getRandomNumberExcludingCurrent(0, musicList.length, n); if (isShuffle && musicList.length > 1) {
} else { final n = musicList.indexWhere((e) => e.videoId == musicPlayerController.getMusicModel()?.videoId);
index = NumUtil.getRandomNumber(0, musicList.length); if (n != -1) {
} index = NumUtil.getRandomNumberExcludingCurrent(0, musicList.length, n);
} } else {
musicPlayerController.playMusic(musicList[index].videoId, playList: musicList); index = NumUtil.getRandomNumber(0, musicList.length);
}
}
Get.toNamed(AppRoutes.playPage, arguments: {
'videoId': musicList[index].videoId,
'playList': musicList,
});
},
);
FirebaseAnalyticsManager.logSongClick('来自自建歌单列表');
} }
} }
@ -103,9 +115,15 @@ class CustomPlaylistController extends GetxController {
} }
void onTapItem(MusicModel musicModel) { void onTapItem(MusicModel musicModel) {
Get.toNamed(AppRoutes.playPage, arguments: { InterstitialAdManager().showAdIfAvailable(
'videoId': musicModel.videoId, AdScenes.play.name,
'playList': musicList.toList(), onTap: () {
}); Get.toNamed(AppRoutes.playPage, arguments: {
'videoId': musicModel.videoId,
'playList': musicList,
});
},
);
FirebaseAnalyticsManager.logSongClick('来自自建歌单列表');
} }
} }

View File

@ -1,13 +1,21 @@
import 'package:easy_refresh/easy_refresh.dart'; import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/ads/interstitial_ad_manager.dart';
import 'package:tone_snap/components/view_state_widget.dart'; import 'package:tone_snap/components/view_state_widget.dart';
import 'package:tone_snap/data/api/music_api.dart'; import 'package:tone_snap/data/api/music_api.dart';
import 'package:tone_snap/data/api/tikustok_api.dart';
import 'package:tone_snap/data/enum/ad_scenes.dart';
import 'package:tone_snap/data/enum/music_type.dart'; import 'package:tone_snap/data/enum/music_type.dart';
import 'package:tone_snap/data/models/base_model.dart';
import 'package:tone_snap/data/models/browse_group_model.dart'; import 'package:tone_snap/data/models/browse_group_model.dart';
import 'package:tone_snap/data/models/browse_model.dart'; import 'package:tone_snap/data/models/browse_model.dart';
import 'package:tone_snap/data/models/isocode_model.dart';
import 'package:tone_snap/data/models/music_model.dart'; import 'package:tone_snap/data/models/music_model.dart';
import 'package:tone_snap/data/network/base_error.dart';
import 'package:tone_snap/firebase/firebase_analytics_manager.dart';
import 'package:tone_snap/global/app_config.dart';
import 'package:tone_snap/routes/app_routes.dart'; import 'package:tone_snap/routes/app_routes.dart';
import 'package:tone_snap/utils/obj_util.dart';
class HomeController extends GetxController { class HomeController extends GetxController {
static HomeController get to => Get.find<HomeController>(); static HomeController get to => Get.find<HomeController>();
@ -42,13 +50,29 @@ class HomeController extends GetxController {
firstBrowse(); firstBrowse();
} }
///
Future<void> _getIsoCode() async {
BaseModel<IsoCodeModel>? model = await TikUsTokApi.getIsoCode();
if (model != null && model.success && model.data?.isoCode != null) {
AppConfig.isoCode = model.data!.isoCode!;
}
}
/// ///
Future<void> firstBrowse() async { Future<void> firstBrowse() async {
await _getIsoCode();
Map<String, dynamic> queryParameters = { Map<String, dynamic> queryParameters = {
'prettyPrint': false, 'prettyPrint': false,
'browseId': 'FEmusic_home' 'browseId': 'FEmusic_home'
}; };
BrowseModel? browseModel = await MusicApi.browse<BrowseModel>(queryParameters: queryParameters, formJson: BrowseModel.fromMap); BrowseModel? browseModel = await MusicApi.browse<BrowseModel>(
queryParameters: queryParameters,
formJson: BrowseModel.fromMap,
fail: (BaseError baseError) {
refreshController.finishRefresh(IndicatorResult.fail);
FirebaseAnalyticsManager.logHomeBModuleFailAction('${baseError.code},${baseError.message}');
},
);
if (browseModel != null) { if (browseModel != null) {
refreshController.finishRefresh(); refreshController.finishRefresh();
@ -65,8 +89,11 @@ class HomeController extends GetxController {
clickTrackingParams = continuations[0].nextContinuationData?.clickTrackingParams; clickTrackingParams = continuations[0].nextContinuationData?.clickTrackingParams;
} }
_reBrowse(continuation: continuation, clickTrackingParams: clickTrackingParams); _reBrowse(continuation: continuation, clickTrackingParams: clickTrackingParams);
} else { if (groupList.isNotEmpty) {
refreshController.finishRefresh(IndicatorResult.fail); FirebaseAnalyticsManager.logHomeBModuleShowsuccesAction();
} else {
FirebaseAnalyticsManager.logHomeBModuleFailAction('无数据');
}
} }
viewState.value = groupList.isNotEmpty ? ViewState.normal : ViewState.empty; viewState.value = groupList.isNotEmpty ? ViewState.normal : ViewState.empty;
} }
@ -80,7 +107,11 @@ class HomeController extends GetxController {
'itct': clickTrackingParams, 'itct': clickTrackingParams,
'prettyPrint': false 'prettyPrint': false
}; };
BrowseModel? browseModel = await MusicApi.browse<BrowseModel>(visitorData: visitorData, queryParameters: queryParameters, formJson: BrowseModel.fromMap); BrowseModel? browseModel = await MusicApi.browse<BrowseModel>(
visitorData: visitorData,
queryParameters: queryParameters,
formJson: BrowseModel.fromMap,
);
if (browseModel != null) { if (browseModel != null) {
_extractAssemblyData(browseModel); _extractAssemblyData(browseModel);
@ -191,6 +222,7 @@ class HomeController extends GetxController {
} }
void openSearch() { void openSearch() {
FirebaseAnalyticsManager.logSearchFromAction('来自首页');
Get.toNamed(AppRoutes.searchResult); Get.toNamed(AppRoutes.searchResult);
} }
@ -198,11 +230,18 @@ class HomeController extends GetxController {
Get.toNamed(AppRoutes.setting); Get.toNamed(AppRoutes.setting);
} }
void openPlayPage(MusicModel musicModel) { void openPlayPage(BrowseGroupModel browseGroupModel, MusicModel musicModel) {
Get.toNamed(AppRoutes.playPage, arguments: { InterstitialAdManager().showAdIfAvailable(
'videoId': musicModel.videoId, AdScenes.play.name,
'playlistId': musicModel.playlistId, onTap: () {
}); Get.toNamed(AppRoutes.playPage, arguments: {
'videoId': musicModel.videoId,
'playlistId': musicModel.playlistId,
});
},
);
FirebaseAnalyticsManager.logHomeBModuleClick(ObjUtil.getStr(browseGroupModel.groupTitle));
FirebaseAnalyticsManager.logSongClick('来自首页');
} }
void openAlbumSong(BrowseGroupModel browseGroupModel, MusicModel musicModel) { void openAlbumSong(BrowseGroupModel browseGroupModel, MusicModel musicModel) {
@ -214,5 +253,6 @@ class HomeController extends GetxController {
'title': musicModel.title, 'title': musicModel.title,
'subtitle': musicModel.subtitle, 'subtitle': musicModel.subtitle,
}); });
FirebaseAnalyticsManager.logHomeBModuleClick(ObjUtil.getStr(browseGroupModel.groupTitle));
} }
} }

View File

@ -154,7 +154,7 @@ class HomeView extends GetView<HomeController> {
final musicModel = browseGroupModel.browseList![index]; final musicModel = browseGroupModel.browseList![index];
return BrowseItemAtv( return BrowseItemAtv(
musicModel: musicModel, musicModel: musicModel,
onTap: () => controller.openPlayPage(musicModel), onTap: () => controller.openPlayPage(browseGroupModel, musicModel),
); );
}, },
), ),

View File

@ -1,6 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/firebase/firebase_analytics_manager.dart';
import 'package:tone_snap/generated/assets.dart'; import 'package:tone_snap/generated/assets.dart';
import 'package:tone_snap/global/app_lifecycle_reactor.dart';
import 'package:tone_snap/global/app_tracking_transparency_manager.dart'; import 'package:tone_snap/global/app_tracking_transparency_manager.dart';
import 'package:tone_snap/modules/sideb/home/home_view.dart'; import 'package:tone_snap/modules/sideb/home/home_view.dart';
import 'package:tone_snap/modules/sideb/personal_music_library/personal_music_library_controller.dart'; import 'package:tone_snap/modules/sideb/personal_music_library/personal_music_library_controller.dart';
@ -17,11 +19,19 @@ class InitialController extends GetxController {
]; ];
var currentIndex = 0.obs; var currentIndex = 0.obs;
late AppLifecycleReactor _appLifecycleReactor;
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
AppTrackingTransparencyManager().requestATT(); AppTrackingTransparencyManager().requestATT();
_appLifecycleReactor = AppLifecycleReactor();
_appLifecycleReactor.listenToAppStateChanges();
pageController = PageController(initialPage: currentIndex.value); pageController = PageController(initialPage: currentIndex.value);
FirebaseAnalyticsManager.logHomeBPV();
} }
@override @override
@ -33,12 +43,18 @@ class InitialController extends GetxController {
Future<void> onBottomAppBarItemChanged(int index) async { Future<void> onBottomAppBarItemChanged(int index) async {
currentIndex.value = index; currentIndex.value = index;
pageController.jumpToPage(index); pageController.jumpToPage(index);
if (index == 0) {
FirebaseAnalyticsManager.logHomeBPV();
}
if (index == 1) {
FirebaseAnalyticsManager.logSearchPV();
}
if (index == 2) { if (index == 2) {
if (Get.isRegistered<PersonalMusicLibraryController>()) { if (Get.isRegistered<PersonalMusicLibraryController>()) {
PersonalMusicLibraryController.to.refreshLoveSongs(); PersonalMusicLibraryController.to.refreshLoveSongs();
PersonalMusicLibraryController.to.refreshOffline(); PersonalMusicLibraryController.to.refreshOffline();
} }
FirebaseAnalyticsManager.logMeBPV();
} }
} }
} }

View File

@ -1,7 +1,10 @@
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/ads/interstitial_ad_manager.dart';
import 'package:tone_snap/components/view_state_widget.dart'; import 'package:tone_snap/components/view_state_widget.dart';
import 'package:tone_snap/data/enum/ad_scenes.dart';
import 'package:tone_snap/data/models/music_model.dart'; import 'package:tone_snap/data/models/music_model.dart';
import 'package:tone_snap/data/storage/love_songs_box.dart'; import 'package:tone_snap/data/storage/love_songs_box.dart';
import 'package:tone_snap/firebase/firebase_analytics_manager.dart';
import 'package:tone_snap/routes/app_routes.dart'; import 'package:tone_snap/routes/app_routes.dart';
class LoveSongsController extends GetxController { class LoveSongsController extends GetxController {
@ -21,9 +24,15 @@ class LoveSongsController extends GetxController {
} }
void onTapItem(MusicModel musicModel) { void onTapItem(MusicModel musicModel) {
Get.toNamed(AppRoutes.playPage, arguments: { InterstitialAdManager().showAdIfAvailable(
'videoId': musicModel.videoId, AdScenes.play.name,
'playList': LoveSongsBox().getReversedList(), onTap: () {
}); Get.toNamed(AppRoutes.playPage, arguments: {
'videoId': musicModel.videoId,
'playList': loveList,
});
},
);
FirebaseAnalyticsManager.logSongClick('来自收藏列表');
} }
} }

View File

@ -6,6 +6,7 @@ import 'package:tone_snap/data/models/music_model.dart';
import 'package:tone_snap/data/storage/love_songs_box.dart'; import 'package:tone_snap/data/storage/love_songs_box.dart';
import 'package:tone_snap/data/storage/offline_box.dart'; import 'package:tone_snap/data/storage/offline_box.dart';
import 'package:tone_snap/data/storage/playlists_box.dart'; import 'package:tone_snap/data/storage/playlists_box.dart';
import 'package:tone_snap/firebase/firebase_analytics_manager.dart';
import 'package:tone_snap/global/download_manager.dart'; import 'package:tone_snap/global/download_manager.dart';
import 'package:tone_snap/modules/sideb/add_to_playlist_bottom_sheet/add_to_playlist_bottom_sheet_view.dart'; import 'package:tone_snap/modules/sideb/add_to_playlist_bottom_sheet/add_to_playlist_bottom_sheet_view.dart';
import 'package:tone_snap/modules/sideb/custom_playlist/custom_playlist_controller.dart'; import 'package:tone_snap/modules/sideb/custom_playlist/custom_playlist_controller.dart';
@ -33,9 +34,19 @@ class MoreBottomSheetController extends GetxController {
void onTapLove() async { void onTapLove() async {
if (ObjUtil.isEmpty(musicModel.videoId)) return; if (ObjUtil.isEmpty(musicModel.videoId)) return;
if (isLove.value) { if (isLove.value) {
FirebaseAnalyticsManager.logPlayerBUnloveClick(
musicModel.videoId,
musicModel.title,
musicModel.subtitle,
);
await LoveSongsBox().delete(musicModel.videoId!); await LoveSongsBox().delete(musicModel.videoId!);
BaseEasyLoading.toast('Removed'); BaseEasyLoading.toast('Removed');
} else { } else {
FirebaseAnalyticsManager.logPlayerBLoveClick(
musicModel.videoId,
musicModel.title,
musicModel.subtitle,
);
await LoveSongsBox().add(musicModel.copyWith()); await LoveSongsBox().add(musicModel.copyWith());
BaseEasyLoading.toast('Collected'); BaseEasyLoading.toast('Collected');
} }

View File

@ -1,5 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/ads/interstitial_ad_manager.dart';
import 'package:tone_snap/data/enum/ad_scenes.dart';
import 'package:tone_snap/routes/app_routes.dart'; import 'package:tone_snap/routes/app_routes.dart';
class MusicBarController extends GetxController with GetSingleTickerProviderStateMixin { class MusicBarController extends GetxController with GetSingleTickerProviderStateMixin {
@ -28,8 +30,13 @@ class MusicBarController extends GetxController with GetSingleTickerProviderStat
/// ///
void openPlayPage() { void openPlayPage() {
Get.toNamed(AppRoutes.playPage, arguments: { InterstitialAdManager().showAdIfAvailable(
'isFormMusicBar': true, AdScenes.play.name,
}); onTap: () {
Get.toNamed(AppRoutes.playPage, arguments: {
'isFormMusicBar': true,
});
},
);
} }
} }

View File

@ -1,7 +1,10 @@
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/ads/interstitial_ad_manager.dart';
import 'package:tone_snap/components/view_state_widget.dart'; import 'package:tone_snap/components/view_state_widget.dart';
import 'package:tone_snap/data/enum/ad_scenes.dart';
import 'package:tone_snap/data/models/music_model.dart'; import 'package:tone_snap/data/models/music_model.dart';
import 'package:tone_snap/data/storage/offline_box.dart'; import 'package:tone_snap/data/storage/offline_box.dart';
import 'package:tone_snap/firebase/firebase_analytics_manager.dart';
import 'package:tone_snap/routes/app_routes.dart'; import 'package:tone_snap/routes/app_routes.dart';
class OfflineController extends GetxController { class OfflineController extends GetxController {
@ -21,9 +24,15 @@ class OfflineController extends GetxController {
} }
void onTapItem(MusicModel model) { void onTapItem(MusicModel model) {
Get.toNamed(AppRoutes.playPage, arguments: { InterstitialAdManager().showAdIfAvailable(
'videoId': model.videoId, AdScenes.play.name,
'playList': OfflineBox().getReversedList(), onTap: () {
}); Get.toNamed(AppRoutes.playPage, arguments: {
'videoId': model.videoId,
'playList': offlineList,
});
},
);
FirebaseAnalyticsManager.logSongClick('来自离线列表');
} }
} }

View File

@ -1,11 +1,16 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/ads/interstitial_ad_manager.dart';
import 'package:tone_snap/data/enum/ad_scenes.dart';
import 'package:tone_snap/data/storage/love_songs_box.dart'; import 'package:tone_snap/data/storage/love_songs_box.dart';
import 'package:tone_snap/data/storage/offline_box.dart'; import 'package:tone_snap/data/storage/offline_box.dart';
import 'package:tone_snap/firebase/firebase_analytics_manager.dart';
import 'package:tone_snap/modules/sideb/collect_playlists/collect_playlists_view.dart'; import 'package:tone_snap/modules/sideb/collect_playlists/collect_playlists_view.dart';
import 'package:tone_snap/modules/sideb/playlists/playlists_view.dart'; import 'package:tone_snap/modules/sideb/playlists/playlists_view.dart';
import 'package:tone_snap/routes/app_routes.dart'; import 'package:tone_snap/routes/app_routes.dart';
import '../../../ads/library_native_ad_manager.dart';
class PersonalMusicLibraryController extends GetxController with GetSingleTickerProviderStateMixin { class PersonalMusicLibraryController extends GetxController with GetSingleTickerProviderStateMixin {
static PersonalMusicLibraryController get to => Get.find<PersonalMusicLibraryController>(); static PersonalMusicLibraryController get to => Get.find<PersonalMusicLibraryController>();
var loveSongsCoverUrl = ''.obs; var loveSongsCoverUrl = ''.obs;
@ -32,19 +37,37 @@ class PersonalMusicLibraryController extends GetxController with GetSingleTicker
@override @override
void onClose() { void onClose() {
tabController.dispose(); tabController.dispose();
LibraryNativeAdManager().nativeAd?.dispose();
super.onClose(); super.onClose();
} }
void onTapModule(int index) { void onTapModule(int index) {
String routeName;
if (index == 0) { if (index == 0) {
Get.toNamed(AppRoutes.loveSongs); routeName = AppRoutes.loveSongs;
} FirebaseAnalyticsManager.logLibraryClick(
if (index == 1) { '曲库页面',
Get.toNamed(AppRoutes.artists); '收藏歌曲',
} );
if (index == 2) { } else if (index == 1) {
Get.toNamed(AppRoutes.offline); routeName = AppRoutes.artists;
FirebaseAnalyticsManager.logLibraryClick(
'曲库页面',
'收藏艺术家',
);
} else {
routeName = AppRoutes.offline;
FirebaseAnalyticsManager.logLibraryClick(
'曲库页面',
'离线列表',
);
} }
InterstitialAdManager().showAdIfAvailable(
AdScenes.list.name,
onTap: () {
Get.toNamed(routeName);
},
);
} }
void refreshLoveSongs() { void refreshLoveSongs() {

View File

@ -1,6 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:tone_snap/ads/library_native_ad_manager.dart';
import 'package:tone_snap/components/keep_alive_wrapper.dart'; import 'package:tone_snap/components/keep_alive_wrapper.dart';
import 'package:tone_snap/components/my_custom_indicator.dart'; import 'package:tone_snap/components/my_custom_indicator.dart';
import 'package:tone_snap/components/network_image_widget.dart'; import 'package:tone_snap/components/network_image_widget.dart';
@ -20,12 +22,14 @@ class PersonalMusicLibraryView extends GetView<PersonalMusicLibraryController> {
return Stack( return Stack(
children: [ children: [
_buildPageBg(), _buildPageBg(),
SafeArea( Padding(
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_buildTitle(), _buildTitle(),
_buildModule(), _buildModule(),
// _buildAdWidget(),
_buildTabBar(), _buildTabBar(),
_buildTabBarView(), _buildTabBarView(),
], ],
@ -57,9 +61,25 @@ class PersonalMusicLibraryView extends GetView<PersonalMusicLibraryController> {
); );
} }
Widget _buildAdWidget() {
return Obx(() {
if (LibraryNativeAdManager().nativeAdIsLoaded.value
&& LibraryNativeAdManager().nativeAd != null) {
return Container(
width: 1.sw,
height: 320.h,
padding: EdgeInsets.symmetric(horizontal: 16.w),
child: AdWidget(ad: LibraryNativeAdManager().nativeAd!),
);
} else {
return Container();
}
});
}
Widget _buildModule() { Widget _buildModule() {
return Padding( return Padding(
padding: EdgeInsets.symmetric(vertical: 28.h, horizontal: 16.w), padding: EdgeInsets.symmetric(vertical: 10.h, horizontal: 16.w),
child: Row( child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween, // mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [

View File

@ -1,12 +1,15 @@
import 'package:background_downloader/background_downloader.dart'; import 'package:background_downloader/background_downloader.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/ads/interstitial_ad_manager.dart';
import 'package:tone_snap/components/base_easyloading.dart'; import 'package:tone_snap/components/base_easyloading.dart';
import 'package:tone_snap/components/dialog/remind_dialog.dart'; import 'package:tone_snap/components/dialog/remind_dialog.dart';
import 'package:tone_snap/data/api/music_api.dart'; import 'package:tone_snap/data/api/music_api.dart';
import 'package:tone_snap/data/enum/ad_scenes.dart';
import 'package:tone_snap/data/models/music_model.dart'; import 'package:tone_snap/data/models/music_model.dart';
import 'package:tone_snap/data/models/next_model.dart'; import 'package:tone_snap/data/models/next_model.dart';
import 'package:tone_snap/data/storage/love_songs_box.dart'; import 'package:tone_snap/data/storage/love_songs_box.dart';
import 'package:tone_snap/data/storage/offline_box.dart'; import 'package:tone_snap/data/storage/offline_box.dart';
import 'package:tone_snap/firebase/firebase_analytics_manager.dart';
import 'package:tone_snap/global/download_manager.dart'; import 'package:tone_snap/global/download_manager.dart';
import 'package:tone_snap/modules/sideb/controllers/music_player_controller.dart'; import 'package:tone_snap/modules/sideb/controllers/music_player_controller.dart';
import 'package:tone_snap/modules/sideb/personal_music_library/personal_music_library_controller.dart'; import 'package:tone_snap/modules/sideb/personal_music_library/personal_music_library_controller.dart';
@ -30,9 +33,13 @@ class PlayPageController extends GetxController {
musicPlayerController.playlist.clear(); musicPlayerController.playlist.clear();
musicPlayerController.resetPlaybackStatus(); musicPlayerController.resetPlaybackStatus();
playList = await _next(videoId, playlistId); playList = await _next(videoId, playlistId);
if (playList.isNotEmpty) {
FirebaseAnalyticsManager.logPlayerBList();
}
} }
musicPlayerController.playMusic(videoId, playList: playList); musicPlayerController.playMusic(videoId, playList: playList);
} }
FirebaseAnalyticsManager.logPlayerBImp();
} }
/// ///
@ -91,9 +98,19 @@ class PlayPageController extends GetxController {
if (ObjUtil.isEmpty(musicPlayerController.getMusicModel()?.videoId)) return; if (ObjUtil.isEmpty(musicPlayerController.getMusicModel()?.videoId)) return;
final isLove = LoveSongsBox().checkLove(musicPlayerController.getMusicModel()!.videoId); final isLove = LoveSongsBox().checkLove(musicPlayerController.getMusicModel()!.videoId);
if (isLove) { if (isLove) {
FirebaseAnalyticsManager.logPlayerBUnloveClick(
musicPlayerController.getMusicModel()?.videoId,
musicPlayerController.getMusicModel()?.title,
musicPlayerController.getMusicModel()?.subtitle,
);
await LoveSongsBox().delete(musicPlayerController.getMusicModel()!.videoId!); await LoveSongsBox().delete(musicPlayerController.getMusicModel()!.videoId!);
BaseEasyLoading.toast('Removed'); BaseEasyLoading.toast('Removed');
} else { } else {
FirebaseAnalyticsManager.logPlayerBLoveClick(
musicPlayerController.getMusicModel()?.videoId,
musicPlayerController.getMusicModel()?.title,
musicPlayerController.getMusicModel()?.subtitle,
);
await LoveSongsBox().add(musicPlayerController.getMusicModel()!.copyWith()); await LoveSongsBox().add(musicPlayerController.getMusicModel()!.copyWith());
BaseEasyLoading.toast('Collected'); BaseEasyLoading.toast('Collected');
} }
@ -103,6 +120,7 @@ class PlayPageController extends GetxController {
update([loveStateId]); update([loveStateId]);
} }
///
void onTapDownload() { void onTapDownload() {
if (OfflineBox().checkDownloaded(musicPlayerController.getMusicModel()?.videoId)) { if (OfflineBox().checkDownloaded(musicPlayerController.getMusicModel()?.videoId)) {
Get.dialog( Get.dialog(
@ -141,4 +159,24 @@ class PlayPageController extends GetxController {
musicPlayerController.currentIndex.value--; musicPlayerController.currentIndex.value--;
} }
} }
///
void onTapPreviousTrack() {
InterstitialAdManager().showAdIfAvailable(
AdScenes.playCut.name,
onTap: () {
musicPlayerController.previousTrack();
},
);
}
///
void onTapNextTrack() {
InterstitialAdManager().showAdIfAvailable(
AdScenes.playCut.name,
onTap: () {
musicPlayerController.nextTrack();
},
);
}
} }

View File

@ -355,7 +355,7 @@ class PlayPageView extends StatelessWidget {
child: Material( child: Material(
color: Colors.transparent, color: Colors.transparent,
child: InkWell( child: InkWell(
onTap: musicPlayerController.previousTrack, onTap: controller.onTapPreviousTrack,
child: Padding( child: Padding(
padding: const EdgeInsets.all(10).w, padding: const EdgeInsets.all(10).w,
child: Image.asset( child: Image.asset(
@ -411,7 +411,7 @@ class PlayPageView extends StatelessWidget {
child: Material( child: Material(
color: Colors.transparent, color: Colors.transparent,
child: InkWell( child: InkWell(
onTap: musicPlayerController.nextTrack, onTap: controller.onTapNextTrack,
child: Padding( child: Padding(
padding: const EdgeInsets.all(10).w, padding: const EdgeInsets.all(10).w,
child: Image.asset( child: Image.asset(

View File

@ -4,6 +4,7 @@ import 'package:tone_snap/components/dialog/add_playlist_dialog.dart';
import 'package:tone_snap/components/view_state_widget.dart'; import 'package:tone_snap/components/view_state_widget.dart';
import 'package:tone_snap/data/models/playlist_model.dart'; import 'package:tone_snap/data/models/playlist_model.dart';
import 'package:tone_snap/data/storage/playlists_box.dart'; import 'package:tone_snap/data/storage/playlists_box.dart';
import 'package:tone_snap/firebase/firebase_analytics_manager.dart';
class PlaylistsController extends GetxController { class PlaylistsController extends GetxController {
static PlaylistsController get to => Get.find<PlaylistsController>(); static PlaylistsController get to => Get.find<PlaylistsController>();
@ -24,7 +25,7 @@ class PlaylistsController extends GetxController {
} }
void getList() { void getList() {
playLists.value = PlaylistsBox().getReversedList(); playLists.value = PlaylistsBox().getList();
viewState.value = playLists.isNotEmpty ? ViewState.normal : ViewState.empty; viewState.value = playLists.isNotEmpty ? ViewState.normal : ViewState.empty;
} }
@ -35,6 +36,7 @@ class PlaylistsController extends GetxController {
onTap: (value) async { onTap: (value) async {
await PlaylistsBox().add(value); await PlaylistsBox().add(value);
getList(); getList();
FirebaseAnalyticsManager.logCreateList();
}, },
), ),
); );

View File

@ -1,5 +1,6 @@
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/data/storage/music_box.dart'; import 'package:tone_snap/data/storage/music_box.dart';
import 'package:tone_snap/firebase/firebase_analytics_manager.dart';
import 'package:tone_snap/routes/app_routes.dart'; import 'package:tone_snap/routes/app_routes.dart';
class SearchMusicController extends GetxController { class SearchMusicController extends GetxController {
@ -27,6 +28,7 @@ class SearchMusicController extends GetxController {
} }
void openSearch() { void openSearch() {
FirebaseAnalyticsManager.logSearchFromAction('来自搜索页面');
Get.toNamed(AppRoutes.searchResult); Get.toNamed(AppRoutes.searchResult);
} }
} }

View File

@ -1,14 +1,18 @@
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/ads/interstitial_ad_manager.dart';
import 'package:tone_snap/components/view_state_widget.dart'; import 'package:tone_snap/components/view_state_widget.dart';
import 'package:tone_snap/data/api/music_api.dart'; import 'package:tone_snap/data/api/music_api.dart';
import 'package:tone_snap/data/enum/ad_scenes.dart';
import 'package:tone_snap/data/enum/music_type.dart'; import 'package:tone_snap/data/enum/music_type.dart';
import 'package:tone_snap/data/models/music_model.dart'; import 'package:tone_snap/data/models/music_model.dart';
import 'package:tone_snap/data/models/search_result_model.dart'; import 'package:tone_snap/data/models/search_result_model.dart';
import 'package:tone_snap/data/models/search_result_tabbar_model.dart'; import 'package:tone_snap/data/models/search_result_tabbar_model.dart';
import 'package:tone_snap/data/models/search_suggestions_model.dart'; import 'package:tone_snap/data/models/search_suggestions_model.dart';
import 'package:tone_snap/data/network/base_error.dart';
import 'package:tone_snap/data/storage/music_box.dart'; import 'package:tone_snap/data/storage/music_box.dart';
import 'package:tone_snap/firebase/firebase_analytics_manager.dart';
import 'package:tone_snap/modules/sideb/search_music/search_music_controller.dart'; import 'package:tone_snap/modules/sideb/search_music/search_music_controller.dart';
import 'package:tone_snap/modules/sideb/search_result_child/search_result_child_controller.dart'; import 'package:tone_snap/modules/sideb/search_result_child/search_result_child_controller.dart';
import 'package:tone_snap/modules/sideb/search_result_child/search_result_child_view.dart'; import 'package:tone_snap/modules/sideb/search_result_child/search_result_child_view.dart';
@ -83,6 +87,9 @@ class SearchResultController extends GetxController with GetTickerProviderStateM
} }
} }
searchSuggestionsViewState.value = ViewState.normal; searchSuggestionsViewState.value = ViewState.normal;
if (searchSuggestionsList.isNotEmpty) {
FirebaseAnalyticsManager.logSearchSugShow();
}
} }
void cleanTextEditingController() { void cleanTextEditingController() {
@ -114,6 +121,8 @@ class SearchResultController extends GetxController with GetTickerProviderStateM
if (ObjUtil.isEmpty(textEditingController.text)) { if (ObjUtil.isEmpty(textEditingController.text)) {
return; return;
} }
FirebaseAnalyticsManager.logSearchSugClick(value);
await _cleanTab();
if (isSearchSuggestionsItem) { if (isSearchSuggestionsItem) {
textEditingController.text = value; textEditingController.text = value;
} }
@ -121,11 +130,19 @@ class SearchResultController extends GetxController with GetTickerProviderStateM
if (Get.isRegistered<SearchMusicController>()) { if (Get.isRegistered<SearchMusicController>()) {
SearchMusicController.to.getList(); SearchMusicController.to.getList();
} }
await _cleanTab();
searchResultViewState.value = ViewState.loading; searchResultViewState.value = ViewState.loading;
await _searchPreviewResult(value); await _searchPreviewResult(value);
searchResultViewState.value = tabs.length > 1 ? ViewState.normal : ViewState.empty; if (tabs.isNotEmpty) {
tabController.value = TabController(length: tabs.length, vsync: this); FirebaseAnalyticsManager.logSearchResultPV();
FirebaseAnalyticsManager.logSearchResultsuccessAction();
}
InterstitialAdManager().showAdIfAvailable(
AdScenes.search.name,
onTap: () {
searchResultViewState.value = tabs.isNotEmpty ? ViewState.normal : ViewState.empty;
tabController.value = TabController(length: tabs.length, vsync: this);
},
);
} }
Future<void> _searchPreviewResult(String keyword) async { Future<void> _searchPreviewResult(String keyword) async {
@ -133,7 +150,13 @@ class SearchResultController extends GetxController with GetTickerProviderStateM
'prettyPrint': false, 'prettyPrint': false,
'query': keyword 'query': keyword
}; };
SearchResultModel? searchResultModel = await MusicApi.search<SearchResultModel>(queryParameters: queryParameters, formJson: SearchResultModel.fromMap); SearchResultModel? searchResultModel = await MusicApi.search<SearchResultModel>(
queryParameters: queryParameters,
formJson: SearchResultModel.fromMap,
fail: (BaseError baseError) {
FirebaseAnalyticsManager.logSearchResultfailAction('${baseError.code},${baseError.message}');
},
);
if (searchResultModel != null) { if (searchResultModel != null) {
var tabs = searchResultModel.contents?.tabbedSearchResultsRenderer?.tabs; var tabs = searchResultModel.contents?.tabbedSearchResultsRenderer?.tabs;
if (tabs != null && tabs.isNotEmpty) { if (tabs != null && tabs.isNotEmpty) {
@ -266,6 +289,9 @@ class SearchResultController extends GetxController with GetTickerProviderStateM
} }
} }
} }
if (this.tabs.isEmpty) {
FirebaseAnalyticsManager.logSearchResultfailAction('无数据');
}
} }
} }
} }

View File

@ -1,8 +1,10 @@
import 'package:easy_refresh/easy_refresh.dart'; import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/ads/interstitial_ad_manager.dart';
import 'package:tone_snap/components/view_state_widget.dart'; import 'package:tone_snap/components/view_state_widget.dart';
import 'package:tone_snap/data/api/music_api.dart'; import 'package:tone_snap/data/api/music_api.dart';
import 'package:tone_snap/data/enum/ad_scenes.dart';
import 'package:tone_snap/data/enum/music_type.dart'; import 'package:tone_snap/data/enum/music_type.dart';
import 'package:tone_snap/data/models/music_model.dart'; import 'package:tone_snap/data/models/music_model.dart';
import 'package:tone_snap/data/models/search_result_model.dart'; import 'package:tone_snap/data/models/search_result_model.dart';
@ -183,10 +185,15 @@ class SearchResultChildController extends GetxController {
void onTapItem(MusicModel musicModel) { void onTapItem(MusicModel musicModel) {
if (musicModel.musicType == MusicType.musicVideoTypeAtv.name) { if (musicModel.musicType == MusicType.musicVideoTypeAtv.name) {
Get.toNamed(AppRoutes.playPage, arguments: { InterstitialAdManager().showAdIfAvailable(
'videoId': musicModel.videoId, AdScenes.play.name,
'playlistId': musicModel.playlistId, onTap: () {
}); Get.toNamed(AppRoutes.playPage, arguments: {
'videoId': musicModel.videoId,
'playlistId': musicModel.playlistId,
});
},
);
} else if (musicModel.musicType == MusicType.musicPageTypeAlbum.name } else if (musicModel.musicType == MusicType.musicPageTypeAlbum.name
|| musicModel.musicType == MusicType.musicPageTypePlaylist.name) { || musicModel.musicType == MusicType.musicPageTypePlaylist.name) {
Get.toNamed(AppRoutes.albumSongList, arguments: { Get.toNamed(AppRoutes.albumSongList, arguments: {

View File

@ -1,4 +1,6 @@
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tone_snap/ads/interstitial_ad_manager.dart';
import 'package:tone_snap/data/enum/ad_scenes.dart';
import 'package:tone_snap/data/enum/music_type.dart'; import 'package:tone_snap/data/enum/music_type.dart';
import 'package:tone_snap/data/models/music_model.dart'; import 'package:tone_snap/data/models/music_model.dart';
import 'package:tone_snap/routes/app_routes.dart'; import 'package:tone_snap/routes/app_routes.dart';
@ -6,10 +8,15 @@ import 'package:tone_snap/routes/app_routes.dart';
class SearchResultChildOptimumController extends GetxController { class SearchResultChildOptimumController extends GetxController {
void onTapItem(MusicModel musicModel) { void onTapItem(MusicModel musicModel) {
if (musicModel.musicType == MusicType.musicVideoTypeAtv.name) { if (musicModel.musicType == MusicType.musicVideoTypeAtv.name) {
Get.toNamed(AppRoutes.playPage, arguments: { InterstitialAdManager().showAdIfAvailable(
'videoId': musicModel.videoId, AdScenes.play.name,
'playlistId': musicModel.playlistId, onTap: () {
}); Get.toNamed(AppRoutes.playPage, arguments: {
'videoId': musicModel.videoId,
'playlistId': musicModel.playlistId,
});
},
);
} else if (musicModel.musicType == MusicType.musicPageTypeAlbum.name } else if (musicModel.musicType == MusicType.musicPageTypeAlbum.name
|| musicModel.musicType == MusicType.musicPageTypePlaylist.name) { || musicModel.musicType == MusicType.musicPageTypePlaylist.name) {
Get.toNamed(AppRoutes.albumSongList, arguments: { Get.toNamed(AppRoutes.albumSongList, arguments: {

View File

@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts # In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix. # of the product and file versions while build-number is used as the build suffix.
version: 1.0.4+14 version: 1.0.5+15
environment: environment:
sdk: '>=3.4.1 <4.0.0' sdk: '>=3.4.1 <4.0.0'
@ -100,7 +100,7 @@ dependencies:
google_mobile_ads: ^5.1.0 google_mobile_ads: ^5.1.0
# Firebase # Firebase
firebase_core: ^3.2.0 firebase_core: ^3.3.0
firebase_analytics: ^11.2.0 firebase_analytics: ^11.2.0
firebase_crashlytics: ^4.0.3 firebase_crashlytics: ^4.0.3
firebase_remote_config: ^5.0.3 firebase_remote_config: ^5.0.3