以前总是没有经常写技术博客的习惯, 这样每次遇到问题, 甚至一些以前就遇到的问题, 还是要到处去找资料。另外,现在针对UWP编程方面的知识总结博客也不是那么丰富,对许多新的技术更是少得可怜, 有时候没有办法只能自己独自摸索。
最近公司在做一个案子,是Win10的一个平板方面的应用, 里面涉及到网络连接的问题, 先贴上wifi扫描部分的代码:
1 //接口 2 //初始化Adapter 3 public void Init() 4 { 5 WiFiAdapter.FindAllAdaptersAsync().AsTask().ContinueWith(antecedent => 6 { 7 if (antecedent.Result.Count >= 1) 8 { 9 _firstAdapter = antecedent.Result[0]; 10 DoCoMoSystem.WriteLog(_firstAdapter.NetworkAdapter.NetworkAdapterId.ToString()); 11 } 12 else 13 { 14 OnError(this, "NoWiFiAdapter"); 15 } 16 }); 17 }
1 //获取所有连接 2 public async void GetAll() 3 { 4 if (_firstAdapter == null) return; 5 try 6 { 7 await _firstAdapter.ScanAsync(); 8 } 9 catch (Exception ex) 10 { 11 DoCoMoSystem.WriteLog("wifi scan exception..." + ex); 12 List_list = new List (); 13 14 if (OnGetAvailableNetworks != null) 15 OnGetAvailableNetworks(this, new AvailableNetworksEventArgs(_list)); 16 return; 17 } 18 19 List list = await getWiFiInfoList(); 20 if (list == null) return; 21 22 if (OnGetAvailableNetworks != null) 23 OnGetAvailableNetworks(this, new AvailableNetworksEventArgs(list)); 24 25 }
1 //获取所有wifiinfo的列表 2 private async Task> getWiFiInfoList() 3 { 4 try 5 { 6 string connectedSsid = await getConnectedSsid(); 7 List
wifilist = new List (); 8 DoCoMoSystem.WriteLog("Connected WiFi is " + connectedSsid); 9 WiFiInfo connectedWifi = null; 10 foreach (WiFiAvailableNetwork nt in _firstAdapter.NetworkReport.AvailableNetworks) 11 { 12 if (nt.Ssid == "") 13 { 14 DoCoMoSystem.WriteLog("Discover a empty string wifi..."); 15 continue; 16 } 17 WiFiInfo info = new WiFiInfo(); 18 info.BeaconInterval = nt.BeaconInterval; 19 info.Bssid = nt.Bssid; 20 info.ChannelCenterFrequencyInKilohertz = nt.ChannelCenterFrequencyInKilohertz; 21 info.IsWiFiDirect = nt.IsWiFiDirect; 22 info.PhyKind = nt.PhyKind; 23 info.Ssid = nt.Ssid; 24 info.SignalBars = nt.SignalBars; 25 info.NetworkKind = nt.NetworkKind; 26 info.NetworkRssiInDecibelMilliwatts = nt.NetworkRssiInDecibelMilliwatts; 27 info.Uptime = nt.Uptime; 28 if (nt.SecuritySettings.NetworkAuthenticationType == NetworkAuthenticationType.Open80211 && 29 nt.SecuritySettings.NetworkEncryptionType == NetworkEncryptionType.None) 30 { 31 info.IsSecurity = false; 32 } 33 else 34 { 35 info.IsSecurity = true; 36 } 37 if (connectedSsid != null && nt.Ssid == connectedSsid) 38 { 39 info.IsConnected = true; 40 Ssid = connectedSsid; 41 _state = WiFiStatus.CONNECTED; 42 connectedWifi = info; 43 } 44 else 45 { 46 info.IsConnected = false; 47 wifilist.Add(info); 48 } 49 } 50 51 wifilist.Sort(SortBySignalStrenth); 52 if (connectedWifi != null) 53 wifilist.Insert(0, connectedWifi); 54 55 return wifilist; 56 } 57 catch (Exception ex) 58 { 59 if (OnError != null) 60 OnError(this, "WIFIGETWIFIEXCEPTION"); 61 DoCoMoSystem.WriteLog("DCMWiFi.getWiFiInfoList exception." + ex.Message); 62 } 63 return null; 64 }
上面加背景部分的代码是获取wifi AP的名称, 如果直接获取并在界面上去显示的话,如果AP名称中包含中文名字的话, 会显示乱码, 一开始接到这个问题反馈的时候,也认为这个肯定是编码方面的问题嘛, 应该不难解决, 以前即使没有认真对待这个问题, 但是应该也是遇到过的, 解决起来应该不成问题, 可悲催的是, 网上搜了一大圈, 居然都没有正确的解决方法, 要不就是方法无法在UWP上使用, 这么一个问题居然困扰了我一整天, 仍然解决不了。
后来还是将抓取到的乱码名称copy到notepad++中, 然后用不同的编码格式去转换, 才发现, 原始的SSID编码格式是ANSI, 而如果用UTF-8去重新编码的话, 中文名称也就正常显示了, Okay,至少知道解决方法的算法应该是什么了: 如何将ANSI编码格式转换为UTF-8编码格式。
System.Text.Encoding类用于编码转换,查询资料知道ANSI编码格式,对应Encoding.Default编码格式, 但是这个枚举类型在UWP中不可用, 但是有提供一个方法Encoding.GetEncoding(int codepage)用于手动添加编码格式(语言编码表可以参见链接:https://msdn.microsoft.com/zh-cn/library/86hf4sb8(v=vs.80).aspx), 但其实Encoding.Default对应的值是0, 所以采用方法Encoding.GetEncoding(0)来获取ANSI的编码格式。
所以编码转换方法写成:
1 ///2 /// 编码转换,解决SSID乱码问题 3 /// 4 /// 5 /// 6 private string convertSSID(string ssid_src) 7 { 8 var encoding = Encoding.GetEncoding(0); 9 var bytes = encoding.GetBytes(ssid_src); 10 string ssid_dst = Encoding.UTF8.GetString(bytes); 11 return ssid_dst; 12 }
但是在运行的时候会报错:
按照提示, 表示要新注册encoding类型的话, 需要乃至Encoding.RegisterProvider这个方法, 在这篇文章中(http://www.cnblogs.com/artech/p/encoding-registeration-4-net-core.html)查询到这个方法的调用方法:
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
这样, 编码转换方法即改为:
1 ///2 /// 编码转换,解决SSID乱码问题 3 /// 4 /// 5 /// 6 private string convertSSID(string ssid_src) 7 { 8 Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); 9 var encoding = Encoding.GetEncoding(0); 10 var bytes = encoding.GetBytes(ssid_src); 11 string ssid_dst = Encoding.UTF8.GetString(bytes); 12 return ssid_dst; 13 }
回到上面的private async Task> getWiFiInfoList()方法, 在保存SSID处改为:
info.Ssid = convertSSID(nt.Ssid);
大功告成!实测结果:
P.S.: 我写的Demo程式,在运行的时候还遇到一个问题, 就是如果是运行在Win10的NB上 时候,并且wifi名称用日文(没有试过其他语言了)命名的时候, 程式显示的是一串类似于MD5码一样的字符, 此时无论如何转换也没有办法正常显示日文出来, 不是很了解原因, 但是如果是运行在我们公司在做那款机器上, 却是正常显示日文wifi名称的, 这个问题暂时没有去解(因为主要目的是解决在机器上的运行结果问题啊- -), 如果有看到的大神可以提供一下建议。
P.S.: 不是太经常写, 如果有看得不舒服的,欢迎指正, 以后的博客会改进, 谢谢!