• No results found

Connect Two Android Devices Via Bluetooth

In document Rapid Android Development - English (Page 186-197)

Peer-To-Peer Networking Using Bluetooth and WiFi Direct

7.5 Connect Two Android Devices Via Bluetooth

In the following sketch, we’ll work with three tabs. The main tab BluetoothCursors contains our usual setup() and draw() methods, and global variables. The second tab EnableBluetooth contains some code that is necessary to enable Bluetooth on startup, registering our Bluetooth class when the so-called Android Activity18 is created (this step might not be necessary in future versions of Processing). Processing allows us not dive too deep into the Android application life cycle, and we’ll try to keep it that way. The third tab called UI contains all the code we’ll use for GUI elements, like menus, an Android list to select Bluetooth devices, and the software keyboard to enter user input. When the sketch is complete, we’ll get a screen similar to the one shown in Figure 28, Bluetooth Cursors App, on page 171

16. http://developer.android.com/reference/android/app/Activity.html#onActivityResult%28int,%20int,%20android.con-tent.Intent%29

17. http://developer.android.com/reference/android/app/Activity.html#onResume%28%29 18. http://developer.android.com/reference/android/app/Activity.html

Chapter 7. Peer-To-Peer Networking Using Bluetooth and WiFi Direct

170

Figure 28—Bluetooth Cursors App. The illustration shows the local (white) and the remote mouse pointer position (red), marked as ellipses on the screen. The software keyboard is made visible using the keyboard tab shown atop. Also shown is the Bluetooth and Interact

tab, which we use to interact with the cursors.

The code needs to facilitate the Bluetooth pairing process as follows. We start by making both Androids discoverable for Bluetooth, listing discovered devices.

Then we choose the device to connect to from the list of discovered devices (you might be surprised to see what shows up). Finally, we pair and connect the devices to transfer the data via OSC, which we’ve already used in Section 6.3, Using the Open Sound Control Networking Format, on page 143. We’ll need

to confirm the Bluetooth connection in a popup window because we connect the devices for the first time.

We’ll use the Android software keyboard to discover other Bluetooth devices, make the device itself discoverable, connect to another device, list already paired devices, and show the current Bluetooth status. To work with the keyboard, we’ll use the KetaiKeyboard class. And to show and pick discoverable Bluetooth devices to connect to, we’ll use the KetaiList class, making it easy for us to work with a native Android list without importing additional packages.

Working with a KetaiList

We can create a KetaiList object using either a String array, or a String ArrayList.19 Because an ArrayList stores a variable number of objects and we have a variable number of discoverable Bluetooth devices to connect to, it’s the better choice for us here. We can easily add or remove an item dynamically in an ArrayList, and because we work with Bluetooth device names in our sketch, we’ll create an ArrayList of type String.

Andreas Schlegel has updated his excellent ControlP520 UI library (09/2012) to also work with the Android mode in Processing 2, making it a great tool to develop all custom aspects of UI elements, like including controllers, lists, sliders, buttons, and input forms. Although the UI elements do not use Android’s native UI classes, ControlP5 elements can be fully customized to match the look and feel of your app while still maintaining consistency with the Android’s UI style guide21

Let’s get started with the main tab of our BluetoothCursors sketch.

P2P/BluetoothCursors/BluetoothCursors.pde

PVector remoteCursor = new PVector();

19. http://processing.org/reference/ArrayList.html 20. http://sojamo.de/libraries/controlP5 21. http://developer.android.com/design/style

Chapter 7. Peer-To-Peer Networking Using Bluetooth and WiFi Direct

172

boolean isConfiguring = true;

UIText = "[b] - make this device discoverable\n" +

"[d] - discover devices\n" +

"[c] - pick device to connect to\n" +

"[p] - list paired devices\n" +

"[i] - show Bluetooth info";

}

for (int i=0; i < devices.size(); i++) {

info += "["+i+"] "+devices.get(i).toString() + "\n";

} }

text(UIText + "\n\n" + info, 5, 90);

} else {

background(78, 93, 75);

OscMessage m = new OscMessage("/remoteMouse/");

m.add(mouseX);

m.add(mouseY);

bt.broadcast(m.getBytes());

// use writeToDevice(String _devName, byte[] data) to target a specific device ellipse(mouseX, mouseY, 20, 20);

}

void onBluetoothDataEvent(String who, byte[] data)

{

if (isConfiguring) return;

KetaiOSCMessage m = new KetaiOSCMessage(data);

String btInfo = "Server Running: ";

btInfo += bt.isStarted() + "\n";

Chapter 7. Peer-To-Peer Networking Using Bluetooth and WiFi Direct

174

btInfo += "Device Discoverable: "+bt.isDiscoverable() + "\n";

btInfo += "\nConnected Devices: \n";

ArrayList<String> devices = bt.getConnectedDeviceNames();

for (String device: devices) {

btInfo+= device+"\n";

}

return btInfo;

}

Here are the steps we need to take.

❸ Create a KetaiBluetooth type variable bt

❹ Create a KetaiList variable which we’ll use to select the device to connect to

❺ Create a String variable info to store changing status messages that we want to output to the Android screen

❻ Start the bt Bluetooth object

❼ Provide a instructions for connecting to the other device using the key-board

❽ Create an ArrayList of type String to store the Bluetooth device devices

❾ Retrieve a Bluetooth status update and assign it to our info variable for screen output, when we press the i on the keyboard

❿ Get a list of paired devices and assign it to the devices ArrayList, to update the KetaiList when we press the p on the keyboard

⓫ Get a list of discovered devices and assign it to the devices ArrayList, to update the KetaiList when we press the d on the keyboard

⓬ Append each Bluetooth device entry in devices to our info text output, con-verting the each individual ArrayList item into a human readable text using the toString() method

⓭ Use the x and y component of the remoteCursor PVector, which stores the remote cursor location, and draw an ellipse at the exact same X and Y location

⓮ Create a new OSC message m to add our mouseX and mouseY cursor position to

⓯ Broadcast the OSC message containing the cursor position to all connected devices using the OSC broadcast() method. Alternatively, we can use

write-ToDevice(String _devName, byte[] data) to send the message only to one specific device

⓰ Receive the byte[] array when new Bluetooth data is sent from the remote device

⓱ Receive the data as an OSC message

⓲ Check if the OSC message contains two integer values, for the mouse X and Y position. We’ve also checked if the OSC message is valid, and if the message we’ve sent contains the label "remoteCursor"

⓳ Return a String containing Bluetooth status info, including if Bluetooth isStarted(), isDiscoverable(), and the individual names of connected Bluetooth devices

⓴ Get a list of all connected Bluetooth devices using getConnectedDeviceNames() We’ve completed the crucial components of our sketch in setup() and draw(). To enable Bluetooth when the app starts up, we’ll need to work with the Activity Lifecycle as described in Section 7.4, Working with the Android Activity Lifecy-cle, on page 168. We’ll put the code to enable Bluetooth into the tab named EnableBluetooth. Let’s take a look.

P2P/BluetoothCursors/EnableBluetooth.pde

void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

bt = new KetaiBluetooth(this);

}

void onActivityResult(int requestCode, int resultCode, Intent data) { bt.onActivityResult(requestCode, resultCode, data);

}

These are the steps we need to take to enable Bluetooth:

❶ Import the os.bundle Android package containing the onCreate() method we need to initialize Bluetooth

❷ Import the os.bundle Android package containing the onCreate() method we need to initialize Bluetooth

❶ Use the Android onCreate() method to initialize our Bluetooth object. The method is called when the Activity is starting

❷ Initialize the Bluetooth object bt when the Activity is created

❸ Return the bt object to the sketch using onActivityResult(), called right before onResume() in the Activity Lifecycle

Chapter 7. Peer-To-Peer Networking Using Bluetooth and WiFi Direct

176

We’ve looked at the required onCreate() and onActivityResult() methods to initialize Bluetooth at the beginning of the Activity.

Programming the UI

Now let’s return to the part of the code that is responsible for all the UI ele-ments, which we’ll put in the UI tab of the sketch. It takes care of GUI elements and keyboard menu items.

Because the Bluetooth pairing process requires us to select a device from a whole list discovered devices (you’ll probably be surprise how many Bluetooth devices are broadcasting around you). We’ll use a KetaiList to simplify the selection process. We’ll also need the keyboard to make menu selections during the pairing process, and we’ll use the KetaiKeyboard class to toggle the keyboard on and off. For the KetaiList, we’ll use the onKetaiListSelection() method to capture when the user picks an item from the list. And to show and hide the KetaiKeyboard, we’ll work with the toggle() method.

P2P/BluetoothCursors/UI.pde // UI methods

void mousePressed() {

if (mouseY <= 50 && mouseX > 0 && mouseX < width/3) KetaiKeyboard.toggle(this);

else if (mouseY <= 50 && mouseX > width/3 && mouseX < 2*(width/3)) //config button isConfiguring=true;

else if (mouseY <= 50 && mouseX > 2*(width/3) && mouseX < width) // draw button {

//If we have not discovered any devices, try prior paired devices if (bt.getDiscoveredDeviceNames().size() > 0)

connectionList = new KetaiList(this, bt.getDiscoveredDeviceNames());

else if (bt.getPairedDeviceNames().size() > 0)

connectionList = new KetaiList(this, bt.getPairedDeviceNames());

bt.makeDiscoverable();

❶ Toggle the Android’s software keyboard using toggle(). Make the KetaiKeyboard visible, if it’s hidden; hide it, if it’s visible

❷ Set the boolean variable isConfiguring to true, so we can switch to the Blue-tooth configuration screen and for the pairing process

Chapter 7. Peer-To-Peer Networking Using Bluetooth and WiFi Direct

178

❸ Assign the list of paired Bluetooth devices to the KetaiList connectionList, given there are paried devices

❹ Assign the list of discovered Bluetooth devices to the KetaiList connectionList using the String array returned by bt.getDiscoveredDeviceNames(), given there are discovered devices

❺ Discover Bluetooth devices using discoverDevices() when we press d on the software keyboard

❻ Make the device discoverable using the makeDiscoverable() method

❼ Save the current style settings using pushStyle(), to preserve the stroke, text size, and alignment for the UI elements. Use the method in combina-tion with popStyle() to restore the previous style settings

❽ Draw the "Keyboard" UI tab

❾ Draw the "Bluetooth" UI tab

❿ Draw the "Interact" UI tab

⓫ Call the onKetaiListSelection() event method when a user selects an item from the KetaiList

⓬ Get the String which the user picked from the KetaiList

⓭ Connect to the selected Bluetooth device using the connectToDeviceByName() method

⓮ Remove all items from the list using my setting the connectionList object to null

Now, let’s test the app.

Run the App

Let’s set the correct Android permissions before we run the sketch. Open the Android Permission Selector as we’ve done previously (See Section 4.4, Setting Sketch Permissions, on page 83), and check the following permissions:

BLUETOOTH

• BLUETOOTH ADMIN

INTERNET

Now connect your first device to your workstation with a USB cable and run the sketch. When the app is compiled, all three tabs in the sketch, BluetoothCur-sors, EnableBluetooth, and UI will be compiled into one app. You’ll see our Bluetooth

tab active and the menu options displayed on the screen. Before we interact, let’s install the app on our second Android device.

Disconnect your first device from the USB port, connect your second Android, and install the identical BluetoothCursors sketch on the device. The sketch launches, and we are ready to pair the two devices.

On your first device, (currently disconnected from USB), show the software keyboard by pressing the "Keyboard" tab. Then press b on the keyboard. If Bluetooth is turned off on your device (Settings → Bluetooth), you will be prompted to allow Bluetooth, as shown below. Otherwise the device will become discoverable for 300 seconds.

Android 1

[b] - make this device discoverable [d] - discover devices

[c] - pick device to connect to [p] - list paired devices [i] - show Bluetooth info

b Alert:

An app on your phone wants to make your phone discoverable by other Bluetooth devices for 300 seconds. Allow?

Yes

Now switch to your second device (currently connected to USB), and follow the process of discovering devices, and picking the name of the first Android device:

Chapter 7. Peer-To-Peer Networking Using Bluetooth and WiFi Direct

180

Connected Devices:

Nexus S (78:47:1D:B6:20:48)

When your screen output looks like what’s shown above, the Bluetooth server is running on your second device, and you have your first device show up in the list of "Connected Devices". You are now ready to interact.

Press the "Interact" screen tab on both devices. You’ll see a white dot for the local cursor, and a red one for the remote one. As you move your finger over the screen surface of one Android device, observe the other device and see how the red dot is moving magically to that position.

Congratulations! You’ve established a data connection between two Android devices using Bluetooth. Now it all depends on your Bluetooth antenna, which should reach a distance of about 30 feet. If you have a friend nearby to test this, try it our. It will not be possible to otherwise to observe how the connec-tions goes out of range.

The process of discovering and and pairing a Bluetooth device can seem cumbersome. Bluetooth however can’t just accept an incoming connection without confirmation, for good security reasons. Once paired, we can reconnect automatically by picking the device address again from the list of paired devices. This is a sketch refinement you can try. If you’d like to "unpair" pre-viously paired devices on your Android, tap the device name under Settings→ Bluetooth→Paired Devices, and choose unpair.

We will implement this remote cursors app using WiFi Direct later in this chapter on page 198, and you can then compare how the two standards perform in terms of update rate and wireless range.

Since you’ve mastered peer-to-peer networking using Bluetooth, let’s build on our Bluetooth skills and create a survey app for multiple Bluetooth users.

In document Rapid Android Development - English (Page 186-197)