Android - 蓝牙发现未找到任何设备
Android - Bluetooth discovery doesn't find any device
我目前正在开发一个小应用程序来开始使用蓝牙 Android API 可以提供的服务。
编辑 -> 答案:
问题似乎是由特定的 Nexus 5 设备引起的。好像他们的蓝牙接收器不能正常工作。以下解决方案应该适用于其他设备
备注:
我已阅读此处的文档:http://developer.android.com/guide/topics/connectivity/bluetooth.html
以及本教程的以下源代码 http://www.londatiga.net/it/programming/android/how-to-programmatically-scan-or-discover-android-bluetooth-device/ 位于 /lorensiuswlt/AndroBluetooth
下的 github
我几乎完成了所有我感兴趣的功能(例如检查适配器是否存在、enable/disable 蓝牙、查询配对设备、设置适配器可发现)。
问题:
实际上,当我启动 .onDiscovery() 方法时,没有找到任何设备,即使在我的 Nexus 5 上 Settings/Bluetooth 找到了设备。
我是这样处理的:
public class MainActivity extends AppCompatActivity {
private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
...
protected void onCreate(Bundle savedInstanceState) {
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mReceiver, filter);
}
据我所知,过滤器运行良好,即 ACTION_STATE_CHANGED(启用蓝牙)和两个 ACTION_DISCOVERY_***。
然后成功调用了以下方法:
public void onDiscovery(View view)
{
mBluetoothAdapter.startDiscovery();
}
然后我有我的蓝牙接收器:
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
if (state == BluetoothAdapter.STATE_ON) {
showToast("ACTION_STATE_CHANGED: STATE_ON");
}
}
else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
mDeviceList = new ArrayList<>();
showToast("ACTION_DISCOVERY_STARTED");
mProgressDlg.show();
}
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action) && !bluetoothSwitchedOFF) {
mProgressDlg.dismiss();
showToast("ACTION_DISCOVERY_FINISHED");
Intent newIntent = new Intent(MainActivity.this, DeviceListActivity.class);
newIntent.putParcelableArrayListExtra("device.list", mDeviceList);
startActivity(newIntent);
}
else if (BluetoothDevice.ACTION_FOUND.equals(action)) {// When discovery finds a device
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
mDeviceList.add(device);
showToast("Device found = " + device.getName());
}
}
};
我在 logcat 中没有遇到任何问题,在我进行的测试中也没有发现任何问题。唯一的问题是扫描结束时没有发现任何设备,而周围有许多可发现的设备。
我尽量不放太多代码以免淹没主题。问我是否需要更多。
感谢阅读我的文章,并提前感谢您的回答。
你 运行 使用的 Android 是什么版本?如果是 Android 6.x,我相信你需要在清单中添加 ACCESS_FINE_LOCATION
权限。例如:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
我遇到了类似的问题,这为我解决了。
更新:在此添加documentation direct from Google:
To access the hardware identifiers of nearby external devices via Bluetooth and Wi-Fi scans, your app must now have the ACCESS_FINE_LOCATION
or ACCESS_COARSE_LOCATION
permissions
2020 年更新: 我们最近将我们的应用程序更新为目标 SDK 版本 29。在执行此操作时,我们的应用程序不再能够再次发现蓝牙设备。自从最初编写此答案以来,我们一直在使用 ACCESS_COARSE_LOCATION
。更改为 ACCESS_FINE_LOCATION
似乎可以解决问题。我现在建议开发者尝试 ACCESS_FINE_LOCATION
如果目标是 29+。已更新答案以反映这一点。
聚会有点晚了,但这对其他人可能会派上用场。
你需要做两件事
- 添加
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
或<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
给你的AndroidManifest.xml
确保您也在使用类似这样的方式为 Android 6.0 设备请求运行时权限
int MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION = 1;
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION);
就在mBluetoothAdapter.startDiscovery();
之前
如果您不执行第 2 步,您将无法在 Android >= 6.0
的设备上获取任何硬件标识符信息
UPDATE/EDIT:
Android 版本检查和警报对话框作为警告的示例
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // Only ask for these permissions on runtime when running Android 6.0 or higher
switch (ContextCompat.checkSelfPermission(getBaseContext(), Manifest.permission.ACCESS_COARSE_LOCATION)) {
case PackageManager.PERMISSION_DENIED:
((TextView) new AlertDialog.Builder(this)
.setTitle("Runtime Permissions up ahead")
.setMessage(Html.fromHtml("<p>To find nearby bluetooth devices please click \"Allow\" on the runtime permissions popup.</p>" +
"<p>For more info see <a href=\"http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id\">here</a>.</p>"))
.setNeutralButton("Okay", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (ContextCompat.checkSelfPermission(getBaseContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(DeviceListActivity.this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_ACCESS_COARSE_LOCATION);
}
}
})
.show()
.findViewById(android.R.id.message))
.setMovementMethod(LinkMovementMethod.getInstance()); // Make the link clickable. Needs to be called after show(), in order to generate hyperlinks
break;
case PackageManager.PERMISSION_GRANTED:
break;
}
}
我目前正在开发一个小应用程序来开始使用蓝牙 Android API 可以提供的服务。
编辑 -> 答案:
问题似乎是由特定的 Nexus 5 设备引起的。好像他们的蓝牙接收器不能正常工作。以下解决方案应该适用于其他设备
备注:
我已阅读此处的文档:http://developer.android.com/guide/topics/connectivity/bluetooth.html 以及本教程的以下源代码 http://www.londatiga.net/it/programming/android/how-to-programmatically-scan-or-discover-android-bluetooth-device/ 位于 /lorensiuswlt/AndroBluetooth
下的 github
我几乎完成了所有我感兴趣的功能(例如检查适配器是否存在、enable/disable 蓝牙、查询配对设备、设置适配器可发现)。
问题:
实际上,当我启动 .onDiscovery() 方法时,没有找到任何设备,即使在我的 Nexus 5 上 Settings/Bluetooth 找到了设备。
我是这样处理的:
public class MainActivity extends AppCompatActivity {
private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
...
protected void onCreate(Bundle savedInstanceState) {
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mReceiver, filter);
}
据我所知,过滤器运行良好,即 ACTION_STATE_CHANGED(启用蓝牙)和两个 ACTION_DISCOVERY_***。
然后成功调用了以下方法:
public void onDiscovery(View view)
{
mBluetoothAdapter.startDiscovery();
}
然后我有我的蓝牙接收器:
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
if (state == BluetoothAdapter.STATE_ON) {
showToast("ACTION_STATE_CHANGED: STATE_ON");
}
}
else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
mDeviceList = new ArrayList<>();
showToast("ACTION_DISCOVERY_STARTED");
mProgressDlg.show();
}
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action) && !bluetoothSwitchedOFF) {
mProgressDlg.dismiss();
showToast("ACTION_DISCOVERY_FINISHED");
Intent newIntent = new Intent(MainActivity.this, DeviceListActivity.class);
newIntent.putParcelableArrayListExtra("device.list", mDeviceList);
startActivity(newIntent);
}
else if (BluetoothDevice.ACTION_FOUND.equals(action)) {// When discovery finds a device
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
mDeviceList.add(device);
showToast("Device found = " + device.getName());
}
}
};
我在 logcat 中没有遇到任何问题,在我进行的测试中也没有发现任何问题。唯一的问题是扫描结束时没有发现任何设备,而周围有许多可发现的设备。
我尽量不放太多代码以免淹没主题。问我是否需要更多。
感谢阅读我的文章,并提前感谢您的回答。
你 运行 使用的 Android 是什么版本?如果是 Android 6.x,我相信你需要在清单中添加 ACCESS_FINE_LOCATION
权限。例如:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
我遇到了类似的问题,这为我解决了。
更新:在此添加documentation direct from Google:
To access the hardware identifiers of nearby external devices via Bluetooth and Wi-Fi scans, your app must now have the
ACCESS_FINE_LOCATION
orACCESS_COARSE_LOCATION
permissions
2020 年更新: 我们最近将我们的应用程序更新为目标 SDK 版本 29。在执行此操作时,我们的应用程序不再能够再次发现蓝牙设备。自从最初编写此答案以来,我们一直在使用 ACCESS_COARSE_LOCATION
。更改为 ACCESS_FINE_LOCATION
似乎可以解决问题。我现在建议开发者尝试 ACCESS_FINE_LOCATION
如果目标是 29+。已更新答案以反映这一点。
聚会有点晚了,但这对其他人可能会派上用场。
你需要做两件事
- 添加
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
或<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
给你的AndroidManifest.xml
确保您也在使用类似这样的方式为 Android 6.0 设备请求运行时权限
int MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION = 1; ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION);
就在
mBluetoothAdapter.startDiscovery();
之前
如果您不执行第 2 步,您将无法在 Android >= 6.0
的设备上获取任何硬件标识符信息UPDATE/EDIT:
Android 版本检查和警报对话框作为警告的示例
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // Only ask for these permissions on runtime when running Android 6.0 or higher
switch (ContextCompat.checkSelfPermission(getBaseContext(), Manifest.permission.ACCESS_COARSE_LOCATION)) {
case PackageManager.PERMISSION_DENIED:
((TextView) new AlertDialog.Builder(this)
.setTitle("Runtime Permissions up ahead")
.setMessage(Html.fromHtml("<p>To find nearby bluetooth devices please click \"Allow\" on the runtime permissions popup.</p>" +
"<p>For more info see <a href=\"http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id\">here</a>.</p>"))
.setNeutralButton("Okay", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (ContextCompat.checkSelfPermission(getBaseContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(DeviceListActivity.this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_ACCESS_COARSE_LOCATION);
}
}
})
.show()
.findViewById(android.R.id.message))
.setMovementMethod(LinkMovementMethod.getInstance()); // Make the link clickable. Needs to be called after show(), in order to generate hyperlinks
break;
case PackageManager.PERMISSION_GRANTED:
break;
}
}