[英]Android's bluetooth BluetoothDevice.ACTION_FOUND is not being triggered?
[英]Register broadcast receiver dynamically does not work - BluetoothDevice.ACTION_FOUND
使用Log
类跟踪运行时显示onReceive()
方法没有调用,为什么?
动态注册广播接收器
private void discoverDevices () {
Log.e("MOHAB","BEFORE ON RECEIVE");
mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
Log.e("MOHAB","ON RECEIVE");
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
Bluetooth b = new Bluetooth(device.getName(),device.getAddress());
list.add(b);
}
}
};
Log.e("MOHAB","create intentFilter");
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
}
除了从Android 6.0 开始,您必须拥有ACCESS_COARSE_LOCATION
权限才能接收ACTION_FOUND
(正如@siniux 已经提到的),还有另一个相关的事情:
ACCESS_COARSE_LOCATION
是您必须在运行时向用户明确请求的危险权限之一(6.0 中的另一项安全改进)。
要诊断,您可以运行adb logcat | grep BroadcastQueue
adb logcat | grep BroadcastQueue
,并看到如下内容:
W/BroadcastQueue: Permission Denial: receiving Intent {
act=android.bluetooth.device.action.FOUND flg=0x10 (has extras) }
to ProcessRecord{9007:com.examplepackage} (pid=9007, uid=10492)
requires android.permission.ACCESS_COARSE_LOCATION due to sender
com.android.bluetooth (uid 1002)
因此,在 Marshmallow上发现 BT 设备的正确过程如下:
在清单中具有ACCESS_COARSE_LOCATION
权限要求以及通常的蓝牙权限:
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
确保您拥有ACCESS_COARSE_LOCATION
运行时权限
protected void checkLocationPermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_COARSE_LOCATION); } } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case REQUEST_COARSE_LOCATION: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { proceedDiscovery(); // ---> } else { //TODO re-request } break; } }
}
为ACTION_FOUND
注册广播接收器并调用BluetoothAdapter.startDiscovery()
protected void proceedDiscovery() { IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); filter.addAction(BluetoothDevice.ACTION_NAME_CHANGED); registerReceiver(mReceiver, filter); mBluetoothAdapter.startDiscovery(); }
关于ACTION_NAME_CHANGED
有趣的事情。 虽然 6.0 不会在未经粗略位置许可的情况下为您提供ACTION_FOUND
但您仍然会收到ACTION_NAME_CHANGED
事件,这些事件通常在设备被发现时与ACTION_FOUND
联手。 即你得到两个事件,所以没有许可,你仍然可以处理几乎相同的行为的ACTION_NAME_CHANGED
。 (大师们,如果我错了,请纠正我)
我在使用广播接收器时遇到了类似的问题。 然后我发现了这个: https : //developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id
基本上,在 6.0 上,您必须使用位置权限来扫描蓝牙设备。
您错过的是您需要启动设备发现
首先,获取蓝牙适配器
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
之后,您通过调用开始发现
mBtAdapter.startDiscovery();
您也应该在这里阅读详细信息,例如关于cancelDiscovery()
http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery%28%29
PS此外,根据官方文档,建议使用context.getSystemService(Context.BLUETOOTH_SERVICE)
在 API 18+ 上获取蓝牙适配器。
获取代表本地蓝牙适配器的BluetoothAdapter,在JELLY_BEAN_MR1及以下运行时,调用静态getDefaultAdapter()方法; 在 JELLY_BEAN_MR2 及更高版本上运行时,通过 getSystemService(Class) 和 BLUETOOTH_SERVICE 检索它。
编辑:请注意,您需要BLUETOOTH_ADMIN权限才能startDiscovery()
如专家所回复,Android 6 及以上版本的 ACTION_FOUND 工作请检查以下几点: 1. 除了设置 BLUETOOTH 和 BLUETOOTH_ADMIN 的权限外,尝试
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
有时可能不需要这两个,但它对我有用。 您还必须使用代码动态寻求用户权限
int MY_PERMISSIONS_REQUEST = 200;
int permissions=ContextCompat.checkSelfPermission (this,Manifest.permission.ACCESS_FINE_LOCATION);
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST);
现在编写用于执行所需操作的代码。 在此之后,我添加了一个 startDiscovery() 方法。 当然,这对你有用......快乐编码......
我不知道你的代码在获取蓝牙设备时是否正确。 这是我对你的代码的感受。 在函数内初始化和注册 BroadcastReceiver 是一个坏主意。 您应该在onCreate()
方法之外执行此操作。 这是您需要在代码中做的事情
至于注册 Reciver 必须像这样在onCreate()
完成
registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
跟随初始化或接收器
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.e("MOHAB","ON RECEIVE");
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
Bluetooth b = new Bluetooth(device.getName(),device.getAddress());
list.add(b);
}
}
};
在onPause()
取消注册接收器不要忘记
并且在您的discoverDevices()
只需返回reciver 为该功能的每次调用添加的设备list
;
将此作为答案发布,因为我无法对我当前的代表级别发表评论。
您的 AndroidManifest.xml 中是否包含蓝牙权限?
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
如果没有,请分别尝试(和研究)每一项,因为我不记得每一项的重要性。
如果您确实有这些,请包含更多代码,以便可以诊断您的问题。
我发现我正在开发的设备(Galaxy S4)需要重新启动才能继续接收广播。
但是,在我的情况下,我一直在毫无问题地接收它们,直到它们(随机?)停止接收并且无论我做什么(关闭应用程序,重新安装应用程序)都没有接收到广播。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.