I am building a bluetooth service discovery on Android using BluetoohDevice.fetchUuidsWithSdp().
Currently i test the code on 3 different devices:
devices "A" and "B" running Android 8.1.0
device "C" is on 5.1.1.
Each device can act as Bluetooth server
using
mBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(serviceName, serviceUUID)
or as Bluetooth client
mmDevice.createRfcommSocketToServiceRecord(serviceUUID);
If a server is discovered by a client device the UUIDs of services running on the server will be fetched using fetchUuidsWithSdp().
Then i get the UUIDs in the BroadcastReceiver:
private BroadcastReceiver UUIDFetchedReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
final String action = intent.getAction();
if (action.equals(BluetoothDevice.ACTION_UUID))
{
try
{
// Getting the Service UUIDs
Parcelable[] uuidExtra = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.d(TAG, "UUIDFetchedReceiver: received device: " + device.getName());
for (Parcelable uuid : uuidExtra)
{
Log.d(TAG, "UUIDFetchedReceiver: Service found on " + device.getName() + " | uuid: " + uuid);
if (uuid.toString().equals("3253f2d2-f49a-11ec-b939-0242ac120002"))
{
foundSDPService(device, uuid.toString());
}
}
}
catch (NullPointerException e)
{
Log.e(TAG, "UUIDFetchedReceiver: Nu UUIDs received ");
}
}
}
};
That works on device "A" and "C" the log output there shows:
UUIDFetchedReceiver: Service found on Device B | uuid: 3253f2d2-f49a-11ec-b939-0242ac120002
On Device "B" it looks like this:
UUIDFetchedReceiver: Service found on Device A | uuid: 020012ac-4202-39b9-ec11-9af4d2f25332
Device "B" shows the same UUID but as little endian.
The code is the same and for device "A" and "B" even the Android version is the same.
Does anybody know what causes this issue and how it can be fixed?
The devices are:
A = Samsung Galaxy Tab A (2016)
B = Lenovo TB-X304L
C = LG G Flex 2
The problem seems to be similar to the one described in this Question :
Strange UUID reversal from fetchUuidsWithSdp
Related
I created a UDP Broadcast listener in my application and work great with all most device.
But does not work with these two f****g tablet, the application get stuck at :
"socket.receive(packet)"
The application is exactly the same and also android version is the same: Android 12.
My snipped code :
try {
//Keep a socket open to listen to all the UDP trafic that is destined for this port
val ip = getLocalIpAddress()?.split(".")
val broadcastIp = ip!![0] + "." + ip[1] + "." + ip[2] + ".255"
val inetAddress = InetAddress.getByName(broadcastIp)
val socket = DatagramSocket(9098, inetAddress)
socket.broadcast = true
while (true) {
val recvBuf = ByteArray(15000)
val packet = DatagramPacket(recvBuf, recvBuf.size)
//Receive a packet
socket.receive(packet)
//Packet received
val data = String(packet.data).trim { it <= ' ' }
count++
runOnUiThread {
txt?.append("Ricevo $count <------------$data\n")
sv!!.fullScroll(ScrollView.FOCUS_DOWN)
}
Log.d("Main", data)
}
} catch (err: Exception) {
err.printStackTrace()
}
Someone had the same issue with the new Samsung Devices???
The tablets are not rooted.
Thanks in advance.
I created a very simple application that only can receive UDP broadcast message, just to avoid other releated issue from my application.
On the older device with android 12 the UDP broadcast works correctly instead on the new Samsung device the UDP broadcast message does not work at all.
I have managed to make an android device and scan and enlist all bluetooth devices in the area..I have the mac address of a remote device i just discovered in form of string and i want to start the bonding process with it.. i try BluetoothDevice object and then method createBond() but its not communicating with the remote device to pair..
Here is the code
class BluetoothM: AppCompatActivity{
// mac address of remote bluetooth device
string address;
//the discovered devices are listed in a ListView so i call a listview item click method to start pairing
private void Dlist_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
//the mac address has already been assigned in the OnReceive broadcast Receiver
if (e.Position == e.Id)
{
//Get the default adapter of the device
BluetoothAdapter adapt = BluetoothAdapter.DefaultAdapter;
//Get the remote device based on its MAC address
BluetoothDevice device = adapt.GetRemoteDevice(address);
//start the pairing process for the device
device.CreateBond();
}
}
}
//This class discovers bluetooth devices and pass MAC address to our string address for use in the listview click method
[BroadcastReceiver(Name = BluetoothDevice.ActionFound, Enabled = true)]
public class DeviceDiscovered : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
string ac = intent.Action; string name;
if (BluetoothDevice.ActionFound.Equals(ac))
{
BluetoothDevice device = (BluetoothDevice)intent.GetParcelableExtra(BluetoothDevice.ExtraDevice);
//add bluetooth name and address if they do not already exist
if (!MainActivity.avail.Contains(device.Name + "\n" + device.Address))
{
MainActivity.avail.Add(device.Name + "\n" + device.Address);
ArrayAdapter arrayAdapter1 = new ArrayAdapter(context, Android.Resource.Layout.SimpleListItem1, MainActivity.avail);
MainActivity.dlist.Adapter = arrayAdapter1;
//address assigned a value
MainActivity.address = device.Address; MainActivity.name = device.Name;
MainActivity.mydevice = device;
}
}
Toast.MakeText(context, "Received the intent", ToastLength.Short).Show();
}
The remote device is not receiving this communication and i don't know why, Thank You
Check you have BLUETOOTH_ADMIN permission in Manifest. Register for ACTION_BOND_STATE_CHANGED intents to be notified when the bonding process completes, and its result. Get the result of device.CreateBond(), it returns false on immediate error, true if bonding will begin.
https://developer.android.com/reference/android/bluetooth/BluetoothDevice#createBond()
I'm currently testing the Glucose Profile of BLE. In order to get Glucose Records the BLE Glucose Meter has to be bonded first. After the Device is bonded I don't get this device anymore in the onLeScan callback when doing startLeScan.
I however can get a List of all bonded BLE devices by using BluetoothAdapter.getDefaultAdapter().getBondedDevices();
Now I want to filter the bonded devices for devices that are currently in range/available.
To check if there are devices in range/available you need to scan, so that is not a solution for you given that you said they are not being detected for some reason.
Therefore, you could try to connect directly to the bonded device by knowing it Adress or Name.
Set<BluetoothDevice> myBondedDevices = mBluetoothAdapter.getBondedDevices();
String MAC = "your device Adress"
for(BluetoothDevice mydevice:myBondedDevices ){
Log.i("BondedInfo", MAC + " " + mydevice.getAddress());
if(mydevice.getAddress().equals(MAC)){
mydevice.connectGatt(mycontext,true,mygattcallback);
break;
}
}
Or the most adequated aproximation(according to myself):
Implement a broadcast receiver that detect bonding and connect when the device bonding is complete:
BroadcastReceiver myServiceBroadcast = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final int state=intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,BluetoothDevice.ERROR);
switch(state){
case BluetoothDevice.BOND_BONDING:
Log.i("Bondind Status:"," Bonding...");
break;
case BluetoothDevice.BOND_BONDED:
Log.i("Bondind Status:","Bonded!!");
myBluetoothDevice.connectGatt(mycontext, true, myBluetoothGattCallBack);
break;
case BluetoothDevice.BOND_NONE:
Log.i("Bondind Status:","Fail");
break;
}
};
Register it properly:
registerReceiver(myServiceBroadcast,new IntenFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED));
I have two different bluetooth apps. The first provides a service and listens to commands from the other commander app. I have a GT-I9100T phone and a GT-P5210 tablet. The tablet when acting at the listener works fine and the phone can see the UUID for my app. But when I run the phone as the listener, the UUID of the listener is not listed.
I filter the devices by my application UUID so that I know I am talking only to those devices with my application running.
My listening app looks like this (I get the same result if I use an insecure connection as well):
private final UUID GUID = UUID.fromString("3DEF793A-FA94-4478-AE56-108854B1EF4B");
// other stuff....
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(APP_NAME, GUID);
My commander app MainActivity looks likes this:
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
Log.i(TAG,"Action received: "+action);
if(action.equals(BluetoothDevice.ACTION_UUID)) {
BluetoothDevice btd = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.i(TAG,"Received uuids for "+btd.getName());
Parcelable[] uuidExtra = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
StringBuilder sb = new StringBuilder();
List<String> uuids = new ArrayList<String>(uuidExtra.length);
if(uuidExtra != null) {
for (int i = 0; i < uuidExtra.length; i++) {
sb.append(uuidExtra[i].toString()).append(',');
uuids.add(uuidExtra[i].toString());
}
}
Log.i(TAG,"ACTION_UUID received for "+btd.getName()+" uuids: "+sb.toString());
ListContent.addItemWithUUIDs(btd, uuids);
}
}
}
My list content (I am using the master/detail template):
public static synchronized void addItem(BluetoothItem item) {
BluetoothDevice btd = item.mBluetoothDevice;
Log.i(TAG,"Attempting to add "+item.mBluetoothDevice.getName());
if(ITEMS.contains(item)) {
Log.i(TAG,item.mBluetoothDevice.getName()+" already in list");
return;
}
// Do we know this device?
Parcelable[] uuids = btd.getUuids();
Set<String> setUUIDs = new HashSet<String>();
StringBuilder sb = new StringBuilder();
if(uuids != null) {
for (Parcelable parcelable : uuids) {
sb.append(parcelable.toString()).append(',');
setUUIDs.add(parcelable.toString());
}
}
Log.v(TAG,"Device has uuids: "+sb.toString());
if ((btd.getUuids() != null && setUUIDs.contains(BluetoothItem.GUID.toLowerCase()))){
Log.i(TAG, "Found app device: " + btd.getName());
addItem(btd);
} else {
// If we don't know this device, perform sdp fetch of uuids
Log.i(TAG,"Requesting fresh UUIDs for: "+btd.getName());
// this is flushed when discovering finishes
CANDIDATES.add(btd);
}
}
public static synchronized void addItemWithUUIDs(BluetoothDevice btd, List<String> uuids) {
Log.i(TAG,"Attempting to add with uuids"+btd.getName()+" uuids: "+btd.getUuids());
if (uuids.contains(BluetoothItem.GUID)) {
Log.i(TAG, "Found app device: " + btd.getName());
addItem(btd);
} else {
Log.i(TAG, "Ignoring device " + btd.getName() + " without app guid");
}
}
When discovery is finished, this happens:
for (BluetoothDevice i : ListContent.CANDIDATES) {
Log.i(TAG,"Fetching UUIDs for "+i.getName());
i.fetchUuidsWithSdp();
}
ListContent.CANDIDATES.clear();
The logcat output when using the tablet as the commander and phone as listener:
DeviceListActivity(29524): Received uuids for GT-I9100T
DeviceListActivity(29524): ACTION_UUID received for GT-I9100T uuids:
0000110a-0000-1000-8000-00805f9b34fb,
00001105-0000-1000-8000-00805f9b34fb,
00001116-0000-1000-8000-00805f9b34fb,
0000112d-0000-1000-8000-00805f9b34fb,
0000112f-0000-1000-8000-00805f9b34fb,
00001112-0000-1000-8000-00805f9b34fb,
0000111f-0000-1000-8000-00805f9b34fb,
00001132-0000-1000-8000-00805f9b34fb,
I get the correct output with phone as commander and tablet as listener:
DeviceListActivity(23121): Received uuids for GT-P5210
DeviceListActivity(23121): ACTION_UUID received for GT-P5210 uuids:
00001105-0000-1000-8000-00805f9b34fb,
0000110a-0000-1000-8000-00805f9b34fb,
0000110c-0000-1000-8000-00805f9b34fb,
00001112-0000-1000-8000-00805f9b34fb,
00001115-0000-1000-8000-00805f9b34fb,
0000111f-0000-1000-8000-00805f9b34fb,
00001200-0000-1000-8000-00805f9b34fb,
3def793a-fa94-4478-ae56-108854b1ef4b,
As you can see, the GUID for my app is listed as the last item. I've tried making the devices discoverable and bonding and unbonding, but the GUID for my app is never returned for the phone. I have other non-Android devices that also use this GUID and they are discovered normally as well.
The phone is running 4.1.2 and the tablet is 4.2.2
I want to clear the blueooth cache.
I'm making application about bluetooth.
I just knowed Android bluetooth device name is cached in the phone. (when phone find the bluetooth device)
I can't find solution anywhere.
I just saw fetchUuidsWithSdp().
someone said it clears the bluetooth cache in android phone.
but I don't know how use this method and I don't think that fetchUuidsWithSdp() will clear the cache.
Please Let me know how to clear the bluetooth cache in Android or how to use fetchUuidsWithSdp().
Thanks:)
Follow the instructions of the Android Guide in order to start the discovery.
When declaring your IntentFilter, add (at least) ACTION_FOUND and ACTION_UUID :
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothDevice.ACTION_UUID);
Inside your receiver call fetchUuidsWithSdp().
You will get the UUIDs inside the ACTION_UUID:
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// get fresh uuids
device.fetchUuidsWithSdp();
}
else if (BluetoothDevice.ACTION_UUID.equals(action)) {
// Get the device and teh uuids
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Parcelable[] uuidExtra = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
if(uuidExtra !=null){
for (Parcelable uuid : uuidExtra) {
Log.d("YOUR_TAG", "Device: " + device.getName() + " ( "+ device.getAddress() +" ) - Service: " + uuid.toString());
}
}
}