What's new in Firebase

2594ac7ce91fd7d9a3ce71ca7cc2d0c0?s=47 d_date
May 28, 2018

What's new in Firebase

2018/05/28 FJUG #4

2594ac7ce91fd7d9a3ce71ca7cc2d0c0?s=128

d_date

May 28, 2018
Tweet

Transcript

  1. What’s new in Firebase Daiki Matsudate / @d_date 2018/05/28 FJUG

    #4
  2. Daiki Matsudate @d_date

  3. iOSΞϓϦ։ൃऀͷͨΊͷFirebaseೖ໳

  4. https://yakiringo.booth.pm/ items/835645 iOSΞϓϦ։ൃऀͷͨΊͷFirebaseೖ໳

  5. ։࢝5࣌ؒͰ੒ཱʂiOSΞϓϦઃܭύλʔϯೖ໳

  6. ։࢝5࣌ؒͰ੒ཱʂiOSΞϓϦઃܭύλʔϯೖ໳ https://peaks.cc/iOS_architecture

  7. Google I/O

  8. Yosemite Bishop

  9. Hakone

  10. Part1: What’s new in iOS SDK v5.0.0 Daiki Matsudate /

    @d_date 2018/05/28 FJUG #4
  11. v5.0.0 Released!

  12. v5.0.0 • Support iOS version (iOS7.0 and later -> iOS

    8.0 and later) • Performance Monitoring graduated beta • Phone Auth Testing • Firebase Testlab for iOS • MLKit
  13. None
  14. Graduated from beta!

  15. - Automatic Trace Measuring performances about app • Automatic trace

    • App start • Network • App in foreground / background • • Screen ← NEW!
  16. - Screen Trace iOS keyWindow಺ʹ͋ΔUIViewControllerͷ ɾStart: viewDidAppear:͕ݺ͹Εͨͱ͖ ɾStop: viewDidDisappear:͕Α͹Εͨͱ͖ɻ ※Container

    View ControllerͰ͸Ωϟϓνϟ͠ͳ͍
  17. Android ͢΂ͯͷActivityͷ ɾStart: onActivityStarted()͕ݺ͹Εͨͱ͖ ɾStop: onActivityStopped()͕ݺ͹Εͨͱ͖ - Screen Trace

  18. https://www.youtube.com/watch?v=e-8fiv-vteQ&t=1671s

  19. https://www.youtube.com/watch?v=e-8fiv-vteQ&t=1671s

  20. Appendix: Performance Monitoring - Custom Trace let trace = Performance.startTrace(name:

    "request_trace") let contents: String do { contents = try String(contentsOfFile: fileName, encoding: .utf8) } catch { print("Log file doesn't exist yet") contents = "" } let fileLength = contents.lengthOfBytes(using: .utf8) trace?.incrementMetric("log_file_size", by: Int64(fileLength))
  21. let trace = Performance.startTrace(name: "request_trace") let contents: String do {

    contents = try String(contentsOfFile: fileName, encoding: .utf8) } catch { print("Log file doesn't exist yet") contents = "" } let fileLength = contents.lengthOfBytes(using: .utf8) trace?.incrementMetric("log_file_size", by: Int64(fileLength)) 1. Call startTrace with label name 2. Set your metric with parameter Appendix: Performance Monitoring - Custom Trace
  22. let target = "https://www.google.com/images/branding/googlelogo/2x/ googlelogo_color_272x92dp.png" guard let targetUrl = URL(string:

    target) else { return } guard let metric = HTTPMetric(url: targetUrl, httpMethod: .get) else { return } metric.start() var request = URLRequest(url:targetUrl) request.httpMethod = "GET" let task = URLSession.shared.dataTask(with: request) { data, response, error in if let httpResponse = response as? HTTPURLResponse { metric.responseCode = httpResponse.statusCode } metric.stop() ɾSpecified network trace Appendix: Performance Monitoring - Custom Trace
  23. let target = "https://www.google.com/images/branding/googlelogo/2x/ googlelogo_color_272x92dp.png" guard let targetUrl = URL(string:

    target) else { return } guard let metric = HTTPMetric(url: targetUrl, httpMethod: .get) else { return } metric.start() var request = URLRequest(url:targetUrl) request.httpMethod = "GET" let task = URLSession.shared.dataTask(with: request) { data, response, error in if let httpResponse = response as? HTTPURLResponse { metric.responseCode = httpResponse.statusCode } metric.stop() 1. Initialize HTTPMetric with targetUrl 3. Call stop() when finished downloading 2.Call start() ɾSpecified network trace Appendix: Performance Monitoring - Custom Trace
  24. None
  25. https://www.youtube.com/watch?v=e-8fiv-vteQ&t=1671s

  26. Phone Auth Testing

  27. Set phone number and verification code for testing Phone Auth

    Testing
  28. Auth.auth().createUser(withEmail: email, password: password) { (user, error) in self.hideSpinner {

    guard let email = user.email, error == nil else { self.showMessagePrompt(error!.localizedDescription) return } print("\(email) created") self.navigationController!.popViewController(animated: true) } } Breaking change
  29. Auth.auth().createUser(withEmail: email, password: password) { (user, error) in self.hideSpinner {

    guard let email = user.email, error == nil else { self.showMessagePrompt(error!.localizedDescription) return } print("\(email) created") self.navigationController!.popViewController(animated: true) } } Breaking change
  30. Auth.auth().createUser(withEmail: email, password: password) { (authResult, error) in self.hideSpinner {

    guard let email = authResult?.user.email, error == nil else { self.showMessagePrompt(error!.localizedDescription) return } print("\(email) created") self.navigationController!.popViewController(animated: true) } } Breaking change
  31. Auth.auth().createUser(withEmail: email, password: password) { (authResult, error) in self.hideSpinner {

    guard let email = authResult?.user.email, error == nil else { self.showMessagePrompt(error!.localizedDescription) return } print("\(email) created") self.navigationController!.popViewController(animated: true) } } Breaking change
  32. authResult: AuthDataResult user: User additionalUserInfo: AdditionalUserInfo profile: [String: NSObject]? isNewUser:

    Bool username: String? Breaking change
  33. Goodbye Twitter Kit SDK! https://blog.twitter.com/developer/en_us/topics/tools/2018/discontinuing-support-for-twitter-kit-sdk.html

  34. None
  35. • Run test in physical and virtual devices • Available

    in • android • iOS
  36. None
  37. • Run Unit test and UI test with XCTest •

    Firebase Console • gcloud CLI Firebase Test Lab for iOS
  38. https://firebase.google.com/docs/test-lab/ios/available-testing-devices Available iOS devices

  39. Firebase Test Lab for iOS

  40. https://g.co/firebase/TestLabSignUp Signup Test Lab for iOS

  41. Summary • Automatic screen trace in performance monitoring → NEW!

    • Phone auth testing with whitelist phone number → NEW! • Test Lab for iOS → NEW! • MLKit → NEW!
  42. Resources • Session: • What’s new in Firebase https://www.youtube.com/watch? v=e-8fiv-vteQ&t=57s

    • Release note: • iOS: https://firebase.google.com/support/release-notes/ios • Android: https://firebase.google.com/support/release-notes/ android
  43. Part2: Introduction to MLKit Daiki Matsudate / @d_date 2018/05/28 FJUG

    #4
  44. https://www.youtube.com/watch?v=Z-dqGRSsaBs

  45. https://www.youtube.com/watch?v=Z-dqGRSsaBs

  46. DEMO

  47. ML Kit • iOS / Android SDK • Base API

    and Custom Model Support • On device / On Cloud • Deeply integrated into Firebase
  48. ML Kit - iOS / Android SDK https://www.youtube.com/watch?v=Z-dqGRSsaBs

  49. ML Kit - Custom Model Support • Dynamic model downloads

    • No need to bundle every custom model in your ipa / apk • A/B testing via Firebase Remote Config • Model conversion and compression (coming soon)
  50. ML Kit - Custom Local Model guard let localModelFilePath =

    Bundle.main.path( forResource: Constants.quantizedModelFilename, ofType: DetectorConstants.modelExtension ), let labelsFilePath = Bundle.main.path( forResource: Constants.quantizedLabelsFilename, ofType: DetectorConstants.labelsExtension ) else { resultsTextView.text = "Failed to get the paths to the local model and labels files." return } let localModelSource = LocalModelSource( modelName: Constants.localModelName, path: localModelFilePath ) let modelManager = ModelManager.modelManager() if !modelManager.register(localModelSource) { print("Model source was already registered with name: \(localModelSource.modelName).") } let options = ModelOptions(cloudModelName: nil, localModelName: Constants.localModelName) detectorService.loadModel(options: options, labelsPath: labelsFilePath)
  51. ML Kit - Custom Local Model guard let localModelFilePath =

    Bundle.main.path( forResource: Constants.quantizedModelFilename, ofType: DetectorConstants.modelExtension ), let labelsFilePath = Bundle.main.path( forResource: Constants.quantizedLabelsFilename, ofType: DetectorConstants.labelsExtension ) else { resultsTextView.text = "Failed to get the paths to the local model and labels files." return } let localModelSource = LocalModelSource( modelName: Constants.localModelName, path: localModelFilePath ) let modelManager = ModelManager.modelManager() if !modelManager.register(localModelSource) { print("Model source was already registered with name: \(localModelSource.modelName).") } let options = ModelOptions(cloudModelName: nil, localModelName: Constants.localModelName) detectorService.loadModel(options: options, labelsPath: labelsFilePath) 1. Get model path from bundle 2. Register to ModelManager 3. Load model
  52. ML Kit - Custom Cloud Model https://www.youtube.com/watch?v=Z-dqGRSsaBs

  53. ML Kit - Custom Cloud Model let conditions = ModelDownloadConditions(wiFiRequired:

    false, idleRequired: false) let cloudModelSource = CloudModelSource( modelName: cloudModelName, enableModelUpdates: true, initialConditions: conditions, updateConditions: conditions ) let modelManager = ModelManager.modelManager() if !modelManager.register(cloudModelSource) { print("Model source was already registered with name: \(cloudModelSource.modelName).") } let options = ModelOptions(cloudModelName: cloudModelName, localModelName: nil) detectorService.loadModel(options: options, labelsPath: labelsFilePath)
  54. ML Kit - Custom Cloud Model let conditions = ModelDownloadConditions(wiFiRequired:

    false, idleRequired: false) let cloudModelSource = CloudModelSource( modelName: cloudModelName, enableModelUpdates: true, initialConditions: conditions, updateConditions: conditions ) let modelManager = ModelManager.modelManager() if !modelManager.register(cloudModelSource) { print("Model source was already registered with name: \(cloudModelSource.modelName).") } let options = ModelOptions(cloudModelName: cloudModelName, localModelName: nil) detectorService.loadModel(options: options, labelsPath: labelsFilePath) 1.specifiy model registed on Firebase Console 2. Register to ModelManager 3. Load model
  55. ML Kit with Firebase Remote Config https://www.youtube.com/watch?v=Z-dqGRSsaBs

  56. ML Kit with Firebase Remote Config let conditions = ModelDownloadConditions(wiFiRequired:

    false, idleRequired: false) let cloudModelSource = CloudModelSource( modelName: remoteConfig[cloudModelConfigKey].stringValue, enableModelUpdates: true, initialConditions: conditions, updateConditions: conditions ) let modelManager = ModelManager.modelManager() if !modelManager.register(cloudModelSource) { print("Model source was already registered with name: \(cloudModelSource.modelName).") } let options = ModelOptions(cloudModelName: cloudModelName, localModelName: nil) detectorService.loadModel(options: options, labelsPath: labelsFilePath) Specify cloud model name key in Remote Config
  57. ML Kit - On device / On Cloud https://www.youtube.com/watch?v=Z-dqGRSsaBs

  58. ML Kit - On device / On Cloud https://firebase.google.com/docs/ml-kit/

  59. ML Kit - Coming Soon Features • High density face

    contour • smart reply API • Custom model compression and conversion
  60. ML Kit - High density face contour • Detect about

    100 points in face contour https://www.youtube.com/watch?v=Z-dqGRSsaBs
  61. ML Kit - Smart Reply API https://www.youtube.com/watch?v=Z-dqGRSsaBs

  62. ML Kit - Model Compression and Conversion • Convert Tensorflow

    model to Tensorflow Lite model https://www.youtube.com/watch?v=Z-dqGRSsaBs
  63. ML Kit - Coming Soon Features https://g.co/firebase/SignUp

  64. ML Kit - Resources • Session: • ML Kit: Machine

    Learning SDK for mobile developers https:// www.youtube.com/watch?v=Z-dqGRSsaBs • TensorFlow Lite for mobile developers https:// www.youtube.com/watch?v=ByJnpbDd-zc • Document • https://firebase.google.com/docs/ml-kit/
  65. Summary - MLKit vs CoreML • Can be used Cloud

    computing resource • CoreML only support on-device model • CoreML supports NLP (smart reply API?)
  66. Part3: ARCore on ARKit with Firebase Daiki Matsudate / @d_date

    2018/05/28 FJUG #4
  67. None
  68. - Argumented Images • Respond to 2D images, such as

    posters or product packaging • Only support android
  69. - Cloud Anchors • Create AR experience with multiplayer •

    Support iOS and Android
  70. - Cloud Anchors • Create AR experience with multiplayer •

    Support iOS and Android • iOS ARCore needs ARKit
  71. DEMO

  72. - Cloud Anchors

  73. - Cloud Anchors

  74. - Cloud Anchors Host Cloud Anchor ID

  75. - Cloud Anchors Resolve with Cloud Anchor ID

  76. - Cloud Anchors Anchor information

  77. - Cloud Anchors Cloud Anchor ID

  78. ua-44417245235b466b84220d681b6da6a2 - Cloud Anchors

  79. ua-44417245235b466b84220d681b6da6a2 " - Cloud Anchors

  80. Host ID - Cloud Anchors Host ID Room ID: 1

    Room ID: 1
  81. Host ID - Cloud Anchors Host ID Room ID: 1

    Room ID: 1
  82. Host ID - Cloud Anchors Host ID Room ID: 1

    Room ID: 1 Room ID: 1
  83. - Host Cloud Anchor func addAnchor(transform: matrix_float4x4) { let arAnchor

    = ARAnchor(transform: transform) self.arAnchor = arAnchor sceneView.session.add(anchor: arAnchor) do { garAnchor = try gSession.hostCloudAnchor(arAnchor) enter(state: .hosting) } catch { print(error) } }
  84. - Host Cloud Anchor func addAnchor(transform: matrix_float4x4) { let arAnchor

    = ARAnchor(transform: transform) self.arAnchor = arAnchor sceneView.session.add(anchor: arAnchor) do { garAnchor = try gSession.hostCloudAnchor(arAnchor) enter(state: .hosting) } catch { print(error) } } Add anchor on AR Space Host to Cloud by ARCore
  85. func session(_ session: GARSession, didHostAnchor anchor: GARAnchor) { guard state

    == .hosting, anchor == garAnchor else { return } garAnchor = anchor enter(state: .hostingFinished) firebaseReference.child("hotspot_list").child(roomCode).child("hosted_anchor_id").setValu e(anchor.cloudIdentifier) let timestampInteger = NSDate().timeIntervalSince1970 * 1000 let timestamp = NSNumber(value: timestampInteger) firebaseReference.child("hotspot_list").child(roomCode).child("updated_at_timestamp").set Value(timestamp) } - After host anchor to cloud
  86. - After host anchor to cloud func session(_ session: GARSession,

    didHostAnchor anchor: GARAnchor) { guard state == .hosting, anchor == garAnchor else { return } garAnchor = anchor enter(state: .hostingFinished) firebaseReference.child("hotspot_list").child(roomCode).child("hosted_anchor_id").setValu e(anchor.cloudIdentifier) let timestampInteger = NSDate().timeIntervalSince1970 * 1000 let timestamp = NSNumber(value: timestampInteger) firebaseReference.child("hotspot_list").child(roomCode).child("updated_at_timestamp").set Value(timestamp) } Save hosted_anchor_id to Realtime Database Save timestamp
  87. func resolveAnchor(roomCode: String) { self.roomCode = roomCode enter(state: .resolving) firebaseReference.child("hotspot_list").child(roomCode).observe(.value)

    { (snapshot) in DispatchQueue.main.async { [weak self] in guard let strongSelf = self, strongSelf.state == .resolving, strongSelf.roomCode == roomCode else { return } if let anchorId: String = { if let value = snapshot.value as? [String: Any] { return value["hosted_anchor_id"] as? String } return nil }() { strongSelf.firebaseReference.child("hotspot_list").child(roomCode).removeAllObservers() strongSelf.resolveAnchor(identifier: anchorId) } } } } - Get Anchor ID from Realtime Database
  88. - Get Anchor ID from Realtime Database func resolveAnchor(roomCode: String)

    { self.roomCode = roomCode enter(state: .resolving) firebaseReference.child("hotspot_list").child(roomCode).observe(.value) { (snapshot) in DispatchQueue.main.async { [weak self] in guard let strongSelf = self, strongSelf.state == .resolving, strongSelf.roomCode == roomCode else { return } if let anchorId: String = { if let value = snapshot.value as? [String: Any] { return value["hosted_anchor_id"] as? String } return nil }() { strongSelf.firebaseReference.child("hotspot_list").child(roomCode).removeAllObservers() strongSelf.resolveAnchor(identifier: anchorId) } } } } Type room code stored in Realtime Database Get host_anchor_id from Realtime Database Resolve
  89. func resolveAnchor(identifier: String) { do { garAnchor = try gSession?.resolveCloudAnchor(withIdentifier:

    identifier) } catch { print(error) } } - Resolve with anchor ID func session(_ session: GARSession, didResolve anchor: GARAnchor) { guard state == .resolving, anchor == garAnchor else { return } self.garAnchor = anchor let arAnchor = ARAnchor(transform: anchor.transform) self.arAnchor = ARAnchor(transform: anchor.transform) sceneView.session.add(anchor: arAnchor) enter(state: .resolvingFinished) }
  90. func resolveAnchor(identifier: String) { do { garAnchor = try gSession?.resolveCloudAnchor(withIdentifier:

    identifier) } catch { print(error) } } - Resolve with anchor ID Resolve with anchor id func session(_ session: GARSession, didResolve anchor: GARAnchor) { guard state == .resolving, anchor == garAnchor else { return } self.garAnchor = anchor let arAnchor = ARAnchor(transform: anchor.transform) self.arAnchor = ARAnchor(transform: anchor.transform) sceneView.session.add(anchor: arAnchor) enter(state: .resolvingFinished) } Add anchor to AR Space
  91. - Cloud Anchors with Firebase • Good use case for

    Realtime Database / Firestore • Realtime • Store host_id in only active room • Can wait until creating new room by observing • Easy to build database with such features • Scalable
  92. - Summary • Argumented Image • Only for Android now

    • Cloud Anchors • Available on both iOS and Android • More useful to use with Firebase Database
  93. - Resources • Swift Sample • https://github.com/d-date/arcore-ios-sdk/tree/swift-sample • Session •

    https://www.youtube.com/watch?v=MeZcQguH124 • Document • https://developers.google.com/ar
  94. Summary • Automatic screen trace in performance monitoring → NEW!

    • Phone auth testing with whitelist phone number → NEW! • Test Lab for iOS → NEW! • MLKit is useful to use cloud model than CoreML • ARCore can be used with ARKit to share anchor
  95. 7/2 ٕज़ಉਓࢽ࠶ൢNight˒

  96. 7/2 ٕज़ಉਓࢽ࠶ൢNight˒ ຊ࣋ͬͯΔਓ͖࣋ͬͯͯʙʂ چόʔδϣϯ࣋ࢀͰɺ৽͍͠΋ͷʹަ׵ʂ

  97. Thank you!