android - 动态注册广播接收器不起作用 - BluetoothDevice.ACTION_FOUND

标签 android android-broadcastreceiver

使用 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

}

最佳答案

除了starting with Android 6.0 you have to have the ACCESS_COARSE_LOCATION permission to receive ACTION_FOUND (正如@siniux 已经提到的),还有另一个相关的事情:

ACCESS_COARSE_LOCATIONdangerous 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 设备的正确过程如下:

  1. list 中有 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" />
    
  2. 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;
        }
    }
    

  3. 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 发现设备时。 IE。你得到了这两个事件,所以没有许可,你仍然可以处理 ACTION_NAME_CHANGED 几乎相同的行为。 (大师,如果我错了请纠正我)

关于android - 动态注册广播接收器不起作用 - BluetoothDevice.ACTION_FOUND,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32656510/

相关文章:

android - 无法使用 ksoap 在嵌套对象内发送数组

android - 如何在 Android Studio 中生成和使用 UML 图

android - 从网站切换到免安装应用

android - 如何获取带有日期和时间的拨出电话号码?

android - 如何创建永远不会在任务管理器中强制停止的服务/广播接收器

android - 除非断点,否则通知不会更新

Android - 尝试添加应用程序快捷方式时出错

android - Intent 错误以更改 Activity

java - 使用 Toast 监控传入的短信

android - 如何让我的广播接收器保持活力