Ketai
We could continue with the direct approach and build all of the individual components required from scratch. However,
since Bluetooth is widely used, there are many libraries that contain ready-made solutions to these problems.
In this exercise you will use the ketai library to handle the Bluetooth operations as well as some more sophisticated
UI features. You can find reference documentation on the library by following the link on the right. You may also
find that this library could be useful for your project.
The code below is adapted from the examples provided on the ketai site in keeping with the learning-by-doing approach
taken by the module overall. The important thing to remember when working from example code is that you need to spend
the time working through to understand how it works. Some notes are provided at the end of each listing - again
there are three which correspond to the different tabs in your PDE.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 | import android.os.Bundle;
import android.content.Intent;
import ketai.net.bluetooth.*;
import ketai.ui.*;
import ketai.net.*;
import oscP5.*;
KetaiBluetooth bt;
KetaiList connectionList;
String info = "";
PVector remoteCursor = new PVector();
boolean isConfiguring = true;
String UIText;
String LEDText;
void setup()
{
fullScreen();
orientation(PORTRAIT);
background(78, 93, 75);
stroke(255);
textSize(48);
bt.start();
UIText = "[d] - discover devices\n" +
"[c] - pick device to connect to\n" +
"[p] - list paired devices\n" +
"[i] - show Bluetooth info";
LEDText = "[1] - turn LED on\n" +
"[0] - turn LED off\n";
}
void draw()
{
ArrayList devices;
byte[] message = new byte[1];
if (isConfiguring)
{
background(78, 93, 75);
if (key == 'i')
info = getBluetoothInformation();
else
{
if (key == 'p')
{
info = "Paired Devices:\n";
devices = bt.getPairedDeviceNames();
}
else
{
info = "Discovered Devices:\n";
devices = bt.getDiscoveredDeviceNames();
}
for (int i=0; i < devices.size(); i++)
{
info += "["+i+"] "+devices.get(i).toString() + "\n";
}
}
text(UIText + "\n\n" + info, 5, 200);
}
else
{
background(78, 93, 75);
text(LEDText + "\n\n", 5, 200);
devices = bt.getConnectedDeviceNames();
if (key == '1' || key == '2') {
if (devices.size() > 0) {
message[0] = (byte)key;
bt.writeToDeviceName(devices.get(0).substring(0,devices.get(0).indexOf("(")), message );
}
else
text("No connected device", 5, 100);
}
else
text("Invalid key - try again", 5, 100);
}
drawUI();
}
String getBluetoothInformation()
{
String btInfo = "Server Running: ";
btInfo += bt.isStarted() + "\n";
btInfo += "Discovering: " + bt.isDiscovering() + "\n";
btInfo += "Device Discoverable: "+bt.isDiscoverable() + "\n";
btInfo += "\nConnected Devices: \n";
ArrayList devices = bt.getConnectedDeviceNames();
for (String device: devices)
{
btInfo+= device+"\n";
}
return btInfo;
}
|
Line 39: Notice that discovered devices are held in a java arraylist.
Line 40: the library function to write to a connected Bluetooth device requires a byte array as its second parameter.
The message variable is only there to satisfy this requirement.
Lines 47, 53, 58, etc. Calls to library methods. As in the case of all library code, these simplify the task that
you need to do.
Lines 76-77: Translating the character read by the app into the required datatype for sending to the connected device.
Some string processing is required on line 77 to get the correct format of the device name.
Because we are using library code, we do not have to interact directly with Android quite so directly. Instead,
we make use of the Android lifecycle hook onCreate()
to set up the broadcast receiver.
| void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bt = new KetaiBluetooth(this);
}
void onActivityResult(int requestCode, int resultCode, Intent data) {
bt.onActivityResult(requestCode, resultCode, data);
}
|
This example takes a different approach to creating UI widgets such as buttons. Both strategies have their advantages -
you should spend a little time thinking about which is most appropriate for a particular case and also whether
there might be further alternatives.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 | void mousePressed()
{
if (mouseY <= 100 && mouseX > 0 && mouseX < width/3) // keyboard button
KetaiKeyboard.toggle(this);
else if
(mouseY <= 100 && mouseX > width/3 && mouseX < 2*(width/3)) //config button
isConfiguring=true;
else if
(mouseY <= 100 && mouseX > 2*(width/3) && mouseX < width) // draw button
{
if (isConfiguring)
{
background(78, 93, 75);
isConfiguring=false;
}
}
}
void keyPressed() {
if (key =='c')
{
//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());
}
else if (key == 'd')
bt.discoverDevices();
}
void drawUI()
{
pushStyle();
fill(0);
stroke(255);
rect(0, 0, width/3, 100);
if (isConfiguring)
{
noStroke();
fill(78, 93, 75);
}
else
fill(0);
rect(width/3, 0, width/3, 100);
if (!isConfiguring)
{
noStroke();
fill(78, 93, 75);
}
else
{
fill(0);
stroke(255);
}
rect((width/3)*2, 0, width/3, 100);
fill(255);
text("Keyboard", 5, 70);
text("Bluetooth", width/3+5, 70);
text("Interact", width/3*2+5, 70);
popStyle();
}
void onKetaiListSelection(KetaiList connectionList)
{
String selection = connectionList.getSelection();
bt.connectToDeviceByName(selection);
connectionList = null;
}
|
Lines 36, 66: the methods pushStyle()
and popStyle()
allow you to temporarily change the style characteristics
of the drawing and to restore them to their previous settings once you are finished. Don't take my word for it -
check them out on the Processing reference site.
Lines 69-74: This is the code for connecting to a discovered device
NB. Don't forget to set the Android permissions for the new sketch
Further reading
Ketai
Processing reference