Scan Ble Android / getName() or device not complete or null - android

I'have an issue with the BLE scan of Android, I dont get the full name of the scanned devices found, I get only the first letter do you have any idea how to resolve this issue ?
I'm working with a 7.0 Nougat device which is supporting BLE
This is a part of my code :
mBluetoothScanner = mBluetoothAdapter.getBluetoothLeScanner();
settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
.build();
if (Build.VERSION.SDK_INT >= 21) {
mScanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
messageLog.error("onScanResult");
BluetoothDevice btDevice = null;
if (Build.VERSION.SDK_INT >= 21) {
btDevice = result.getDevice();
messageLog.error("btDevice : " + btDevice.getName() + "|" + btDevice.getAddress() + "|" + Arrays.toString(btDevice.getUuids()));
}
if (btDevice != null && btDevice.getName() != null && !isInDeviceList(btDevice))
mDeviceList.add(btDevice);
}
#Override
public void onBatchScanResults(List<ScanResult> results) {
}
#Override
public void onScanFailed(int errorCode) {
Log.e("Scan Failed", "Error Code: " + errorCode);
}
};
}
With btDevice.getName( ) I only get the first letter of a device scanned, is this my fault or is it coming from the Android BLE API ?

If the peripheral's name does not fit in the Advertising data since it needs to include other data therein, it will only send the prefix of the name over the air. It's nothing you can do about that other than change the advertisement data in the peripheral's firmware.
To get the exact advertisement data, you can investigate the "result.getScanRecord()" ScanRecord in onScanResult.

Related

Getting UUID of nearby beacon

I have an application that i want to scan nearby beacons and get their RSSI , UUID , major and minor. to test my code i used to make a virtual beacon using Beacon Simulator app on another device. I checked several ways but none of them worked fine:
1) in this code i made a scanner class and starting scan in my fragment and get address(I think it is mac address of BLE device) and RSSI but when i want to get UUID it says that it is null
private val mLeScanCallback = BluetoothAdapter.LeScanCallback { device, rssi, scanRecord ->
if (rssi > signalStrength) {
mHandler.post{
val uuid : String
if(device.uuids != null){
uuid = device.uuids[0].uuid.toString()
}
else{
uuid = "nullll"
scanRecord
}
Log.i("scan" , "device founded -> address:" + device.address + " name: " + device.name +" uuid: " + uuid + " RSSI: " + rssi + " type: " + device.type)
}
}
}
and call this function in my fragment to do the scan:
private fun scanLeDevice(enable: Boolean) {
if (enable && !isScanning) {
Log.i("scan" , "starting scan ...")
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed({
Log.i("scan" , "stopping scan ...")
isScanning = false
mBluetoothAdapter.stopLeScan(mLeScanCallback)
stopScan()
}, scanPeriod)
isScanning = true
mBluetoothAdapter.startLeScan(mLeScanCallback)
} else {
isScanning = false
mBluetoothAdapter.stopLeScan(mLeScanCallback)
}
}
2)second way i checked was to use this function in my fragment but nothing happened and no beacon was detected:
private val beaconManager = BeaconManager.getInstanceForApplication(MainApplication.applicationContext())
override fun onBeaconServiceConnect() {
beaconManager.removeAllRangeNotifiers()
beaconManager.addRangeNotifier(object : RangeNotifier {
override fun didRangeBeaconsInRegion(beacons: Collection<Beacon>, region: Region) {
if (beacons.size > 0) {
Log.i(TAG, "The first beacon I see is about " + beacons.iterator().next().getDistance() + " meters away.")
}
}
})
try {
beaconManager.startRangingBeaconsInRegion(Region("myRangingUniqueId", null, null, null))
} catch (e: RemoteException) {
}
}
I really dont know what is wrong ...
For the second listing using the Android Beacon Library, the problem is that you never call beaconManager.bind(this) and as a result, you never get a callback to onBeaconServiceConnect and none of the code inside that method executes.
Since you are using a Fragment not an Activity, take care that you actually implement all the methods of BeaconConsumer, which the class with the onBeaconServiceConnect method must implement. See here for more info on that chaining.
Finally, if you are looking for iBeacon transmitters you must set a beacon layout. The java code to do this is beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));

Android Application to Discover Nearby iPhone Devices

I am developing an Android Application where in I display the nearby iPhone devices. I have used the standard Android Bluetooth API's as well as Android Bluetooth LE API's for scanning the nearby iPhones. But I am unable to get the list of iPhones.
Note:
I see that the Settings Application present in the Stock Android is able to display all the devices.
Target Android OS - Marshmallow.
I am a newbie to Android. Kindly elaborate the answers for my better understanding. I have checked other links on Google and was not getting my desired result.
Standard Android Bluetooth Scan/discover(Scan and displays nearby devices but not an iPhone)
private void displayListOfFoundDevices(){
arrayOfFoundBTDevices = new ArrayList<BluetoothObject>();
// start looking for bluetooth devices
mBluetoothAdapter.startDiscovery();
// Discover new devices
// Create a BroadcastReceiver for ACTION_FOUND
final BroadcastReceiver mReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action))
{
// Get the bluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Get the "RSSI" to get the signal strength as integer,
// but should be displayed in "dBm" units
int rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE);
// Create the device object and add it to the arrayList of devices
BluetoothObject bluetoothObject = new BluetoothObject();
bluetoothObject.setBluetooth_name(device.getName());
bluetoothObject.setBluetooth_address(device.getAddress());
bluetoothObject.setBluetooth_state(device.getBondState());
bluetoothObject.setBluetooth_type(device.getType()); // requires API 18 or higher
bluetoothObject.setBluetooth_uuids(device.getUuids());
bluetoothObject.setBluetooth_rssi(rssi);
arrayOfFoundBTDevices.add(bluetoothObject);
// 1. Pass context and data to the custom adapter
FoundBTDevicesAdapter adapter = new FoundBTDevicesAdapter(getApplicationContext(), arrayOfFoundBTDevices);
// 2. setListAdapter
setListAdapter(adapter);
}
}
};
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); }
BluetoothLE Code snippet(Scan and displays nearby devices but not an iPhone)
btManager =(BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
btAdapter = btManager.getAdapter();
btScanner = btAdapter.getBluetoothLeScanner();
if (btAdapter != null && !btAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent,REQUEST_ENABLE_BT);
}
// Make sure we have access coarse location enabled, if not, prompt the user to enable it
if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("This app needs location access");
builder.setMessage("Please grant location access so this app can detect peripherals.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
}
});
builder.show();
}
}
// Device scan callback.
private ScanCallback leScanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
Log.i("Main","Scan Result: Add: " +result.getDevice().getAddress());
peripheralTextView.append("Device Name: " + result.getDevice().getName()+ " add: " + result.getDevice().getAddress() + " rssi: " + result.getRssi() + "\n");
// auto scroll for text view
final int scrollAmount = peripheralTextView.getLayout().getLineTop(peripheralTextView.getLineCount()) - peripheralTextView.getHeight();
// if there is no need to scroll, scrollAmount will be <=0
if (scrollAmount > 0)
peripheralTextView.scrollTo(0, scrollAmount);
}
};

scan WiFi List return 0 in android nougat

I am building my code for Android Nougat.
I have given location and WiFi permission in manifest file, still, I am getting "0" from wlan_Manager.getScanResults();
my code snippet is
wlan_Manager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wlan_switch = (Switch)findViewById(R.id.switch1);
list = (ListView)findViewById(R.id.listview);
wlan_switch.setChecked(wlan_Manager.isWifiEnabled());
wifi_list = new ArrayList<>();
adapter = new Adapter(this,R.layout.default_listview,wifi_list);
list.setAdapter(adapter);
wifireceiver = new wifi_Receiver(adapter,wifi_list);
registerReceiver(wifireceiver,new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
.
public void onClick(View view) {
Log.d("switch", "onClick: ");
if (wlan_switch.isChecked() && !wlan_Manager.isWifiEnabled())
{
Log.d(TAG, "true: ");
wlan_Manager.setWifiEnabled(true);
wifi_list.clear();
wlan_Manager.startScan();
}
else {
Log.d(TAG, "false ");
wlan_Manager.setWifiEnabled(false);
wifi_list.clear();
adapter.clear();
}
}
.
#Override
public void onReceive(Context context, Intent intent)
{
int size =0 ;
//scan_Result.clear();
Log.d("WifScanner", "onReceive");
wlan_Manager = (WifiManager)context.getApplicationContext().getSystemService(context.WIFI_SERVICE);
scan_Result = wlan_Manager.getScanResults();
size = scan_Result.size();
Log.d(TAG, "onReceive: " + size);
while (size > 0)
{
Log.d(TAG, "size : "+size);
size--;
wifi_list.add(scan_Result.get(size).SSID);
adapter.notifyDataSetChanged();
}
}
But when I build code for the Lower android version it is showing WiFi list.
It's one problem in version of Android 7.x. Exists two solutions :
Update version your device for 8.
Edit build.gradle for targetSdkVersion 22
You are calling getScanResults() before you started any scan.
For your use case you need to start wifi scanning with the startScan()-method and register a BroadcastReceiver which filter for intents with the action:
WifiManager.SCAN_RESULTS_AVAILABLE_ACTION
Here you can find some example code:
Android Wifi Scan - BroadcastReceiver for SCAN_RESULTS_AVAILABLE_ACTION not getting called

Scanning BLE device not working

I am trying to scan BLE devices with
mBluetoothAdapter.startLeScan(this);
(I know its obsolete for newer versions but just to see it works with my phone [4.4], I am using it). So it starts scanning and then moves on without giving errors but no device is detected. OnLEScan event is also fired but the device parameter in it is null. My LE device is right there and connected.
On googling, I found this happens if the BluetoothAdapter doesnot have a UUID.
How do I set UUID? When is OnLeScan called/fired? Is there any other solution?
My callback code goes here
//BluetoothAdapte.LEScanCallBack on MainActivity
#Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord){
Log.i(TAG, "New LE Device: " + device.getName() + "#" + rssi);
if(Device_Name.equals(device.getName())){
mDevices.put(device.hashCode(), device);
invalidateOptionsMenu();
}
}
Use this code as it will provide you insight of all the data
available in your BLE device (will display the data in logs).
UUIDs are basically provided by the manufacturer of the device and you can't set it on your own.
For Instance : I was using BLE Beacons and its manufacturer provided me the API which helped me to fetch its UUID.
Sometimes, a special ID is available on the device itself(factory id in my case) which can help you to retrieve your UUID and that too from the manufacturer's website or API.
BluetoothAdapter bluetoothAdapter;
BluetoothLeScanner bluetoothLeScanner;
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
bluetoothLeScanner.startScan(new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
String s = "\nRssi : "+result.getRssi()+"" +
"\nName (Get Device) : "+result.getDevice().getName()+"" +
"\nBytes"+result.getScanRecord().getBytes()+"" +
"\nGet Device : " + result.getDevice()+"" +
"\nAddress : "+result.getDevice().getAddress()+"" +
"\nService UUIds : "+result.getScanRecord().getServiceUuids().get(0)+"" + //Unique
"\nName (Scan Record) : "+result.getScanRecord().getDeviceName()+"" +
"\nUuids device : "+result.getDevice().getUuids()+"" +
"\nDescribe contents : "+result.describeContents();
//This will show you all the data in logs.
Log.e("All Data",s);
}
#Override
public void onBatchScanResults(List<ScanResult> results) {
super.onBatchScanResults(results);
}
#Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
}
});
}
Anroid 4.4 is not compatible, i used android 5.1 device and it worked like a charm!

list connected bluetooth devices?

How can I list all connected bluetooth devices on android ?
thanks!
public void checkConnected()
{
// true == headset connected && connected headset is support hands free
int state = BluetoothAdapter.getDefaultAdapter().getProfileConnectionState(BluetoothProfile.HEADSET);
if (state != BluetoothProfile.STATE_CONNECTED)
return;
try
{
BluetoothAdapter.getDefaultAdapter().getProfileProxy(_context, serviceListener, BluetoothProfile.HEADSET);
}
catch (Exception e)
{
e.printStackTrace();
}
}
private ServiceListener serviceListener = new ServiceListener()
{
#Override
public void onServiceDisconnected(int profile)
{
}
#Override
public void onServiceConnected(int profile, BluetoothProfile proxy)
{
for (BluetoothDevice device : proxy.getConnectedDevices())
{
Log.i("onServiceConnected", "|" + device.getName() + " | " + device.getAddress() + " | " + proxy.getConnectionState(device) + "(connected = "
+ BluetoothProfile.STATE_CONNECTED + ")");
}
BluetoothAdapter.getDefaultAdapter().closeProfileProxy(profile, proxy);
}
};
As of API 14 (Ice Cream), Android has a some new BluetoothAdapter methods including:
public int getProfileConnectionState (int profile)
where profile is one of HEALTH, HEADSET, A2DP
Check response, if it's not STATE_DISCONNECTED you know you have a live connection.
Here is code example that will work on any API device:
BluetoothAdapter mAdapter;
/**
* Check if a headset type device is currently connected.
*
* Always returns false prior to API 14
*
* #return true if connected
*/
public boolean isVoiceConnected() {
boolean retval = false;
try {
Method method = mAdapter.getClass().getMethod("getProfileConnectionState", int.class);
// retval = mAdapter.getProfileConnectionState(android.bluetooth.BluetoothProfile.HEADSET) != android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
retval = (Integer)method.invoke(mAdapter, 1) != 0;
} catch (Exception exc) {
// nothing to do
}
return retval;
}
First you need to retrieve the BluetoothAdapter:
final BluetoothAdapter btAdapter =
BluetoothAdapter.getDefaultAdapter();
Second you need to make sure Bluetooth is available and turned on :
if (btAdapter != null && btAdapter.isEnabled()) // null means no
Bluetooth!
If the Bluetooth is not turned out you can either use btAdapter.enable() which is not recommended in the documentation or ask the user to do it : Programmatically enabling bluetooth on Android
Third you need to define an array of states (to filter out
unconnected devices):
final int[] states = new int[] {BluetoothProfile.STATE_CONNECTED,
BluetoothProfile.STATE_CONNECTING};
Fourth, you create a BluetoothProfile.ServiceListener which
contains two callbacks triggered when a service is connected and
disconnected :
final BluetoothProfile.ServiceListener listener = new BluetoothProfile.ServiceListener() {
#Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
}
#Override
public void onServiceDisconnected(int profile) {
}
};
Now since you have to repeat the querying process for all available Bluetooth Profiles in the Android SDK (A2Dp, GATT, GATT_SERVER, Handset, Health, SAP) you should proceed as follow :
In onServiceConnected, place a condition that check what is the current profile so that we add the found devices into the correct collection and we use : proxy.getDevicesMatchingConnectionStates(states) to filter out unconnected devices:
switch (profile) {
case BluetoothProfile.A2DP:
ad2dpDevices.addAll(proxy.getDevicesMatchingConnectionStates(states));
break;
case BluetoothProfile.GATT: // NOTE ! Requires SDK 18 !
gattDevices.addAll(proxy.getDevicesMatchingConnectionStates(states));
break;
case BluetoothProfile.GATT_SERVER: // NOTE ! Requires SDK 18 !
gattServerDevices.addAll(proxy.getDevicesMatchingConnectionStates(states));
break;
case BluetoothProfile.HEADSET:
headsetDevices.addAll(proxy.getDevicesMatchingConnectionStates(states));
break;
case BluetoothProfile.HEALTH: // NOTE ! Requires SDK 14 !
healthDevices.addAll(proxy.getDevicesMatchingConnectionStates(states));
break;
case BluetoothProfile.SAP: // NOTE ! Requires SDK 23 !
sapDevices.addAll(proxy.getDevicesMatchingConnectionStates(states));
break;
}
And finally, the last thing to do is start the querying process :
btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.A2DP);
btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.GATT); // NOTE ! Requires SDK 18 !
btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.GATT_SERVER); // NOTE ! Requires SDK 18 !
btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.HEADSET);
btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.HEALTH); // NOTE ! Requires SDK 14 !
btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.SAP); // NOTE ! Requires SDK 23 !
source: https://stackoverflow.com/a/34790442/2715054
So you get the list of paired devices.
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> pairedDevicesList = btAdapter.getBondedDevices();
for (BluetoothDevice pairedDevice : pairedDevicesList) {
Log.d("BT", "pairedDevice.getName(): " + pairedDevice.getName());
Log.d("BT", "pairedDevice.getAddress(): " + pairedDevice.getAddress());
saveValuePreference(getApplicationContext(), pairedDevice.getName(), pairedDevice.getAddress());
}
Android system doesn't let you query for all "currently" connected devices. It however, you can query for paired devices. You will need to use a broadcast receiver to listen to ACTION_ACL_{CONNECTED|DISCONNECTED} events along with STATE_BONDED event to update your application states to track what's currently connected.
I found a solution and it works on android 10
Kotlin
private val serviceListener: ServiceListener = object : ServiceListener {
var name: String? = null
var address: String? = null
var threadName: String? = null
override fun onServiceDisconnected(profile: Int) {}
override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
for (device in proxy.connectedDevices) {
name = device.name
address = device.address
threadName = Thread.currentThread().name
Toast.makeText(
this#MainActivity,
"$name $address$threadName",
Toast.LENGTH_SHORT
).show()
Log.i(
"onServiceConnected",
"|" + device.name + " | " + device.address + " | " + proxy.getConnectionState(
device
) + "(connected = "
+ BluetoothProfile.STATE_CONNECTED + ")"
)
}
BluetoothAdapter.getDefaultAdapter().closeProfileProxy(profile, proxy)
}
}
Call this method in main thread
BluetoothAdapter.getDefaultAdapter()
.getProfileProxy(this, serviceListener, BluetoothProfile.HEADSET)
Java
original code
Please analyze this class online.
Here you will find how to discover all connected (paired) Bluetooth devices.
Well here are the steps:
First, you start intent to discover devices
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
Register a broadcast reciver for it:
registerReceiver(mReceiver, filter);
On the definition of mReceiver:
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a ListView
arrayadapter.add(device.getName())//arrayadapter is of type ArrayAdapter<String>
lv.setAdapter(arrayadapter); //lv is the list view
arrayadapter.notifyDataSetChanged();
}
}
and the list will be automatically populated on new device discovery.

Categories

Resources