import 'dart:async'; import 'dart:io'; import 'package:app_tracking_transparency/app_tracking_transparency.dart'; import 'package:flutter/foundation.dart'; import 'package:umeng_common_sdk/umeng_common_sdk.dart'; import 'package:umeng_verify_sdk/umeng_verify_sdk.dart'; import '../config/umeng_config.dart'; import '../services/device_header_service.dart'; import '../storage/storage_keys.dart'; import '../storage/storage_service.dart'; /// 合规门禁后的友盟公共初始化入口;运营商认证只可由显式登录动作触发。 abstract final class UmengService { static Future? _initializing; static bool _ready = false; static Future? _oneKeyInitializing; static bool _oneKeyReady = false; static Future initIfAllowed() { if (_ready || kIsWeb) return Future.value(); if (Platform.isAndroid && !StorageService.to.getBool(storagePrivacyAgreed)) { return Future.value(); } return _initializing ??= _init().whenComplete(() => _initializing = null); } static Future _init() async { await DeviceHeaderService.to.ensureInitialized(); // Keep the carrier-login launch path independent of UMeng Common's // network initialization. Waiting for this future is what left the login // overlay spinning forever in the base project; U-Verify is configured // immediately below by initOneKeyLoginIfAllowed, as in Yanting. unawaited( UmengCommonSdk.initCommon( UmengConfig.androidAppKey, UmengConfig.iosAppKey, DeviceHeaderService.to.commonHeaders()['User-Channel'] ?? 'default', UmengConfig.androidPushSecret, ).catchError((Object _) {}), ); _ready = true; } /// 研听最新合规策略:禁止启动、隐私同意、推送注册等路径预取运营商认证。 /// 该方法仅允许在用户明确点按登录后由 [OneKeyLoginService] 调用。 static Future initOneKeyLoginIfAllowed() async { if (_oneKeyReady || kIsWeb) return; if (Platform.isAndroid && !StorageService.to.getBool(storagePrivacyAgreed)) { return; } await initIfAllowed(); return _oneKeyInitializing ??= _initOneKey().whenComplete( () => _oneKeyInitializing = null, ); } static Future _initOneKey() async { if (Platform.isAndroid) UmengVerifySdk.register_android(); await UmengVerifySdk.setVerifySDKInfo( UmengConfig.androidLoginSecret, UmengConfig.iosLoginSecret, ); _oneKeyReady = true; } static Future requestTrackingAuthorizationIfNeeded() async { if (kIsWeb || !Platform.isIOS) return; try { final status = await AppTrackingTransparency.requestTrackingAuthorization(); if (status != TrackingStatus.authorized) return; final idfa = await AppTrackingTransparency.getAdvertisingIdentifier(); await DeviceHeaderService.to.saveIosIdfa(idfa); } catch (_) { // ATT 拒绝/不可用不能阻断启动。 } } }