2023-12-21 09:14:40 +00:00
|
|
|
|
import 'dart:io';
|
|
|
|
|
|
|
|
|
|
|
|
import 'package:adjust_sdk/adjust_event.dart';
|
|
|
|
|
|
import 'package:firebase_analytics/firebase_analytics.dart';
|
|
|
|
|
|
import 'package:firebase_core/firebase_core.dart';
|
|
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
|
import 'package:guru_app/account/account_data_store.dart';
|
|
|
|
|
|
import 'package:guru_app/account/account_manager.dart';
|
2024-03-07 03:46:50 +00:00
|
|
|
|
import 'package:guru_app/account/model/account.dart';
|
|
|
|
|
|
import 'package:guru_app/account/model/credential.dart';
|
|
|
|
|
|
import 'package:guru_app/account/model/user.dart';
|
2023-12-21 09:14:40 +00:00
|
|
|
|
import 'package:guru_app/ads/ads_manager.dart';
|
2024-03-07 03:46:50 +00:00
|
|
|
|
import 'package:guru_app/analytics/abtest/abtest_model.dart';
|
2023-12-21 09:14:40 +00:00
|
|
|
|
import 'package:guru_app/analytics/guru_analytics.dart';
|
|
|
|
|
|
import 'package:guru_app/app/app_models.dart';
|
|
|
|
|
|
import 'package:guru_app/database/guru_db.dart';
|
|
|
|
|
|
import 'package:guru_app/financial/financial_manager.dart';
|
|
|
|
|
|
import 'package:guru_app/financial/iap/iap_manager.dart';
|
|
|
|
|
|
import 'package:guru_app/financial/manifest/manifest.dart';
|
|
|
|
|
|
import 'package:guru_app/financial/manifest/manifest_manager.dart';
|
|
|
|
|
|
import 'package:guru_app/financial/product/product_model.dart';
|
|
|
|
|
|
import 'package:guru_app/financial/reward/reward_manager.dart';
|
|
|
|
|
|
import 'package:guru_app/firebase/dxlinks/dxlink_manager.dart';
|
2024-03-07 03:46:50 +00:00
|
|
|
|
import 'package:guru_app/inventory/inventory_manager.dart';
|
2023-12-21 09:14:40 +00:00
|
|
|
|
import 'package:guru_applovin_flutter/guru_applovin_flutter.dart';
|
2024-03-07 03:46:50 +00:00
|
|
|
|
import 'package:guru_app/property/app_property.dart';
|
|
|
|
|
|
import 'package:guru_app/property/property_keys.dart';
|
|
|
|
|
|
import 'package:guru_utils/auth/auth_credential_manager.dart';
|
2023-12-21 09:14:40 +00:00
|
|
|
|
import 'package:guru_utils/collection/collectionutils.dart';
|
|
|
|
|
|
import 'package:guru_utils/controller/aware/ads/overlay/ads_overlay.dart';
|
|
|
|
|
|
import 'package:guru_utils/datetime/datetime_utils.dart';
|
2024-03-07 03:46:50 +00:00
|
|
|
|
import 'package:guru_utils/device/device_utils.dart';
|
2023-12-21 09:14:40 +00:00
|
|
|
|
import 'package:guru_utils/lifecycle/lifecycle_manager.dart';
|
|
|
|
|
|
import 'package:guru_utils/network/network_utils.dart';
|
|
|
|
|
|
import 'package:guru_utils/property/app_property.dart';
|
|
|
|
|
|
import 'package:guru_app/property/settings/guru_settings.dart';
|
|
|
|
|
|
import 'package:guru_app/firebase/firebase.dart';
|
|
|
|
|
|
import 'package:guru_utils/http/http_ex.dart';
|
|
|
|
|
|
import 'package:guru_utils/log/log.dart';
|
|
|
|
|
|
import 'package:guru_utils/packages/guru_package.dart';
|
|
|
|
|
|
import 'package:guru_utils/ads/ads.dart';
|
|
|
|
|
|
import 'package:guru_utils/guru_utils.dart';
|
2024-03-07 03:46:50 +00:00
|
|
|
|
import 'package:guru_utils/property/property_model.dart';
|
2023-12-21 09:14:40 +00:00
|
|
|
|
import 'package:logger/logger.dart' as Logger;
|
|
|
|
|
|
import 'package:guru_utils/aigc/bi/ai_bi.dart';
|
|
|
|
|
|
import 'package:package_info_plus/package_info_plus.dart';
|
|
|
|
|
|
import 'package:guru_popup/guru_popup.dart';
|
2024-03-07 03:46:50 +00:00
|
|
|
|
import 'package:guru_app/analytics/abtest/abtest_model.dart';
|
|
|
|
|
|
|
2023-12-21 09:14:40 +00:00
|
|
|
|
export 'package:firebase_core/firebase_core.dart';
|
|
|
|
|
|
export 'package:guru_app/app/app_models.dart';
|
|
|
|
|
|
export 'package:guru_utils/log/log.dart';
|
|
|
|
|
|
export 'package:guru_spec/guru_spec.dart';
|
|
|
|
|
|
export 'package:guru_app/analytics/guru_analytics.dart';
|
|
|
|
|
|
export 'package:guru_app/financial/product/product_model.dart';
|
|
|
|
|
|
export 'package:adjust_sdk/adjust_event.dart';
|
|
|
|
|
|
export 'package:guru_utils/ads/ads.dart';
|
|
|
|
|
|
export 'package:guru_utils/guru_utils.dart';
|
|
|
|
|
|
export 'dart:io';
|
|
|
|
|
|
export 'dart:math';
|
|
|
|
|
|
export 'package:guru_app/financial/manifest/manifest.dart';
|
|
|
|
|
|
export 'package:guru_app/firebase/messaging/remote_messaging_manager.dart';
|
2024-03-07 03:46:50 +00:00
|
|
|
|
export 'package:guru_app/analytics/abtest/abtest_model.dart';
|
2023-12-21 09:14:40 +00:00
|
|
|
|
|
|
|
|
|
|
/// Created by Haoyi on 2022/8/25
|
|
|
|
|
|
|
|
|
|
|
|
abstract class AppSpec {
|
|
|
|
|
|
String get appName;
|
|
|
|
|
|
|
2024-03-07 03:46:50 +00:00
|
|
|
|
AppCategory get appCategory;
|
|
|
|
|
|
|
2023-12-21 09:14:40 +00:00
|
|
|
|
String get flavor;
|
|
|
|
|
|
|
|
|
|
|
|
AppDetails get details;
|
|
|
|
|
|
|
|
|
|
|
|
AdsProfile get adsProfile;
|
|
|
|
|
|
|
|
|
|
|
|
ProductProfile get productProfile;
|
|
|
|
|
|
|
|
|
|
|
|
AdjustProfile get adjustProfile;
|
|
|
|
|
|
|
|
|
|
|
|
Deployment get deployment;
|
|
|
|
|
|
|
|
|
|
|
|
Map<String, dynamic> get defaultRemoteConfig;
|
2024-03-07 03:46:50 +00:00
|
|
|
|
|
|
|
|
|
|
Map<String, ABTestExperiment> get localABTestExperiments;
|
|
|
|
|
|
|
|
|
|
|
|
String getRemoteConfigKey(String key);
|
2023-12-21 09:14:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class NotImplementationAppSpecCreatorException implements Exception {
|
|
|
|
|
|
NotImplementationAppSpecCreatorException();
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
|
String toString() {
|
|
|
|
|
|
return 'NotImplementationAppSpecCreatorException';
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class AppEnv {
|
|
|
|
|
|
final AppSpec spec;
|
|
|
|
|
|
final RootPackage package;
|
2024-03-07 03:46:50 +00:00
|
|
|
|
final IGuruSdkProtocol protocol;
|
2023-12-21 09:14:40 +00:00
|
|
|
|
|
|
|
|
|
|
AppEnv(
|
|
|
|
|
|
{required this.spec,
|
|
|
|
|
|
required this.package,
|
2024-03-07 03:46:50 +00:00
|
|
|
|
required this.protocol});
|
2023-12-21 09:14:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extension _GuruPackageExtension on GuruPackage {
|
|
|
|
|
|
Iterable<Locale> _mergeSupportedLocales() {
|
|
|
|
|
|
final Set<Locale> locales = supportedLocales.toSet();
|
|
|
|
|
|
for (var child in children) {
|
|
|
|
|
|
locales.addAll(child._mergeSupportedLocales());
|
|
|
|
|
|
}
|
|
|
|
|
|
return locales;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Iterable<LocalizationsDelegate<dynamic>> _mergeLocalizationsDelegates() {
|
|
|
|
|
|
final Set<LocalizationsDelegate<dynamic>> delegates = localizationsDelegates.toSet();
|
|
|
|
|
|
for (var child in children) {
|
|
|
|
|
|
delegates.addAll(child._mergeLocalizationsDelegates());
|
|
|
|
|
|
}
|
|
|
|
|
|
return delegates;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Future _dispatchInitialize() async {
|
|
|
|
|
|
await initialize();
|
|
|
|
|
|
children.sort((p1, p2) {
|
|
|
|
|
|
return p2.priority.compareTo(p1.priority);
|
|
|
|
|
|
});
|
|
|
|
|
|
for (var child in children) {
|
|
|
|
|
|
if (flattenChildrenAsyncInit) {
|
|
|
|
|
|
child._dispatchInitialize();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
await child._dispatchInitialize();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Future _dispatchInitializeAsync() async {
|
|
|
|
|
|
initializeAsync();
|
|
|
|
|
|
for (var child in children) {
|
|
|
|
|
|
child._dispatchInitializeAsync();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-03-07 03:46:50 +00:00
|
|
|
|
|
|
|
|
|
|
Future _dispatchSwitchSession(String oldToken, String newToken) async {
|
|
|
|
|
|
await switchSession(oldToken, newToken);
|
|
|
|
|
|
children.sort((p1, p2) {
|
|
|
|
|
|
return p2.priority.compareTo(p1.priority);
|
|
|
|
|
|
});
|
|
|
|
|
|
for (var child in children) {
|
|
|
|
|
|
if (flattenChildrenAsyncInit) {
|
|
|
|
|
|
child._dispatchSwitchSession(oldToken, newToken);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
await child._dispatchSwitchSession(oldToken, newToken);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-12-21 09:14:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-03-07 03:46:50 +00:00
|
|
|
|
enum AppCategory { game, app }
|
|
|
|
|
|
|
|
|
|
|
|
abstract class IGuruSdkProtocol {
|
|
|
|
|
|
static void _unimplementedError(String name) {
|
|
|
|
|
|
Log.e(
|
|
|
|
|
|
"[$name] It is critically important that the GuruSDK protocol be implemented with precision. \n"
|
|
|
|
|
|
"Failure to adhere to its standards will result in inaccuracies within our analytics data,\n"
|
|
|
|
|
|
"thereby severely compromising our marketing strategies and the effectiveness of our user acquisition efforts.\n"
|
|
|
|
|
|
"It is essential to understand that non-compliance is not an option,\n"
|
|
|
|
|
|
"as it poses significant risks to our operational success and strategic objectives.");
|
|
|
|
|
|
throw UnimplementedError("Please fully implement the IGuruSdkProtocol!");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
InventoryDelegate? get inventoryDelegate => null;
|
|
|
|
|
|
|
|
|
|
|
|
BackgroundMessageHandler? get backgroundMessageHandler => null;
|
|
|
|
|
|
|
|
|
|
|
|
ToastDelegate? get toastDelegate => null;
|
|
|
|
|
|
|
|
|
|
|
|
IAccountAuthDelegate? get accountAuthDelegate => null;
|
|
|
|
|
|
|
|
|
|
|
|
String getLevelName() {
|
|
|
|
|
|
if (GuruApp.instance.appSpec.appCategory == AppCategory.game) {
|
|
|
|
|
|
_unimplementedError("getLevelName");
|
|
|
|
|
|
}
|
|
|
|
|
|
return "app";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int getCurrentLevel() {
|
|
|
|
|
|
if (GuruApp.instance.appSpec.appCategory == AppCategory.game) {
|
|
|
|
|
|
_unimplementedError("getCurrentLevel");
|
|
|
|
|
|
}
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
final Set<PropertyKey> _deviceSharedProperties = {
|
|
|
|
|
|
PropertyKeys.deviceId,
|
|
|
|
|
|
PropertyKeys.version,
|
|
|
|
|
|
PropertyKeys.buildNumber,
|
|
|
|
|
|
PropertyKeys.firstInstallTime,
|
|
|
|
|
|
PropertyKeys.firstInstallVersion,
|
|
|
|
|
|
PropertyKeys.prevInstallVersion,
|
|
|
|
|
|
PropertyKeys.latestInstallVersion,
|
|
|
|
|
|
PropertyKeys.previousInstalledVersion,
|
|
|
|
|
|
PropertyKeys.latestLtDate,
|
|
|
|
|
|
PropertyKeys.ltDays,
|
|
|
|
|
|
PropertyKeys.appInstanceId,
|
|
|
|
|
|
PropertyKeys.debugMode,
|
|
|
|
|
|
PropertyKeys.keepOnScreenDuration,
|
|
|
|
|
|
PropertyKeys.analyticsAdId,
|
|
|
|
|
|
PropertyKeys.analyticsAdjustId,
|
|
|
|
|
|
PropertyKeys.analyticsDeviceId,
|
|
|
|
|
|
PropertyKeys.analyticsIdfa,
|
|
|
|
|
|
PropertyKeys.analyticsFirebaseId,
|
|
|
|
|
|
PropertyKeys.latestAnalyticsStrategy
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2023-12-21 09:14:40 +00:00
|
|
|
|
class GuruApp {
|
|
|
|
|
|
static late GuruApp _instance;
|
|
|
|
|
|
|
|
|
|
|
|
static GuruApp get instance => _instance;
|
|
|
|
|
|
|
|
|
|
|
|
final RootPackage rootPackage;
|
|
|
|
|
|
|
|
|
|
|
|
final AppSpec appSpec;
|
|
|
|
|
|
|
2024-03-07 03:46:50 +00:00
|
|
|
|
final IGuruSdkProtocol protocol;
|
|
|
|
|
|
RemoteDeployment? _remoteDeployment;
|
|
|
|
|
|
|
|
|
|
|
|
RemoteDeployment get remoteDeployment =>
|
|
|
|
|
|
_remoteDeployment ??= RemoteConfigManager.instance.getRemoteDeployment();
|
|
|
|
|
|
|
2023-12-21 09:14:40 +00:00
|
|
|
|
String get appName => appSpec.appName;
|
|
|
|
|
|
|
|
|
|
|
|
String get flavor => appSpec.flavor;
|
|
|
|
|
|
|
|
|
|
|
|
AppDetails get details => appSpec.details;
|
|
|
|
|
|
|
|
|
|
|
|
AdsProfile get adsProfile => appSpec.adsProfile;
|
|
|
|
|
|
|
|
|
|
|
|
AdjustProfile get adjustProfile => appSpec.adjustProfile;
|
|
|
|
|
|
|
|
|
|
|
|
ProductProfile get productProfile => appSpec.productProfile;
|
|
|
|
|
|
|
|
|
|
|
|
Map<String, dynamic> get defaultRemoteConfig => appSpec.defaultRemoteConfig;
|
|
|
|
|
|
|
|
|
|
|
|
Set<String> get conversionEvents => appSpec.deployment.conversionEvents;
|
|
|
|
|
|
|
2024-03-07 03:46:50 +00:00
|
|
|
|
GuruApp._(
|
|
|
|
|
|
{required this.appSpec,
|
|
|
|
|
|
required this.rootPackage,
|
|
|
|
|
|
required this.protocol,
|
|
|
|
|
|
}) {
|
|
|
|
|
|
GuruUtils.toastDelegate = protocol.toastDelegate;
|
2023-12-21 09:14:40 +00:00
|
|
|
|
AdsOverlay.bind(showBanner: GuruPopup.instance.showAdsBanner);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Iterable<Locale> get supportedLocales => rootPackage._mergeSupportedLocales();
|
|
|
|
|
|
|
|
|
|
|
|
Iterable<LocalizationsDelegate<dynamic>> get localizationsDelegates =>
|
|
|
|
|
|
rootPackage._mergeLocalizationsDelegates();
|
|
|
|
|
|
|
2024-03-07 03:46:50 +00:00
|
|
|
|
String getRemoteConfigKey(String key) => appSpec.getRemoteConfigKey(key);
|
|
|
|
|
|
|
2023-12-21 09:14:40 +00:00
|
|
|
|
bool? _check;
|
|
|
|
|
|
|
2024-03-07 03:46:50 +00:00
|
|
|
|
@visibleForTesting
|
|
|
|
|
|
static void setMockInstance(GuruApp app) {
|
|
|
|
|
|
_instance = app;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-21 09:14:40 +00:00
|
|
|
|
Future _initialize() async {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await GuruDB.instance.initDatabase();
|
|
|
|
|
|
AppProperty.initialize(GuruDB.instance, cacheSize: appSpec.deployment.propertyCacheSize);
|
|
|
|
|
|
await GuruSettings.instance.refresh();
|
|
|
|
|
|
Paint.enableDithering = appSpec.deployment.enableDithering; // 3.16 default enabled
|
|
|
|
|
|
await _dispatchInitializeSync();
|
|
|
|
|
|
_dispatchInitializeAsync();
|
|
|
|
|
|
} catch (error, stacktrace) {
|
|
|
|
|
|
Log.w("initialize error:$error, $stacktrace");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-03-07 03:46:50 +00:00
|
|
|
|
Future _migrateDeviceSharedData(PropertyBundle latestData) async {
|
|
|
|
|
|
final PropertyBundle bundle = PropertyBundle();
|
|
|
|
|
|
final keys = {
|
|
|
|
|
|
..._deviceSharedProperties,
|
|
|
|
|
|
...(protocol.accountAuthDelegate?.deviceSharedProperties ?? {})
|
|
|
|
|
|
};
|
|
|
|
|
|
for (var key in keys) {
|
|
|
|
|
|
final value = latestData.getString(key);
|
|
|
|
|
|
if (value != null) {
|
|
|
|
|
|
bundle.setString(key, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
await AppProperty.getInstance().setProperties(bundle);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RemoteDeployment refreshRemoteDeployment() {
|
|
|
|
|
|
try {
|
|
|
|
|
|
return _remoteDeployment ??= RemoteConfigManager.instance.getRemoteDeployment();
|
|
|
|
|
|
} catch (error, stacktrace) {
|
|
|
|
|
|
Log.w("refreshRemoteDeployment error:$error, $stacktrace");
|
|
|
|
|
|
}
|
|
|
|
|
|
return RemoteDeployment.fromJson({});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Future<bool> switchAccount(GuruUser user, Credential credential, {GuruUser? oldUser}) async {
|
|
|
|
|
|
final String oldToken = oldUser?.uid ?? "";
|
|
|
|
|
|
final String newToken = user.uid;
|
|
|
|
|
|
try {
|
|
|
|
|
|
final previousUserProperties =
|
|
|
|
|
|
PropertyBundle(map: await AppProperty.getInstance().loadAllValues());
|
|
|
|
|
|
|
|
|
|
|
|
final result = await GuruDB.instance.switchSession(oldToken, newToken);
|
|
|
|
|
|
if (!result) {
|
|
|
|
|
|
Log.w("switchSession failed");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
AppProperty.reload(cacheSize: appSpec.deployment.propertyCacheSize);
|
|
|
|
|
|
await _migrateDeviceSharedData(previousUserProperties);
|
|
|
|
|
|
await GuruSettings.instance.refresh();
|
|
|
|
|
|
await DeviceUtils.reload();
|
|
|
|
|
|
FinancialManager.instance.switchSession(oldToken, newToken);
|
|
|
|
|
|
GuruAnalytics.instance.switchSession(oldToken, newToken);
|
|
|
|
|
|
await AccountManager.instance.processLogin(user, credential);
|
|
|
|
|
|
await rootPackage._dispatchSwitchSession(oldToken, newToken);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} catch (error, stacktrace) {
|
|
|
|
|
|
Log.w("switchSession error:$error, $stacktrace");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-21 09:14:40 +00:00
|
|
|
|
Future<bool> _checkApp() async {
|
|
|
|
|
|
try {
|
|
|
|
|
|
final pkgName = (await PackageInfo.fromPlatform()).appName;
|
|
|
|
|
|
final result = _check ??= (pkgName != GuruApp.instance.details.appId);
|
|
|
|
|
|
GuruAnalytics.instance.logGuruEvent(
|
|
|
|
|
|
"dev_audit",
|
|
|
|
|
|
CollectionUtils.filterOutNulls({
|
|
|
|
|
|
"item_category": "pkg",
|
|
|
|
|
|
"result": result == true ? 1 : 0,
|
|
|
|
|
|
"err_info": result != true ? pkgName : null,
|
|
|
|
|
|
}));
|
|
|
|
|
|
return result == true;
|
|
|
|
|
|
} catch (error, stacktrace) {
|
|
|
|
|
|
Log.w("checkApp error:$error, $stacktrace");
|
|
|
|
|
|
GuruAnalytics.instance.logException(error, stacktrace: stacktrace);
|
|
|
|
|
|
GuruAnalytics.instance.logGuruEvent(
|
|
|
|
|
|
"dev_audit",
|
|
|
|
|
|
CollectionUtils.filterOutNulls({
|
|
|
|
|
|
"item_category": "pkg",
|
|
|
|
|
|
"result": 0,
|
|
|
|
|
|
"err_info": error.runtimeType.toString(),
|
|
|
|
|
|
}));
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Future _dispatchInitializeSync() async {
|
|
|
|
|
|
await RemoteConfigManager.instance.init(appSpec.defaultRemoteConfig);
|
2024-03-07 03:46:50 +00:00
|
|
|
|
refreshRemoteDeployment();
|
|
|
|
|
|
await DeviceUtils.initialize();
|
|
|
|
|
|
await GuruAnalytics.instance.prepare();
|
2023-12-21 09:14:40 +00:00
|
|
|
|
await rootPackage._dispatchInitialize();
|
|
|
|
|
|
try {
|
|
|
|
|
|
GuruUtils.isTablet = (await GuruApplovinFlutter.instance.isTablet()) ?? false;
|
|
|
|
|
|
Log.d("isTablet: ${GuruUtils.isTablet}");
|
|
|
|
|
|
} catch (error, stacktrace) {
|
|
|
|
|
|
Log.w("invoke isTablet error:$error, $stacktrace");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Future _dispatchInitializeAsync() async {
|
|
|
|
|
|
_initCommon();
|
|
|
|
|
|
_initRemoteConfig();
|
|
|
|
|
|
_initRemoteMessaging();
|
|
|
|
|
|
_initAnalytics();
|
|
|
|
|
|
if (appSpec.adsProfile != AdsProfile.invalid) {
|
|
|
|
|
|
_initAds();
|
|
|
|
|
|
}
|
|
|
|
|
|
_initFinancial();
|
|
|
|
|
|
_initAccount();
|
|
|
|
|
|
_initDxLink();
|
|
|
|
|
|
rootPackage._dispatchInitializeAsync();
|
|
|
|
|
|
Future.delayed(const Duration(seconds: 15), () async {
|
|
|
|
|
|
await _checkApp();
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static Future initialize({required AppEnv appEnv}) async {
|
2024-03-07 03:46:50 +00:00
|
|
|
|
final backgroundMessageHandler = appEnv.protocol.backgroundMessageHandler;
|
2023-12-21 09:14:40 +00:00
|
|
|
|
if (backgroundMessageHandler != null) {
|
|
|
|
|
|
FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
|
|
|
|
|
|
}
|
|
|
|
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
|
|
|
|
try {
|
|
|
|
|
|
await Firebase.initializeApp();
|
|
|
|
|
|
} catch (error, stacktrace) {
|
|
|
|
|
|
Log.e("Firebase.initializeApp() error!", error: error, stackTrace: stacktrace);
|
|
|
|
|
|
}
|
|
|
|
|
|
GuruUtils.flavor = appEnv.spec.flavor;
|
2024-03-07 03:46:50 +00:00
|
|
|
|
|
|
|
|
|
|
/// 这里不用担心重复初始化,因为initialize会把对应的 AuthType 重新赋值
|
|
|
|
|
|
/// 如果传入的 AuthType 有重复,会覆盖之前的 AuthType
|
|
|
|
|
|
AuthCredentialManager.initialize([
|
|
|
|
|
|
...AccountManager.defaultSupportedAuthCredentialDelegates,
|
|
|
|
|
|
...appEnv.protocol.accountAuthDelegate?.supportedAuthCredentialDelegates ?? []
|
|
|
|
|
|
]);
|
2023-12-21 09:14:40 +00:00
|
|
|
|
try {
|
|
|
|
|
|
_instance = GuruApp._(
|
2024-03-07 03:46:50 +00:00
|
|
|
|
appSpec: appEnv.spec,
|
|
|
|
|
|
rootPackage: appEnv.package,
|
|
|
|
|
|
protocol: appEnv.protocol);
|
2023-12-21 09:14:40 +00:00
|
|
|
|
Log.init(_instance.appName,
|
|
|
|
|
|
persistentLogFileSize: appEnv.spec.deployment.logFileSizeLimit,
|
|
|
|
|
|
persistentLogCount: appEnv.spec.deployment.logFileCount,
|
|
|
|
|
|
persistentLevel: appEnv.spec.deployment.persistentLogLevel);
|
|
|
|
|
|
AiBi.instance.init();
|
|
|
|
|
|
AdsManager.instance.ensureInitialize();
|
|
|
|
|
|
await _instance._initialize();
|
|
|
|
|
|
LifecycleManager.instance.init();
|
|
|
|
|
|
} catch (error, stacktrace) {
|
|
|
|
|
|
Log.e("GuruApp initialize error!", error: error, stackTrace: stacktrace);
|
|
|
|
|
|
rethrow;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void showToast(String message, {Duration duration = const Duration(seconds: 3)}) {
|
|
|
|
|
|
GuruUtils.showToast(message, duration: duration);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extension GuruAppInitializerExt on GuruApp {
|
|
|
|
|
|
Future _initCommon() async {
|
|
|
|
|
|
await NetworkUtils.init();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Future _initRemoteConfig() async {
|
|
|
|
|
|
await RemoteConfigManager.instance.fetchAndActivate();
|
|
|
|
|
|
final cdnConfig = RemoteConfigManager.instance.getCdnConfig();
|
|
|
|
|
|
HttpEx.init(cdnConfig, GuruApp.instance.appSpec.details.storagePrefix);
|
2024-03-07 03:46:50 +00:00
|
|
|
|
refreshRemoteDeployment();
|
2023-12-21 09:14:40 +00:00
|
|
|
|
Settings.get()
|
|
|
|
|
|
.keepOnScreenDuration
|
|
|
|
|
|
.set(remoteDeployment.keepScreenOnDuration * DateTimeUtils.minuteInMillis);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void _initAnalytics() {
|
|
|
|
|
|
GuruAnalytics.instance.init();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void _initRemoteMessaging() async {
|
|
|
|
|
|
RemoteMessagingManager.instance.init();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void _initDxLink() {
|
|
|
|
|
|
Future.delayed(const Duration(seconds: 2), () {
|
|
|
|
|
|
DxLinkManager.instance.init();
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void _initAds() async {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await AccountDataStore.instance.observableSaasUser
|
|
|
|
|
|
.firstWhere((saasUser) => saasUser?.isValid == true)
|
|
|
|
|
|
.timeout(const Duration(seconds: 3));
|
|
|
|
|
|
} catch (error, stacktrace) {
|
|
|
|
|
|
Log.w("wait account error! $error", stackTrace: stacktrace);
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
await AdsManager.instance.initialize(saasUser: AccountDataStore.instance.user);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Future _initFinancial() async {
|
|
|
|
|
|
ManifestManager.instance.addBuilders(GuruApp.instance.productProfile.manifestBuilders);
|
|
|
|
|
|
|
|
|
|
|
|
FinancialManager.instance.init();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Future _initAccount() async {
|
|
|
|
|
|
await AccountManager.instance.init();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extension GuruAppFinancialExt on GuruApp {
|
|
|
|
|
|
ProductId defineProductId(String sku, int attr, TransactionMethod method) {
|
|
|
|
|
|
return productProfile.define(sku, attr, method);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ProductId? findProductId({String? sku, int? attr}) {
|
|
|
|
|
|
return productProfile.find(sku: sku, attr: attr);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Set<ProductId> offerProductIds(ProductId productId) {
|
|
|
|
|
|
return productProfile.offerProductIds(productId);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
extension GuruRemoteConfigExt on GuruApp {
|
|
|
|
|
|
String getDefaultRemoteConfig(String key, {String defaultValue = ""}) {
|
|
|
|
|
|
return defaultRemoteConfig[key] ?? defaultValue;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|