Android Things Tutorial: Getting Started

Did you ever want to tinker with all those little pins on hardware boards? Well in this tutorial, you’ll learn how to do just that, with AndroidThings! By Dean Djermanović.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 4 of 4 of this article. Click here to view the first page.

Connect with Firebase

You’ll create a simple infrastructure that will simulate a doorbell. To do that, you need three things:

  1. Doorbell – a button tap on a board will simulate a doorbell.
  2. Database – ring events will be sent to the Firebase database.
  3. Mobile app – ring events will be displayed on your mobile app. Using this app, you’ll control whether you’ll let the person at the door in or not.

This is how it looks graphically:

Note: The logic for saving ring events to the Firebase is implemented for you. You need to create a project in Firebase, ensure that a database has been created for it and that it has public permissions for read and write. Once you have done that, create an app for it and download the google-services.json file for the app. If you are unfamiliar with how to do this, refer on our Firebase tutorial, which is linked at the beginning of this tutorial.

Capture the Ring Event

First, add RingEvent singleton class to the bottom of the BoardManager class by pasting the following:

object RingEvent

Next, add a ringEvent field of MutableLiveData type:

private val ringEvent = MutableLiveData()

Now, add a function which will expose ring events:

fun listenForRingEvents() = ringEvent

Next, replace the initializeButtonCallback() function with the following:

private fun initializeButtonCallback() {
  buttonCallback = GpioCallback {
    try {
      val buttonValue = it.value
      blueLedGpio.value = buttonValue
      // call the database
      ringEvent.postValue(RingEvent)
    } catch (exception: IOException) {
      handleError(exception)
    }
    true
  }
}

When you press a button on the board, a ring event will be sent to the database.

Then, in your MainActivity class paste in the following code:

private fun onRingEvent(ringEvent: RingEvent?) = ringRepository.saveRingEvent()

This function will handle ring events, by notifying the ringRepository.

Now, replace your MainActivity‘s initialize() with the following:

private fun initialize() {
  boardManager = BoardManager()
  // initialize your ring repository
  ringRepository = RingRepository()
  boardManager.initialize()
  // listen for ring events
  boardManager
   .listenForRingEvents()
   .observe(this, Observer { ringEvent ->
     onRingEvent(ringEvent)
    })
}

This listens for ring events coming from your board and triggers your onRingEvent function.

Finally, add the Google Play Services plug-in to your app level build.gradle.

apply plugin: 'com.google.gms.google-services'

Notify the User

In your materials there is also a knockknockmobile project. Open it in Android Studio and copy the google-services.json file that you have in the knockknock project to the knockknockmobile project.
Open the google-services.json file and search for the package_name attribute and replace its value with com.raywenderlich.knockknockmobile package name.

Build and run the mobile app on your mobile device. You’ll see this screen:

Build and run your Android Things app on the board. Tap on a button and check the Firebase database data. You should see ring event there:

Your mobile app will also change and you should now see the following screen:

By tapping the YES or NO buttons you will decide whether to let the person in or not. The answer is sent to Firebase.

Handle Response

Right now your board doesn’t do anything with the response, but you’re going to fix that!

To begin, paste the following into your BoardManager class:

private lateinit var redLedGpio: Gpio
private lateinit var greenLedGpio: Gpio

This adds the GPIO fields for the red and green LEDs. Next paste the following into the same class:

fun turnRedLedLightOn() {
  redLedGpio.value = true
}

fun turnRedLedLightOff() {
  redLedGpio.value = false
}

fun turnGreenLedLightOn() {
  greenLedGpio.value = true
}

fun turnGreenLedLightOff() {
  greenLedGpio.value = false
}

This adds methods for turning red and green LED lights ON and OFF. Now, add the following to your MainActivity:

private fun turnLightsOffAfterDelay() {
  Handler().postDelayed({
    boardManager.turnGreenLedLightOff()
    boardManager.turnRedLedLightOff()
  }, LIGHT_OFF_DELAY_MILLIS)
}

This adds a turnLightsOffAfterDelay() function which turns LED lights off after a small delay. Next, paste the following in the same class.

private fun onRingResponseReceived(dataSnapshot: DataSnapshot?) {
  //1
  val unlockDoor = dataSnapshot?.value as Boolean
  //2
  if (unlockDoor) 
    boardManager.turnGreenLedLightOn() 
  else 
    boardManager.turnRedLedLightOn()
  //3
  turnLightsOffAfterDelay()
}

This adds a onRingResponseReceived(dataSnapshot: DataSnapshot?) function which you call on every ring response event.

Going through it:

  1. When you receive a response boolean it indicates whether to unlock the door or not. You get this boolean by using dataSnapshot?.value as Boolean
  2. If you should unlock the door, you’ll turn on the green LED light on the board, otherwise you turn on the red LED light.
  3. This function turns the LED light off after 3 seconds.

Now, replace the initialize function of your MainActivity with:

private fun initialize() {
  boardManager = BoardManager()
  ringRepository = RingRepository()
  boardManager.initialize()
  boardManager
    .listenForRingEvents()
    .observe(this, Observer { ringEvent ->
      onRingEvent(ringEvent)
    })
  // ringRepository listener
  ringRepository
    .listenForRingResponseEvents()
    .observe(this, Observer { dataSnapshot ->
      onRingResponseReceived(dataSnapshot)
    })
}

This adds an observer to your ringRepository to observe ring response events. Now there are two more things you will need to do to button this up.

First, replace initializeLedLights with the following in your BoardManager class:

private fun initializeLedLights() {
  try {
     // initialize red LEDs
    redLedGpio = peripheralManager.openGpio(RED_LED_PIN_NAME)
    redLedGpio.apply { setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW) }

    // initialize green LEDs
    greenLedGpio = peripheralManager.openGpio(GREEN_LED_PIN_NAME)
    greenLedGpio.apply { setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW) }
  
    blueLedGpio = peripheralManager.openGpio(BLUE_LED_PIN_NAME)
    blueLedGpio.apply { setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW) }
  } catch (exception: IOException) {
    handleError(exception)
  }
}

This initializes the red and green LED lights.

Finally, replace your clear() function with the following:

fun clear() {
  buttonGpio.unregisterGpioCallback(buttonCallback)
  arrayOf(buttonGpio, redLedGpio, greenLedGpio, blueLedGpio)
    .forEach {
        try {
          it.close()
        } catch (exception: IOException) {
          handleError(exception)
        }
      }
}

This updates your array with the red and green LED GPIOs so that they are closed properly.

Build and run the app. Press the button on the board and use mobile app to either let the person in or deny them access. The green LED will light up if you let them in and the red one will light up if you deny access. You can find the final project in the downloaded materials.

Where to Go From Here?

As an Android developer, Android Things is a great way to begin to explore the world of the IOT and hardware. While you are exploring the platform for your own projects, this list is a great resource with additional tutorials, drivers and example projects. You can also visit this site to play around with an extensive list of resources from Google, or visit these interesting projects on hackster.io.

If you are new to electronics, Adafuit has a number or tutorials ranging from electronics basics to intermediate and advanced topics.

I hope you enjoyed this tutorial. If you have any questions or comments, please join the forum discussion below!