使用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
}
答案 0 :(得分:36)
除了starting with Android 6.0 you have to have the ACCESS_COARSE_LOCATION
permission to receive ACTION_FOUND
(正如@siniux已经提到的那样)之外,还有另一个相关的事情:
ACCESS_COARSE_LOCATION
属于dangerous permissions,您必须在运行时向用户明确请求(6.0中的另一项安全性改进)。
要进行诊断,您可以运行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" />
Ensure you have run-time permission 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
几乎相同的行为。 (大师,如果我错了,请纠正我)
答案 1 :(得分:13)
我遇到了与广播接收器类似的问题。 然后我发现了这个: https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id
基本上,在6.0上,您必须使用位置权限来扫描蓝牙设备。
答案 2 :(得分:7)
您错过的是您需要启动设备恢复
首先,获取蓝牙适配器
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
之后,您可以通过调用
来启动发现mBtAdapter.startDiscovery();
您也应该在此处阅读详细信息,例如:关于cancelDiscovery()
http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery%28%29
P.S。此外,根据官方文档,建议使用context.getSystemService(Context.BLUETOOTH_SERVICE)
在API 18+上获取BluetoothAdapter。
要获得代表本地蓝牙适配器的BluetoothAdapter, 在JELLY_BEAN_MR1及以下运行时,请调用静态 getDefaultAdapter()方法;在JELLY_BEAN_MR2及更高版本上运行时, 使用BLUETOOTH_SERVICE通过getSystemService(Class)检索它。
修改强>
请注意,startDiscovery()
答案 3 :(得分:4)
我不知道你的代码是否正确获取蓝牙设备。这是我对你的代码的感觉。在函数内初始化和注册BroadcastReceiver是一个坏主意。你应该在onCreate()
方法之外做。
这是您需要在代码中执行的操作
关于注册必须在此onCreate()
中完成的Reciver
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()
中的reciver不要忘记
并在discoverDevices()
中只返回reciver为每次调用该函数而添加的list
个设备;
答案 4 :(得分:1)
据专家回复,您可以查看以下几点以使ACTION_FOUND在Android 6及更高版本中正常工作, 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()方法。 当然,这对你有用...... 快乐的编码...
答案 5 :(得分:0)
将此作为答案发布,因为我无法评论我目前的代表级别。
您是否拥有包含在AndroidManifest.xml中的蓝牙权限?
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
如果没有,请分别尝试(和研究)每一个,因为我不记得每一个的重要性。
如果您有这些,请包含更多代码,以便诊断您的问题。
答案 6 :(得分:0)
我发现我在(Galaxy S4)上开发的设备需要重新启动,然后才能继续接收广播。
但是,就我而言,直到他们(随机?)停止接收并且无论我做什么(关闭应用程序,重新安装应用程序)都没有收到广播之前,我一直没有收到它们。