I am programming an Android app, where users can connect to a bluetooth device. In order to do that, I initiate a bonding process, set the bonding pin and wait for the pairing to finish to initialize the connection.
If the user closes the app while the bonding process is running, I need to abort the process to prevent the mobile phone from connecting to the bluetooth device.
To start the bonding process, I use the following code:
BluetoothDevice.CreateBond();
For recognizing the status of the bonding process I register a broadcast receiver, which triggers on the "ActionBondStateChanged"-Intent:
BondStatusReceiver = new BondStatusBroadcastReceiver();
IntentFilter filter = new IntentFilter(BluetoothDevice.ActionBondStateChanged);
Platform.CurrentActivity.RegisterReceiver(BondStatusReceiver, filter);
Once the bonding process is started and the correct bonding pin is entered, I cannot stop the process of bonding and connecting to the device.
I have implemented a method, which is executed, when MainActivity.OnPause() is called or an app crash was observed. In it, I tried to manually unbond the device by executing
public void RemoveBond(Device device)
{
Java.Lang.Reflect.Method method = BluetoothDevice.Class.GetMethod("removeBond", null);
if(method != null)
{
Java.Lang.Object result = method.Invoke(BluetoothDevice, null);
}
}
This didn't stop my mobile phone from bonding and connecting to the mobile device.
Related
We've been trying to get iOS push notifications to work but it's been very inconsistent. We've created a test project with as little code as possible just to get notifications to work.
We decided to test with alert notifications since we couldn't even get that to work consistently.
This is what we've been doing in the FinishedLaunching method of the AppDelegate:
UNUserNotificationCenter.Current.Delegate = this;
var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
UNUserNotificationCenter.Current.RequestAuthorization(authOptions, (granted, error) =>
{
LogInformation("RequestAuthorization", $"Granted: {granted}, Error: {error}");
if (granted)
InvokeOnMainThread(UIApplication.SharedApplication.RegisterForRemoteNotifications);
});
And we log the registration token of the device in the console so that we can use that to send notifications.
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
LogInformation("RegisteredForRemoteNotifications", "init");
var token = ExtractToken(deviceToken);
LogInformation("RegisteredForRemoteNotifications", token);
}
That's basically all we have in the app for now.
We use the notification token in a test app to send notifications to that specific device.
These are our results:
Use case 1
Restart device
Send notification to device
Result: Notification shows up and all new notifications keep working too.
Use case 2
Restart device
Send notification to device
Result: Notification is not shown and no matter how often you send the notification, it won't be shown.
Use case 3
Restart device
Send notification to device
Notification is not shown.
Restart device
Result: Notification shows up and all new notifications keep working too.
Use case 4
Restart device
Start application once
Put app in background, or close it completely
Send notification to device
Result: Notification is shown and all new notifications keep working too.
So it looks like that once we receive 1 notification, all future notifications will work too up until the device is restarted.
After restarting the device, it's basically a coinflip: You either are lucky and receive a notification and all future notifications. Or you don't receive anything at all.
We want to receive notifications consistently and are trying to figure out how to get this done and we hope someone can shed some light into this matter.
Thanks in advance.
Notes
We're using a 6th gen iPad with iOS 13.5.1
iPad is WiFi only
We've got a stable WiFi and internet connection
I am Trying to run BluetoothLE code from Universal Windows Sample-->https://github.com/Microsoft/Windows-universal-samples
Initially the device gets paired successfully
But when i click the Connect button it shows error message "Device Unreachable"
I put a breakpoint at the starting of this code snippet and the result varible was not equal to GattCommunicationStatus.Success.
GattDeviceServicesResult result = await bluetoothLeDevice.GetGattServicesAsync(BluetoothCacheMode.Uncached);
gatt = (int)result.Status;
if (result.Status == GattCommunicationStatus.Success)
{
var services = result.Services;
rootPage.NotifyUser(String.Format("Found {0} services", services.Count), NotifyType.StatusMessage);
foreach (var service in services)
{
ServiceCollection.Add(new BluetoothLEAttributeDisplay(service));
}
ConnectButton.Visibility = Visibility.Collapsed;
ServiceList.Visibility = Visibility.Visible;
}
else
{
rootPage.NotifyUser("Device unreachable", NotifyType.ErrorMessage);
}
Please help
Thanks
I was struggling with exactly the same problem, but I think I've found the answer. From a post on the Microsoft Q&A website. I'm relatively inexperienced, so take my explanation with a pinch of salt, but this is my understanding of the problem:
It revolves around Bluetooth Low Energy (BLE) Privacy. To prevent the tracking of a user via the Bluetooth advertisements their smartphone is constantly emitting, the MAC address of the device is changed periodically; no more than every fifteen minutes. The randomised address is known as a Resolvable Random Private Address. For paired devices to be able to keep track of the device, a symmetric key called an Identity Resolving Key (IRK) is exchanged during pairing. This key can then be used to resolve the identity of the device from the random MAC addresses it is advertising.
Microsoft's implementation of BLE on Windows doesn't include all aspects of BLE Privacy. Specifically, it only supports Random Private Addresses while advertising. This means that, after you pair a device with a Windows PC, Windows doesn't randomise it's MAC address or provide the paired device with an Identity Resolving Key. Modern implementations of BLE, specifically on smartphones, seemingly do not allow connections with devices that don't implement Resolvable Random Private Addresses, such as Windows PCs. This could be because it is seen as suspicious behaviour.
Therefore, when using BLE to connect a Windows PC to another device, Android in my case, you can connect to the device and read the BLE services from the device while not paired. As soon as you pair the two devices however, the second device rejects the connection and the Windows device will always return "Device Unreachable" when trying to read the Gatt services.
This issue may be caused by your device or the Bluetooth environment, you can try to turn off your Bluetooth device then turn on it again on your devices to test it again. You can open and close the Bluetooth on your device Settings app => Devices => Bluetooth & other devices.
See the MSDN thread Problem with BluetoothLE code, GattCommunicationStatus.Success is not working
I'm using Windows.Devices API in a WinForms App on Windows 10. I'm connecting to a Bluetooth Barcode scanner. The connection works fine and I'm getting an Event when the connection has been established and also when the connection has been dropped (disconnected).
But when I change the battery in the scanner and the scanner re-connects to Windows I'm getting no Event.
My question now is: if there's any possibility to get an Event when the device re-connects over Bleutooth?
My need is to reconnect the socket to the device after the device has been reconnected over Bluetooth.
EDIT: Dear admins, this is not a WinForms issue. This issue even doesn't deal with UI at all. It's just an API issue with the Windows.Devices UWP API. Please stop suggesting changing the tags.
Thanks
Sven
Some Sample Code:
_device = await BluetoothDevice.FromBluetoothAddressAsync(decimalAddress);
_device.ConnectionStatusChanged += OnDeviceConnectionStatusChanged;
Event is called only on first connect and on disconnect of device:
private void OnDeviceConnectionStatusChanged(BluetoothDevice sender, object args)
{
}
What I've found out so far is that it seems very common that the event never raises again. One has to actively create a new connection to the device, that is, for example by opening a socket for receiving data.
So the solution for my problem was to connect to the bluetooth device by calling
StreamSocket.ConnectAsync()
again to establish a new connection. Afterwards the ConnectionStatusChanged is raised with state connected.
Good luck
Sven
I'm pretty new to Android programming that's why I need your advice.
Current Situation:
I built an Android application (C#) aswell as a regular Server application (C++) which runs on a Raspberry Pi. Both programs communicate via UDP. At the moment that the Server application receives a signal it sends out a broadcast message which the Android application is listening for. Everything works just fine to the moment that the Android device falls asleep/goes idle which leads to my question.
Question:
How can I accomplish that the Android applications' listener still works, when the device falls asleep? I do not expect any solutions but any kind of advice so I don't waste time with wrong approaches.
Research:
- I read about and tried services that will keep running in the background but the service also stopped as the device went to sleep.
- I read about Broadcast Receivers which allow the application/service to get further information of the system.
- I read about WAKELOCK which allows me to keep the CPU alive, but for my purpose it should be up 'all the time' and that would drain to much energy.
Code that I would like to run in the background:
public void AsyncReceive()
{
// ...
Task.Run(() =>
{
while (this.isActive)
{
byte[] buffer = new byte[1];
DatagramPacket incoming = new DatagramPacket(buffer,
buffer.Length);
try
{
sock.Receive(incoming);
}
catch (...)
{
// Exception handling goes here...
}
// Communicate with the Android application
this.FireBroadCastReceivedEvent();
}
});
}
Edit
I also need to notice the application about incoming messages (#the 'FireBroadCastReceivedEvent()' part of the code). What would be a good way to do that?
I think you must read this link : https://developer.android.com/training/run-background-service/index.html
Hope you find what are you looking for.
I have a device that responds async, on event that occurs on the device it sends a status over serial to the host.
So as mono does not have DataReceived event implemented i created a thread "PollRun" in which i have:
void PollRun(object param)
{
byte rcvResponse = 0x00;
_serialPort.ReadTimeout = System.IO.Ports.SerialPort.InfiniteTimeout;
while (true)
{
rcvResponse = _serialPort.ReadByte();
// SOME handle code...
}
}
The poll run works ok until some point... poll run is a separate thread in the application, but what it happens when i run this application after some inactivity time from the user (eg. no key press on the console app in the main thread....) it stops to work, like if the readByte blocks the whole application
Also no ctrl-c signal helps... I have to manually kill the process.
I'm using ubuntu 11.10 with mono 2.10.5
Is there any known issue with using infinite timeout ? What other way would you do this kind of reading where i must wait for event always?
Thank you!