以前总是没有经常写技术博客的习惯, 这样每次遇到问题, 甚至一些以前就遇到的问题, 还是要到处去找资料。另外,现在针对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<WiFiInfo> _list = new List<WiFiInfo>();
13
14 if (OnGetAvailableNetworks != null)
15 OnGetAvailableNetworks(this, new AvailableNetworksEventArgs(_list));
16 return;
17 }
18
19 List<WiFiInfo> 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<List<WiFiInfo>> getWiFiInfoList()
3 {
4 try
5 {
6 string connectedSsid = await getConnectedSsid();
7 List<WiFiInfo> wifilist = new List<WiFiInfo>();
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 /// <summary>
2 /// 编码转换,解决SSID乱码问题
3 /// </summary>
4 /// <param name="ssid_src"></param>
5 /// <returns></returns>
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这个方法, 在这篇文章中()查询到这个方法的调用方法:
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
这样, 编码转换方法即改为:
1 /// <summary>
2 /// 编码转换,解决SSID乱码问题
3 /// </summary>
4 /// <param name="ssid_src"></param>
5 /// <returns></returns>
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<List<WiFiInfo>> getWiFiInfoList()方法, 在保存SSID处改为:
info.Ssid = convertSSID(nt.Ssid);
大功告成!实测结果:
P.S.: 我写的Demo程式,在运行的时候还遇到一个问题, 就是如果是运行在Win10的NB上 时候,并且wifi名称用日文(没有试过其他语言了)命名的时候, 程式显示的是一串类似于MD5码一样的字符, 此时无论如何转换也没有办法正常显示日文出来, 不是很了解原因, 但是如果是运行在我们公司在做那款机器上, 却是正常显示日文wifi名称的, 这个问题暂时没有去解(因为主要目的是解决在机器上的运行结果问题啊- -), 如果有看到的大神可以提供一下建议。
P.S.: 不是太经常写, 如果有看得不舒服的,欢迎指正, 以后的博客会改进, 谢谢!