May 15, 2017

Panic Button is an Android application targeting Android Things that integrates with Twilio to deliver SMS’s or phone calls to a configured phone number when a physical button is pressed.

Wow, that’s a lot of buzzwords. Let’s break it down and build one.

The Idea

I have been an Android Developer for the last few years and I recently got a Raspberry Pi 3 as a gift.
I was interested in getting one since Android Things was announced but for some reason never did. Now the excuses are over, and it’s time to play with it.

I have also been very interested in services that link the physical world to the internet, and vice versa.

Considering that Android Things connects hardware to the internet, why not come back to the disconnected world and receive a plain old SMS or a Phone call to close the circle?

The Hardware

This was the part of the project that I was most intimidated about.

I do not have any sort of electronic or electrical experience whatsoever, but I have to say that this circuit is really simple to put together.

Here’s the list of hardware components you will need for this project:

One RaspberryPI3

One Breadboard for easy prototyping

One button

One resistor

Four jumper wires

Here is the diagram with the layout of the components:

If you tried the SimplePIO sample button project in the past, you might have realised that it is exactly the same circuit.

API Key

Enter a friendly name, and click Create API Key. After this you will see a very important screen where the API_KEY and API_SECRET will be displayed. Make sure your write this two strings somewhere (specially the secret), as you will not be able to see it again after leaving that screen.

Phone Numbers

Next step is to choose a Twilio phone number. This will be the origin number calling or sending the SMS.

Gradle will pickup this properties at build time, and with a little bit of configuration on the build.gradle, add them to the BuildConfig class so the application code can access them as final static variables.

With all the config out of the way, let’s take a high level look at the main classes in the project.

This class is responsible for implementing the Twilio API’s details mentioned in the previous section.
Also, it exposes two public methods that invokes the correspondent API: sms() and call().

public void sms() {
Log.d(TAG, "Sending SMS request...");
RequestBody formBody = new FormBody.Builder()
.add("From", BuildConfig.PHONE_NUMBER_FROM)
.add("To", BuildConfig.PHONE_NUMBER_TO)
.add("Body", "SMS text body")
.build();
Request.Builder builder = new Request.Builder()
.url(BASE_URL + "/Messages")
.post(formBody);
execute(builder);
}
```
In order to decide if we should send an SMS or request a phone call, we first need to detect what kind of event was generated by the hardware button.
The wanted the application to trigger an SMS request if the event is a `simple press` and to perform a phone call request if the event happens to be a `long press`.
[`GpioEventCallback`][code4] takes cares of handling the events from the `Gpio` and deciding the type of the event, based on the duration of the button being pressed.
You can think of this class as a listener for the `click down` and `click up` events, that also counts the amount of time between them and compares it to `LONG_PRESS_DELAY_MS` to decide wether the event was a `single press` or a `long press`.
Once it knows what kind of event was generated, it takes care of invoking the correct method on `TwilioClient`.
```java
private static final long LONG_PRESS_DELAY_MS = 600;
private TwilioClient twilio;
private long pressStartedAt;
@Override public boolean onGpioEdge(Gpio gpio) {
boolean gpioValue;
try {
gpioValue = gpio.getValue();
} catch (IOException e) {
Log.e(TAG, "Error reading PIO value.", e);
return true;
}
// gpioValue == false, button pressed
// gpioValue == true, button released
if (!gpioValue) {
pressStartedAt = System.currentTimeMillis();
} else {
long duration = System.currentTimeMillis() - pressStartedAt;
if ( duration < LONG_PRESS_DELAY_MS) {
twilio.sms();
} else {
twilio.call();
}
}
}

Lastly, we need to create an Activity to connect all this pieces together, and for the system to be able to launch our application.