From 27293db312c9057307458207f01c15fc1e5a0d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Allard?= Date: Thu, 7 Nov 2019 16:35:28 +0100 Subject: [PATCH] Add bind() with PIN. --- .../com/megster/cordova/BluetoothSerial.java | 99 ++++++++++++++----- www/bluetoothSerial.js | 9 +- 2 files changed, 82 insertions(+), 26 deletions(-) diff --git a/src/android/com/megster/cordova/BluetoothSerial.java b/src/android/com/megster/cordova/BluetoothSerial.java index 8be5575f..d5915cc8 100644 --- a/src/android/com/megster/cordova/BluetoothSerial.java +++ b/src/android/com/megster/cordova/BluetoothSerial.java @@ -34,6 +34,7 @@ public class BluetoothSerial extends CordovaPlugin { private static final String LIST = "list"; private static final String CONNECT = "connect"; private static final String CONNECT_INSECURE = "connectInsecure"; + private static final String BIND = "bind"; private static final String DISCONNECT = "disconnect"; private static final String WRITE = "write"; private static final String AVAILABLE = "available"; @@ -119,6 +120,10 @@ public boolean execute(String action, CordovaArgs args, CallbackContext callback boolean secure = false; connect(args, secure, callbackContext); + } else if (action.equals(BIND)) { + + bind(args, callbackContext); + } else if (action.equals(DISCONNECT)) { connectCallback = null; @@ -301,7 +306,7 @@ public void onReceive(Context context, Intent intent) { if (BluetoothDevice.ACTION_FOUND.equals(action)) { BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); try { - JSONObject o = deviceToJSON(device); + JSONObject o = deviceToJSON(device); unpairedDevices.put(o); if (ddc != null) { PluginResult res = new PluginResult(PluginResult.Status.OK, o); @@ -354,28 +359,74 @@ private void connect(CordovaArgs args, boolean secure, CallbackContext callbackC } } + private void bind(CordovaArgs args, CallbackContext callbackContext) throws JSONException { + String macAddress = args.getString(0); + BluetoothDevice device = bluetoothAdapter.getRemoteDevice(macAddress); + if (device == null) { + Log.e(TAG, "Unknown device: " + macAddress); + callbackContext.error("Could not bind with " + macAddress); + return; + } + + String Pin = args.getString(1); + + final BroadcastReceiver pairingReceiver = new BroadcastReceiver() { + + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + int previousState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, 0); + int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, 0); + Log.d(TAG, "Received: " + action + " previous: " + previousState + " current: " + bondState); + if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)) { + Log.d(TAG, "Setting the PIN"); + BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + byte[] pinBytes = Pin.getBytes(); + device.setPin(pinBytes); + device.setPairingConfirmation(true); + } + if (bondState == BluetoothDevice.BOND_BONDED) + callbackContext.success("PAIRED correctly"); + else if (bondState == BluetoothDevice.BOND_NONE) + callbackContext.error("PAIR failed because of state:" + bondState); + if (bondState == BluetoothDevice.BOND_BONDED || bondState == BluetoothDevice.BOND_NONE) + cordova.getActivity().unregisterReceiver(this); + } + }; + + Activity activity = cordova.getActivity(); + activity.registerReceiver(pairingReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED)); + activity.registerReceiver(pairingReceiver, new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST)); + activity.registerReceiver(pairingReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)); + + if (!device.createBond()) { + Log.e(TAG, "Somehow unable to createBound(). Already bound ?"); + callbackContext.success("PAIRED already"); + } + + } + // The Handler that gets information back from the BluetoothSerialService // Original code used handler for the because it was talking to the UI. // Consider replacing with normal callbacks private final Handler mHandler = new Handler() { - public void handleMessage(Message msg) { - switch (msg.what) { - case MESSAGE_READ: - buffer.append((String)msg.obj); + public void handleMessage(Message msg) { + switch (msg.what) { + case MESSAGE_READ: + buffer.append((String) msg.obj); - if (dataAvailableCallback != null) { - sendDataToSubscriber(); - } + if (dataAvailableCallback != null) { + sendDataToSubscriber(); + } - break; - case MESSAGE_READ_RAW: - if (rawDataAvailableCallback != null) { - byte[] bytes = (byte[]) msg.obj; - sendRawDataToSubscriber(bytes); - } - break; - case MESSAGE_STATE_CHANGE: + break; + case MESSAGE_READ_RAW: + if (rawDataAvailableCallback != null) { + byte[] bytes = (byte[]) msg.obj; + sendRawDataToSubscriber(bytes); + } + break; + case MESSAGE_STATE_CHANGE: if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1); switch (msg.arg1) { @@ -469,22 +520,22 @@ private String readUntil(String c) { public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) throws JSONException { - for(int result:grantResults) { - if(result == PackageManager.PERMISSION_DENIED) { + for (int result : grantResults) { + if (result == PackageManager.PERMISSION_DENIED) { LOG.d(TAG, "User *rejected* location permission"); this.permissionCallback.sendPluginResult(new PluginResult( PluginResult.Status.ERROR, "Location permission is required to discover unpaired devices.") - ); + ); return; } } - switch(requestCode) { - case CHECK_PERMISSIONS_REQ_CODE: - LOG.d(TAG, "User granted location permission"); - discoverUnpairedDevices(permissionCallback); - break; + switch (requestCode) { + case CHECK_PERMISSIONS_REQ_CODE: + LOG.d(TAG, "User granted location permission"); + discoverUnpairedDevices(permissionCallback); + break; } } } diff --git a/www/bluetoothSerial.js b/www/bluetoothSerial.js index 250b8aab..e6a03fe6 100644 --- a/www/bluetoothSerial.js +++ b/www/bluetoothSerial.js @@ -10,6 +10,11 @@ module.exports = { cordova.exec(success, failure, "BluetoothSerial", "connectInsecure", [macAddress]); }, + // Android only + bind: function (macAddress, pin, success, failure) { + cordova.exec(success, failure, "BluetoothSerial", "bind", [macAddress, pin]); + }, + disconnect: function (success, failure) { cordova.exec(success, failure, "BluetoothSerial", "disconnect", []); }, @@ -72,7 +77,7 @@ module.exports = { // calls the success callback when new data is available with an ArrayBuffer subscribeRawData: function (success, failure) { - successWrapper = function(data) { + successWrapper = function (data) { // Windows Phone flattens an array of one into a number which // breaks the API. Stuff it back into an ArrayBuffer. if (typeof data === 'number') { @@ -134,7 +139,7 @@ module.exports = { }; -var stringToArrayBuffer = function(str) { +var stringToArrayBuffer = function (str) { var ret = new Uint8Array(str.length); for (var i = 0; i < str.length; i++) { ret[i] = str.charCodeAt(i);