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

Err*_*ror 13 android android-broadcastreceiver

Logclass跟踪运行时显示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

}
Run Code Online (Sandbox Code Playgroud)

Iva*_*sov 40

除了从Android 6.0开始你必须ACCESS_COARSE_LOCATION有权接收ACTION_FOUND(如@siniux已经提到的),还有另一个相关的事情:

ACCESS_COARSE_LOCATION是您必须在运行时向用户明确请求的危险权限之一(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)
Run Code Online (Sandbox Code Playgroud)

因此,在棉花糖发现BT设备正确程序如下:

  1. 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" />
    
    Run Code Online (Sandbox Code Playgroud)
  2. 确保已运行时允许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;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    }

  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();
    }
    
    Run Code Online (Sandbox Code Playgroud)

有趣的事情ACTION_NAME_CHANGED.虽然6.0在ACTION_FOUND没有粗略位置许可的情况下无法为您提供服务,但您仍然可以获得ACTION_NAME_CHANGED事件,这些事件通常会ACTION_FOUND在发现设备时与其联系.也就是说你得到了这两个事件,所以如果没有这个许可,你仍然可以处理ACTION_NAME_CHANGED几乎相同的行为.(大师,如果我错了,请纠正我)

  • 这个答案带来了很多有用的信息。谢谢 (2认同)

小智 13

我的广播接收器遇到了类似的问题.然后我发现了这个:https: //developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id

基本上,在6.0上,您必须使用位置权限来扫描蓝牙设备.


Der*_*ung 7

您错过的是您需要启动设备恢复

首先,获取蓝牙适配器

BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
Run Code Online (Sandbox Code Playgroud)

之后,您通过调用开始发现

mBtAdapter.startDiscovery();
Run Code Online (Sandbox Code Playgroud)

你也应该在这里阅读详细信息,例如cancelDiscovery() http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery%28%29

PS此外,context.getSystemService(Context.BLUETOOTH_SERVICE)根据官方文档,建议用于在API 18+上获取BluetoothAdapter.

要获得代表本地蓝牙适配器的BluetoothAdapter,在JELLY_BEAN_MR1及更低版本上运行时,请调用静态getDefaultAdapter()方法; 在JELLY_BEAN_MR2及更高版本上运行时,使用BLUETOOTH_SERVICE通过getSystemService(Class)检索它.

编辑: 提醒您需要BLUETOOTH_ADMIN权限startDiscovery()


小智 6

根据专家的回答,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" />
Run Code Online (Sandbox Code Playgroud)

有时可能不需要这两个,但它对我有用。您还必须使用代码动态寻求用户权限

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);
Run Code Online (Sandbox Code Playgroud)

现在编写用于执行所需操作的代码。在此之后,我添加了一个 startDiscovery() 方法。当然,这对你有用......快乐编码......