开发者

Bluetooth pairing request on notification bar?

Hey everyone!

Started programming with Bluetooth on Android awhile ago. 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:

Bluetooth pairing request on notification bar?

And sometimes I don't have to bother with the notification, my dialog just shows up as I intended it to be.

Bluetooth pairing request on notification bar?

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:

Checked out the answer Reno gave me and it actually depends on a variety of things. 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):

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) {
        retur开发者_StackOverflown 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

BluetoothPairingRequest is a receiver for any Bluetooth pairing request. It checks if the Bluetooth Settings is currently visible and brings up the PIN, the passkey or a confirmation entry dialog. 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.

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?


Yes the thread is old but there is slightly more to it than the solution of @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. 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.

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. But it takes one more step as well. I have to have a handler for the event in a 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. It handled BOTH classic and Btle devices. 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.

Now I am writing a similar PHG that only does BTLE. I kept the startDiscovery() cycle in the background scanner because I knew I needed at LEAST that in order to get the dialog. But I removed the handlers in the 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. 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜