// Call this when the app needs to update the local keys
        public static async Task <bool> UpdateKeysFromServer(CancellationToken cancellationToken = default)
        {
            var processedAnyFiles = false;

            await Handler?.FetchExposureKeyBatchFilesFromServerAsync(async downloadedFiles =>
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (!downloadedFiles.Any())
                {
                    return;
                }

                if (nativeImplementation != null)
                {
                    var r = await nativeImplementation.DetectExposuresAsync(downloadedFiles);

                    var hasMatches = (r.summary?.MatchedKeyCount ?? 0) > 0;

                    if (hasMatches)
                    {
                        await Handler.ExposureDetectedAsync(r.summary, r.getInfo);
                    }
                }
                else
                {
#if __IOS__
                    // On iOS we need to check this ourselves and invoke the handler
                    var(summary, info) = await PlatformDetectExposuresAsync(downloadedFiles, cancellationToken);

                    // Check that the summary has any matches before notifying the callback
                    if (summary?.MatchedKeyCount > 0)
                    {
                        await Handler.ExposureDetectedAsync(summary, info);
                    }
#elif __ANDROID__
                    // on Android this will happen in the broadcast receiver
                    await PlatformDetectExposuresAsync(downloadedFiles, cancellationToken);
#endif
                }

                processedAnyFiles = true;
            }, cancellationToken);

            return(processedAnyFiles);
        }
        // Call this when the app needs to update the local keys
        public static async Task <bool> UpdateKeysFromServer()
        {
            using var batches = new TemporaryExposureKeyBatches();

            await Handler?.FetchExposureKeysFromServerAsync(batches);

            if (!batches.Files.Any())
            {
                return(false);
            }

            if (nativeImplementation != null)
            {
                var r = await nativeImplementation.DetectExposuresAsync(batches);

                var hasMatches = (r.summary?.MatchedKeyCount ?? 0) > 0;

                if (hasMatches)
                {
                    await Handler.ExposureDetectedAsync(r.summary, r.info);
                }

                return(true);
            }

#if __IOS__
            // On iOS we need to check this ourselves and invoke the handler
            var(summary, info) = await PlatformDetectExposuresAsync(batches.Files);

            // Check that the summary has any matches before notifying the callback
            if (summary?.MatchedKeyCount > 0)
            {
                await Handler.ExposureDetectedAsync(summary, info);
            }
#elif __ANDROID__
            // on Android this will happen in the broadcast receiver
            await PlatformDetectExposuresAsync(batches.Files);
#endif

            return(true);
        }