Here I made a app to demonstrate how I handle each challenge and maybe other related problem. The link to the source code is at the bottom of this article.

This demo firstly have a list view to display all of the available devices around your android device. The paired devices is labeled with pink color while the unpaired is labeled with brown color. The paired device is always listed at the top. For each item in the list literally describes the device's name, 16 hex digits MAC address and the status of it's paired or not.
The device will pop on the list view one by one after user clicks on "Scan Device" button at the bottom. With the time Bluetooth adapter found new devices, it will check if it's paired, if it's paired, then it's already in the list, otherwise, add it to the list as a new device.

If user clicks on a new device, the app will pair it for user, while if the user clicks on the paired device, the app will unpair the device first, after the device is unpaired, the app will pair with device again with a request from Bluetooth adapter asking for the pass code to get paired. Once the device is newly paired, the app will connect with it.
Then, it will works like a SPP app on the Android device.
The following are the main challenges I had when I went through the whole process.
Challenge #1: How to pair and unpair programmable with other Bluetooth Device on Android?
private void pairDevice(BluetoothDevice device) {
try { if (D) Log.d(TAG, "Start Pairing..."); Method m = device.getClass() .getMethod("createBond", (Class[]) null); m.invoke(device, (Object[]) null); } catch (Exception e) { Log.e(TAG, e.getMessage()); } }
private void unpairDevice(BluetoothDevice device) { try { Method m = device.getClass() .getMethod("removeBond", (Class[]) null); m.invoke(device, (Object[]) null); } catch (Exception e) { Log.e(TAG, e.getMessage()); } }
Challenge #2: How to make unpair -> pair -> connect in order ?
This challenge is raised when I try to connect the Bluetooth device right after unpair with it. I thought the Bluetooth Adapter will have my application enough time to let user input the that looks short but feels damn long four digits passcode, while the adapter will give you a new passcode request each time the application try to connect with the device. So finally I think maybe it's better for my application to handle corresponding event at each state.
1st, The first state change is from paired to unpaired state, when this state change is done, the app is ready to pair with that device again.The state change monitor is implemented with Broadcast Receiver.
2nd, The second state change is from paring to paired state, when this is done, the app finally is ready to connect with the device.
// The BroadcastReceiver that listens for discovered devices and // changes the title when discovery is finished private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // When discovery finds a device if (BluetoothDevice.ACTION_FOUND.equals(action)) { // Get the BluetoothDevice object from the Intent BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // If it's already paired, skip it, because it's been listed // already CustomizedBluetoothDevice mDevice = new CustomizedBluetoothDevice( device); if (device.getBondState() != BluetoothDevice.BOND_BONDED) { if (mDeviceList.contains(mDevice) == false) { mDeviceList.add(mDevice); updateUI(); } } } // When the device bond state changed. else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) { int prevBondState = intent.getIntExtra( BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, -1); int bondState = intent.getIntExtra( BluetoothDevice.EXTRA_BOND_STATE, -1); if (prevBondState == BluetoothDevice.BOND_BONDED && bondState == BluetoothDevice.BOND_NONE) { BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (currentPosition != -1 && currentPosition < mDeviceList.size()) { CustomizedBluetoothDevice mDevice = mDeviceList .get(currentPosition); if (device.getAddress().compareTo(mDevice.getAddress()) == 0) { mDevice.setStatusPaired(false); updateUI(); pairDevice(device); } } } else if (prevBondState == BluetoothDevice.BOND_BONDING && bondState == BluetoothDevice.BOND_BONDED) { BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (currentPosition != -1 && currentPosition < mDeviceList.size()) { CustomizedBluetoothDevice mDevice = mDeviceList .get(currentPosition); if (device.getAddress().compareTo(mDevice.getAddress()) == 0) { mDevice.setStatusPaired(true); updateUI(); startConnect(mDevice); } } } } } };
The whole source code of this demo on Android is published on Github.
No comments :
Post a Comment