If I have a Android phone which is already connected with a bluetooth headset (paired and connected) to it.
How I can get information about that specific headset.
Using getBondedDevices() method I get list of all paired devices..I need information about CONNECTED device only.
I can not wait for broadcast receiver to check status, because I need this information at the start of my application. So please suggest is there any way to get this information without waiting for broadcast.
You can do this through the IBluetoothA2dp interface in API 11 and up. Some more info on there is here: Android connect to a paired bluetooth headset
Here is a great resource to see the difference in what is available to this interface between API 10 and 11 where it changed quite a bit.
http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/bluetooth/BluetoothA2dp.java/?v=diff&id2=2.2_r1.1
Hope that helps.
You can use the getConnectedDevices for the HEADSET Profile to get the device to which it is connected.
Check this out to see if headset is connected (ICS only):
public boolean isVoiceConnected()
{
boolean retval = true;
try {
retval = BluetoothAdapter.getDefaultAdapter().getProfileConnectionState(android.bluetooth.BluetoothProfile.HEADSET) != android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
} catch (Exception exc) {
// nothing to do
}
return retval;
}
Related
Android 10 released support for BLE CoC connection so I wanted to try this out by making two simple android 10 apps, which would connect to each other with l2Cap and exchange "Hello World".
I wrote two apps, Server app and Client app, both having all permissions they need in their manifest files, and I run that apps on two Android 10 phones, and the connection was not established.
Here is the relevant part of my server app code:
try {
mServerSocket = bluetoothAdapter.listenUsingInsecureL2capChannel();
int psm = mServerSocket.getPsm();
} catch (IOException e) {
e.printStackTrace();
}
BluetoothSocket socket = mmServerSocket.accept();
Variable int psm is the PSM value I am using in client app.
Here is the relevant part of my client app code:
for (BluetoothDevice bluetoothDevice : deviceSet) {
if (!bluetoothDevice.getName().equals(PAIRED_DEVICE_NAME)) continue;
BluetoothDevice bd = adapter.getRemoteDevice(bluetoothDevice.getAddress());
bluetoothSocket = bd.createInsecureL2capChannel(psm_value);
break;
}
bluetoothSocket.connect();
where the string PAIRED_DEVICE_NAME is name of expected device, which is successfully found because devices are Bluetooth paired.
Int psm_value is the PSM value from server app. I suspect this might be a problem because I hard-coded this value from Server every time I tried to test this (every time was different value because this value is dynamically assigned and it lasts until you close server socket).
So my question is how to get remote PSM value? And how to connect these devices, because if I am using RFCOMM connection, this code works perfectly.
With this code I am getting error in bluetoothSocket.connect() line from client app saying:
java.io.IOException: read failed, socket might closed or timeout, read ret: -1
Thanks!
I'm using Plugin.BLE to iterate a bluetooth device's services / characteristics / descriptors. When I find the descriptor I'm looking for, I try enabling notifications by writing 02-00 into the descriptor. This works for Android devices but on iOS, I get a an error:
Objective-C exception thrown. Name: NSInternalInconsistencyException Reason: Client Characteristic Configuration descriptors must be configured using setNotifyValue:forCharacteristic
The offending C# code looks like:
await descriptor.WriteAsync(new byte[2] { 02, 00 });
Is there a different way on iOS devices to enable notifications?
It is apparent that this is one of those platform specific issues that will have to be refactored out into an interface / platform-implementation pattern. So for the iOS version of the application, in order to do the above, I had to write against CoreBluetooth. Once you have your device / service / characteristic / client configuration descriptor, you call the following:
peripheral.SetNotifyValue(true, characteristic);
After setting that value, a callback is issued to the peripheral delegate:
public override void UpdatedCharacterteristicValue(CBPeripheral peripheral, CBCharacteristic characteristic, NSError error) { }
From there I was able to continue what I was doing before.
The BLE Peripheral Simulator app, combined with the Web Bluetooth Samples, is a tremendous resource for developers.
Once a device is paired, is there any way through Web Bluetooth to bypass the pairing screen and go straight to the app?
Yes, this is possible. Code Source. Not my code though.
// Selected device object cache
let deviceCache = null;
// Launch Bluetooth device chooser and connect to the selected
function connect() {
return (deviceCache ? Promise.resolve(deviceCache) :
requestBluetoothDevice())
.then(device => connectDeviceAndCacheCharacteristic(device))
.then(characteristic => startNotifications(characteristic))
.catch(error => log(error));
function requestBluetoothDevice() {
log('Requesting bluetooth device...');
return navigator.bluetooth.requestDevice({
filters: [{services: [myService]}],
})
.then(device => {
log('"' + device.name + '" bluetooth device selected');
deviceCache = device;
// Listen for disconnet event
deviceCache.addEventListener('gattserverdisconnected',
handleDisconnection);
return deviceCache;
});
}
Also, there is a way of reconnecting after site refresh, but it is not implemented yet
I recently implemented a new permissions backend as well as two APIs that will enable previously permitted Bluetooth devices to be used.
The new permissions backend is implemented behind the chrome://flags/#enable-web-bluetooth-new-permissions-backend. The new backend will persist device permissions granted through requestDevice() until the permission is reset in Site Settings or the Page Info dialog box.
The getDevices() and watchAdvertisements() are implemented behind the chrome://flags/#enable-experimental-web-platform-features flag for Chrome 85.0.4165.0 or greater. The recommended use of these APIs is to use getDevices() to retrieve an array of permitted BluetoothDevices and then calling watchAdvertisements() on these devices to start a scan. When advertisement packets are detected from the devices, the advertisementreceived Event will be fired on the device that it corresponds to. At this point, the Bluetooth device is in range and can be connected to.
Please give this new feature a try, and file any bugs at https://crbug.com using the Blink>Bluetooth component.
I have previously paired with a Bluetooth device that supports RFCOMM.
When my app is opened I continuously try to connect to the device by opening the RFCOMM. This way my app automatically connects when the device comes in range.
deviceInfoCollection = await DeviceInformation.FindAllAsync(RfcommDeviceService.GetDeviceSelector(RfcommServiceId.SerialPort));
LogData(String.Format("Number of mldp devices is {0}", deviceInfoCollection.Count));
foreach (DeviceInformation deviceInfo in deviceInfoCollection)
{
LogData(String.Format("ID:{0}, NAME:{1}", deviceInfo.Id, deviceInfo.Name));
}
Then run this on a timer:
try
{
// The first time this method is invoked by a store app, it should be called
// from a UI thread in order to display the consent prompt
// https://msdn.microsoft.com/en-us/windows.devices.bluetooth.rfcomm.rfcommdeviceservice.fromidasync
RfcommDeviceService rfcommService = await RfcommDeviceService.FromIdAsync(deviceInfo.Id);
LogData(String.Format("ID:{0}, NAME:{1}", deviceInfo.Id, deviceInfo.Name));
}
catch (Exception)
{
LogData(String.Format("Can not request rfcomm service from device ID:{0}, NAME:{1}", deviceInfo.Id, deviceInfo.Name));
}
Is there any way to query when the device is in range , rather than trying to connect? I would prefer to only attempt connection when the device is in range.
For RFCOMM (BT2.0, BT2.1) you can run a device enumeration periodically, see also Get bluetooth devices in range
However your actual implementation with a connection attempt may work a little better.
For Bluetooth 4.0, you can listen to the advertisements of the BT module, see also https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/BluetoothAdvertisement
If you're talking to an embedded device (e.g. some robot, or homebrew appliances using RFCOMM) I am afraid there is no better solution than what you're doing.
If you're taking to a phone (which supports both BT4.0 and BT2.1) you can use the BT4 advertisements to signal the proximity of the device, then connect via RFCOMM.
I am trying to stream Audio to a bluetooth device in-code in C#. I've picked up the 32feet.net library to help with this. I am able to get a bluetooth speaker paired just fine, and then I use the code below to connect to the device.
globalClient.BeginConnect(device.DeviceAddress, BluetoothService.SerialPort, new AsyncCallback(BluetoothConnectedAsyncHandler), device);
Async Callback method:
private void BluetoothConnectedAsyncHandler(IAsyncResult result)
{
BluetoothDeviceInfo connectedDevice = (BluetoothDeviceInfo)result.AsyncState;
globalClient.EndConnect(result);
if (result.IsCompleted)
{
NetworkStream btStream = globalClient.GetStream();
}
}
This all works well, but when I try to set the service from BluetoothService.SerialPort to BluetoothService.AudioSource, then I receive a SocketException on the "globalClient.EndConnect(result);" line saying "A socket operation failed because the destination host was down". See screenshot:
I've also tried to throw data at the speaker through the NetworkStream when it is setup with BluetoothService.SerialPort, but it doesn't play anything - no noise or static.
My running hypothesis is that this can't be done easily with 32feet.net, and I would have to code up the a2dp spec in code. I think the 32feet.net library is used so that I can tell the Operating System to use the speaker as an output device, rather than control audio output in-code as a supported feature.
Please help! Has anyone done this?
Would it even work if I sent an a2dp compliant stream to the device over the BluetoothService.SerialPort connection?
A2DP spec: https://www.bluetooth.org/docman/handlers/DownloadDoc.ashx?doc_id=8236
Thanks for any help!
Update:
This isn't possible within the 32feet.net library, you can only set the device up to talk the the Microsoft audio service using the setService method call in 32feet.net
www.nudoq.org/#!/Packages/32feet.NET/InTheHand.Net.Personal/MicrosoftSdpService/M/SetService
This MS service manages the A2DP output to the device. There is no way to directly output audio from code into the Bluetooth Device using this library in C#.