11

I'm a beginner in Android programming since I only started 3 months ago. I'm doing a project which connects the android app to arduino using bluetooth. I already have a code for the android app (bluetooth.adapter,sockets,.etc.). The code for connection is already working. One of the goal is for the android app to automatically input the password when pairing with the bluetooth device without asking user to input the PIN.

The old posts on this forum do not help much. (many suggested using insecure mode, but I do need secure mode, also in my case, the arduino is the server while cellphone app is the client, so the createInsecureRfcommSocketToServiceRecord() server method does not work for me)

I searched and found this in android developer site about bluetoothdevice class:

setPairingConfirmation(boolean confirm) Confirm passkey for PAIRING_VARIANT_PASSKEY_CONFIRMATION pairing.

PAIRING_VARIANT_PIN = "The user will be prompted to enter a pin or an app will enter a pin for user".

PAIRING_VARIANT_PASSKEY_CONFIRMATION = "The user will be prompted to confirm the passkey displayed on the screen or an app will confirm the passkey for the user"

Seems using the code, the app will be the one to input the password and confirm the password making it an "auto-connect" features but the android site does not give a sample code on how to use this. Does any of you have a sample code in using this or related process? I appreciate your help!

anticafe
  • 6,816
  • 9
  • 43
  • 74
ian
  • 269
  • 1
  • 2
  • 6

3 Answers3

14

First to clarify, this solution is designed for newer version of API (15 or later?)

I found the answer written in another post (see Roldofo's answer in Here). Here is my reorganized answer with detailed code.

In a nutshell, you need to setup a broadcast receiver to trap the ACTION_PAIRING_REQUEST, and then programmatically pass the PIN and confirm.

Register a broadcast receiver:

    IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST);
    getActivity().registerReceiver(mPairingRequestReceiver, filter);

The definition of the receiver:

private final BroadcastReceiver mPairingRequestReceiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) {
            try {
                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    int pin=intent.getIntExtra("android.bluetooth.device.extra.PAIRING_KEY", 1234);
                    //the pin in case you need to accept for an specific pin
                    Log.d(TAG, "Start Auto Pairing. PIN = " + intent.getIntExtra("android.bluetooth.device.extra.PAIRING_KEY",1234));
                    byte[] pinBytes;
                    pinBytes = (""+pin).getBytes("UTF-8");
                    device.setPin(pinBytes);
                    //setPairing confirmation if neeeded
                    device.setPairingConfirmation(true);
            } catch (Exception e) {
                Log.e(TAG, "Error occurs when trying to auto pair");
                e.printStackTrace();
            }
        }
    }
};

Then at your activity or fragment (wherever you want to initiate the pairing), you can call the following defined pairDevice() method to invoke pairing attempt (which will generate a ACTION_PAIRING_REQUEST)

private void pairDevice(BluetoothDevice device) {
    try {
        Log.d(TAG, "Start Pairing... with: " + device.getName());
        device.createBond();
        Log.d(TAG, "Pairing finished.");
    } catch (Exception e) {
        Log.e(TAG, e.getMessage());
    }
}
Community
  • 1
  • 1
ian
  • 269
  • 1
  • 2
  • 6
  • How can I handle passcode/pin contains varchars like string "hello123"? – mumair Nov 20 '16 at 17:44
  • 2
    Why is setPairingConfirmation() needed ? Android docs say that it only applies for PAIRING_VARIANT_PASSKEY_CONFIRMATION, not legacy pairing. Furthermore, on Android6 it requires BLUETOOTH_PRIVILEGED – Sergio Martins Jan 12 '17 at 11:39
  • 1
    Unfortunately in current API level the BLUETOOTH_PRIVILEGED is not available. Doc: `This is not available to third party applications.` – appsthatmatter Feb 10 '17 at 19:47
  • 1
    what to do if I don't want the pairing key input pop up to be visible? – Pooja Rajendran C Feb 16 '17 at 07:31
  • 2
    @SergioMartins I see in documentation of `BluetoothDevice.setPairingConfirmation` and realize it requires permission BLUETOOTH_ADMIN instead of BLUETOOTH_PRIVILEGED – anticafe Aug 29 '17 at 04:44
  • For BLUETOOTH_PRIVILEGED permission to work, the app must me installed like a system app. – gregoryp Jan 16 '18 at 10:47
  • Its not working fine. User Confirmation popup (Dialog) is again shown. – sivaprakash Jan 19 '18 at 11:45
  • This code stopped working in Android version 7, see https://android.googlesource.com/platform/packages/apps/Bluetooth/+/android-7.0.0_r24 – rastik Nov 05 '18 at 22:30
  • Yes the reasons are this approach dont work in latest android versions are : 1. From Android API version 26 onward requires permission required BLUETOOTH_ADMIN instead of BLUETOOTH_PRIVILEGED and for admin it shall be system app. 2. Even on Android API 28 onward due to more enhanced security even we have to enter code in each connection means even it is paired we have to enter the pairing code again before establishing connection – Jitendra Chaudhari Nov 07 '19 at 05:27
3

I also faced the same problem and after all the research, I figured out the below solution.

(Tested and working!!!)

I am basically looking for a particular bluetooth device (I know MAC address) and pair with it once found. The first thing to do is to create pair request using boradcast receiver and handle the request as below.

IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST);
                intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
                registerReceiver(broadCastReceiver,intentFilter);

You need to write the broadcastReceiver and handle it as below.

String BLE_PIN = "1234"
private BroadcastReceiver broadCastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if(BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action))
        {
            BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            bluetoothDevice.setPin(BLE_PIN.getBytes());
            Log.e(TAG,"Auto-entering pin: " + BLE_PIN);
            bluetoothDevice.createBond();
            Log.e(TAG,"pin entered and request sent...");
        }
    }
};

Voila! You should be able to pair to bluetooth device without ANY MANUAL INTERVENTION.

Hope this helps :-) Please make it right answer if it works for you.

Varun A M
  • 1,103
  • 2
  • 14
  • 29
  • is this solution also work for android oreo and pie ? – Tejas Pandya Feb 04 '19 at 07:48
  • Yes. As far as I know, it works. You can please try and post your update here. – Varun A M Feb 05 '19 at 08:24
  • can you shed some light on [my question](https://stackoverflow.com/q/54529441/6880611) – Tejas Pandya Feb 05 '19 at 08:44
  • 3
    Not working! Firstly if you set a Pin, you also have to confirm the pairing request, this operation can only be make with manual intervention (Android security). Second, you are not dismissing the intent inside the receiver with "abortBroadcast()" – Onivas May 11 '19 at 12:42
1

Yes this possible to do by code

In you main activity add the following code

BluetoothReceiver myreceiver = new BluetoothReceiver();
var intentfilterparingrequest = new IntentFilter(BluetoothDevice.ActionPairingRequest);
RegisterReceiver(myreceiver, intentfilterparingrequest);

In your broadcast receiver write following code, if not create a new broadcast receiver

public class BluetoothReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        string BLE_PIN = "0000";
        var action = intent.Action;
        switch (action)
        {
            case BluetoothDevice.ActionPairingRequest:
                BluetoothDevice bluetoothDevice = 
              (BluetoothDevice)intent.GetParcelableExtra(BluetoothDevice.ExtraDevice);
                bluetoothDevice.SetPin(Encoding.ASCII.GetBytes(BLE_PIN));
                bluetoothDevice.CreateBond();
                break;
        }
    } 
}
Mehul Sant
  • 29
  • 3