Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Connecting your phone and home with firebase and android things - James Coggan, MyDrive

187 views

Published on

As presented in Droidcon Tel Aviv 2017:
http://il.droidcon.com

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Connecting your phone and home with firebase and android things - James Coggan, MyDrive

  1. 1. 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
  2. 2. A little bit about me.. James Coggan Android tech lead https://jamescoggan.com @mad_team
  3. 3. What is Android Things?
  4. 4. Android + Internet of ThingsAndroid Things
  5. 5. The hardware NXP Pico i.MX7D Raspberry Pi 3 NXP Argon i.MX6UL NXP Pico i.MX6UL
  6. 6. Development kits NXP Pico i.MX7D Raspberry pi kit
  7. 7. Android
  8. 8. Android Things
  9. 9. What Android Things does support
  10. 10. What Android Things doesn’t support
  11. 11. Good to know ● Main application started on boot ● Permissions are free and set on reboot ● adb connect 192.168.1.111:5555
  12. 12. Why Android Things? ● Kotlin :) ● Maintained by Google ● OTA updates ● Android community ● Hardware agnostic ● Relatively cheap hardware ● Reusable code
  13. 13. Getting started https://partner.android.com/things/console/u/0/#/tools
  14. 14. Getting started
  15. 15. Getting started
  16. 16. 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)
  17. 17. Raspberry Pi NXP MX7D
  18. 18. val pioService = PeripheralManagerService() try { val pinName = "BCM6" ledGpio = pioService.openGpio(pinName) ledGpio?.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW) } catch (e: IOException) { e.printStackTrace() }
  19. 19. 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() }
  20. 20. override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { if (keyCode == KeyEvent.KEYCODE_SPACE) { setLedValue(true) return true } return super.onKeyDown(keyCode, event) }
  21. 21. override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { if (keyCode == KeyEvent.KEYCODE_SPACE) { setLedValue(false) return true } return super.onKeyUp(keyCode, event) }
  22. 22. 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) } }
  23. 23. 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) } }
  24. 24. val pinName = gpioForLED ledGpio = pioService.openGpio(pinName) ... val pinName = gpioForButton button = ButtonInputDriver( pinName, Button.LogicState.PRESSED_WHEN_LOW, KeyEvent.KEYCODE_SPACE) ...
  25. 25. 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)
  26. 26. ● 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", } }
  27. 27. // Base build.gradle for all modules buildscript { ... dependencies { classpath "com.google.gms:google-services:$googleServicesClassVersion" } }
  28. 28. // 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"
  29. 29. // 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 }
  30. 30. // 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") } } }
  31. 31. // Light.kt class FirebaseTables { companion object { val LIGHTS_BASE = "light" } } data class Light(val light : Boolean)
  32. 32. 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) } }
  33. 33. // 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")
  34. 34. // Mobile Activity override fun onCreate(savedInstanceState: Bundle?) { ... toggleButton.setOnCheckedChangeListener({ _, state: Boolean -> databaseReference.child("light").setValue(state) }) }
  35. 35. Nearby ● Pub/Sub ● Send messages, files or stream data ● No need for server ● Peer to peer ● Wifi or BLE
  36. 36. Nearby
  37. 37. 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()
  38. 38. 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")
  39. 39. 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}")
  40. 40. private val connectionLifecycleCallback = object : ConnectionLifecycleCallback() { override fun onConnectionResult(endpointId: String?, result: ConnectionResolution?) { Timber.d("connectionResult from " + endpointId, result) sendDataPayload() } }
  41. 41. // 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()) ) }
  42. 42. 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) } } }
  43. 43. firebaseAuth.signInWithEmailAndPassword(email,password) .addOnFailureListener { exception -> exception.printStackTrace() } .addOnSuccessListener { loadData() } }
  44. 44. Success!!
  45. 45. https://github.com/jamescoggan/thingspresentationn ● Common code in shared module ● Nearby ● RainbowHat: ○ Sensors ○ Led ○ Button ● Philips Hue (in progress)
  46. 46. Q&A sli.do #thingstelaviv
  47. 47. Feedback: https://goo.gl/gwPxpY Thank you! https://jamescoggan.com @mad_team

×