protected override async Task InitializeAsync() { await base.InitializeAsync(); // BLE requires location permissions if (await SensusServiceHelper.Get().ObtainPermissionAsync(Permission.Location) != PermissionStatus.Granted) { // throw standard exception instead of NotSupportedException, since the user might decide to enable location in the future // and we'd like the probe to be restarted at that time. string error = "Geolocation is not permitted on this device. Cannot start Bluetooth probe."; await SensusServiceHelper.Get().FlashNotificationAsync(error); throw new Exception(error); } _deviceIdCharacteristic = new BluetoothGattCharacteristic(UUID.FromString(DEVICE_ID_CHARACTERISTIC_UUID), GattProperty.Read, GattPermission.Read); _deviceIdCharacteristic.SetValue(Encoding.UTF8.GetBytes(SensusServiceHelper.Get().DeviceId)); _deviceIdService = new BluetoothGattService(UUID.FromString(Protocol.Id), GattServiceType.Primary); _deviceIdService.AddCharacteristic(_deviceIdCharacteristic); _bluetoothAdvertiserCallback = new AndroidBluetoothServerAdvertisingCallback(_deviceIdService, _deviceIdCharacteristic); if (ScanMode.HasFlag(BluetoothScanModes.Classic)) { _bluetoothBroadcastReceiver = new AndroidBluetoothDeviceReceiver(this); IntentFilter intentFilter = new IntentFilter(); intentFilter.AddAction(BluetoothDevice.ActionFound); Application.Context.RegisterReceiver(_bluetoothBroadcastReceiver, intentFilter); } }
protected override async Task ScanAsync(CancellationToken cancellationToken) { // start a scan if bluetooth is present and enabled if (BluetoothAdapter.DefaultAdapter?.IsEnabled ?? false) { try { if (ScanMode.HasFlag(BluetoothScanModes.LE)) { List <ScanFilter> scanFilters = new List <ScanFilter>(); if (DiscoverAll == false) { ScanFilter scanFilter = new ScanFilter.Builder() .SetServiceUuid(new ParcelUuid(_deviceIdService.Uuid)) .Build(); scanFilters.Add(scanFilter); } ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder() .SetScanMode(global::Android.Bluetooth.LE.ScanMode.Balanced); // return batched scan results periodically if supported on the BLE chip if (BluetoothAdapter.DefaultAdapter.IsOffloadedScanBatchingSupported) { scanSettingsBuilder.SetReportDelay((long)(ScanDurationMS / 2.0)); } // start a fresh manager delegate to collect/read results _bluetoothScannerCallback = new AndroidBluetoothClientScannerCallback(_deviceIdService, _deviceIdCharacteristic, this); BluetoothAdapter.DefaultAdapter.BluetoothLeScanner.StartScan(scanFilters, scanSettingsBuilder.Build(), _bluetoothScannerCallback); } if (ScanMode.HasFlag(BluetoothScanModes.Classic)) { BluetoothAdapter.DefaultAdapter.StartDiscovery(); } TaskCompletionSource <bool> scanCompletionSource = new TaskCompletionSource <bool>(); cancellationToken.Register(() => { try { if (ScanMode.HasFlag(BluetoothScanModes.LE)) { BluetoothAdapter.DefaultAdapter.BluetoothLeScanner.StopScan(_bluetoothScannerCallback); } else if (ScanMode.HasFlag(BluetoothScanModes.Classic) && BluetoothAdapter.DefaultAdapter.IsDiscovering) { BluetoothAdapter.DefaultAdapter.CancelDiscovery(); } } catch (Exception ex) { SensusServiceHelper.Get().Logger.Log("Exception while stopping scan: " + ex.Message, LoggingLevel.Normal, GetType()); } finally { scanCompletionSource.TrySetResult(true); } }); await scanCompletionSource.Task; } catch (Exception ex) { SensusServiceHelper.Get().Logger.Log("Exception while scanning: " + ex.Message, LoggingLevel.Normal, GetType()); } } }