简体   繁体   English

通知栏上的蓝牙配对请求?

[英]Bluetooth pairing request on notification bar?

Hey everyone!嘿大家!

Started programming with Bluetooth on Android awhile ago.不久前开始在 Android 上使用蓝牙进行编程。 But now I've run into some issues.但现在我遇到了一些问题。 I'm wondering why the pairing request sometimes shows up in the notification bar and sometimes this is skipped and the dialog is shown directly.我想知道为什么配对请求有时会显示在通知栏中,有时会被跳过而直接显示对话框。

For example: I initiate my pairing request from an embedded device and then there's a notification such as this one:例如:我从嵌入式设备发起配对请求,然后出现如下通知:

中文:蓝牙配对请求

And sometimes I don't have to bother with the notification, my dialog just shows up as I intended it to be.有时我不必理会通知,我的对话框会按照我的预期显示。

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

Is there way to catch that notification and display the dialog or is this a bug in my code when I initiate bluetooth pairing?有没有办法捕获该通知并显示对话框,或者这是我启动蓝牙配对时代码中的错误?

EDIT:编辑:

UPDATE 1:更新1:

Checked out the answer Reno gave me and it actually depends on a variety of things.查看 Reno 给我的答案,它实际上取决于多种情况。 There are other means of showing the dialog directly.还有其他方法可以直接显示对话框。 The following method is called when the pairing request arrives.当配对请求到达时调用以下方法。 A check is done in order to see if the dialog should be displayed in the foreground (true) or as a notification (false):进行检查以查看对话框是否应显示在前台 (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;
}

This is a snippet from the source code and as you can see that there are ways of making the dialog show:这是源代码中的一个片段,正如您所看到的,有多种方法可以显示对话框:

  1. If the device was in discoverable mode recently如果设备最近处于可发现模式
  2. If the device was discovering recently如果设备最近正在发现
  3. If the device was picked in the device picker recently如果最近在设备选择器中选择了设备
  4. If Bluetooth Settings is visible如果蓝牙设置可见

As per a comment I saw in the android source code根据我在 android 源代码中看到的评论

BluetoothPairingRequest is a receiver for any Bluetooth pairing request. BluetoothPairingRequest 是任何蓝牙配对请求的接收器。 It checks if the Bluetooth Settings is currently visible and brings up the PIN, the passkey or a confirmation entry dialog.它会检查蓝牙设置当前是否可见并显示 PIN、密码或确认输入对话框。 Otherwise it puts a Notification in the status bar, which can be clicked to bring up the Pairing entry dialog.否则,它会在状态栏中放置一个通知,可以单击该通知以显示配对条目对话框。

So yeah, depending on the BT visibility, the dialog/notification will be shown.所以是的,根据 BT 的可见性,将显示对话框/通知。

ninja edit: 

This may vary depending on the hardware used.这可能会因所使用的硬件而异。

  • If the device was in discoverABLE mode recently如果设备最近处于可发现模式
  • If the device was discoverING recently如果设备最近正在发现
  • If the device was picked in the device picker recently如果最近在设备选择器中选择了设备

I know this thread is old but I would like to add a simple answer for people having the same problem.我知道这个帖子很旧,但我想为有同样问题的人添加一个简单的答案。 The answer above very well explains why and what but does not show a simple solution.上面的答案很好地解释了原因和内容,但没有显示简单的解决方案。

Calling this function before initiating a bonding does the job:在启动绑定之前调用此函数可以完成以下工作:

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

It just triggers a discovery.它只是触发了一个发现。 Looks somehow stupid but seems to work very well.看起来有点愚蠢,但似乎工作得很好。

See also here: Android Bluetooth Pairing: How to make sure to get bluetooth pairing request in the front dialog instead of a notification?另请参见此处: Android 蓝牙配对:如何确保在前面的对话框中获得蓝牙配对请求而不是通知?

Yes the thread is old but there is slightly more to it than the solution of @maze.是的,线程很旧,但它比@maze 的解决方案略多。

EDIT: I take this addition following back.编辑:我接受了这个补充。 I found in my BTLE-only application that I did not invoke startDiscovery in the period allocated for it, and that was why @maze solution did not work.我发现在我的 BTLE-only 应用程序中,我没有在为其分配的时间段内调用 startDiscovery,这就是 @maze 解决方案不起作用的原因。 I think the only reason the addition worked is that I had tried my classic & BTLE app just before and the time had not elapsed.我认为添加工作的唯一原因是我之前尝试过我的经典和 BTLE 应用程序并且时间还没有过去。

If I want a dialog to popup instead of a notification on a pairing event, I must have called startDiscovery() within one minute of the pairing request.如果我想要弹出一个对话框而不是配对事件的通知,我必须在配对请求的一分钟内调用 startDiscovery()。 But it takes one more step as well.但这也需要多走一步。 I have to have a handler for the event in a BroadcastReceiver.我必须在 BroadcastReceiver 中有一个事件处理程序。

I stumbled upon this because I had written a PHG that uses a continuous background search process which cycles between startDiscovery() for X seconds and then a Btle Scan for Y seconds.我偶然发现了这一点,因为我编写了一个使用连续后台搜索过程的 PHG,该过程在 startDiscovery() 之间循环 X 秒,然后 Btle 扫描 Y 秒。 It handled BOTH classic and Btle devices.它处理经典和 Btle 设备。 I knew that I needed to have the startDiscovery call but since the classic discovery is handled in a BroadcastReceiver I had handlers for it.我知道我需要调用 startDiscovery 但由于经典发现是在 BroadcastReceiver 中处理的,因此我有处理程序。

Now I am writing a similar PHG that only does BTLE.现在我正在写一个类似的 PHG,它只支持BTLE。 I kept the startDiscovery() cycle in the background scanner because I knew I needed at LEAST that in order to get the dialog.我在后台扫描程序中保留了 startDiscovery() 循环,因为我知道我至少需要它才能获得对话框。 But I removed the handlers in the BroadcastReceiver.但是我删除了 BroadcastReceiver 中的处理程序。 The only handlers I had were for pairing events.我唯一的处理程序是配对事件。 Result - no dialog.结果 - 没有对话框。 SO I added the following back even though they now do nothing but print a log:所以我添加了以下内容,即使他们现在除了打印日志什么都不做:

    //================ 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());
    }

Unfortunately I don't know if I need all of the above or just the 'ACTION_FOUND' handler.不幸的是,我不知道我是否需要上述所有内容或仅需要“ACTION_FOUND”处理程序。 I suppose I could remove the others one by one and see if I still get the dialog, but I have been hit by a streak of laziness.我想我可以一个一个地删除其他人,看看我是否仍然能看到对话,但我被一连串的懒惰击中了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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