Xamarin安卓应用启用WiFi连接代码后启动即崩溃无日志问题
Xamarin Android WiFi功能启动崩溃问题排查
问题说明
我写了一段Xamarin Android代码,用来获取WiFi网络信息并连接指定WiFi。代码里有两段被注释的逻辑,取消注释启用后,应用启动直接崩溃,连日志都打不出来,加了try/catch也抓不到异常。我知道把逻辑塞MainActivity里是不良实践,但这只是学习测试用,而且已经在应用信息页面手动给了所有需要的权限。
AndroidManifest.xml 关键配置
<!-- 声明的权限 --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
MainActivity.cs 核心代码(含崩溃触发逻辑)
using Android.App; using Android.Content; using Android.Net.Wifi; using Android.OS; using Android.Runtime; using Android.Views; using Android.Widget; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace WifiTestApp { [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)] public class MainActivity : Activity { protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); Xamarin.Essentials.Platform.Init(this, savedInstanceState); SetContentView(Resource.Layout.activity_main); try { WifiManager wifiManager = (WifiManager)GetSystemService(WifiService); // 注释1:取消注释后触发崩溃的WiFi扫描逻辑 //List<ScanResult> scanResults = wifiManager.ScanResults.ToList(); //foreach (var result in scanResults) //{ // Console.WriteLine($"SSID: {result.Ssid}, RSSI: {result.Level}"); //} // 注释2:取消注释后触发崩溃的WiFi连接逻辑 //WifiConfiguration config = new WifiConfiguration(); //config.Ssid = "\"TestWiFi\""; //config.PreSharedKey = "\"TestPassword123\""; //int networkId = wifiManager.AddNetwork(config); //wifiManager.Disconnect(); //wifiManager.EnableNetwork(networkId, true); //wifiManager.Reconnect(); } catch (Exception ex) { Console.WriteLine($"Exception: {ex.Message}"); Toast.MakeText(this, ex.Message, ToastLength.Long).Show(); } } public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults) { Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults); base.OnRequestPermissionsResult(requestCode, permissions, grantResults); } } }
设备日志关键报错信息
从设备崩溃日志中提取到核心原因:
AndroidRuntime: FATAL EXCEPTION: main Process: WifiTestApp.WifiTestApp, PID: 18765 java.lang.SecurityException: WifiService: Neither user 10156 nor current process has android.permission.ACCESS_FINE_LOCATION.
解决办法
- 补全动态权限请求逻辑
Android 6.0(API 23)及以上,危险权限(如ACCESS_FINE_LOCATION)仅在Manifest声明+手动授予还不够,必须在代码中触发运行时权限检查。手动授予后系统可能未更新进程的权限状态,导致权限异常。修改MainActivity代码添加权限检查:
const int RequestLocationPermission = 0; string[] requiredPermissions = { Android.Manifest.Permission.AccessFineLocation }; protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); Xamarin.Essentials.Platform.Init(this, savedInstanceState); SetContentView(Resource.Layout.activity_main); // 先检查位置权限 if (CheckSelfPermission(Android.Manifest.Permission.AccessFineLocation) != Android.Content.PM.Permission.Granted) { RequestPermissions(requiredPermissions, RequestLocationPermission); return; } // 权限通过后执行WiFi逻辑 ExecuteWifiOperations(); } private void ExecuteWifiOperations() { try { WifiManager wifiManager = (WifiManager)GetSystemService(WifiService); // 启用WiFi扫描逻辑 List<ScanResult> scanResults = wifiManager.ScanResults.ToList(); foreach (var result in scanResults) { Console.WriteLine($"SSID: {result.Ssid}, RSSI: {result.Level}"); } // 启用WiFi连接逻辑 WifiConfiguration config = new WifiConfiguration(); config.Ssid = "\"TestWiFi\""; config.PreSharedKey = "\"TestPassword123\""; int networkId = wifiManager.AddNetwork(config); wifiManager.Disconnect(); wifiManager.EnableNetwork(networkId, true); wifiManager.Reconnect(); } catch (Exception ex) { Console.WriteLine($"Exception: {ex.Message}"); Toast.MakeText(this, ex.Message, ToastLength.Long).Show(); } } public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults) { base.OnRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == RequestLocationPermission) { if (grantResults.Length > 0 && grantResults[0] == Android.Content.PM.Permission.Granted) { // 权限授予后执行WiFi操作 ExecuteWifiOperations(); } else { Toast.MakeText(this, "必须授予位置权限才能获取WiFi信息", ToastLength.Long).Show(); } } }
- 检查设备位置服务状态
Android 8.0及以上版本,获取WiFi扫描结果不仅需要位置权限,还要求设备的位置服务处于开启状态。可以添加检查逻辑引导用户开启:
// 在ExecuteWifiOperations方法开头添加 LocationManager locationManager = (LocationManager)GetSystemService(LocationService); if (!locationManager.IsProviderEnabled(LocationManager.GpsProvider) && !locationManager.IsProviderEnabled(LocationManager.NetworkProvider)) { Intent openLocationSettings = new Intent(Android.Provider.Settings.ActionLocationSourceSettings); StartActivity(openLocationSettings); Toast.MakeText(this, "请开启位置服务以获取WiFi信息", ToastLength.Long).Show(); return; }
- 避免在OnCreate中直接执行敏感操作
即使是测试,也建议将WiFi扫描、连接逻辑放到异步线程或OnResume生命周期中执行,避免阻塞UI线程导致崩溃或ANR。
内容的提问来源于stack exchange,提问作者Éder Rocha
相关产品推荐
相关产品推荐

