优化:Facebook统计问题,设备ID获取bug
This commit is contained in:
parent
4e90e6f030
commit
4ef714453e
@ -59,6 +59,11 @@ android {
|
|||||||
targetSdk 36
|
targetSdk 36
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
|
// Flutter 引擎仅提供 arm + x86_64 的 libflutter.so,不再提供 32 位 x86;勿加 x86,否则 32 位模拟器会缺 .so
|
||||||
|
// Intel/AMD 模拟器请用 **x86_64** 系统镜像(非 x86)
|
||||||
|
ndk {
|
||||||
|
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64'
|
||||||
|
}
|
||||||
// Facebook SDK 调试:正式包调试时设为 true,上线前改回 false
|
// Facebook SDK 调试:正式包调试时设为 true,上线前改回 false
|
||||||
buildConfigField "boolean", "FACEBOOK_DEBUG_LOGS", (localProperties.getProperty("facebook.debug") ?: "true")
|
buildConfigField "boolean", "FACEBOOK_DEBUG_LOGS", (localProperties.getProperty("facebook.debug") ?: "true")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,12 @@
|
|||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.facebook.sdk.ClientToken"
|
android:name="com.facebook.sdk.ClientToken"
|
||||||
android:value="@string/facebook_client_token" />
|
android:value="@string/facebook_client_token" />
|
||||||
|
<!-- 关闭自动 App 事件(含隐式内购 fb_mobile_purchase),避免与 Dart 内 logPurchase 重复计数。
|
||||||
|
会话与显式埋点仍由应用代码负责(如 main.dart activateApp、AdjustEvents.trackPurchaseSuccess)。
|
||||||
|
若开发者后台「自动记录应用事件」与本地冲突,以控制台设置为准。 -->
|
||||||
|
<meta-data
|
||||||
|
android:name="com.facebook.sdk.AutoLogAppEventsEnabled"
|
||||||
|
android:value="false" />
|
||||||
<!-- Facebook SDK 调试:Codeless 事件调试时启用 -->
|
<!-- Facebook SDK 调试:Codeless 事件调试时启用 -->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.facebook.sdk.CodelessDebugLogEnabled"
|
android:name="com.facebook.sdk.CodelessDebugLogEnabled"
|
||||||
|
|||||||
@ -30,6 +30,9 @@
|
|||||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<!-- 关闭 Facebook SDK 自动 App 事件(含隐式购买),与 Android AutoLogAppEventsEnabled=false 对齐 -->
|
||||||
|
<key>FacebookAutoLogAppEventsEnabled</key>
|
||||||
|
<false/>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIMainStoryboardFile</key>
|
<key>UIMainStoryboardFile</key>
|
||||||
|
|||||||
41
lib/app.dart
41
lib/app.dart
@ -1,6 +1,9 @@
|
|||||||
|
import 'package:facebook_app_events/facebook_app_events.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'core/auth/auth_service.dart';
|
import 'core/auth/auth_service.dart';
|
||||||
|
import 'core/config/facebook_config.dart';
|
||||||
|
import 'core/log/app_logger.dart';
|
||||||
import 'core/theme/app_colors.dart';
|
import 'core/theme/app_colors.dart';
|
||||||
import 'core/theme/app_theme.dart';
|
import 'core/theme/app_theme.dart';
|
||||||
import 'core/user/user_state.dart';
|
import 'core/user/user_state.dart';
|
||||||
@ -24,9 +27,45 @@ class App extends StatefulWidget {
|
|||||||
State<App> createState() => _AppState();
|
State<App> createState() => _AppState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppState extends State<App> {
|
class _AppState extends State<App> with WidgetsBindingObserver {
|
||||||
NavTab _currentTab = NavTab.home;
|
NavTab _currentTab = NavTab.home;
|
||||||
|
|
||||||
|
static final _fbLog = AppLogger('FB');
|
||||||
|
final FacebookAppEvents _fbAppEvents = FacebookAppEvents();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
WidgetsBinding.instance.addObserver(this);
|
||||||
|
// 冷启动时进程已在 resumed,didChangeAppLifecycleState 往往收不到「变为 resumed」,需首帧后再手动打一次
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
_reportFacebookActivateApp('first_frame');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `AutoLogAppEventsEnabled=false` 时手动上报 Facebook **安装 + 应用激活**(activateApp)
|
||||||
|
void _reportFacebookActivateApp(String reason) {
|
||||||
|
_fbAppEvents.activateApp().then((_) {
|
||||||
|
if (FacebookConfig.debugLogs) {
|
||||||
|
_fbLog.d('activateApp(手动: $reason)');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 从后台回到前台时触发;冷启动依赖 initState 里的 addPostFrameCallback
|
||||||
|
@override
|
||||||
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||||
|
if (state == AppLifecycleState.resumed) {
|
||||||
|
_reportFacebookActivateApp('lifecycle_resumed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return UserCreditsScope(
|
return UserCreditsScope(
|
||||||
|
|||||||
@ -95,7 +95,7 @@ abstract final class AdjustEvents {
|
|||||||
_trackFb('payment_failed', () => _fb.logEvent(name: 'payment_failed'));
|
_trackFb('payment_failed', () => _fb.logEvent(name: 'payment_failed'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 注册(首次 fast_login 成功)
|
/// 注册(fast_login 返回 equip=true / firstRegister 时)
|
||||||
static void trackRegister() {
|
static void trackRegister() {
|
||||||
_track(register);
|
_track(register);
|
||||||
_trackFb('CompletedRegistration',
|
_trackFb('CompletedRegistration',
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:android_id/android_id.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:crypto/crypto.dart';
|
import 'package:crypto/crypto.dart';
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
@ -10,6 +12,7 @@ import 'package:shared_preferences/shared_preferences.dart';
|
|||||||
|
|
||||||
import '../adjust/adjust_events.dart';
|
import '../adjust/adjust_events.dart';
|
||||||
import '../api/api_client.dart';
|
import '../api/api_client.dart';
|
||||||
|
import 'auth_token_store.dart';
|
||||||
import '../api/api_config.dart';
|
import '../api/api_config.dart';
|
||||||
import '../api/proxy_client.dart';
|
import '../api/proxy_client.dart';
|
||||||
import '../api/services/user_api.dart';
|
import '../api/services/user_api.dart';
|
||||||
@ -56,21 +59,45 @@ class AuthService {
|
|||||||
_log.d(msg);
|
_log.d(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 获取设备 ID(Android: androidId, iOS: identifierForVendor, Web: fallback)
|
static const _prefsKeyFallbackDeviceId = 'persisted_device_id';
|
||||||
|
|
||||||
|
/// 设备唯一标识(用于 fast_login origin 等)。
|
||||||
|
///
|
||||||
|
/// - **Android**:`Settings.Secure.ANDROID_ID`([`android_id`](https://pub.dev/packages/android_id))。\
|
||||||
|
/// 注意:`device_info_plus` 的 `AndroidDeviceInfo.id` 实为 **`Build.ID`(ROM 构建号)**,同版本机型大量相同,**不能**当设备 ID。
|
||||||
|
/// - **iOS**:`identifierForVendor`(同厂商应用间稳定;卸载同厂商全部应用后会变)。
|
||||||
|
/// - **其它 / 读失败**:写入 SharedPreferences 的随机 id,保证进程内稳定且极低碰撞概率。
|
||||||
static Future<String> _getDeviceId() async {
|
static Future<String> _getDeviceId() async {
|
||||||
final deviceInfo = DeviceInfoPlugin();
|
|
||||||
switch (defaultTargetPlatform) {
|
switch (defaultTargetPlatform) {
|
||||||
case TargetPlatform.android:
|
case TargetPlatform.android:
|
||||||
final android = await deviceInfo.androidInfo;
|
final androidId = await const AndroidId().getId();
|
||||||
return android.id;
|
if (androidId != null && androidId.isNotEmpty) {
|
||||||
|
return androidId;
|
||||||
|
}
|
||||||
|
_logMsg('_getDeviceId: ANDROID_ID 为空,使用本地持久化 fallback');
|
||||||
|
return _persistedFallbackDeviceId();
|
||||||
case TargetPlatform.iOS:
|
case TargetPlatform.iOS:
|
||||||
final ios = await deviceInfo.iosInfo;
|
final ios = await DeviceInfoPlugin().iosInfo;
|
||||||
return ios.identifierForVendor ?? 'ios-unknown';
|
final idfv = ios.identifierForVendor;
|
||||||
|
if (idfv != null && idfv.isNotEmpty) return idfv;
|
||||||
|
return _persistedFallbackDeviceId();
|
||||||
default:
|
default:
|
||||||
return 'device-${DateTime.now().millisecondsSinceEpoch}';
|
return _persistedFallbackDeviceId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<String> _persistedFallbackDeviceId() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
var id = prefs.getString(_prefsKeyFallbackDeviceId);
|
||||||
|
if (id != null && id.isNotEmpty) return id;
|
||||||
|
final random = Random.secure();
|
||||||
|
final bytes = List<int>.generate(16, (_) => random.nextInt(256));
|
||||||
|
id = base64UrlEncode(bytes).replaceAll('=', '');
|
||||||
|
await prefs.setString(_prefsKeyFallbackDeviceId, id);
|
||||||
|
_logMsg('_getDeviceId: 已生成并持久化 fallback id');
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
/// 计算 sign:MD5(deviceId) 大写 32 位
|
/// 计算 sign:MD5(deviceId) 大写 32 位
|
||||||
static String _computeSign(String deviceId) {
|
static String _computeSign(String deviceId) {
|
||||||
final bytes = utf8.encode(deviceId);
|
final bytes = utf8.encode(deviceId);
|
||||||
@ -163,6 +190,12 @@ class AuthService {
|
|||||||
_logMsg('init: crest(referrer)=$crest');
|
_logMsg('init: crest(referrer)=$crest');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await AuthTokenStore.restoreToApiClient();
|
||||||
|
if (ApiClient.instance.proxy.userToken != null &&
|
||||||
|
ApiClient.instance.proxy.userToken!.isNotEmpty) {
|
||||||
|
_logMsg('init: 已用本地 token 注入请求头,本次 fast_login 将携带 knight');
|
||||||
|
}
|
||||||
|
|
||||||
ApiResponse? res;
|
ApiResponse? res;
|
||||||
for (var i = 0; i < maxRetries; i++) {
|
for (var i = 0; i < maxRetries; i++) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
@ -193,20 +226,25 @@ class AuthService {
|
|||||||
final token = data?['reevaluate'] as String?;
|
final token = data?['reevaluate'] as String?;
|
||||||
if (token != null && token.isNotEmpty) {
|
if (token != null && token.isNotEmpty) {
|
||||||
ApiClient.instance.setUserToken(token);
|
ApiClient.instance.setUserToken(token);
|
||||||
_logMsg('init: 已设置 userToken');
|
await AuthTokenStore.write(token);
|
||||||
|
_logMsg('init: 已设置 userToken 并写入本地');
|
||||||
} else {
|
} else {
|
||||||
_logMsg('init: 响应中无 reevaluate (userToken)');
|
_logMsg('init: 响应中无 reevaluate (userToken),保留原本地 token(若有)');
|
||||||
}
|
}
|
||||||
final prefs = await SharedPreferences.getInstance();
|
// equip = 服务端 firstRegister(见 docs/user_login.md),为 true/1 时上报注册事件
|
||||||
final hadLoggedIn = prefs.getBool('adjust_has_logged_in') ?? false;
|
final equipRaw = data?['equip'];
|
||||||
if (!hadLoggedIn) {
|
final equipFirstRegister = equipRaw == true ||
|
||||||
|
equipRaw == 1 ||
|
||||||
|
equipRaw == '1' ||
|
||||||
|
(equipRaw is String && equipRaw.toLowerCase() == 'true');
|
||||||
|
if (equipFirstRegister) {
|
||||||
AdjustEvents.trackRegister();
|
AdjustEvents.trackRegister();
|
||||||
await prefs.setBool('adjust_has_logged_in', true);
|
final prefs = await SharedPreferences.getInstance();
|
||||||
await prefs.setString(
|
await prefs.setString(
|
||||||
'adjust_register_date',
|
'adjust_register_date',
|
||||||
DateTime.now().toIso8601String().substring(0, 10),
|
DateTime.now().toIso8601String().substring(0, 10),
|
||||||
);
|
);
|
||||||
_logMsg('init: 首次登录,已上报 register');
|
_logMsg('init: equip=true 首次注册,已上报 register');
|
||||||
}
|
}
|
||||||
final credits = data?['reveal'] as int?;
|
final credits = data?['reveal'] as int?;
|
||||||
if (credits != null) {
|
if (credits != null) {
|
||||||
|
|||||||
31
lib/core/auth/auth_token_store.dart
Normal file
31
lib/core/auth/auth_token_store.dart
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import '../api/api_client.dart';
|
||||||
|
|
||||||
|
/// 持久化用户 Token(代理请求头 `knight`,字段来源 fast_login `reevaluate`)
|
||||||
|
abstract final class AuthTokenStore {
|
||||||
|
static const _prefsKey = 'user_knight_token';
|
||||||
|
|
||||||
|
static Future<String?> read() async {
|
||||||
|
final p = await SharedPreferences.getInstance();
|
||||||
|
return p.getString(_prefsKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> write(String token) async {
|
||||||
|
final p = await SharedPreferences.getInstance();
|
||||||
|
await p.setString(_prefsKey, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> clear() async {
|
||||||
|
final p = await SharedPreferences.getInstance();
|
||||||
|
await p.remove(_prefsKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 启动时调用:若有上次 token,写入 [ApiClient],`fast_login` 等请求会带 `knight`
|
||||||
|
static Future<void> restoreToApiClient() async {
|
||||||
|
final t = await read();
|
||||||
|
if (t != null && t.isNotEmpty) {
|
||||||
|
ApiClient.instance.setUserToken(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ import 'package:flutter_lucide/flutter_lucide.dart';
|
|||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
|
|
||||||
import '../../core/api/api_client.dart';
|
import '../../core/api/api_client.dart';
|
||||||
|
import '../../core/auth/auth_token_store.dart';
|
||||||
import '../../core/api/api_config.dart';
|
import '../../core/api/api_config.dart';
|
||||||
import '../../core/api/services/user_api.dart';
|
import '../../core/api/services/user_api.dart';
|
||||||
import '../../core/user/account_refresh.dart';
|
import '../../core/user/account_refresh.dart';
|
||||||
@ -408,7 +409,9 @@ class _DeleteAccountDialogState extends State<_DeleteAccountDialog> {
|
|||||||
UserState.setAvatar(null);
|
UserState.setAvatar(null);
|
||||||
UserState.setUserName(null);
|
UserState.setUserName(null);
|
||||||
UserState.setNavigate(null);
|
UserState.setNavigate(null);
|
||||||
|
await AuthTokenStore.clear();
|
||||||
ApiClient.instance.setUserToken(null);
|
ApiClient.instance.setUserToken(null);
|
||||||
|
if (!mounted) return;
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
if (widget.parentContext.mounted) {
|
if (widget.parentContext.mounted) {
|
||||||
ScaffoldMessenger.of(widget.parentContext).showSnackBar(
|
ScaffoldMessenger.of(widget.parentContext).showSnackBar(
|
||||||
|
|||||||
@ -266,6 +266,8 @@ class _RechargeScreenState extends State<RechargeScreen>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final purchaseAmount =
|
||||||
|
(AdjustEvents.parsePrice(item.actualAmount) ?? 0).toDouble();
|
||||||
final payUrl = data?['convert']?.toString();
|
final payUrl = data?['convert']?.toString();
|
||||||
if (payUrl != null && payUrl.isNotEmpty) {
|
if (payUrl != null && payUrl.isNotEmpty) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
@ -276,21 +278,28 @@ class _RechargeScreenState extends State<RechargeScreen>
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (mounted && orderId != null && orderId.isNotEmpty) {
|
if (mounted && orderId != null && orderId.isNotEmpty) {
|
||||||
_startOrderPolling(orderId: orderId, userId: userId);
|
_startOrderPolling(
|
||||||
|
orderId: orderId,
|
||||||
|
userId: userId,
|
||||||
|
purchaseAmount: purchaseAmount,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_showSnackBar(
|
_showSnackBar(
|
||||||
context, 'Order created. Complete payment in the page.');
|
context, 'Order created. Complete payment in the page.');
|
||||||
AdjustEvents.trackPurchaseSuccess(
|
|
||||||
(AdjustEvents.parsePrice(item.actualAmount) ?? 0).toDouble());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() => _loadingProductId = null);
|
setState(() => _loadingProductId = null);
|
||||||
_showSnackBar(
|
_showSnackBar(
|
||||||
context, 'Order created. Awaiting payment confirmation.');
|
context, 'Order created. Awaiting payment confirmation.');
|
||||||
|
if (orderId != null && orderId.isNotEmpty) {
|
||||||
|
_startOrderPolling(
|
||||||
|
orderId: orderId,
|
||||||
|
userId: userId,
|
||||||
|
purchaseAmount: purchaseAmount,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AdjustEvents.trackPurchaseSuccess(
|
|
||||||
(AdjustEvents.parsePrice(item.actualAmount) ?? 0).toDouble());
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
@ -304,8 +313,12 @@ class _RechargeScreenState extends State<RechargeScreen>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 三方支付 webview 关闭后轮询订单详情,间隔 1/3/7/15/31/63 秒;status 为 SUCCESS|FAILED|CANCELED 或订单不存在或轮询结束则停止;SUCCESS 时刷新用户信息
|
/// 三方支付 webview 关闭后轮询订单详情,间隔 1/3/7/15/31/63 秒;status 为 SUCCESS|FAILED|CANCELED 或订单不存在或轮询结束则停止;SUCCESS 时刷新用户信息并上报 Adjust/Facebook 购买
|
||||||
void _startOrderPolling({required String orderId, required String userId}) {
|
void _startOrderPolling({
|
||||||
|
required String orderId,
|
||||||
|
required String userId,
|
||||||
|
required double purchaseAmount,
|
||||||
|
}) {
|
||||||
const delays = [1, 2, 4, 8, 16, 32]; // 累计 1,3,7,15,31,63 秒
|
const delays = [1, 2, 4, 8, 16, 32]; // 累计 1,3,7,15,31,63 秒
|
||||||
Future<void> poll(int index) async {
|
Future<void> poll(int index) async {
|
||||||
if (index >= delays.length) return;
|
if (index >= delays.length) return;
|
||||||
@ -326,6 +339,7 @@ class _RechargeScreenState extends State<RechargeScreen>
|
|||||||
RechargeScreen._log.d('订单轮询 orderId=$orderId status=$status');
|
RechargeScreen._log.d('订单轮询 orderId=$orderId status=$status');
|
||||||
if (status == 'SUCCESS' || status == 'FAILED' || status == 'CANCELED') {
|
if (status == 'SUCCESS' || status == 'FAILED' || status == 'CANCELED') {
|
||||||
if (status == 'SUCCESS') {
|
if (status == 'SUCCESS') {
|
||||||
|
await AdjustEvents.trackPurchaseSuccess(purchaseAmount);
|
||||||
refreshAccount();
|
refreshAccount();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import 'package:adjust_sdk/adjust_attribution.dart';
|
import 'package:adjust_sdk/adjust_attribution.dart';
|
||||||
import 'package:adjust_sdk/adjust_config.dart';
|
import 'package:adjust_sdk/adjust_config.dart';
|
||||||
import 'package:adjust_sdk/adjust.dart';
|
import 'package:adjust_sdk/adjust.dart';
|
||||||
import 'package:facebook_app_events/facebook_app_events.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@ -9,7 +8,6 @@ import 'package:flutter/services.dart';
|
|||||||
import 'app.dart';
|
import 'app.dart';
|
||||||
import 'core/api/api_config.dart';
|
import 'core/api/api_config.dart';
|
||||||
import 'core/auth/auth_service.dart';
|
import 'core/auth/auth_service.dart';
|
||||||
import 'core/config/facebook_config.dart';
|
|
||||||
import 'core/log/app_logger.dart';
|
import 'core/log/app_logger.dart';
|
||||||
import 'core/referrer/referrer_service.dart';
|
import 'core/referrer/referrer_service.dart';
|
||||||
import 'core/theme/app_colors.dart';
|
import 'core/theme/app_colors.dart';
|
||||||
@ -18,7 +16,7 @@ import 'features/recharge/google_play_purchase_service.dart';
|
|||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
_initAdjust();
|
_initAdjust();
|
||||||
_initFacebookAppEvents();
|
// Facebook:安装/启动由 App 内生命周期手动 activateApp(见 app.dart),关闭 AutoLog 后依赖此项
|
||||||
// 等待 Adjust 归因(ReferrerService 会调用 Adjust.getAttributionWithTimeout)
|
// 等待 Adjust 归因(ReferrerService 会调用 Adjust.getAttributionWithTimeout)
|
||||||
await ReferrerService.init();
|
await ReferrerService.init();
|
||||||
SystemChrome.setSystemUIOverlayStyle(
|
SystemChrome.setSystemUIOverlayStyle(
|
||||||
@ -46,7 +44,6 @@ void _initAdjust() {
|
|||||||
appToken,
|
appToken,
|
||||||
kDebugMode ? AdjustEnvironment.sandbox : AdjustEnvironment.production,
|
kDebugMode ? AdjustEnvironment.sandbox : AdjustEnvironment.production,
|
||||||
);
|
);
|
||||||
// config.fbAppId = FacebookConfig.appId;
|
|
||||||
if (kDebugMode || ApiConfig.debugLogs) {
|
if (kDebugMode || ApiConfig.debugLogs) {
|
||||||
config.logLevel = AdjustLogLevel.verbose;
|
config.logLevel = AdjustLogLevel.verbose;
|
||||||
}
|
}
|
||||||
@ -54,16 +51,6 @@ void _initAdjust() {
|
|||||||
Adjust.initSdk(config);
|
Adjust.initSdk(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
final _fbAppEvents = FacebookAppEvents();
|
|
||||||
|
|
||||||
void _initFacebookAppEvents() {
|
|
||||||
// activateApp:应用启动事件,Facebook 用于统计与广告归因
|
|
||||||
_fbAppEvents.activateApp();
|
|
||||||
if (FacebookConfig.debugLogs) {
|
|
||||||
AppLogger('FB').d('activateApp 已上报');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final _adjustLog = AppLogger('Adjust');
|
final _adjustLog = AppLogger('Adjust');
|
||||||
|
|
||||||
void _onAdjustAttribution(AdjustAttribution attribution) {
|
void _onAdjustAttribution(AdjustAttribution attribution) {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
name: pets_hero_ai
|
name: pets_hero_ai
|
||||||
description: PetsHero AI Application.
|
description: PetsHero AI Application.
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
version: 1.1.11+22
|
version: 1.1.13+24
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.0.0 <4.0.0'
|
sdk: '>=3.0.0 <4.0.0'
|
||||||
@ -34,6 +34,7 @@ dependencies:
|
|||||||
webview_flutter: ^4.10.0
|
webview_flutter: ^4.10.0
|
||||||
screen_secure: ^1.0.3
|
screen_secure: ^1.0.3
|
||||||
flutter_native_splash: ^2.4.7
|
flutter_native_splash: ^2.4.7
|
||||||
|
android_id: ^0.5.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user