4

I am using DeviceListActivity for discovering Bluetooth devices. This is the activity that is used on Android Bluetooth Chat program sample.

I run the program on a virtual machine.

Problem: When I start scanning/discovering Bluetooth devices:

enter image description here

it lists duplicate devices name:

enter image description here

I have one device that is discoverable but the program lists it more than once.

How can I prevent to list duplicate devices name?

The activity code:

package com.example.android.BluetoothChat;

import java.util.Set;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

/**
 * This Activity appears as a dialog. It lists any paired devices and
 * devices detected in the area after discovery. When a device is chosen
 * by the user, the MAC address of the device is sent back to the parent
 * Activity in the result Intent.
 */
public class DeviceListActivity extends Activity {
    // Debugging
    private static final String TAG = "DeviceListActivity";
    private static final boolean D = true;

    // Return Intent extra
    public static String EXTRA_DEVICE_ADDRESS = "device_address";

    // Member fields
    private BluetoothAdapter mBtAdapter;
    private ArrayAdapter<String> mPairedDevicesArrayAdapter;
    private ArrayAdapter<String> mNewDevicesArrayAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Setup the window
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        setContentView(R.layout.device_list);

        // Set result CANCELED incase the user backs out
        setResult(Activity.RESULT_CANCELED);

        // Initialize the button to perform device discovery
        Button scanButton = (Button) findViewById(R.id.button_scan);
        scanButton.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                doDiscovery();
                v.setVisibility(View.GONE);
            }
        });

        // Initialize array adapters. One for already paired devices and
        // one for newly discovered devices
        mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);
        mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);

        // Find and set up the ListView for paired devices
        ListView pairedListView = (ListView) findViewById(R.id.paired_devices);
        pairedListView.setAdapter(mPairedDevicesArrayAdapter);
        pairedListView.setOnItemClickListener(mDeviceClickListener);

        // Find and set up the ListView for newly discovered devices
        ListView newDevicesListView = (ListView) findViewById(R.id.new_devices);
        newDevicesListView.setAdapter(mNewDevicesArrayAdapter);
        newDevicesListView.setOnItemClickListener(mDeviceClickListener);

        // Register for broadcasts when a device is discovered
        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        this.registerReceiver(mReceiver, filter);

        // Register for broadcasts when discovery has finished
        filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        this.registerReceiver(mReceiver, filter);

        // Get the local Bluetooth adapter
        mBtAdapter = BluetoothAdapter.getDefaultAdapter();

        // Get a set of currently paired devices
        Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();

        // If there are paired devices, add each one to the ArrayAdapter
        if (pairedDevices.size() > 0) {
            findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
            for (BluetoothDevice device : pairedDevices) {
                mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
            }
        } else {
            String noDevices = getResources().getText(R.string.none_paired).toString();
            mPairedDevicesArrayAdapter.add(noDevices);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        // Make sure we're not doing discovery anymore
        if (mBtAdapter != null) {
            mBtAdapter.cancelDiscovery();
        }

        // Unregister broadcast listeners
        this.unregisterReceiver(mReceiver);
    }

    /**
     * Start device discover with the BluetoothAdapter
     */
    private void doDiscovery() {
        if (D) Log.d(TAG, "doDiscovery()");

        // Indicate scanning in the title
        setProgressBarIndeterminateVisibility(true);
        setTitle(R.string.scanning);

        // Turn on sub-title for new devices
        findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);

        // If we're already discovering, stop it
        if (mBtAdapter.isDiscovering()) {
            mBtAdapter.cancelDiscovery();
        }

        // Request discover from BluetoothAdapter
        mBtAdapter.startDiscovery();
    }

    // The on-click listener for all devices in the ListViews
    private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {
        public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {
            // Cancel discovery because it's costly and we're about to connect
            mBtAdapter.cancelDiscovery();

            // Get the device MAC address, which is the last 17 chars in the View
            String info = ((TextView) v).getText().toString();
            String address = info.substring(info.length() - 17);

            // Create the result Intent and include the MAC address
            Intent intent = new Intent();
            intent.putExtra(EXTRA_DEVICE_ADDRESS, address);

            // Set result and finish this Activity
            setResult(Activity.RESULT_OK, intent);
            finish();
        }
    };

    // The BroadcastReceiver that listens for discovered devices and
    // changes the title when discovery is finished
    private 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);
                // If it's already paired, skip it, because it's been listed already
                if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
                    mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
                }
            // When discovery is finished, change the Activity title
            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                setProgressBarIndeterminateVisibility(false);
                setTitle(R.string.select_device);
                if (mNewDevicesArrayAdapter.getCount() == 0) {
                    String noDevices = getResources().getText(R.string.none_found).toString();
                    mNewDevicesArrayAdapter.add(noDevices);
                }
            }
        }
    };

}

Edit: This problem is disappeared on my real device(smart phone). I don't know why an emulator has such problem!

Behzad
  • 1,740
  • 1
  • 22
  • 49

5 Answers5

3

Simple. To filter, use a Set.

Example

HashSet

Add bluetooth address on HashSet and verify with method contains().

if contains() returns false, then add the bluetooth data to the list

if contains() returns true, then DON'T add the bluetooth data to the list

Alexander
  • 9,737
  • 4
  • 53
  • 59
0

Write this inside you ACTION_FOUND.

if (mNewDevicesArrayAdapter.size() < 1) {
    mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
    mNewDevicesArrayAdapter.notifyDataSetChanged();
}
else {
    boolean flag = true;    // flag to indicate that particular device is already in the arlist or not
    for(int i = 0; i<mNewDevicesArrayAdapter.size();i++)
    {
        if(device.getAddress().equals(mNewDevicesArrayAdapter.get(i).getAddress()))
        {
            flag = false;
        }
    }
    if(flag == true)
    {
        mNewDevicesArrayAdapter.add(device.getName()+"\n"+device.getAddress());

        mNewDevicesArrayAdapter.notifyDataSetChanged();
    }
}
Raymond
  • 2,276
  • 2
  • 20
  • 34
Narendra Pal
  • 6,474
  • 13
  • 49
  • 85
  • please let me know your response after doing this – Narendra Pal Sep 22 '12 at 10:59
  • 1
    It has this error: "The method size() is undefined for the type ArrayAdapter" – Behzad Sep 22 '12 at 22:52
  • make it NewDevicesArrayAdapter.length() – Charan Pai Sep 24 '12 at 07:28
  • @AbdulRahman: No it's not. It can't be complied because of this error: "The method length() is undefined for the type ArrayAdapter". Could you use "getCount()" instead of length() and let us to know the result? – Behzad Oct 29 '12 at 09:22
  • @Behzad: Did you get the solution for the above problem, i am also looking for it... – Abdul Rahman Oct 29 '12 at 14:49
  • @AbdulRahman No I didn't. Because the time was over and I had to present the project. Have you tested it on a real device? – Behzad Oct 29 '12 at 18:42
  • 1
    @Behzad: After your comment only it crossed my mind, i checked it in real android device, it shows the device only one time. – Abdul Rahman Oct 30 '12 at 00:49
  • Sorry was unable to reach stackoverflow from last few days.Can anybody tell me that whether my solution is working fine or not. and if not then which kind of problem you are facing – Narendra Pal Oct 31 '12 at 03:29
  • @nick Thanks for response. Nope. The length() and size() methods are undefined for the type ArrayAdapter. Maybe getCount() works, but I can't test it now. – Behzad Nov 01 '12 at 09:12
0

This one worked for me

public class MainActivity extends ActionBarActivity {

    private ListView listView;
    private ArrayList<String> mDeviceList = new ArrayList<String>();
    private BluetoothAdapter mBluetoothAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        listView = (ListView) findViewById(R.id.listView);

        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        mBluetoothAdapter.startDiscovery();

        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        registerReceiver(mReceiver, filter);

    }


    @Override
    protected void onDestroy() {
        unregisterReceiver(mReceiver);
        super.onDestroy();
    }

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                BluetoothDevice device = intent
                        .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                mDeviceList.add(device.getName() + "\n" + device.getAddress());
                Log.i("BT", device.getName() + "\n" + device.getAddress());
                listView.setAdapter(new ArrayAdapter<String>(context,
                        android.R.layout.simple_list_item_1, mDeviceList));
            }
        }
    };
Aditya Vyas-Lakhan
  • 13,409
  • 16
  • 61
  • 96
0

In onReceive of BluetoothDevice.ACTION_FOUND, before adding a BlueTooth device to the Arraylist check if the Arraylist already contains that device using the method contains() of the ArrayList. Add the device to the list only if contains() returns false.

Code is as below:

List<BluetoothDevice> availableDevices = new ArrayList<>();

 class BluetoothReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action != null) {
            switch (action) {
                case BluetoothDevice.ACTION_FOUND: {
                    // Discovery has found a device. Get the BluetoothDevice
                    // object and its info from the Intent.
                    BluetoothDevice bluetoothDevice =
                            intent.getParcelableExtra(BluetoothDevice
                                    .EXTRA_DEVICE);

                   //Add the device to the list only if contains() returns false.

                    if (!availableDevices.contains(bluetoothDevice)) {
                        availableDevices.add(bluetoothDevice);
                    }

                    displayAvailableDevices();
                    break;
                }
Dharmik Thakkar
  • 1,650
  • 1
  • 9
  • 18
0

It worked for me

    @Override
public void onDeviceDiscovered(BluetoothDevice device) {
    listener.endLoading(true);
    devices.contains(device);
    //======================To add only unique device not repeating same device in listView========================
    if(  devices.contains(device)){

    }else {
        devices.add(device);
    }

    //======================End of add only unique device not repeating same device in listView====================
    notifyDataSetChanged();
}
ranojan
  • 819
  • 8
  • 11