Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Connect your Phone and Home with Firebase and...
Search
James Coggan
December 28, 2017
Programming
0
110
Connect your Phone and Home with Firebase and Android Things
Presentation done at Droidcon Tel Aviv 2017
James Coggan
December 28, 2017
Tweet
Share
More Decks by James Coggan
See All by James Coggan
Build accessible conversational Experiences with Actions on Google
jamescoggan
0
60
How to test your Android Things code in a clean way
jamescoggan
0
88
GDG DevFest Kansas city - Connect your Phone and Home with Firebase and Android Things
jamescoggan
0
66
GDG DevFest Minneapolis - How to write your own custom driver for Android Things
jamescoggan
0
64
Londroind - Thingyfy your home with Android Things and Firebase
jamescoggan
0
110
Other Decks in Programming
See All in Programming
Codexに役割を持たせる 他のAIエージェントと組み合わせる実務Tips
o8n
4
1.4k
どんと来い、データベース信頼性エンジニアリング / Introduction to DBRE
nnaka2992
1
330
コードレビューをしない選択 #でぃーぷらすトウキョウ
kajitack
3
1.1k
ロボットのための工場に灯りは要らない
watany
11
3.1k
AI時代のシステム設計:ドメインモデルで変更しやすさを守る設計戦略
masuda220
PRO
6
1.1k
安いハードウェアでVulkan
fadis
0
750
20260228_JAWS_Beginner_Kansai
takuyay0ne
5
610
[SF Ruby Feb'26] The Silicon Heel
palkan
0
120
PHP でエミュレータを自作して Ubuntu を動かそう
m3m0r7
PRO
2
130
AI活用のコスパを最大化する方法
ochtum
0
290
車輪の再発明をしよう!PHP で実装して学ぶ、Web サーバーの仕組みと HTTP の正体
h1r0
2
300
20260320登壇資料
pharct
0
110
Featured
See All Featured
Rails Girls Zürich Keynote
gr2m
96
14k
Claude Code のすすめ
schroneko
67
220k
Facilitating Awesome Meetings
lara
57
6.8k
Building the Perfect Custom Keyboard
takai
2
720
[SF Ruby Conf 2025] Rails X
palkan
2
850
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
400
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.3k
Exploring anti-patterns in Rails
aemeredith
2
290
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
230
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
118
110k
Reality Check: Gamification 10 Years Later
codingconduct
0
2.1k
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
480
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