Bluetooth pairing request on notification bar?
Asked Answered
A

3

14

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:

In english: Pairing request for Bluetooth

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

Pairing dialog shows up and there was no notification on the status 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) {
        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
Aquavit answered 25/7, 2011 at 14:20 Comment(0)
T
9

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
Team answered 27/7, 2011 at 8:11 Comment(5)
Wow thanks Reno. This should really be explained in the dev. docs! So I should put it in front I guess or make it somewhat visibile, i'll try it out but if you know the answer please feel free to share it :)Aquavit
I'm talking about BT visibility, you should send an ACTION_REQUEST_DISCOVERABLE intent to request the device to be visible so that other devices can find it.Team
I actually do that, but i run cancelDiscovery() when the device is discovered. At this link You can see under "Discovering devices" that one should run cancelDiscovery() once the device is discovered... right?Aquavit
True, it seems you have some kind of timing of events issue with your application. (i.e. when your pairing request arrives, the phone is not discoverable.)Team
Actually, The embedded device should be discoverable right? I don't have to be discoverable in order to connect to the device. The thing I do is that I search for devices and then request to connect. A PIN i selected on the embedded device and then the request comes.. thats when the program either shows a dialog or a notificationAquavit
C
1

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?

Connive answered 23/1, 2020 at 15:31 Comment(1)
Doesn't work in my caseCartie
T
0

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.

Threadbare answered 14/3, 2020 at 16:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.