Upgrade to Pro — share decks privately, control downloads, hide ads and more …

What's new in Firebase

d_date
May 28, 2018

What's new in Firebase

2018/05/28 FJUG #4

d_date

May 28, 2018
Tweet

More Decks by d_date

Other Decks in Programming

Transcript

  1. 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
  2. - Automatic Trace Measuring performances about app • Automatic trace

    • App start • Network • App in foreground / background • • Screen ← NEW!
  3. 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))
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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
  11. • Run Unit test and UI test with XCTest •

    Firebase Console • gcloud CLI Firebase Test Lab for iOS
  12. Summary • Automatic screen trace in performance monitoring → NEW!

    • Phone auth testing with whitelist phone number → NEW! • Test Lab for iOS → NEW! • MLKit → NEW!
  13. 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
  14. ML Kit • iOS / Android SDK • Base API

    and Custom Model Support • On device / On Cloud • Deeply integrated into Firebase
  15. 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)
  16. 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)
  17. 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
  18. 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)
  19. 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
  20. 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
  21. ML Kit - Coming Soon Features • High density face

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

    100 points in face contour https://www.youtube.com/watch?v=Z-dqGRSsaBs
  23. ML Kit - Model Compression and Conversion • Convert Tensorflow

    model to Tensorflow Lite model https://www.youtube.com/watch?v=Z-dqGRSsaBs
  24. 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/
  25. Summary - MLKit vs CoreML • Can be used Cloud

    computing resource • CoreML only support on-device model • CoreML supports NLP (smart reply API?)
  26. - Argumented Images • Respond to 2D images, such as

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

    Support iOS and Android • iOS ARCore needs ARKit
  28. - 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) } }
  29. - 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
  30. 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
  31. - 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
  32. 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
  33. - 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
  34. 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) }
  35. 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
  36. - 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
  37. - Summary • Argumented Image • Only for Android now

    • Cloud Anchors • Available on both iOS and Android • More useful to use with Firebase Database
  38. - 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
  39. 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