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"));
Related
first post here!
I'm trying to use an Arduino Nano RP2040 Connect as a Bluetooth Low Energy peripheral, currently having 1 service with 3 characteristic exposing:
a Int representing the value off of a potentiometer;
a Int representing the RSSI (did it as for visual debug, there's a LED representing it);
a Bool representing the status of a LED;
Service and characteristics UUIDs are randomly generated.
The code is this:
#include <ArduinoBLE.h>
#define LED_RSSI 2
#define LED_STATUS 4
int oldSensorValue = 0;
int oldRssiValue = 0;
bool ledState = false;
long previousMillis = 0;
BLEService sensorService("18902a9a-1f4a-44fe-936f-14c8eea41800");
BLEIntCharacteristic sensorChar("18902a9a-1f4a-44fe-936f-14c8eea41801", BLERead | BLENotify);
BLEIntCharacteristic rssiChar("18902a9a-1f4a-44fe-936f-14c8eea41802", BLERead | BLENotify);
BLEBoolCharacteristic ledChar("18902a9a-1f4a-44fe-936f-14c8eea41803", BLERead | BLEWrite | BLENotify);
void setup() {
Serial.begin(9600);
while (!Serial) {
;
}
pinMode(LED_BUILTIN, OUTPUT);
pinMode(LED_RSSI, OUTPUT);
pinMode(LED_STATUS, OUTPUT);
digitalWrite(LED_STATUS, ledState);
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1)
;
}
BLE.setEventHandler(BLEConnected, blePeripheralConnectHandler);
BLE.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler);
BLE.setLocalName("Sensor Monitor");
//BLE.setDeviceName(name); //defaults “Arduino”
BLE.setAppearance(0x015); //set appearance as "Sensor" 0x015
sensorService.addCharacteristic(sensorChar);
sensorService.addCharacteristic(rssiChar);
sensorService.addCharacteristic(ledChar);
BLE.addService(sensorService);
BLE.setAdvertisedService(sensorService); // add the service UUID
sensorChar.writeValue(oldSensorValue);
rssiChar.writeValue(oldRssiValue);
ledChar.writeValue(ledState);
ledChar.setEventHandler(BLEWritten, onUpdateLed);
sensorChar.setEventHandler(BLESubscribed, onSubscribedChar);
rssiChar.setEventHandler(BLESubscribed, onSubscribedChar);
ledChar.setEventHandler(BLESubscribed, onSubscribedChar);
sensorChar.setEventHandler(BLEUnsubscribed, onUnsubscribedChar);
rssiChar.setEventHandler(BLEUnsubscribed, onUnsubscribedChar);
ledChar.setEventHandler(BLEUnsubscribed, onUnsubscribedChar);
startAdvertise();
}
void loop() {
BLEDevice central = BLE.central();
if (central) {
while (central.connected()) {
long currentMillis = millis();
long timer2 = millis();
if (currentMillis - previousMillis >= 200) {
previousMillis = currentMillis;
updateSensorValue();
updateRSSI();
}
}
}
}
void startAdvertise() {
if (!BLE.advertise()) {
Serial.println("Bluetooth® device failed to advertise.");
while (1) {
;
}
} else {
Serial.println("Bluetooth® device active, waiting for connections...");
}
}
void updateSensorValue() {
int sensorValue = analogRead(A0);
if (sensorValue != oldSensorValue) {
// Serial.print("sensor Level % is now: ");
// Serial.println(sensorValue);
sensorChar.writeValue(sensorValue);
oldSensorValue = sensorValue;
}
}
void updateRSSI() {
int newRssiValue = BLE.rssi();
if (newRssiValue != 127)
analogWrite(LED_RSSI, map(abs(newRssiValue), 0, 128, 255, 0));
else
analogWrite(LED_RSSI, 0);
if (newRssiValue != oldRssiValue) {
// Serial.print("RSSI is now: ");
// Serial.println(newRssiValue);
rssiChar.writeValue(newRssiValue);
oldRssiValue = newRssiValue;
}
}
void onUpdateLed(BLEDevice central, BLECharacteristic characteristic) {
Serial.println("Central '" + central.address() + "' wrote '" + ledChar.value() + "' to characteristic '" + characteristic.uuid() + "'");
ledState = ledChar.value();
digitalWrite(LED_STATUS, ledState);
}
void onSubscribedChar(BLEDevice central, BLECharacteristic characteristic) {
Serial.println("Central '" + central.address() + "' subscribed to characteristic '" + characteristic.uuid() + "'");
}
void onUnsubscribedChar(BLEDevice central, BLECharacteristic characteristic) {
Serial.println("Central '" + central.address() + "' unsubscribed to characteristic '" + characteristic.uuid() + "'");
}
void blePeripheralConnectHandler(BLEDevice central) {
// central connected event handler
Serial.println("Central '" + central.address() + "' connected");
digitalWrite(LED_BUILTIN, HIGH);
BLE.stopAdvertise();
}
void blePeripheralDisconnectHandler(BLEDevice central) {
// central disconnected event handler
Serial.println("Central '" + central.address() + "' disconnected");
digitalWrite(LED_BUILTIN, LOW);
analogWrite(LED_RSSI, 0);
startAdvertise();
}
I have tried its functionality with nRF Connect and LightBlue on Android, trying to read, subscribe and write characteristics, everything seems to work as intended.
The problem I'm facing is that whatever I do with the UUIDs on the Arduino side I keep seeing the same ones on the apps mentioned above.
On nRF Connect there's the possibility to "Refresh services" and that does fixes temporarely the issue but if I disconnect from the peripheral and reconnect the issue appears again.
Tried cleaning data and cache of both apps, of bluetooth system app, without success.
Its not only those 2 apps that do this behaviour:I'm trying to interface the Arduino with a Unity app ran on Android and it fails to subscribe to the characteristics with the "new" UUIDs but somehow succeed if I set the Arduino with the UUIDs my phone is stuck seeing.
A completely different phone sees updates UUIDs, everytime, but I need to use my phone for developing.
Is there something wrong with my phone behaviour? It's a Motorola Moto G52.
How can I fix this? What am I doing wrong? Any help appreciated
Apparently the client uses GATT caching. This way it saves some round trips for service discovery for every connection start.
A client can cache the database structure (only) in one of the following cases:
The devices are bonded. The server uses the Service Changed characteristic to inform the client when something changes with the db structure, by sending an indication containing the range of the handles that have changed.
Both the client and server support the relatively new Database Hash characteristic, which contains a hash of the db structure which the server stores in a characteristic which the client reads on every reconnection. If it has changed since the last time, the client must rediscover.
The server never changes the db structure during its lifetime. This is indicated to the client by not having the Service Changed characteristic.
If none of the above cases apply, then the client is buggy and behaves incorrectly.
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!
I am trying to play with BLE transmission on my device.
Here is the code I use and the output:
// check BLE support
Log.i(TAG, "BLE supported: " + getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)); // true
// check BLE transmission support
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();
Log.i(TAG, "isMultipleAdvertisementSupported: " + mBluetoothAdapter.isMultipleAdvertisementSupported()); // false
Log.i(TAG, "isOffloadedFilteringSupported: " + mBluetoothAdapter.isOffloadedFilteringSupported()); // false
Log.i(TAG, "isOffloadedScanBatchingSupported: " + mBluetoothAdapter.isOffloadedScanBatchingSupported()); // false
BluetoothLeAdvertiser mBluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
Log.i(TAG, mBluetoothLeAdvertiser.toString()); //android.bluetooth.le.BluetoothLeAdvertiser#1c51f789
// check BLE transmission support
// android-beacon-library, https://github.com/AltBeacon/android-beacon-library
int result = BeaconTransmitter.checkTransmissionSupported(getApplicationContext());
Log.i(TAG, "ABL checkTransmissionSupported: " + result); // 0
I can not understand why mBluetoothLeAdvertiser is not null, since mBluetoothLeAdvertiser verifies that it is not false:
package android.bluetooth;
// ...
public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
if (getState() != STATE_ON) {
return null;
}
if (!isMultipleAdvertisementSupported()) {
return null;
}
synchronized(mLock) {
if (sBluetoothLeAdvertiser == null) {
sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
}
}
return sBluetoothLeAdvertiser;
}
// ...
public boolean isMultipleAdvertisementSupported() {
if (getState() != STATE_ON) return false;
try {
return mService.isMultiAdvertisementSupported();
} catch (RemoteException e) {
Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e);
}
return false;
}
Welcome to the world of Android, which is both open source and closed source at the same time! Your analysis of the open source BluetoothLeAdvertiser code above is correct. If that code is running on your mobile device, you would not see the output that your test in the top code snippet shows. Conclusion: the code shown in the second snippet must not be what is on the device.
Android device OEMs are free to fork the source code and modify it to make it work with their hardware. In this case, I know that Motorola did the same thing in this code for their Moto X and Moto G devices. These devices return a BluetoothLeAdvertiser despite the fact that isMultipleAdvertisementSupported() returns false. A Motorola engineer explained to me that they changed this because they wanted to support Advertising despite using a BLE chip that could support only one Advertisement at a time. Indeed, I have verified that Motorola devices can advertise, but if you try to get two advertisements going simultaneously, it fails.
I'm trying to read the initial state of a BLE device when I connect to it. Here's the code I have to try to do that:
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status)
{
if(status == BluetoothGatt.GATT_SUCCESS)
{
Log.i(TAG, gatt.getDevice().toString() + "Discovered Service Status: " + gattStatusToString(status));
for(BluetoothGattService service : gatt.getServices())
{
Log.i(TAG, "Discovered Service: " + service.getUuid().toString() + " with " + "characteristics:");
for(BluetoothGattCharacteristic characteristic : service.getCharacteristics())
{
// Set notifiable
if(!gatt.setCharacteristicNotification(characteristic, true))
{
Log.e(TAG, "Failed to set notification for: " + characteristic.toString());
}
// Enable notification descriptor
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CCC_UUID);
if(descriptor != null)
{
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
// Read characteristic
if(!gatt.readCharacteristic(characteristic))
{
Log.e(TAG, "Failed to read characteristic: " + characteristic.toString());
}
}
}
}
else
{
Log.d(TAG, "Discover Services status: " + gattStatusToString(status));
}
}
But the read fails every time! Later if I initiate a read based on UI interaction it reads just fine! Any ideas about what's going on here?
In the Android BLE implementation, the gatt operation calls need to be queued so that only one operation (read, write, etc.) is in effect at a time. So for example, after gatt.readCharacteristic(characteristicX) is called, you need to wait for the gatt callbackBluetoothGattCallback.onCharacteristicRead() to indicate the read is finished. If you initiate a second gatt.readCharacteristic() operation before the previous one completes, the second one will fail (by returning false) This goes for all of the gatt.XXX() operations.
Its a little work, but I think the best solution is to create a command queue for all the gatt operations and run them one at a time. You can use the command pattern to accomplish this.
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.