// 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);
            }
        }
예제 #2
0
        // 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);
            //}
        }
예제 #3
0
        // 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);
            }
        }
예제 #4
0
        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);
        }
예제 #6
0
        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);
            }
        }