// this will be called when a potential exposure has been detected public async Task ExposureDetectedAsync(ExposureDetectionSummary summary, Func <Task <IEnumerable <ExposureInfo> > > getExposureInfo) { userData.ExposureSummary = summary; var exposureInfo = await getExposureInfo(); // Add these on main thread in case the UI is visible so it can update await Device.InvokeOnMainThreadAsync(() => { foreach (var i in exposureInfo) { userData.ExposureInformation.Add(i); } }); await userDataService.SetAsync(userData); // If Enabled Local Notifications if (userData.IsNotificationEnabled) { var notification = new NotificationRequest { NotificationId = 100, Title = "Possible COVID-19 Exposure", Description = "It is possible you have been exposed to someone who was a confirmed diagnosis of COVID-19. Tap for more details." }; NotificationCenter.Current.Show(notification); } }
// this will be called when a potential exposure has been detected public async Task ExposureDetectedAsync(ExposureDetectionSummary summary, Func <Task <IEnumerable <ExposureInfo> > > getExposureInfo) { UserExposureSummary userExposureSummary = new UserExposureSummary(summary.DaysSinceLastExposure, summary.MatchedKeyCount, summary.HighestRiskScore, summary.AttenuationDurations, summary.SummationRiskScore); userData.ExposureSummary = userExposureSummary; var exposureInfo = await getExposureInfo(); // Add these on main thread in case the UI is visible so it can update await Device.InvokeOnMainThreadAsync(() => { foreach (var exposure in exposureInfo) { Console.WriteLine($"COCOA found exposure {exposure.Timestamp}"); UserExposureInfo userExposureInfo = new UserExposureInfo(exposure.Timestamp, exposure.Duration, exposure.AttenuationValue, exposure.TotalRiskScore, (Covid19Radar.Model.UserRiskLevel)exposure.TransmissionRiskLevel); userData.ExposureInformation.Add(userExposureInfo); } }); await userDataService.SetAsync(userData); // If Enabled Local Notifications //if (userData.IsNotificationEnabled) //{ // var notification = new NotificationRequest // { // NotificationId = 100, // Title = AppResources.LocalNotificationTitle, // Description = AppResources.LocalNotificationDescription // }; // NotificationCenter.Current.Show(notification); //} }
// this will be called when a potential exposure has been detected public async Task ExposureDetectedAsync(ExposureDetectionSummary summary, Func <Task <IEnumerable <ExposureInfo> > > getExposureInfo) { userData.ExposureSummary = summary; var exposureInfo = await getExposureInfo(); // Add these on main thread in case the UI is visible so it can update await Device.InvokeOnMainThreadAsync(() => { foreach (var i in exposureInfo) { userData.ExposureInformation.Add(i); } }); await userDataService.SetAsync(userData); // If Enabled Local Notifications if (userData.IsNotificationEnabled) { var notification = new NotificationRequest { NotificationId = 100, Title = AppResources.LocalNotificationTitle, Description = AppResources.LocalNotificationDescription }; NotificationCenter.Current.Show(notification); } }
private async Task DisabledAsync() { userData.IsExposureNotificationEnabled = false; await userDataService.SetAsync(userData); await UpdateStatusMessage(); }
/* * public async Task TestDownloadBatch() * { * long sinceEpochSeconds = new DateTimeOffset(DateTime.UtcNow.AddDays(-14)).ToUnixTimeSeconds(); * TemporaryExposureKeysResult tekResult = await httpDataService.GetTemporaryExposureKeys(sinceEpochSeconds); * Console.WriteLine("Fetch Exposure Key"); * * foreach (var keys in tekResult.Keys) * { * Console.WriteLine(keys.Url); * } * * } * * public bool GetOptInStatus() * { * return userData.IsOptined; * } */ /* * public async Task SetOptinStatusAsync(bool flg) * { * userData.IsOptined = flg; * await userDataService.SetAsync(userData); * } * public bool GetOptInStatus() * { * return userData.IsOptined; * } * * * public async Task SetExposureNotificationStatusAsync(bool flg) * { * userData.IsExposureNotificationEnabled = flg; * await userDataService.SetAsync(userData); * } * public bool GetExposureNotificationStatus() * { * return userData.IsExposureNotificationEnabled; * } * * public async Task SetNotificationStatusAsync(bool flg) * { * userData.IsNotificationEnabled = flg; * await userDataService.SetAsync(userData); * } * public bool GetNotificationStatus() * { * return userData.IsNotificationEnabled; * } */ public async Task <bool> StartExposureNotification() { if (!userData.IsOptined) { await UserDialogs.Instance.AlertAsync("利用規約に同意する必要があります。同意ページへ遷移します。"); await navigationService.NavigateAsync(nameof(PrivacyPolicyPage)); } Status status = await ExposureNotification.GetStatusAsync(); if (status == Status.BluetoothOff // || status == Status.Restricted || status == Status.NotAuthorized) { await UserDialogs.Instance.AlertAsync(GetStatusMessage(status)); userData.IsExposureNotificationEnabled = false; await userDataService.SetAsync(userData); return(false); } // bool IsEnabled = await ExposureNotification.IsEnabledAsync(); if (userData.IsOptined && userData.IsExposureNotificationEnabled && (status == Status.Unknown || status == Status.Active || status == Status.Disabled)) { try { await ExposureNotification.StartAsync(); } catch (Exception) { userData.IsExposureNotificationEnabled = false; await userDataService.SetAsync(userData); return(false); } } return(true); }
public async Task <bool> StartExposureNotification() { /* * if (!userData.IsOptined) * { * await UserDialogs.Instance.AlertAsync("利用規約に同意する必要があります。同意ページへ遷移します。"); * await navigationService.NavigateAsync(nameof(PrivacyPolicyPage)); * } */ try { await ExposureNotification.StartAsync(); var count = 0; while (true) { Thread.Sleep(1000); await ExposureNotification.StartAsync(); Status status = await ExposureNotification.GetStatusAsync(); if (status == Status.Active) { return(true); } else if (status == Status.BluetoothOff) { await UserDialogs.Instance.AlertAsync(GetStatusMessage()); return(true); } else { if (count > 2) { throw new Exception(); } count++; } } } catch (Exception) { userData.IsExposureNotificationEnabled = false; await userDataService.SetAsync(userData); return(false); } /* * ExposureNotificationStatus = await ExposureNotification.GetStatusAsync(); * if (ExposureNotificationStatus == Status.BluetoothOff * // || ExposureNotificationStatus == Status.Restricted || ExposureNotificationStatus == Status.NotAuthorized) ||{ || await UserDialogs.Instance.AlertAsync(GetStatusMessage()); || userData.IsExposureNotificationEnabled = false; || await userDataService.SetAsync(userData); || return false; ||} || ||if (userData.IsOptined && userData.IsExposureNotificationEnabled && (ExposureNotificationStatus == Status.Unknown || ExposureNotificationStatus == Status.Active || ExposureNotificationStatus == Status.Disabled)) ||{ || try || { || await ExposureNotification.StartAsync(); || || } || catch (Exception) || { || userData.IsExposureNotificationEnabled = false; || await userDataService.SetAsync(userData); || return false; || } ||} ||return true; */ }
// this will be called when they keys need to be collected from the server public async Task FetchExposureKeyBatchFilesFromServerAsync(Func <IEnumerable <string>, Task> submitBatches) { // This is "default" by default var rightNow = DateTimeOffset.UtcNow; try { foreach (var serverRegion in userData.ServerBatchNumbers.ToArray()) { // Find next directory to start checking var dirNumber = serverRegion.Value + 1; // For all the directories while (true) { // Download all the files for this directory var(batchNumber, downloadedFiles) = await DownloadBatchAsync(serverRegion.Key, dirNumber); if (batchNumber == 0) { break; } // Process the current directory, if there were any files if (downloadedFiles.Count > 0) { await submitBatches(downloadedFiles); // delete all temporary files foreach (var file in downloadedFiles) { try { File.Delete(file); } catch { // no-op } } } // Update the preferences userData.ServerBatchNumbers[serverRegion.Key] = dirNumber; await userDataService.SetAsync(userData); dirNumber++; } } } catch (Exception ex) { // any expections, bail out and wait for the next time // TODO: log the error on some server! Console.WriteLine(ex); } async Task <(int, List <string>)> DownloadBatchAsync(string region, ulong dirNumber) { var downloadedFiles = new List <string>(); var batchNumber = 0; // For all the batches in a directory while (true) { // TODO Implement httpdata service // Build the blob storage url for the given batch file we are on next var url = $"{apiUrlBlobStorageBase}/{blobStorageContainerNamePrefix}{region.ToLowerInvariant()}/{dirNumber}/{batchNumber + 1}.dat"; var response = await http.GetAsync(url); // If we get a 404, there are no newer batch files available to download if (response.StatusCode == System.Net.HttpStatusCode.NotFound) { break; } response.EnsureSuccessStatusCode(); // Skip batch files which are older than 14 days if (response.Content.Headers.LastModified.HasValue && response.Content.Headers.LastModified < rightNow.AddDays(-14)) { // If the first one is too old, the fake download it and pretend there was only one // We can do this because each batch was created at the same time batchNumber++; break; } var tmpFile = Path.Combine(FileSystem.CacheDirectory, Guid.NewGuid().ToString() + ".zip"); // Read the batch file stream into a temporary file using var responseStream = await response.Content.ReadAsStreamAsync(); using var fileStream = File.Create(tmpFile); await responseStream.CopyToAsync(fileStream); downloadedFiles.Add(tmpFile); batchNumber++; } return(batchNumber, downloadedFiles); } }