diff --git a/android/app/build.gradle b/android/app/build.gradle
index 169edc2..5424e86 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -37,6 +37,7 @@ configurations.all {
android {
namespace "com.petsheroai.app"
compileSdk 36
+ buildFeatures { buildConfig = true }
ndkVersion flutter.ndkVersion
compileOptions {
@@ -58,6 +59,8 @@ android {
targetSdk 36
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
+ // Facebook SDK 调试:正式包调试时设为 true,上线前改回 false
+ buildConfigField "boolean", "FACEBOOK_DEBUG_LOGS", (localProperties.getProperty("facebook.debug") ?: "true")
}
signingConfigs {
@@ -82,8 +85,10 @@ android {
}
dependencies {
+ implementation 'com.facebook.android:facebook-core:18.0.0'
implementation 'com.google.android.gms:play-services-ads-identifier:18.1.0'
implementation 'com.android.installreferrer:installreferrer:2.2'
+ implementation 'com.adjust.sdk:adjust-android-meta-referrer:5.5.1'
implementation 'androidx.appcompat:appcompat:1.7.0'
// Play Billing Library 6.0.1+ (use 7.1.1 for in_app_purchase plugin compatibility)
implementation 'com.android.billingclient:billing:7.1.1'
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index b0586f2..e827b43 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -27,5 +27,16 @@
+
+
+
+
+
diff --git a/android/app/src/main/kotlin/com/petsheroai/app/MainActivity.kt b/android/app/src/main/kotlin/com/petsheroai/app/MainActivity.kt
index c3c9841..b4ea52a 100644
--- a/android/app/src/main/kotlin/com/petsheroai/app/MainActivity.kt
+++ b/android/app/src/main/kotlin/com/petsheroai/app/MainActivity.kt
@@ -1,5 +1,24 @@
package com.petsheroai.app
+import android.os.Bundle
+import com.facebook.FacebookSdk
+import com.facebook.LoggingBehavior
import io.flutter.embedding.android.FlutterActivity
-class MainActivity: FlutterActivity()
+class MainActivity : FlutterActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ // 必须在 super.onCreate 之前初始化,否则 facebook_app_events 插件注册时会因 SDK 未初始化而崩溃
+ FacebookSdk.sdkInitialize(applicationContext)
+ // Facebook SDK 调试日志:需 buildConfigField FACEBOOK_DEBUG_LOGS=true
+ if (BuildConfig.FACEBOOK_DEBUG_LOGS) {
+ try {
+ FacebookSdk.setIsDebugEnabled(true)
+ FacebookSdk.addLoggingBehavior(LoggingBehavior.APP_EVENTS)
+ FacebookSdk.addLoggingBehavior(LoggingBehavior.REQUESTS)
+ FacebookSdk.addLoggingBehavior(LoggingBehavior.DEVELOPER_ERRORS)
+ } catch (_: Exception) { /* ignore */ }
+ }
+ super.onCreate(savedInstanceState)
+ }
+}
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..b4c992e
--- /dev/null
+++ b/android/app/src/main/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+
+
+ 1684216162986495
+ df562f4ff186aaac5ff56ba190020ffd
+
diff --git a/ios/Runner/GeneratedPluginRegistrant.m b/ios/Runner/GeneratedPluginRegistrant.m
index 13f20ce..9fc859c 100644
--- a/ios/Runner/GeneratedPluginRegistrant.m
+++ b/ios/Runner/GeneratedPluginRegistrant.m
@@ -18,6 +18,12 @@
@import device_info_plus;
#endif
+#if __has_include()
+#import
+#else
+@import facebook_app_events;
+#endif
+
#if __has_include()
#import
#else
@@ -89,6 +95,7 @@
+ (void)registerWithRegistry:(NSObject*)registry {
[AdjustSdk registerWithRegistrar:[registry registrarForPlugin:@"AdjustSdk"]];
[FPPDeviceInfoPlusPlugin registerWithRegistrar:[registry registrarForPlugin:@"FPPDeviceInfoPlusPlugin"]];
+ [FacebookAppEventsPlugin registerWithRegistrar:[registry registrarForPlugin:@"FacebookAppEventsPlugin"]];
[FlutterNativeSplashPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterNativeSplashPlugin"]];
[GalPlugin registerWithRegistrar:[registry registrarForPlugin:@"GalPlugin"]];
[FLTImagePickerPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTImagePickerPlugin"]];
diff --git a/lib/core/adjust/adjust_events.dart b/lib/core/adjust/adjust_events.dart
index 8c74582..bb1aefe 100644
--- a/lib/core/adjust/adjust_events.dart
+++ b/lib/core/adjust/adjust_events.dart
@@ -1,9 +1,21 @@
+import 'dart:async';
+
import 'package:adjust_sdk/adjust.dart';
import 'package:adjust_sdk/adjust_event.dart';
+import 'package:facebook_app_events/facebook_app_events.dart';
+import 'package:logger/logger.dart';
import 'package:shared_preferences/shared_preferences.dart';
-/// Adjust 事件埋点(识别码见 docs/adjuest.md)
+import '../config/facebook_config.dart';
+
+/// 事件埋点:Adjust + Facebook App Events 双通道上报
+/// Adjust 识别码见 docs/adjuest.md
abstract final class AdjustEvents {
+ static final _fb = FacebookAppEvents();
+ static final _fbLog = Logger(
+ printer: PrettyPrinter(methodCount: 0, lineLength: 120),
+ level: FacebookConfig.debugLogs ? Level.trace : Level.off,
+ );
// 购买档位(充值页选择档位时上报)
static const String tier1999 = 'm0r9u9'; // 19.99
static const String tier4999 = 'aht1ve'; // 49.99
@@ -57,56 +69,75 @@ abstract final class AdjustEvents {
Adjust.trackEvent(AdjustEvent(eventToken));
}
+ /// 上报 Facebook(fire-and-forget,不阻塞主流程)
+ static void _trackFb(String eventDesc, Future Function() fn) {
+ if (FacebookConfig.debugLogs) _fbLog.w('FB ↑ $eventDesc');
+ unawaited(fn());
+ }
+
/// 购买档位(用户点击某档位购买时)
static void trackTier(String eventToken) {
_track(eventToken);
}
/// 首日充值
- static void trackFirstPurchase() {
+ static void trackFirstPurchase(double amount) {
_track(firstPurchase);
+ _trackFb(
+ 'FirstRecharge amount=$amount',
+ () => _fb
+ .logEvent(name: 'FirstRecharge', parameters: {'amount': amount}));
}
/// 支付失败
static void trackOrderAbnormal() {
_track(orderAbnormal);
- }
-
- /// 支付成功(若为首日充值需额外调用 trackFirstPurchase)
- static void trackPurchase() {
- _track(purchase);
+ _trackFb('payment_failed', () => _fb.logEvent(name: 'payment_failed'));
}
/// 注册(首次 fast_login 成功)
static void trackRegister() {
_track(register);
+ _trackFb('CompletedRegistration',
+ () => _fb.logCompletedRegistration(registrationMethod: 'device'));
}
/// PetsHero AI Monthly VIP
static void trackMonthlyVip() {
_track(monthlyVip);
+ _trackFb('Subscribe monthly_vip',
+ () => _fb.logSubscribe(orderId: 'monthly_vip'));
}
/// PetsHero AI Weekly VIP
static void trackWeeklyVip() {
_track(weeklyVip);
+ _trackFb(
+ 'Subscribe weekly_vip', () => _fb.logSubscribe(orderId: 'weekly_vip'));
}
static const String _keyRegisterDate = 'adjust_register_date';
/// 支付成功时调用:上报 Purchase,若为首日充值则同时上报 first purchase
- static Future trackPurchaseSuccess() async {
+ static Future trackPurchaseSuccess(double amount) async {
_track(purchase);
final prefs = await SharedPreferences.getInstance();
final registerDate = prefs.getString(_keyRegisterDate);
- if (registerDate != null &&
- registerDate == DateTime.now().toIso8601String().substring(0, 10)) {
- _track(firstPurchase);
+ final isFirstPurchase = registerDate != null &&
+ registerDate == DateTime.now().toIso8601String().substring(0, 10);
+ if (isFirstPurchase) {
+ trackFirstPurchase(amount);
}
+ _trackFb(
+ 'Purchase',
+ () => _fb.logPurchase(
+ amount: amount,
+ currency: 'USD',
+ ));
}
/// 支付失败时调用
static void trackPaymentFailed() {
- _track(orderAbnormal);
+ trackOrderAbnormal();
}
}
diff --git a/lib/core/api/api_config.dart b/lib/core/api/api_config.dart
index a1b8376..d278dba 100644
--- a/lib/core/api/api_config.dart
+++ b/lib/core/api/api_config.dart
@@ -2,6 +2,9 @@ import 'package:flutter/foundation.dart';
/// petsHeroAI API 配置
abstract final class ApiConfig {
+ /// 调试日志:true 时 release 包也输出 debug/info(正式包调试用,上线前改 false)
+ static const bool debugLogs = true;
+
/// AES 密钥
static const String aesKey = 'liyP4LkMfP68XvCt';
@@ -12,7 +15,7 @@ abstract final class ApiConfig {
static const String packageName = 'com.petsheroai.app';
/// 预发环境域名
- static const String preBaseUrl = 'https://pre-ai.petsheroai.xyz';
+ static const String preBaseUrl = 'https://ai.petsheroai.xyz';
//'https://ai.petsheroai.xyz'; //'https://pre-ai.petsheroai.xyz';
/// 生产环境域名
diff --git a/lib/core/api/api_crypto.dart b/lib/core/api/api_crypto.dart
index dc12c3c..0c05443 100644
--- a/lib/core/api/api_crypto.dart
+++ b/lib/core/api/api_crypto.dart
@@ -1,4 +1,5 @@
import 'dart:convert';
+import 'dart:math';
import 'package:encrypt/encrypt.dart';
@@ -29,8 +30,10 @@ abstract final class ApiCrypto {
}
/// 生成随机 Base64 字符串(用于噪音字段)
+ /// 使用 Random.secure() 保证密码学安全随机性
static String randomBase64([int byteLength = 16]) {
- final bytes = List.generate(byteLength, (_) => DateTime.now().millisecondsSinceEpoch % 256);
+ final random = Random.secure();
+ final bytes = List.generate(byteLength, (_) => random.nextInt(256));
return base64Encode(bytes);
}
diff --git a/lib/core/api/proxy_client.dart b/lib/core/api/proxy_client.dart
index 49a7678..dbca292 100644
--- a/lib/core/api/proxy_client.dart
+++ b/lib/core/api/proxy_client.dart
@@ -82,7 +82,7 @@ void _logLong(String text) {
/// 遇到 { 或 [ 视为 JSON 开始,直到与之匹配的 } 或 ] 结束;格式化后单条不超过 1000 字,分条时按行切分保持对齐。
void logWithEmbeddedJson(Object? msg) {
- if (!kDebugMode) return;
+ if (!kDebugMode && !ApiConfig.debugLogs) return;
if (msg is! String) {
_proxyLog.d(msg);
@@ -265,7 +265,7 @@ class ProxyClient {
final loyaltyIndexEnc = ApiCrypto.encrypt(v2BodyEncoded);
final proxyBody = {
- ProxyKeys.heroClass: ApiConfig.appId,
+ ProxyKeys.heroClass: 'petsHeroAI',
ProxyKeys.petSpecies: petSpeciesEnc,
ProxyKeys.powerLevel: powerLevelEnc,
ProxyKeys.questRank: questRankEnc,
@@ -278,9 +278,10 @@ class ProxyClient {
ProxyKeys.accuracyVal: ApiCrypto.randomBase64(),
ProxyKeys.dirPath: ApiCrypto.randomBase64(),
};
+ _log('加密后的请求体: ${jsonEncode(proxyBody)}');
final url = '$_baseUrl${ApiConfig.proxyPath}';
-
+ _log('真实请求URL: $url');
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
diff --git a/lib/core/api/services/user_api.dart b/lib/core/api/services/user_api.dart
index c5be95c..e3a040b 100644
--- a/lib/core/api/services/user_api.dart
+++ b/lib/core/api/services/user_api.dart
@@ -19,7 +19,8 @@ abstract final class UserApi {
path: '/v1/user/fast_login',
method: 'POST',
queryParams: {
- if (crest != null) 'crest': crest,
+ // if (crest != null) 'crest': crest,
+ "sentinel": "HAndroid",
'portal': ApiConfig.packageName,
if (accolade != null) 'accolade': accolade,
},
diff --git a/lib/core/auth/auth_service.dart b/lib/core/auth/auth_service.dart
index 72b57a1..c6895c0 100644
--- a/lib/core/auth/auth_service.dart
+++ b/lib/core/auth/auth_service.dart
@@ -85,7 +85,8 @@ class AuthService {
final realm = data['realm'] as String?;
if (realm != null && realm.isNotEmpty) UserState.setAvatar(realm);
final terminal = data['terminal'] as String?;
- if (terminal != null && terminal.isNotEmpty) UserState.setUserName(terminal);
+ if (terminal != null && terminal.isNotEmpty)
+ UserState.setUserName(terminal);
final navigate = data['navigate'] as String?;
if (navigate != null) UserState.setNavigate(navigate);
@@ -162,6 +163,7 @@ class AuthService {
if (res == null) return;
_logMsg('init: 登录结果 code=${res.code} msg=${res.msg}');
+ _logMsg('init: 登录响应 data=${res.data}');
if (res.isSuccess && res.data != null) {
final data = res.data as Map?;
@@ -213,7 +215,7 @@ class AuthService {
asset: uid!,
digest: crest ?? '',
origin: deviceId,
- accolade: 'android_adjust',
+ accolade: ReferrerService.referrerSource,
);
if (referrerRes.isSuccess) {
_logMsg('referrer 上报成功');
diff --git a/lib/core/config/facebook_config.dart b/lib/core/config/facebook_config.dart
new file mode 100644
index 0000000..c2c3045
--- /dev/null
+++ b/lib/core/config/facebook_config.dart
@@ -0,0 +1,27 @@
+/// Facebook SDK 配置
+///
+/// 用于 Adjust Meta Install Referrer 归因与 Facebook App Events 埋点。
+abstract final class FacebookConfig {
+ /// Facebook 调试日志:true 时 Dart 层会打印所有 FB 事件(正式包调试用,上线前改 false)
+ static const bool debugLogs = true;
+
+ /// Facebook 应用 ID(应用编号)
+ static const String appId = '1684216162986495';
+
+ /// Facebook Client Token(客户端口令)
+ ///
+ /// 在 Facebook 开发者后台获取:应用 → 设置 → 高级 → 客户端口令
+ static const String clientToken = '';
+
+ /// 安装引荐来源解密密钥
+ ///
+ /// 用于解密 Facebook App Install Ads 的加密 referrer。
+ /// 请在 Adjust 控制台填写此密钥以启用解密
+ /// (路径:App Settings → Partner setup → Meta/Facebook)。
+ static const String installReferrerDecryptionKey =
+ '068aff9bac7e8846b94e9fc73d51c7a5ab7c8ac39fe9a2b16d0ff8b74f98f';
+
+ /// 应用密钥(App Secret)仅用于服务端,勿放入客户端。
+ static bool get hasClientToken => clientToken.isNotEmpty;
+}
+
diff --git a/lib/core/log/app_logger.dart b/lib/core/log/app_logger.dart
index c29d58d..9535863 100644
--- a/lib/core/log/app_logger.dart
+++ b/lib/core/log/app_logger.dart
@@ -1,8 +1,10 @@
import 'package:flutter/foundation.dart';
import 'package:logger/logger.dart';
+import '../api/api_config.dart';
+
/// 统一应用日志,提升可读性:时间戳、级别、标签、格式化输出。
-/// 在 release 下仅输出 warning/error,避免泄露信息。
+/// release 下默认仅输出 warning/error;ApiConfig.debugLogs=true 时放开全部级别。
///
/// 使用示例:
/// final _log = AppLogger('GenerateVideo');
@@ -25,7 +27,7 @@ class AppLogger {
printEmojis: true,
dateTimeFormat: DateTimeFormat.onlyTimeAndSinceStart,
),
- level: kReleaseMode ? Level.warning : Level.trace,
+ level: (kDebugMode || ApiConfig.debugLogs) ? Level.trace : Level.warning,
);
return _logger!;
}
diff --git a/lib/core/referrer/referrer_service.dart b/lib/core/referrer/referrer_service.dart
index 2e7631f..aa079fc 100644
--- a/lib/core/referrer/referrer_service.dart
+++ b/lib/core/referrer/referrer_service.dart
@@ -1,32 +1,108 @@
import 'dart:async';
+import 'dart:convert';
+import 'package:adjust_sdk/adjust_attribution.dart';
+import 'package:adjust_sdk/adjust.dart';
import 'package:flutter/foundation.dart';
import 'package:play_install_referrer/play_install_referrer.dart';
-/// 安装来源 referrer 服务(用于 ch/crest 渠道参数)
+/// 归因信息服务(优先从 Adjust 获取,fallback 使用 Play Install Referrer)
class ReferrerService {
ReferrerService._();
static String? _cachedReferrer;
+ static String _referrerSource = 'gg';
static final Completer _completer = Completer();
- /// 获取 referrer,Android 使用 Google Play Install Referrer,iOS 返回空
+ /// attribution 回调的 Completer,与 getAttributionWithTimeout 竞速,谁先返回用谁
+ static final Completer _attributionCallbackCompleter =
+ Completer();
+
+ static const int _adjustTimeoutMs = 15000;
+
+ /// 由 Adjust attributionCallback 调用,首次安装时归因往往通过此回调返回(晚于 getAttributionWithTimeout)
+ static void receiveAttributionFromCallback(AdjustAttribution attribution) {
+ if (!_attributionCallbackCompleter.isCompleted) {
+ _attributionCallbackCompleter.complete(attribution);
+ }
+ }
+
+ /// 归因来源:Adjust 为 android_adjust,Play Install Referrer 为 gg
+ static String get referrerSource => _referrerSource;
+
+ /// JSON 可编码的 costAmount:保留字段,非有限数字用字符串避免 encode 抛错
+ static Object? _jsonEncodableCostAmount(num? v) {
+ if (v == null) return null;
+ if (v is double && !v.isFinite) return v.toString();
+ return v;
+ }
+
+ /// 将完整 AdjustAttribution 序列化为 JSON(供 digest / Base64),不省略任何键
+ static String _attributionToDigest(AdjustAttribution attr) {
+ final map = {
+ 'trackerToken': attr.trackerToken,
+ 'trackerName': attr.trackerName,
+ 'network': attr.network,
+ 'campaign': attr.campaign,
+ 'adgroup': attr.adgroup,
+ 'creative': attr.creative,
+ 'clickLabel': attr.clickLabel,
+ 'costType': attr.costType,
+ 'costAmount': _jsonEncodableCostAmount(attr.costAmount),
+ 'costCurrency': attr.costCurrency,
+ 'jsonResponse': attr.jsonResponse,
+ 'fbInstallReferrer': attr.fbInstallReferrer,
+ };
+ try {
+ return jsonEncode(map);
+ } catch (_) {
+ return '';
+ }
+ }
+
+ /// 获取 referrer/digest,优先从 Adjust 归因获取,fallback 使用 Play Install Referrer
+ /// 同时监听 attributionCallback,首次安装时归因往往通过回调返回(可能晚于 getAttributionWithTimeout)
static Future getReferrer() async {
if (_cachedReferrer != null) return _cachedReferrer;
if (_completer.isCompleted) return _completer.future;
- if (defaultTargetPlatform != TargetPlatform.android) {
- _cachedReferrer = '';
- if (!_completer.isCompleted) _completer.complete('');
- return '';
+ var digest = '';
+ try {
+ // 竞速:getAttributionWithTimeout 与 attribution 回调,谁先返回用谁
+ final attribution = await Future.any([
+ (() async {
+ try {
+ return await Adjust.getAttributionWithTimeout(_adjustTimeoutMs);
+ } catch (_) {
+ return null;
+ }
+ })(),
+ _attributionCallbackCompleter.future,
+ ]);
+ if (attribution != null) {
+ final raw = _attributionToDigest(attribution);
+ if (raw.isNotEmpty) {
+ _referrerSource = 'android_adjust';
+ digest = base64Encode(utf8.encode(raw));
+ }
+ }
+ } catch (_) {
+ digest = '';
}
- try {
- final details = await PlayInstallReferrer.installReferrer;
- _cachedReferrer = details.installReferrer ?? '';
- } catch (_) {
- _cachedReferrer = '';
+ if (digest.isEmpty) {
+ _referrerSource = 'gg';
+ if (defaultTargetPlatform == TargetPlatform.android) {
+ try {
+ final details = await PlayInstallReferrer.installReferrer;
+ digest = details.installReferrer ?? '';
+ } catch (_) {
+ digest = '';
+ }
+ }
}
+
+ _cachedReferrer = digest;
if (!_completer.isCompleted) _completer.complete(_cachedReferrer);
return _cachedReferrer;
}
diff --git a/lib/features/recharge/recharge_screen.dart b/lib/features/recharge/recharge_screen.dart
index e122d0c..4ffc77c 100644
--- a/lib/features/recharge/recharge_screen.dart
+++ b/lib/features/recharge/recharge_screen.dart
@@ -280,7 +280,8 @@ class _RechargeScreenState extends State
}
_showSnackBar(
context, 'Order created. Complete payment in the page.');
- AdjustEvents.trackPurchaseSuccess();
+ AdjustEvents.trackPurchaseSuccess(
+ (AdjustEvents.parsePrice(item.actualAmount) ?? 0).toDouble());
}
} else {
if (mounted) {
@@ -288,7 +289,8 @@ class _RechargeScreenState extends State
_showSnackBar(
context, 'Order created. Awaiting payment confirmation.');
}
- AdjustEvents.trackPurchaseSuccess();
+ AdjustEvents.trackPurchaseSuccess(
+ (AdjustEvents.parsePrice(item.actualAmount) ?? 0).toDouble());
}
} catch (e) {
if (mounted) {
@@ -456,7 +458,8 @@ class _RechargeScreenState extends State
if (mounted) {
_showSnackBar(context, 'Purchase completed.');
}
- AdjustEvents.trackPurchaseSuccess();
+ AdjustEvents.trackPurchaseSuccess(
+ (AdjustEvents.parsePrice(item.actualAmount) ?? 0).toDouble());
} else {
_showSnackBar(
context,
diff --git a/lib/main.dart b/lib/main.dart
index 3c58ab9..2a270ba 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,12 +1,15 @@
import 'package:adjust_sdk/adjust_attribution.dart';
import 'package:adjust_sdk/adjust_config.dart';
import 'package:adjust_sdk/adjust.dart';
+import 'package:facebook_app_events/facebook_app_events.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'app.dart';
+import 'core/api/api_config.dart';
import 'core/auth/auth_service.dart';
+import 'core/config/facebook_config.dart';
import 'core/log/app_logger.dart';
import 'core/referrer/referrer_service.dart';
import 'core/theme/app_colors.dart';
@@ -15,7 +18,9 @@ import 'features/recharge/google_play_purchase_service.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
_initAdjust();
- ReferrerService.init();
+ _initFacebookAppEvents();
+ // 等待 Adjust 归因(ReferrerService 会调用 Adjust.getAttributionWithTimeout)
+ await ReferrerService.init();
SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle(
statusBarColor: AppColors.surface,
@@ -23,7 +28,7 @@ void main() async {
statusBarBrightness: Brightness.light,
),
);
- // 先启动登录,确保首次构建时 loginComplete 可被监听
+ // Adjust 初始化后执行登录,确保登录时归因数据已就绪
AuthService.init();
runApp(const App());
// 尽早订阅 purchaseStream,否则未确认订单不会出现在 queryPastPurchases 中,补单会为空
@@ -31,7 +36,8 @@ void main() async {
GooglePlayPurchaseService.startPendingPurchaseListener();
}
// 登录完成后执行谷歌支付补单(未核销订单上报服务端并 completePurchase)
- AuthService.loginComplete.then((_) => GooglePlayPurchaseService.runOrderRecovery());
+ AuthService.loginComplete
+ .then((_) => GooglePlayPurchaseService.runOrderRecovery());
}
void _initAdjust() {
@@ -40,16 +46,29 @@ void _initAdjust() {
appToken,
kDebugMode ? AdjustEnvironment.sandbox : AdjustEnvironment.production,
);
- if (kDebugMode) {
+ // config.fbAppId = FacebookConfig.appId;
+ if (kDebugMode || ApiConfig.debugLogs) {
config.logLevel = AdjustLogLevel.verbose;
}
config.attributionCallback = _onAdjustAttribution;
Adjust.initSdk(config);
}
+final _fbAppEvents = FacebookAppEvents();
+
+void _initFacebookAppEvents() {
+ // activateApp:应用启动事件,Facebook 用于统计与广告归因
+ _fbAppEvents.activateApp();
+ if (FacebookConfig.debugLogs) {
+ AppLogger('FB').d('activateApp 已上报');
+ }
+}
+
final _adjustLog = AppLogger('Adjust');
void _onAdjustAttribution(AdjustAttribution attribution) {
+ // 注入 ReferrerService,与 getAttributionWithTimeout 竞速,首次安装时归因多由此回调返回
+ ReferrerService.receiveAttributionFromCallback(attribution);
_adjustLog.d('归因信息: '
'trackerToken=${attribution.trackerToken}, '
'trackerName=${attribution.trackerName}, '
diff --git a/pubspec.yaml b/pubspec.yaml
index 833e110..b962d6c 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,7 +1,7 @@
name: pets_hero_ai
description: PetsHero AI Application.
publish_to: 'none'
-version: 1.1.1+12
+version: 1.1.11+22
environment:
sdk: '>=3.0.0 <4.0.0'
@@ -10,6 +10,7 @@ dependencies:
flutter:
sdk: flutter
adjust_sdk: ^5.5.1
+ facebook_app_events: ^0.26.0
cupertino_icons: ^1.0.6
play_install_referrer: ^0.5.0
flutter_lucide: ^1.8.2