如何在android上定期扫描蓝牙设备
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3285580/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to periodically scan for bluetooth devices on android
提问by Ameya Phadke
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 the bluetooth dongles located at different locations in a place like a mall or library.As I move in the mall with android phone in my hand I should be able to get the nearest dongle which I can connect to(Stupid Idea but I want to do something else with this).For this I should be able to continuously scan for the bluetooth devices.
我正在构建一个室内应用程序,它连续扫描位于商场或图书馆等地方不同位置的蓝牙加密狗。当我拿着安卓手机在商场里移动时,我应该能够获得我可以连接的最近的加密狗to(愚蠢的想法,但我想用它做其他事情)。为此,我应该能够连续扫描蓝牙设备。
Please can someone tell me how do I make android scan the available Bluetooth devices periodically.
请有人告诉我如何让android定期扫描可用的蓝牙设备。
回答by Ameya Phadke
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.
因此,我们应该再次开始发现ACTION_DISCOVERY_FINISHED
,它将每 12 秒连续扫描一次设备。
回答by Dwivedi Ji
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.
我从 API 演示中得到了这个想法,我希望这对所有开发人员都有用。
回答by Ben Crowhurst
As stated in the documentationdevice 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.
注意:执行设备发现对于蓝牙适配器来说是一个繁重的过程,会消耗大量资源。一旦找到要连接的设备,请确保在尝试连接之前始终使用 cancelDiscovery() 停止发现。此外,如果您已经与设备保持连接,那么执行发现会显着减少连接可用的带宽,因此您不应在连接时执行发现。
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();
}
}
}
回答by Dennis Mathews
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,
您的代码片段应该可以工作 - 只是它在功耗方面会很昂贵,并且肯定会在几个小时内杀死您的设备/手机。startDiscovery() 执行 2 步过程,通过查询找到设备,然后进行名称发现,即寻呼并连接到设备,
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.
不幸的是,Android 没有提供任何 API 来控制它并且只做查询,而且大多数蓝牙芯片组都定义并支持了定期查询功能,Android 目前没有任何 API 来进行定期查询,这可能更适合您的使用案件。