Android Things: Virtual Button

Android Things is a relatively new IoT platform and developers can develop on it just like your typical Android app (Some limitations apply). Since I had some experience writing Android apps, let’s dive in and have a stab at it.

 

 

Wiring Up 

It is a simple circuit consisting of a 3386 variable resistor, a LED and a few wires. Here are some pictures of the wiring.

This slideshow requires JavaScript.

Here is the hardware schematics.

 

Yes, it’s a little messy since this is the first time I am using fritzing.(or maybe my wiring suck, heh)

Here’s a quick rundown on the wiring. Scroll down for the pin layout.

NOTE: ALWAYS PRACTICE SAFETY WHEN WIRING. Make sure your Pi is not plugged into any power source and ensure you have a bright work space.

  1. Connect +tive of LED to Pin 12(BCM 18)
  2. Connect -tive of LED to Pin 39(Ground)Resistors have no polarity, so you can wire it however you want. Here’s my wiring.
  3. Connect middle pin of resistor to -tive of LED
  4. Connect left pin of resistor to +tive of LED
  5. Connect right pin of resistor to -tive of LED

Image: Pinout.xyz

Software

Alright, so there’s 2 module for the software side. They are companion app running on your Android phone / tablet and Android Things app running on your IoT device. They communicate with each other by utilizing Firebase Database as the middleware.

In plain English

By pressing the toggle button in the companion app, it will send “LED Status=On” to Firebase, the LED will light up. When the companion app send “LED Status=Off” to Firebase, the LED will be turned off. I call this “virtual button” since there is no physical button and everything is controlled in the cloud.

Here’s the code.(Make sure you have your Android SDK, Things development environment  and Firebase setup. This guide will not go into that. Google has a guide to that though.)

Android Things

// Declare which pin is wired up
private String GPIO = "BCM18";
private Gpio gpio;
// Declare Firebase Database services
private DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
private FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();

//Use this for managing GPIO 
PeripheralManagerService peripheralManagerService = new PeripheralManagerService();

Alright, let’s move to onCreate.

 //Setup GPIO connection
 try{
 gpio = peripheralManagerService.openGpio(GPIO);
 gpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
 handler.post(blinkRunnable);
 } catch (IOException ioe){
 Log.e(TAG, "Error on PeripheralIO API(onCreate)", ioe);
 }

The LED status will be controlled in a background thread.(Runnable)


// Background thread
private Runnable blinkRunnable = new Runnable() {
   @Override
   public void run() {
       if (gpio == null){
           return;
       }
        ValueEventListener ledListener = new ValueEventListener() {
             @Override
             public void onDataChange(DataSnapshot dataSnapshot) {

// Get LED Status and use the value
              String databaseValue = dataSnapshot.getValue().toString();
              if(databaseValue.equals("LED Status=True")) {
                  try {
                       gpio.setValue(gpio.getValue());
                  } catch (IOException ioe) {
                      Log.e(TAG, "Error on Peripheral IO API", ioe);
                  }
              }else{
                  try {
                      gpio.setValue(!gpio.getValue());
                  } catch (IOException ioe){
                      Log.e(TAG, "Error on Peripheral IO API", ioe);
                  }
              }
            }
   
            @Override
            public void onCancelled(DatabaseError databaseError) {

             }
           };
           databaseReference.addValueEventListener(ledListener);

      }
 };

Let’s be responsible developers by freeing up the resources after we are done.

 @Override
 protected void onDestroy(){
     super.onDestroy();
     firebaseDatabase.goOffline();
     if(gpio != null){
         try{
              gpio.close();
         } catch (IOException ioe){
             Log.e(TAG, "Error on Peripheral IO API", ioe);
         }
     }
 }

 

Alright! Let’s move on to companion app now. The app will run on your platform as long as have Google Play services installed since we are using Firebase as a middleware.

 


 private ToggleButton toggleButton;
 private DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
 private FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();


 

Inside onCreate

 // Go online and start database
 firebaseDatabase.goOnline();

 // Set database as True first
 databaseReference.child("LED Status").setValue("True");
 buttonListener();

The button code.

public void buttonListener(){
    toggleButton = (ToggleButton) findViewById(R.id.toggleButton);

     //LED is turned on by default
     toggleButton.setChecked(true);

     toggleButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
         @Override
         public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
             // Two states: True, False
             if(compoundButton.isChecked()){
               // True
               // Set database to "True"
               databaseReference.child("LED Status").setValue("True");
             } else{
             // False
            // Set database to "False"
               databaseReference.child("LED Status").setValue("False");
             }

         }
     });
 }

That is pretty much it. Add google-services.json file into the Things app root directory and companion app root directory. Include firebase dependencies into your build.gradle and we are ready to run! Of course, the code is available here on Github, feel free to browse and fork.

A video of it in action is available here.

 

Daniel Quah

18 Year old dude, who loves cat and tech

Latest posts by Daniel Quah (see all)