ExposureNotification.Sample
ExposureNotification.Sample copied to clipboard
Android: StartAsync resolves too fast
When we run StartAsync method with bluetooth OFF it correctly shows us a dialog and after clicking ok it turns the BT on. However if we check status right after that with GetStatusAsync() it returns BluetoothOff as adapter haven't manage it to start fast enough. Because of that we need to start again so we see the dialog for the second time. I think the StartAsync should wait until adapter will be enabled and then resolve.
Issue observed on Xiaomi Redmi Note 8T with Android 9 and Huawei Mate 20 lite with Android 10
Update: I have investigated it further and I have found a differences in start method for Xamarin and android: android solution:
start()
.addOnSuccessListener(
unused -> {
})
.addOnFailureListener(
exception -> {
})
.addOnCanceledListener(() -> {});
Xamarin:
await StartAsync(); // returns only empty Task
So the android solution gives us more information here.
Also I have found a workaround for this issue: If we will create a BroadcastReceiver for bluetooth adapter ("android.bluetooth.adapter.action.STATE_CHANGED") and await for the bluetooth to turn on in OnActivityResult method before we will call ExposureNotification.OnActivityResult(requestCode, resultCode, data) it will work correctly.
My simplified workaround:
public static TaskCompletionSource<bool> AgBluetoothTaskCompletionSource;
public async void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
if (requestCode != EnApiRequestCode || resultCode != Result.Ok) return;
AgBluetoothTaskCompletionSource = new TaskCompletionSource<bool>();
if (BluetoothAdapter.DefaultAdapter != null
&& BluetoothAdapter.DefaultAdapter.IsEnabled)
{
AgBluetoothTaskCompletionSource.TrySetResult(true);
}
// Set timeout
Task.Run(async () =>
{
await Task.Delay(Timeout);
AgBluetoothTaskCompletionSource?.TrySetResult(BluetoothAdapter.DefaultAdapter != null
&& BluetoothAdapter.DefaultAdapter.IsEnabled);
});
await AgBluetoothTaskCompletionSource.Task;
ExposureNotification.OnActivityResult(requestCode, resultCode, data);
}
where AgBluetoothTaskCompletionSource is set to true in broadcast receiver when bluetooth is ON
@nc-kano I looked into this and I am not sure exactly why yours is returning too soon. Have you tested the code on Android and confirmed that it does actually wait?
Looking at our code, we also wait the Android task: https://github.com/xamarin/XamarinComponents/blob/master/XPlat/ExposureNotification/source/Xamarin.ExposureNotification/ExposureNotification.android.cs#L100
The chain from native code to the xplat is basically: start the Android task, convert it to a .NET task, await the .NET task. The only way for the .NET task to finish is to wait for the Android task to complete.
I'll do some tests with my device and see exactly what is happening. Maybe we missed something, maybe the Android SDK has an issue.
@mattleibow Thank you for the response. Yes, I have tested it. Until now it was tested on a wide variety of devices and on all it behaves in the similar way.
Our starting method is more or less like this:
public async Task<bool> StartBluetooth()
{
try
{
await Xamarin.ExposureNotifications.ExposureNotification.StartAsync();
}
catch (Exception e)
{
// Error handling
}
return (await Xamarin.ExposureNotifications.ExposureNotification.GetStatusAsync() == Status.Active);
}
And it always return false if bluetooth was turned off.
I hope you have time to look at this soon. We have this issue in production with half a million users.
Hi. So what is the general consensus on this app/library. Is it now stable enough to use in production?
I've been holding off on implementation until the debugging/refactoring has settled down, and it seems to have at this point.
Anyone using this in production?
@dlandi yes, we are using it in Denmark. Despite this issue with starting API is working fine.
@mattleibow xamarin sample application does not work at all as it is even not on a list of covid tracking apps. it is installed and enabled but android does not recognize it as covid tracking app and when we enable exposure notifications in the app there is no system dialog:
so it cannot be treated as a reference for starting of the app.
@mattleibow Thank you for the response. Yes, I have tested it. Until now it was tested on a wide variety of devices and on all it behaves in the similar way.
Our starting method is more or less like this:
public async Task<bool> StartBluetooth() { try { await Xamarin.ExposureNotifications.ExposureNotification.StartAsync(); } catch (Exception e) { // Error handling } return (await Xamarin.ExposureNotifications.ExposureNotification.GetStatusAsync() == Status.Active); }
And it always return false if bluetooth was turned off.
I have try this on Samsung A20 SC-02M and it doenot start the Exposure notification API
So do you confirm that there is a bug? No it will not start the EN Api before you accept the permission popup.
We would expect StartAsync to not resolve the task before it is in fact started and GetStatusAsync will return Status.Active.