在我的应用中,我需要在后台扫描Wi-Fi接入点。我能够启动任务并初始化Wi-Fi适配器,但是下一次异步调用“await scanner.ScanForNetworks()”执行扫描似乎永远不会完成任务。它可能是众多嵌套异步调用的结果吗?如果是这样,可能的解决办法是什么?
ScanningTask.cs
namespace BackgroundTaskLibrary
{
public sealed class ScanningTask : IBackgroundTask
{
private BackgroundTaskDeferral deferral;
private WiFiScanner scanner = new WiFiScanner();
private Windows.Storage.ApplicationDataContainer localSettings;
private DispatcherTimer timer;
public async void Run(IBackgroundTaskInstance taskInstance)
{
deferral = taskInstance.GetDeferral();
taskInstance.Canceled += TaskInstance_Canceled;
await scanner.InitializeFirstAdapter();
ShowToastNotification("Hi", "Hello from background"); //notification is shown
await scanner.ScanForNetworks();
ShowToastNotification("Hi", "Hello from background1"); //this one never gets shown
deferral.Complete();
}
private void TaskInstance_Canceled(IBackgroundTaskInstance sender,
BackgroundTaskCancellationReason reason)
{
deferral.Complete();
}
private void ShowToastNotification(string title, string stringContent)
{
ToastNotifier ToastNotifier = ToastNotificationManager.CreateToastNotifier();
Windows.Data.Xml.Dom.XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);
Windows.Data.Xml.Dom.XmlNodeList toastNodeList = toastXml.GetElementsByTagName("text");
toastNodeList.Item(0).AppendChild(toastXml.CreateTextNode(title));
toastNodeList.Item(1).AppendChild(toastXml.CreateTextNode(stringContent));
Windows.Data.Xml.Dom.IXmlNode toastNode = toastXml.SelectSingleNode("/toast");
Windows.Data.Xml.Dom.XmlElement audio = toastXml.CreateElement("audio");
audio.SetAttribute("src", "ms-winsoundevent:Notification.SMS");
ToastNotification toast = new ToastNotification(toastXml);
toast.ExpirationTime = DateTime.Now.AddSeconds(10);
ToastNotifier.Show(toast);
}
}
}
WiFiAdapter.cs
namespace BackgroundTaskLibrary
{
class WiFiScanner
{
//WiFi adapter instance
public WiFiAdapter WiFiAdapter { get; private set; }
public Geolocator _geolocator = new Geolocator();
public Geoposition Location { get; set; }
/// <summary>
/// Find the fisrts available WiFi adapter and initialise it
/// </summary>
/// <returns></returns>
public async Task InitializeFirstAdapter()
{
var access = await WiFiAdapter.RequestAccessAsync();
if (access != WiFiAccessStatus.Allowed)
{
throw new Exception("WiFiAccessStatus not allowed");
}
else
{
var wifiAdapterResults =
await DeviceInformation.FindAllAsync(WiFiAdapter.GetDeviceSelector());
if (wifiAdapterResults.Count >= 1)
{
this.WiFiAdapter =
await WiFiAdapter.FromIdAsync(wifiAdapterResults[0].Id);
}
else
{
var dialog = new MessageDialog("WiFi Adapter not found.");
await dialog.ShowAsync();
throw new Exception("WiFi Adapter not found.");
}
}
}
public async Task ScanForNetworks()
{
if (WiFiAdapter != null)
{
await WiFiAdapter.ScanAsync();
}
else
{
throw new Exception("No Wi-Fi adapter");
}
Location = await _geolocator.GetGeopositionAsync();
List<AccessPoint> accessPoints = new List<AccessPoint>();
foreach(var network in WiFiAdapter.NetworkReport.AvailableNetworks)
{
AccessPoint ap = new AccessPoint()
{
SSID = network.Ssid,
Mac = network.Bssid,
SignalStrength = network.NetworkRssiInDecibelMilliwatts,
Open = (int)network.SecuritySettings.NetworkAuthenticationType
};
accessPoints.Add(ap);
}
await SaveData(accessPoints);
}
public async Task SaveData(List<AccessPoint> accessPoints)
{
string info = DateTime.Now + "|" + Location.Coordinate.Point.Position.Latitude
+ "|" + Location.Coordinate.Point.Position.Longitude + "|";
for (int i = 0; i < accessPoints.Count; i++)
{
info += accessPoints[i].ToString();
}
info += Environment.NewLine;
// Get the logical root folder for all external storage devices.
StorageFolder externalDevices = Windows.Storage.KnownFolders.RemovableDevices;
// Get the first child folder, which represents the SD card.
StorageFolder sdCard = (await externalDevices.GetFoldersAsync()).FirstOrDefault();
StorageFile infoFile;
if (sdCard != null)
{
//check if info file exists
try
{
infoFile = await sdCard.GetFileAsync("wifiScanInfo.txt");
}
catch
{
infoFile = await sdCard.CreateFileAsync("wifiScanInfo.txt");
}
await FileIO.AppendTextAsync(infoFile, info);
}
}
}
}
如果您需要整个项目:https://www.dropbox.com/sh/1v9mbr3xhgr3283/AACDbB7skZUI7Z5fiu0HT8r4a?dl=0
编辑:
通过随后简化ScanningTask我能够确定,问题出在呼叫“await WiFiAdapter.ScanAsync();”
我终于设法从“等待WiFiAdapter.ScanAsync();”中捕获异常,这里是堆栈跟踪:
Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at BackgroundTaskLibrary.WiFiScanner.<ScanForNetworks>d__10.MoveNext()
然而,扫描已完成,结果将按预期保存在文本文件中。我可能缺少哪些权限?我已经声明了Internet,位置和可移动存储权限。
答案 0 :(得分:0)
它认为异常来自使用没有requestAccessAsync调用的GeoLocator:
在Windows 10中启动,在访问用户位置之前调用RequestAccessAsync。那时,您的应用必须位于前台,并且必须从UI线程调用RequestAccessAsync。在用户向您的位置授予您的应用权限之前,您的应用无法访问位置数据。