13

嘿大家!

不久前开始在 Android 上使用蓝牙进行编程。但现在我遇到了一些问题。我想知道为什么配对请求有时会出现在通知栏中,有时会被跳过并直接显示对话框。

例如:我从嵌入式设备发起我的配对请求,然后有一个通知,例如:

In Chinese: 蓝牙配对请求

有时我不必理会通知,我的对话框会按照我的预期显示。

配对对话框出现,状态栏上没有通知

当我启动蓝牙配对时,有没有办法捕获该通知并显示对话框,或者这是我的代码中的错误?

编辑:

更新 1:

查看 Reno 给我的答案,它实际上取决于很多事情。还有其他直接显示对话框的方法。当配对请求到达时,会调用以下方法。进行检查是为了查看对话框是否应该显示在前台 (true) 或作为通知 (false):

public boolean shouldShowDialogInForeground(String deviceAddress) {
    // If Bluetooth Settings is visible
    if (mForegroundActivity != null) return true;

    long currentTimeMillis = System.currentTimeMillis();
    SharedPreferences sharedPreferences = getSharedPreferences();

    // If the device was in discoverABLE mode recently
    long lastDiscoverableEndTime = sharedPreferences.getLong(
            BluetoothDiscoverableEnabler.SHARED_PREFERENCES_KEY_DISCOVERABLE_END_TIMESTAMP, 0);
    if ((lastDiscoverableEndTime + GRACE_PERIOD_TO_SHOW_DIALOGS_IN_FOREGROUND)
            > currentTimeMillis) {
        return true;
    }

    // If the device was discoverING recently
    if (mAdapter != null && mAdapter.isDiscovering()) {
        return true;
    } else if ((sharedPreferences.getLong(SHARED_PREFERENCES_KEY_DISCOVERING_TIMESTAMP, 0) +
            GRACE_PERIOD_TO_SHOW_DIALOGS_IN_FOREGROUND) > currentTimeMillis) {
        return true;
    }

    // If the device was picked in the device picker recently
    if (deviceAddress != null) {
        String lastSelectedDevice = sharedPreferences.getString(
                SHARED_PREFERENCES_KEY_LAST_SELECTED_DEVICE, null);

        if (deviceAddress.equals(lastSelectedDevice)) {
            long lastDeviceSelectedTime = sharedPreferences.getLong(
                    SHARED_PREFERENCES_KEY_LAST_SELECTED_DEVICE_TIME, 0);
            if ((lastDeviceSelectedTime + GRACE_PERIOD_TO_SHOW_DIALOGS_IN_FOREGROUND)
                    > currentTimeMillis) {
                return true;
            }
        }
    }
    return false;
}

这是源代码的一个片段,您可以看到有多种方法可以显示对话框:

  1. 如果设备最近处于可发现模式
  2. 如果设备最近发现
  3. 如果最近在设备选择器中选择了设备
  4. 如果蓝牙设置可见
4

3 回答 3

9

根据我在 android 源代码中看到的评论

BluetoothPairingRequest 是任何蓝牙配对请求的接收器。它会检查蓝牙设置当前是否可见,并显示 PIN、密码或确认输入对话框。否则,它会在状态栏中放置一个通知,单击该通知可以调出配对条目对话框。

所以是的,根据 BT 的可见性,将显示对话框/通知。

ninja edit: 

这可能因使用的硬件而异。

  • 如果设备最近处于可发现模式
  • 如果设备最近发现
  • 如果最近在设备选择器中选择了设备
于 2011-07-27T08:11:21.117 回答
0

我知道这个线程很旧,但我想为有同样问题的人添加一个简单的答案。上面的答案很好地解释了为什么和什么,但没有显示一个简单的解决方案。

在启动绑定之前调用此函数可以完成以下工作:

private void feintBluetoothDeviceDiscovery() {
    BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
    btAdapter.startDiscovery();
    btAdapter.cancelDiscovery();
}

它只是触发一个发现。看起来有点愚蠢,但似乎工作得很好。

另请参阅:Android 蓝牙配对:如何确保在前面的对话框中获得蓝牙配对请求而不是通知?

于 2020-01-23T15:31:03.827 回答
0

是的,线程很旧,但它比@maze 的解决方案稍微多一点。

编辑:我把这个添加回来。我在我的 BTLE-only 应用程序中发现我没有在分配给它的时间段内调用 startDiscovery,这就是为什么@maze 解决方案不起作用。我认为添加工作的唯一原因是我之前尝试过我的经典和 BTLE 应用程序并且时间还没有过去。

如果我想弹出一个对话框而不是关于配对事件的通知,我必须在配对请求的一分钟内调用 startDiscovery()。但它也需要多一步。我必须在 BroadcastReceiver 中有一个事件处理程序。

我偶然发现了这一点,因为我编写了一个使用连续后台搜索过程的 PHG,该过程在 startDiscovery() 持续 X 秒和 Btle Scan 持续 Y 秒之间循环。它同时处理经典设备和 Btle 设备。我知道我需要调用 startDiscovery,但由于经典发现是在 BroadcastReceiver 中处理的,所以我有它的处理程序。

现在我正在写一个类似的只做BTLE 的 PHG。我在后台扫描仪中保留了 startDiscovery() 循环,因为我知道我至少需要它才能获得对话框。但是我删除了 BroadcastReceiver 中的处理程序。我拥有的唯一处理程序是用于配对事件。结果 - 没有对话框。所以我添加了以下内容,即使他们现在除了打印日志什么都不做:

    //================ CONNECT ==============================
    if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(intent.getAction()))
    {
        Log.i(TAG, "BT State Receiver signaled with connected for device " + device.getName() + " with bond state " + device.getBondState());
    }

    //================ DISCONNECT ==============================
    else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(intent.getAction()))
    {

        Log.i(TAG, "BT State Receiver signaled with disconnect for device " + device.getName() + " with bond state " + device.getBondState());
    }

    //================ START/STOP DISCOVERY ==============================
    else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(intent.getAction()))
    {
        Log.i(TAG, "BT State Receiver signaled discovery started");
    }
    else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction()))
    {
        Log.v(TAG, "BT State receiver, discovery stopped");
    }

    //================ FOUND DEVICE ==============================
    else if (BluetoothDevice.ACTION_FOUND.equals(intent.getAction()))
    {
            Log.v(TAG, "Device discovered: name " + device.getName() +
                    " Bond state " + device.getBondState());
    }

不幸的是,我不知道我是需要以上所有内容还是只需要“ACTION_FOUND”处理程序。我想我可以一个一个地删除其他人,看看我是否仍然得到对话,但我已经被一连串的懒惰击中了。

于 2020-03-14T16:05:46.457 回答