feat(mobile/telemetry): collect real network type via connectivity_plus
- Add connectivity_plus: ^6.0.3 to pubspec.yaml - DeviceInfoCollector._getNetworkType() calls Connectivity().checkConnectivity() and maps ConnectivityResult → wifi / mobile / ethernet / vpn / bluetooth / none / unknown - networkType field in DeviceContext is now populated on every cold start - All page_view and session events carry the accurate network type in device props Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9b760c56ee
commit
9519e29b8f
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import '../models/device_context.dart';
|
import '../models/device_context.dart';
|
||||||
|
|
@ -25,6 +26,7 @@ class DeviceInfoCollector {
|
||||||
final deviceInfo = DeviceInfoPlugin();
|
final deviceInfo = DeviceInfoPlugin();
|
||||||
final packageInfo = await PackageInfo.fromPlatform();
|
final packageInfo = await PackageInfo.fromPlatform();
|
||||||
final mediaQuery = MediaQuery.of(context);
|
final mediaQuery = MediaQuery.of(context);
|
||||||
|
final networkType = await _getNetworkType();
|
||||||
|
|
||||||
DeviceContext result;
|
DeviceContext result;
|
||||||
|
|
||||||
|
|
@ -49,7 +51,7 @@ class DeviceInfoCollector {
|
||||||
locale: Platform.localeName,
|
locale: Platform.localeName,
|
||||||
timezone: DateTime.now().timeZoneName,
|
timezone: DateTime.now().timeZoneName,
|
||||||
isDarkMode: mediaQuery.platformBrightness == Brightness.dark,
|
isDarkMode: mediaQuery.platformBrightness == Brightness.dark,
|
||||||
networkType: 'unknown', // 需要额外的connectivity包
|
networkType: networkType,
|
||||||
collectedAt: DateTime.now(),
|
collectedAt: DateTime.now(),
|
||||||
);
|
);
|
||||||
} else if (Platform.isIOS) {
|
} else if (Platform.isIOS) {
|
||||||
|
|
@ -73,7 +75,7 @@ class DeviceInfoCollector {
|
||||||
locale: Platform.localeName,
|
locale: Platform.localeName,
|
||||||
timezone: DateTime.now().timeZoneName,
|
timezone: DateTime.now().timeZoneName,
|
||||||
isDarkMode: mediaQuery.platformBrightness == Brightness.dark,
|
isDarkMode: mediaQuery.platformBrightness == Brightness.dark,
|
||||||
networkType: 'unknown',
|
networkType: networkType,
|
||||||
collectedAt: DateTime.now(),
|
collectedAt: DateTime.now(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -84,6 +86,40 @@ class DeviceInfoCollector {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 获取当前网络类型
|
||||||
|
///
|
||||||
|
/// 返回值:'wifi' | 'mobile_2g' | 'mobile_3g' | 'mobile_4g' | 'mobile_5g' |
|
||||||
|
/// 'ethernet' | 'vpn' | 'bluetooth' | 'none' | 'unknown'
|
||||||
|
Future<String> _getNetworkType() async {
|
||||||
|
try {
|
||||||
|
final results = await Connectivity().checkConnectivity();
|
||||||
|
// checkConnectivity 返回 List<ConnectivityResult>,取第一个主要连接
|
||||||
|
final result = results.isNotEmpty ? results.first : ConnectivityResult.none;
|
||||||
|
return _mapConnectivityResult(result);
|
||||||
|
} catch (e) {
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String _mapConnectivityResult(ConnectivityResult result) {
|
||||||
|
switch (result) {
|
||||||
|
case ConnectivityResult.wifi:
|
||||||
|
return 'wifi';
|
||||||
|
case ConnectivityResult.mobile:
|
||||||
|
return 'mobile'; // 无法区分 2G/3G/4G/5G(需原生插件)
|
||||||
|
case ConnectivityResult.ethernet:
|
||||||
|
return 'ethernet';
|
||||||
|
case ConnectivityResult.vpn:
|
||||||
|
return 'vpn';
|
||||||
|
case ConnectivityResult.bluetooth:
|
||||||
|
return 'bluetooth';
|
||||||
|
case ConnectivityResult.none:
|
||||||
|
return 'none';
|
||||||
|
default:
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 收集屏幕信息
|
/// 收集屏幕信息
|
||||||
ScreenInfo _collectScreenInfo(MediaQueryData mediaQuery) {
|
ScreenInfo _collectScreenInfo(MediaQueryData mediaQuery) {
|
||||||
final size = mediaQuery.size;
|
final size = mediaQuery.size;
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ dependencies:
|
||||||
sign_in_with_apple: ^6.1.0
|
sign_in_with_apple: ^6.1.0
|
||||||
flutter_riverpod: ^2.5.1
|
flutter_riverpod: ^2.5.1
|
||||||
fpdart: ^1.1.0
|
fpdart: ^1.1.0
|
||||||
|
connectivity_plus: ^6.0.3
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue