以前总是没有经常写技术博客的习惯, 这样每次遇到问题, 甚至一些以前就遇到的问题, 还是要到处去找资料。另外,现在针对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         }



但是在运行的时候会报错:

android 获取的ssid是乱码 ssid显示乱码_编码格式

按照提示, 表示要新注册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);



大功告成!实测结果:

android 获取的ssid是乱码 ssid显示乱码_编码转换_02

 

P.S.: 我写的Demo程式,在运行的时候还遇到一个问题, 就是如果是运行在Win10的NB上 时候,并且wifi名称用日文(没有试过其他语言了)命名的时候, 程式显示的是一串类似于MD5码一样的字符, 此时无论如何转换也没有办法正常显示日文出来, 不是很了解原因, 但是如果是运行在我们公司在做那款机器上, 却是正常显示日文wifi名称的, 这个问题暂时没有去解(因为主要目的是解决在机器上的运行结果问题啊- -), 如果有看到的大神可以提供一下建议。

P.S.: 不是太经常写, 如果有看得不舒服的,欢迎指正, 以后的博客会改进, 谢谢!