The power of Android Things is realized when developers begin connecting hardware peripherals directly to apps.
In this lesson, you will learn how to use the basic Peripheral I/O APIs to discover and communicate with General Purpose Input Output (GPIO) ports.
List available peripherals
The system service responsible for managing peripheral connections is
PeripheralManager
. You can use this service to list the available ports
for all known peripheral types.
The following code writes the list of available GPIO ports to logcat
:
Kotlin
import com.google.android.things.pio.PeripheralManager class HomeActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val manager = PeripheralManager.getInstance() Log.d(TAG, "Available GPIO: " + manager.getGpioList()) } companion object { private val TAG = "HomeActivity" } }
Java
import com.google.android.things.pio.PeripheralManager; ... public class HomeActivity extends Activity { private static final String TAG = "HomeActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); PeripheralManager manager = PeripheralManager.getInstance(); Log.d(TAG, "Available GPIO: " + manager.getGpioList()); } }
Handle button events
To receive events when a button connected to GPIO is pressed:
- Use
PeripheralManager
to open a connection with the GPIO port wired to the button. - Configure the port with
DIRECTION_IN
. - Configure which state transitions will generate callback events with
setEdgeTriggerType()
. - Register a
GpioCallback
to receive edge trigger events. - Return
true
withinonGpioEdge()
to continue receiving future edge trigger events. - When the application no longer needs the GPIO connection, close the
Gpio
resource.
Kotlin
import com.google.android.things.pio.PeripheralManager import com.google.android.things.pio.Gpio import com.google.android.things.pio.GpioCallback ... class ButtonActivity : Activity() { // GPIO port wired to the button private lateinit var buttonGpio: Gpio // Step 4. Register an event callback. private val callback = object : GpioCallback() { fun onGpioEdge(gpio: Gpio): Boolean { Log.i(TAG, "GPIO changed, button pressed") // Step 5. Return true to keep callback active. return true } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val manager = PeripheralManager.getInstance() try { // Step 1. Create GPIO connection. buttonGpio = manager.openGpio(BUTTON_PIN_NAME) // Step 2. Configure as an input. buttonGpio.setDirection(Gpio.DIRECTION_IN) // Step 3. Enable edge trigger events. buttonGpio.setEdgeTriggerType(Gpio.EDGE_FALLING) // Step 4. Register an event callback. buttonGpio.registerGpioCallback(mCallback) } catch (e: IOException) { Log.e(TAG, "Error on PeripheralIO API", e) } } override fun onDestroy() { super.onDestroy() // Step 6. Close the resource if (buttonGpio != null) { buttonGpio.unregisterGpioCallback(mCallback) try { buttonGpio.close() } catch (e: IOException) { Log.e(TAG, "Error on PeripheralIO API", e) } } } companion object { private val TAG = "ButtonActivity" private val BUTTON_PIN_NAME: String } }
Java
import com.google.android.things.pio.PeripheralManager; import com.google.android.things.pio.Gpio; import com.google.android.things.pio.GpioCallback; ... public class ButtonActivity extends Activity { private static final String TAG = "ButtonActivity"; private static final String BUTTON_PIN_NAME = ...; // GPIO port wired to the button private Gpio buttonGpio; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); PeripheralManager manager = PeripheralManager.getInstance(); try { // Step 1. Create GPIO connection. buttonGpio = manager.openGpio(BUTTON_PIN_NAME); // Step 2. Configure as an input. buttonGpio.setDirection(Gpio.DIRECTION_IN); // Step 3. Enable edge trigger events. buttonGpio.setEdgeTriggerType(Gpio.EDGE_FALLING); // Step 4. Register an event callback. buttonGpio.registerGpioCallback(mCallback); } catch (IOException e) { Log.e(TAG, "Error on PeripheralIO API", e); } } // Step 4. Register an event callback. private GpioCallback mCallback = new GpioCallback() { @Override public boolean onGpioEdge(Gpio gpio) { Log.i(TAG, "GPIO changed, button pressed"); // Step 5. Return true to keep callback active. return true; } }; @Override protected void onDestroy() { super.onDestroy(); // Step 6. Close the resource if (buttonGpio != null) { buttonGpio.unregisterGpioCallback(mCallback); try { buttonGpio.close(); } catch (IOException e) { Log.e(TAG, "Error on PeripheralIO API", e); } } } }
Blink an LED
To execute a blinking pattern on an LED connected to GPIO:
- Use
PeripheralManager
to open a connection with the GPIO port wired to the LED. - Configure the port with
DIRECTION_OUT_INITIALLY_LOW
. - Toggle the state of the LED by passing the inverse of
getValue()
to thesetValue()
method. - Use a
Handler
to schedule an event to toggle the GPIO again after a short delay. - When the application no longer needs the GPIO connection, close the
Gpio
resource.
Kotlin
import com.google.android.things.pio.PeripheralManager import com.google.android.things.pio.Gpio ... class BlinkActivity : Activity() { // GPIO port wired to the LED private val handler = Handler() private lateinit var ledGpio: Gpio private val blinkRunnable = object : Runnable { public override fun run() { // Exit if the GPIO is already closed if (ledGpio == null) { return } try { // Step 3. Toggle the LED state ledGpio.setValue(!ledGpio.getValue()) // Step 4. Schedule another event after delay. handler.postDelayed(blinkRunnable, INTERVAL_BETWEEN_BLINKS_MS) } catch (e:IOException) { Log.e(TAG, "Error on PeripheralIO API", e) } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Step 1. Create GPIO connection. val manager = PeripheralManager.getInstance() try { ledGpio = manager.openGpio(LED_PIN_NAME) // Step 2. Configure as an output. ledGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW) // Step 4. Repeat using a handler. handler.post(blinkRunnable) } catch (e: IOException) { Log.e(TAG, "Error on PeripheralIO API", e) } } override fun onDestroy() { super.onDestroy() // Step 4. Remove handler events on close. handler.removeCallbacks(blinkRunnable) // Step 5. Close the resource. if (ledGpio != null) { try { ledGpio.close() } catch (e: IOException) { Log.e(TAG, "Error on PeripheralIO API", e) } } } companion object { private val TAG = "BlinkActivity" private val INTERVAL_BETWEEN_BLINKS_MS = 1000 private val LED_PIN_NAME: String } }
Java
import com.google.android.things.pio.PeripheralManager; import com.google.android.things.pio.Gpio; ... public class BlinkActivity extends Activity { private static final String TAG = "BlinkActivity"; private static final int INTERVAL_BETWEEN_BLINKS_MS = 1000; private static final String LED_PIN_NAME = ...; // GPIO port wired to the LED private Handler handler = new Handler(); private Gpio ledGpio; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Step 1. Create GPIO connection. PeripheralManager manager = PeripheralManager.getInstance(); try { ledGpio = manager.openGpio(LED_PIN_NAME); // Step 2. Configure as an output. ledGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW); // Step 4. Repeat using a handler. handler.post(blinkRunnable); } catch (IOException e) { Log.e(TAG, "Error on PeripheralIO API", e); } } @Override protected void onDestroy() { super.onDestroy(); // Step 4. Remove handler events on close. handler.removeCallbacks(blinkRunnable); // Step 5. Close the resource. if (ledGpio != null) { try { ledGpio.close(); } catch (IOException e) { Log.e(TAG, "Error on PeripheralIO API", e); } } } private Runnable blinkRunnable = new Runnable() { @Override public void run() { // Exit if the GPIO is already closed if (ledGpio == null) { return; } try { // Step 3. Toggle the LED state ledGpio.setValue(!ledGpio.getValue()); // Step 4. Schedule another event after delay. handler.postDelayed(blinkRunnable, INTERVAL_BETWEEN_BLINKS_MS); } catch (IOException e) { Log.e(TAG, "Error on PeripheralIO API", e); } } }; }