How to periodically scan for bluetooth devices on android

后端 未结 4 1264
没有蜡笔的小新
没有蜡笔的小新 2020-12-07 16:35

Hi this may sound as a stupid question.But I was unable to find any answers for this, thus posting here.

I am building an indoor application which continuously scans

相关标签:
4条回答
  • 2020-12-07 17:17

    As stated in the documentation device discovery is a lofty process that will directly degrade the performance of any bonds you have with other devices.

    Caution: Performing device discovery is a heavy procedure for the Bluetooth adapter and will consume a lot of its resources. Once you have found a device to connect, be certain that you always stop discovery with cancelDiscovery() before attempting a connection. Also, if you already hold a connection with a device, then performing discovery can significantly reduce the bandwidth available for the connection, so you should not perform discovery while connected.

    With this in mind (error handling omitted):

    private final BroadcastReceiver deviceBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
    
                if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                     deviceFound = true;
    
                     adapter.cancelDiscovery();
    
                     //process new device.
    
                     deviceFound = false;
    
                     adapter.startDiscovery();
                }
    }
    
    private final BroadcastReceiver adapterBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
    
                if (BluetoothAdaptor.ACTION_DISCOVERY_FINISHED.equals(action)) {
                     if (deviceFound == false) {
                          adapter.startDiscovery();
                     }
                }
    }
    
    0 讨论(0)
  • 2020-12-07 17:20

    I guess this was so simple but didnt strike me before. Here is the answer,

    private BluetoothAdapter mBtAdapter;
    mBtAdapter.startDiscovery();
    
    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))
                {
                //do something
                }
    
                else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action))
                {
                    Log.v(TAG,"Entered the Finished ");
                    mBtAdapter.startDiscovery();
                }
    

    Thus we should start discovery again on ACTION_DISCOVERY_FINISHED which will continuously scan for devices every 12 seconds.

    0 讨论(0)
  • 2020-12-07 17:29

    Here is the Code to get the list of all Active Bluetooth Devices[Paired or non-paired]

    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.activity_device_list);
    
    
            // 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 i, long l) {
                // 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);
    
    
            }
        };
    
        // 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);
                    }
                }
            }
        };
    
    }
    

    I get the idea from API demo, i hope this could be useful for all developers.

    0 讨论(0)
  • 2020-12-07 17:31

    Your code snippet should work - Only that it will be expensive in terms of power draw and will certainly kill your device/phone in a few hours. The startDiscovery() does a 2 step process, finding the device by inquiring for it and followed by a name discovery ie paging and connecting to the device,

    Unfortunately Android does not provide any API to control this and do only inquiry , also there is a periodic inquiry feature defined and supported by most Bluetooth chipsets, Android currently does not have any API to do periodic inquiry which could have been more ideal for your use case.

    0 讨论(0)
提交回复
热议问题