From 9519e29b8fb04d6b76e226cbd8d8cf7a2a23848c Mon Sep 17 00:00:00 2001 From: hailin Date: Sat, 7 Mar 2026 09:43:04 -0800 Subject: [PATCH] feat(mobile/telemetry): collect real network type via connectivity_plus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- .../collectors/device_info_collector.dart | 40 ++++++++++++++++++- frontend/genex-mobile/pubspec.yaml | 1 + 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/frontend/genex-mobile/lib/core/telemetry/collectors/device_info_collector.dart b/frontend/genex-mobile/lib/core/telemetry/collectors/device_info_collector.dart index 927cd23..1d05828 100644 --- a/frontend/genex-mobile/lib/core/telemetry/collectors/device_info_collector.dart +++ b/frontend/genex-mobile/lib/core/telemetry/collectors/device_info_collector.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:device_info_plus/device_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/foundation.dart'; import '../models/device_context.dart'; @@ -25,6 +26,7 @@ class DeviceInfoCollector { final deviceInfo = DeviceInfoPlugin(); final packageInfo = await PackageInfo.fromPlatform(); final mediaQuery = MediaQuery.of(context); + final networkType = await _getNetworkType(); DeviceContext result; @@ -49,7 +51,7 @@ class DeviceInfoCollector { locale: Platform.localeName, timezone: DateTime.now().timeZoneName, isDarkMode: mediaQuery.platformBrightness == Brightness.dark, - networkType: 'unknown', // 需要额外的connectivity包 + networkType: networkType, collectedAt: DateTime.now(), ); } else if (Platform.isIOS) { @@ -73,7 +75,7 @@ class DeviceInfoCollector { locale: Platform.localeName, timezone: DateTime.now().timeZoneName, isDarkMode: mediaQuery.platformBrightness == Brightness.dark, - networkType: 'unknown', + networkType: networkType, collectedAt: DateTime.now(), ); } else { @@ -84,6 +86,40 @@ class DeviceInfoCollector { return result; } + /// 获取当前网络类型 + /// + /// 返回值:'wifi' | 'mobile_2g' | 'mobile_3g' | 'mobile_4g' | 'mobile_5g' | + /// 'ethernet' | 'vpn' | 'bluetooth' | 'none' | 'unknown' + Future _getNetworkType() async { + try { + final results = await Connectivity().checkConnectivity(); + // checkConnectivity 返回 List,取第一个主要连接 + 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) { final size = mediaQuery.size; diff --git a/frontend/genex-mobile/pubspec.yaml b/frontend/genex-mobile/pubspec.yaml index 5eab877..f08e30a 100644 --- a/frontend/genex-mobile/pubspec.yaml +++ b/frontend/genex-mobile/pubspec.yaml @@ -35,6 +35,7 @@ dependencies: sign_in_with_apple: ^6.1.0 flutter_riverpod: ^2.5.1 fpdart: ^1.1.0 + connectivity_plus: ^6.0.3 dev_dependencies: flutter_test: