Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Connect your Phone and Home with Firebase and...
Search
James Coggan
December 28, 2017
Programming
120
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Connect your Phone and Home with Firebase and Android Things
Presentation done at Droidcon Tel Aviv 2017
James Coggan
December 28, 2017
More Decks by James Coggan
See All by James Coggan
Build accessible conversational Experiences with Actions on Google
jamescoggan
0
76
How to test your Android Things code in a clean way
jamescoggan
0
130
GDG DevFest Kansas city - Connect your Phone and Home with Firebase and Android Things
jamescoggan
0
77
GDG DevFest Minneapolis - How to write your own custom driver for Android Things
jamescoggan
0
82
Londroind - Thingyfy your home with Android Things and Firebase
jamescoggan
0
110
Other Decks in Programming
See All in Programming
カツオ、ご期待ください
suneo3476
0
190
TechTown - Creating Composable Callables in Contemporary C++
rollbear
0
130
コードレビューのボトルネックを"する側"と"される側"の両面から解消する
yub0n
2
1.6k
個人開発者よ、Honoを使え(おじさんver)
tanahiro2010
2
260
Herb in Rails 8.2: Your ERB views, now HTML-aware @ Kaigi on Rails 2026, Tokyo, Japan
marcoroth
2
250
外から家のPCの電源入れたい!をPHPで解決する
kawashimo0
1
140
contenteditable と日本語入力に向き合う
colorful12
0
200
作れる、でも消せるか?──安全に「枯らして消す」機能削除術 / Drain, Then Delete
chobishiba
2
770
S3 TablesのIcebergデータに、AIエージェントからアクセスしてみた / 20261016developersio2026joetsu-accessing-iceberg-in-s3tables-via-agent
kasacchiful
PRO
0
160
Performance Optimization With LLMs
xleitix
0
110
Long Living Tokens, Die, Die, Die! (or: The One Ring is Banned in Modern)
sylph01
0
320
Domain-Driven Transformation
hschwentner
2
2.3k
Featured
See All Featured
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
890
Rails Girls Zürich Keynote
gr2m
96
14k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
7k
Product Roadmaps are Hard
iamctodd
55
13k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
AI: The stuff that nobody shows you
jnunemaker
PRO
10
1.2k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
33
5.2k
The Art of Programming - Codeland 2020
erikaheidi
57
14k
HDC tutorial
michielstock
2
960
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
330
Building Adaptive Systems
keathley
44
3.2k
Embracing the Ebb and Flow
colly
88
5.2k
Transcript
James Coggan, MyDrive Solutions Connect your Phone and Home with
Firebase and Android Things We are hiring! https://www.mydrivesolutions.com/jobs Q&A sli.do #thingstelaviv
A little bit about me.. James Coggan Android tech lead
https://jamescoggan.com @mad_team
None
What is Android Things?
Android + Internet of Things Android Things
The hardware NXP Pico i.MX7D Raspberry Pi 3 NXP Argon
i.MX6UL NXP Pico i.MX6UL
Development kits NXP Pico i.MX7D Raspberry pi kit
Android
Android Things
What Android Things does support
What Android Things doesn’t support
Good to know • Main application started on boot •
Permissions are free and set on reboot • adb connect 192.168.1.111:5555
Why Android Things? • Kotlin :) • Maintained by Google
• OTA updates • Android community • Hardware agnostic • Relatively cheap hardware • Reusable code
Getting started https://partner.android.com/things/console/u/0/#/tools
Getting started
Getting started
Supported I/Os • General Purpose Input/Output (GPIO): Binary • Pulse
Width Modulation (PWM): Servo motors, DC motors • Inter-Integrated Circuit(I2C) • Serial Peripheral Interface (SPI) • Universal Asynchronous Receiver Transmitter (UART)
None
None
Raspberry Pi NXP MX7D
val pioService = PeripheralManagerService() try { val pinName = "BCM6"
ledGpio = pioService.openGpio(pinName) ledGpio?.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW) } catch (e: IOException) { e.printStackTrace() }
val pioService = PeripheralManagerService() try { val pinName = "BCM21"
button = ButtonInputDriver( pinName, Button.LogicState.PRESSED_WHEN_LOW, KeyEvent.KEYCODE_SPACE) button?.register() } catch (e: IOException) { e.printStackTrace() }
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { if (keyCode
== KeyEvent.KEYCODE_SPACE) { setLedValue(true) return true } return super.onKeyDown(keyCode, event) }
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { if (keyCode
== KeyEvent.KEYCODE_SPACE) { setLedValue(false) return true } return super.onKeyUp(keyCode, event) }
val gpioForLED: String // Pin 31 get() { return when
(Build.DEVICE) { DEVICE_RPI3 -> "BCM6" DEVICE_IMX6UL_PICO -> "GPIO4_IO22" DEVICE_IMX7D_PICO -> "GPIO2_IO02" else -> throw IllegalStateException("Unknown Build.DEVICE " + Build.DEVICE) } }
val gpioForButton: String // Pin 40 get() { return when
(Build.DEVICE) { DEVICE_RPI3 -> "BCM21" DEVICE_IMX6UL_PICO -> "GPIO2_IO03" DEVICE_IMX7D_PICO -> "GPIO6_IO14" else -> throw IllegalStateException("Unknown Build.DEVICE " + Build.DEVICE) } }
val pinName = gpioForLED ledGpio = pioService.openGpio(pinName) ... val pinName
= gpioForButton button = ButtonInputDriver( pinName, Button.LogicState.PRESSED_WHEN_LOW, KeyEvent.KEYCODE_SPACE) ...
None
None
None
Setting up Firebase https://console.firebase.google.com • Create a new Firebase project
• Add a new Android app to the project with your package name: ie: com.jamescoggan.thingspresentation • Enable anonymous login on (temporarily)
• Setup a database // Database { "light" : true
} • Add the rules // Rules - don’t expose your data for the world { "rules": { ".write": "auth != null", ".read": "auth != null", } }
// Base build.gradle for all modules buildscript { ... dependencies
{ classpath "com.google.gms:google-services:$googleServicesClassVersion" } }
// mobile & things build.gradle dependencies { ... implementation "com.google.firebase:firebase-core:$playServicesVersion"
implementation "com.google.firebase:firebase-database:$playServicesVersion" implementation "com.google.firebase:firebase-auth:$playServicesVersion" implementation "android.arch.lifecycle:extensions:$androidArchComponentsVersion" } apply plugin: "com.google.gms.google-services"
// MainActivity.kt (Both modules - mobile and things) override fun
onCreate(savedInstanceState: Bundle?) { FirebaseApp.initializeApp(this) // Move me to the Application class val firebaseAuth = FirebaseAuth.getInstance() val databaseReference = FirebaseDatabase.getInstance().reference }
// MainActivity.kt override fun onCreate(savedInstanceState: Bundle?) { ... val databaseReference
= FirebaseDatabase.getInstance().reference firebaseAuth.signInAnonymously() .addOnCompleteListener { task -> if (task.isSuccessful) { observeLightsData() } else { Timber.e(task.exception, "FirebaseAuth:failed") } } }
// Light.kt class FirebaseTables { companion object { val LIGHTS_BASE
= "light" } } data class Light(val light : Boolean)
class LightLiveData(val firebase: DatabaseReference) : LiveData<Light>() { private val valueEventListener
= object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { val newValue = snapshot.getValue(Boolean::class.java) ?: false value = Light(newValue) } override fun onCancelled(error: DatabaseError) { } } override fun onActive() { firebase.child(LIGHTS_BASE).addValueEventListener(valueEventListener) } override fun onInactive() { firebase.child(LIGHTS_BASE).removeEventListener(valueEventListener) } }
// Things Activity private val lightsDataObserver = Observer<Light> { lightState
-> Timber.d("LightState changed: ${lightState?.isOn}") led.setValue(lightState?.isOn ?: false) } override fun onCreate(savedInstanceState: Bundle?) { ... firebaseAuth.signInAnonymously() .addOnCompleteListener { task -> if (task.isSuccessful) { lightsLiveData.observe(this, lightsDataObserver) } else { Timber.e(task.exception, "FirebaseAuth:failed")
// Mobile Activity override fun onCreate(savedInstanceState: Bundle?) { ... toggleButton.setOnCheckedChangeListener({
_, state: Boolean -> databaseReference.child("light").setValue(state) }) }
None
None
None
Nearby • Pub/Sub • Send messages, files or stream data
• No need for server • Peer to peer • Wifi or BLE
Nearby
googleApiClient = GoogleApiClient.Builder(this) .addApi(Nearby.CONNECTIONS_API) .addConnectionCallbacks(object : GoogleApiClient.ConnectionCallbacks { override fun
onConnected(connectionHint: Bundle?) { startService() } override fun onConnectionSuspended(cause: Int) { failed() } }) .build()
private fun startService() { // Android Things Nearby.Connections.startAdvertising( googleApiClient, "appName",
"serviceId", connectionLifecycleCallback, AdvertisingOptions(Strategy.P2P_STAR)) .setResultCallback { result -> when { result.status.isSuccess -> Timber.d("startAdvertising:onResult: SUCCESS") else -> Timber.w("STATE_READY")
private fun startService() { // Phone Nearby.Connections.startDiscovery( googleApiClient, "serviceId", endpointDiscoveryCallback,
DiscoveryOptions(Strategy.P2P_STAR)) .setResultCallback { result -> when { result.status.isSuccess -> Timber.d("startDiscovery:SUCCESS") else -> { Timber.w("startDiscovery:FAILURE ${result.statusMessage}")
private val connectionLifecycleCallback = object : ConnectionLifecycleCallback() { override fun
onConnectionResult(endpointId: String?, result: ConnectionResolution?) { Timber.d("connectionResult from " + endpointId, result) sendDataPayload() } }
// Phone private fun sendDataPayload(email : String, password: String) {
val credentials = Credentials(email, password) val adapter = moshi.adapter(Credentials::class.java) val json = adapter.toJson(credentials) Nearby.Connections.sendPayload( googleApiClient, currentEndpointId, Payload.fromBytes(json.toByteArray()) ) }
private val payloadCallback = object : PayloadCallback() { override fun
onPayloadReceived(endpointId: String?, payload: Payload?) { val adapter = moshi.adapter(Credentials::class.java) val credentials = adapter.fromJson(jsonString) credentials?.let { saveCredentials(credentials) } } }
firebaseAuth.signInWithEmailAndPassword(email,password) .addOnFailureListener { exception -> exception.printStackTrace() } .addOnSuccessListener { loadData()
} }
Success!!
https://github.com/jamescoggan/thingspresentationn • Common code in shared module • Nearby •
RainbowHat: ◦ Sensors ◦ Led ◦ Button • Philips Hue (in progress)
Q&A sli.do #thingstelaviv
Feedback: https://goo.gl/gwPxpY Thank you! https://jamescoggan.com @mad_team