以前總是沒有經常寫技術博客的習慣, 這樣每次遇到問題, 甚至一些以前就遇到的問題, 還是要到處去找資料。另外,現在針對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這個方法, 在這篇文章中(http://www.cnblogs.com/artech/p/encoding-registeration-4-net-core.html)查詢到這個方法的調用方法:
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.: 不是太經常寫, 如果有看得不舒服的,歡迎指正, 以后的博客會改進, 謝謝!