繁体   English   中英

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

[英]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 设备正确过程如下:

  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" />
  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; } }

    }

  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联手。 即你得到两个事件,所以没有许可,你仍然可以处理几乎相同的行为的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM