Files
BlockSeasons/lib/services/consent_service.dart
T

87 lines
2.5 KiB
Dart

// lib/services/consent_service.dart
import 'dart:async';
import 'dart:io' show Platform;
import 'package:app_tracking_transparency/app_tracking_transparency.dart';
import 'package:flutter/foundation.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'ad_service.dart';
/// Runs the App-Review-mandated consent sequence exactly once per launch and
/// in the required order: UMP consent form -> iOS ATT prompt -> MobileAds
/// initialize. Each step is guarded; a failure in one never skips SDK init,
/// because un-initialized ads would silently disable the whole monetization
/// layer. Must be invoked AFTER the first frame (ATT needs the foreground).
class ConsentService {
ConsentService(this._adService);
final AdService _adService;
bool _ran = false;
Future<void> ensureConsentAndInitialize() async {
if (_ran) return;
_ran = true;
await _requestUmp();
await _requestAtt();
await _initializeAds();
}
Future<void> _requestUmp() async {
try {
final params = ConsentRequestParameters();
final completer = Completer<void>();
ConsentInformation.instance.requestConsentInfoUpdate(
params,
() async {
try {
if (await ConsentInformation.instance.isConsentFormAvailable()) {
await _loadAndShowFormIfRequired();
}
} finally {
completer.complete();
}
},
(_) => completer.complete(),
);
await completer.future;
} catch (_) {/* proceed without UMP */}
}
Future<void> _loadAndShowFormIfRequired() async {
final completer = Completer<void>();
ConsentForm.loadConsentForm(
(form) async {
final status = await ConsentInformation.instance.getConsentStatus();
if (status == ConsentStatus.required) {
form.show((_) => completer.complete());
} else {
completer.complete();
}
},
(_) => completer.complete(),
);
await completer.future;
}
Future<void> _requestAtt() async {
if (!Platform.isIOS) return;
try {
final status =
await AppTrackingTransparency.trackingAuthorizationStatus;
if (status == TrackingStatus.notDetermined) {
await AppTrackingTransparency.requestTrackingAuthorization();
}
} catch (_) {/* ATT optional */}
}
Future<void> _initializeAds() async {
try {
await MobileAds.instance.initialize();
_adService.onSdkReady();
} catch (e) {
debugPrint('MobileAds init failed: $e');
}
}
}