Reputation: 2703
In my Xamarin.Forms app, I am writing native Android code to advertise a UUID and some test data for another device to scan and find it. I am running the app on tablet SM-T580. Here is my code:
var parameters = (new AdvertiseSettings.Builder())
.SetAdvertiseMode(AdvertiseMode.Balanced)
.SetConnectable(false)
.SetTimeout(0)
.SetTxPowerLevel(AdvertiseTx.PowerMedium).Build();
AdvertiseData data = (new AdvertiseData.Builder()).AddServiceData(_applicationParcelUuid,
System.Text.Encoding.ASCII.GetBytes("helloTest123"))
.Build();
if (BluetoothAdapter.DefaultAdapter.BluetoothLeAdvertiser != null)
{
BluetoothAdapter.DefaultAdapter.BluetoothLeAdvertiser.StartAdvertising(parameters, data, _customAvertiseCallback);
}
In my _customAvertiseCallback
the OnStartSuccess
override gets called, so I think it should work. I try testing it by using the nRF Connect app on a Nexus 5 device, but I never see my device's advertisement on it.
EDIT
I tried to add code that scans for BLE advertisement to see if I can pick it up myself. It finds other BLE advertisements from other devices, but not from my app. Here is my code for scanning, it's running on the same app:
public void StartBluetoothScanning()
{
if(_bleScanningInitialized)
{
return;
}
/**
* Initialize BluetoothAdapter
* Check the device has the hardware feature BLE
* Then enable the hardware,
*/
BluetoothManager bluetoothManager = (BluetoothManager)GetSystemService(Java.Lang.Class.FromType(typeof(BluetoothManager)));
var bluetoothAdapter = bluetoothManager.Adapter;
bool isBleSupported = bluetoothAdapter != null && this.BaseContext.PackageManager.HasSystemFeature(PackageManager.FeatureBluetoothLe);
if(!isBleSupported)
{
return;
}
/**
* Register GATT update receiver
*/
this.RegisterReceiver(_gattUpdateReceiver, new IntentFilter(BluetoothAdapter.ActionStateChanged));
/**
* Initialize Bluetooth service.
*/
Intent gattServiceIntent = new Intent(BaseContext, typeof(BluetoothGattService));
var componentName = BaseContext.StartService(gattServiceIntent);
bool isBind = BaseContext.BindService(gattServiceIntent, _serviceConnection, Bind.AutoCreate);
/**
* Prepare for scanning
*/
List<ScanFilter> scanFilters = new List<ScanFilter>();
ScanFilter.Builder scanFilterBuilder = new ScanFilter.Builder();
//scanFilterBuilder.SetServiceUuid(_applicationParcelUuid);
scanFilters.Add(scanFilterBuilder.Build());
ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder();
scanSettingsBuilder.SetScanMode(Android.Bluetooth.LE.ScanMode.Balanced);
if (!bluetoothAdapter.IsEnabled)
{
bluetoothAdapter.Enable();
}
if (BluetoothAdapter.DefaultAdapter.BluetoothLeScanner != null)
{
BluetoothAdapter.DefaultAdapter.BluetoothLeScanner.StartScan(scanFilters, scanSettingsBuilder.Build(), _customScanCallback);
_bleScanningInitialized = true;
}
else
{
if (ContextCompat.CheckSelfPermission(ApplicationContext,
Android.Manifest.Permission.AccessFineLocation) != Permission.Granted)
{
}
}
}
public class CustomScanCallback : ScanCallback
{
public override void OnScanResult([GeneratedEnum] ScanCallbackType callbackType, ScanResult result)
{
base.OnScanResult(callbackType, result);
if (result.ScanRecord.ServiceUuids != null)
{
foreach (var x in result.ScanRecord.ServiceUuids)
{
var id = x.Uuid.ToString();
// never true
if(id == _applicationGuid)
{
// Found my advertisement,
}
}
}
}
public override void OnScanFailed([GeneratedEnum] ScanFailure errorCode)
{
// never gets called
base.OnScanFailed(errorCode);
}
}
Upvotes: 2
Views: 2077
Reputation: 2703
Finally found the problem: AddServiceData
should be AddServiceUuid
so I can find it in result.ScanRecord.ServiceUuids
of the scan callback. Also, for anyone else who didn't know, Android 8.0 is required for Bluetooth 5.0, which has the increased data capacity for advertising:
https://source.android.com/devices/bluetooth/ble_advertising
Your device also needs to support Bluetooth 5.0. My SM-T580 does not.
With older versions of bluetooth, you can not advertise more than 1 UUID, or a maximum user payload of 29 bytes.
Upvotes: 5