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
PeripheralManagerto 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
GpioCallbackto receive edge trigger events. - Return
truewithinonGpioEdge()to continue receiving future edge trigger events. - When the application no longer needs the GPIO connection, close the
Gpioresource.
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
PeripheralManagerto 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
Handlerto schedule an event to toggle the GPIO again after a short delay. - When the application no longer needs the GPIO connection, close the
Gpioresource.
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);
}
}
};
}