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
Shipping Apps Confidently with Firebase
Search
Subhrajyoti Sen
November 06, 2021
Programming
110
0
Share
Shipping Apps Confidently with Firebase
Subhrajyoti Sen
November 06, 2021
More Decks by Subhrajyoti Sen
See All by Subhrajyoti Sen
Understanding Incremental Processing in the JVM World
subhrajyotisen
0
22
Updated Lessons from a KMP Developer's Toolkit
subhrajyotisen
0
52
Building Mobile Apps and Scaling them
subhrajyotisen
0
57
Compose Previews as a Power User
subhrajyotisen
1
200
Understanding WindowInsets
subhrajyotisen
0
240
Exploring a KMM Developer’s Toolkit
subhrajyotisen
1
250
Understanding WindowInsets - Android Worldwide
subhrajyotisen
0
370
Understanding WindowInsets
subhrajyotisen
1
220
Demystifying Styles and Themes
subhrajyotisen
0
260
Other Decks in Programming
See All in Programming
Going Multiplatform with Your Android App (Android Makers 2026)
zsmb
1
280
テレメトリーシグナルが導くパフォーマンス最適化 / Performance Optimization Driven by Telemetry Signals
seike460
PRO
2
220
Codex CLI でつくる、Issue から merge までの開発フロー
amata1219
0
310
Vibe하게 만드는 Flutter GenUI App With ADK , 박제창, BWAI Incheon 2026
itsmedreamwalker
0
540
iOS機能開発のAI環境と起きた変化
ryunakayama
0
150
Linux Kernelの1文字のミスで 権限昇格ができた話
rqda
0
2.3k
Codex CLIのSubagentsによる並列API実装 / Parallel API Implementation with Codex CLI Subagents
takatty
2
830
車輪の再発明をしよう!PHP で実装して学ぶ、Web サーバーの仕組みと HTTP の正体
h1r0
3
500
モックわからないマン卒業記 ~振る舞いを起点に見直した、フロントエンドテストにおけるモックの使いどころ~
tasukuwatanabe
3
440
今こそ押さえておきたい アマゾンウェブサービス(AWS)の データベースの基礎 おもクラ #6版
satoshi256kbyte
1
230
AIエージェントで業務改善してみた
taku271
0
400
PHPのバージョンアップ時にも役立ったAST(2026年版)
matsuo_atsushi
0
290
Featured
See All Featured
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Ruling the World: When Life Gets Gamed
codingconduct
0
190
Writing Fast Ruby
sferik
630
63k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
130
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
500
Six Lessons from altMBA
skipperchong
29
4.2k
Facilitating Awesome Meetings
lara
57
6.8k
Scaling GitHub
holman
464
140k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
190
Designing for humans not robots
tammielis
254
26k
The Curious Case for Waylosing
cassininazir
0
290
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.1k
Transcript
Shipping Apps Con dently with Firebase KeepTruckin Subhrajyoti Sen DevFest
Greece & Cyprus 2021 November 2021
Crashes
Crashlytics
Crashlytics • Automatic crash reporting
Crashlytics • • Automatic crash reporting But no limited to
crash reporting
Recording Non-fatal exceptions
Recording Non-fatal exceptions try { // some code can throw
an exception } catch (e: Exception) { Log.d(TAG, e.localizedMessage) }
Recording Non-fatal exceptions try { // some code can throw
an exception } catch (e: Exception) { Log.d(TAG, e.localizedMessage) }
Recording Non-fatal exceptions try { // some code can throw
an exception } catch (e: Exception) { FirebaseCrashlytics.getInstance().recordException(e) }
Recording Non-fatal exceptions private class CrashReportingTree : Timber.Tree() { }
Recording Non-fatal exceptions private class CrashReportingTree : Timber.Tree() { override
fun log(priority: Int, tag: String?, message: String, t: Throwable?) { } }
Recording Non-fatal exceptions private class CrashReportingTree : Timber.Tree() { override
fun log(priority: Int, tag: String?, message: String, t: Throwable?) { if (priority == Log.ERROR && t != null) { FirebaseCrashlytics.getInstance().recordException(t) } } }
Recording Non-fatal exceptions class MainApplication : Application() { override fun
onCreate() { super.onCreate() Timber.plant(CrashReportingTree()) } }
Recording Non-fatal exceptions try { // some code can throw
an exception } catch (e: Exception) { FirebaseCrashlytics.getInstance().recordException(e) }
Recording Non-fatal exceptions try { // some code can throw
an exception } catch (e: Exception) { Timber.e(e) }
Understanding Crashes Better
Analytics
Analytics • We normally use analytics in isolation from crash
reporting
Analytics • • We normally use analytics in isolation from
crash reporting Usually PMs check the analytics and Devs check the crashes
Analytics • • • We normally use analytics in isolation
from crash reporting Usually PMs check the analytics and Devs check the crashes What if you can combine them to get a full view?
Analytics
Analytics
Analytics binding.zoomImage.setOnClickListener { MixpanelAPI.track("Zoom button clicked") }
Analytics binding.zoomImage.setOnClickListener { MixpanelAPI.track("Zoom button clicked") FirebaseAnalytics.getInstance(context) .logEvent("Zoom button clicked",
mapOf("page", "map")) }
Analytics interface AnalyticsProvider { fun track( analyticEvent: String, properties: Map<String,
Any?>? = null ) }
Analytics class FirebaseAnalyticsProvider( private val rebaseAnalytics: FirebaseAnalytics ): AnalyticsProvider {
override fun track(analyticEvent: String, properties: Map<String, Any?>?) { rebaseAnalytics.logEvent(analyticEvent, properties) } }
Analytics class FirebaseAnalyticsProvider( private val rebaseAnalytics: FirebaseAnalytics ): AnalyticsProvider {
override fun track(analyticEvent: String, properties: Map<String, Any?>?) { rebaseAnalytics.logEvent(analyticEvent, properties) } }
Analytics class AnalyticsManager { private val analyticsProviders = mutableListOf<AnalyticsProvider>() fun
addProvider(provider: AnalyticsProvider) { analyticsProviders.add(provider) } }
Analytics class AnalyticsManager { //... fun track(analyticEvent: String, properties: Map<String,
Any?>?) { analyticsProviders.forEach { provider -> provider.track(analyticEvent, properties) } } }
Analytics binding.zoomImage.setOnClickListener { analyticsManager.logEvent( "Zoom button clicked", mapOf("page", "map") )
}
Feature Flags
What's a feature ag?
What's a feature ag? if (isNewFeatureEnabled) { // allow access
to shiny new feature } else { // prevent access to shiny new feature }
Use cases
Use cases • A/B Testing
Use cases • • A/B Testing Rolling out new features
Use cases • • • A/B Testing Rolling out new
features Rolling out rewrite of existing features
Use cases • • • • A/B Testing Rolling out
new features Rolling out rewrite of existing features Merge Work-in-progress features
Types of Feature Flags?
Types of Feature Flags? • Static
Types of Feature Flags? • • Static Decided at build
time
Types of Feature Flags? • • • Static Decided at
build time Based on things like versionCode, buildVariant, etc
Types of Feature Flags? • • • • Static Decided
at build time Based on things like versionCode, buildVariant, etc Dynamic
Types of Feature Flags? • • • • • Static
Decided at build time Based on things like versionCode, buildVariant, etc Dynamic Can be controlled at runtime either locally using dev settings
Types of Feature Flags? • • • • • •
Static Decided at build time Based on things like versionCode, buildVariant, etc Dynamic Can be controlled at runtime either locally using dev settings Or remotely via services like Firebase Remote Con g
None
Show me code!!
interface Con g { val key: String val default: Boolean
val description: String }
enum class FeatureFlags( override val key: String, override val default:
Boolean, override val description: String ): Con g
enum class FeatureFlags( override val key: String, override val default:
Boolean, override val description: String ): Con g { NEW_CHECKOUT_FLOW( "checkout_ ow_v2", true, "Enable checkout ow V2 for trending items" ) }
interface FeatureFlagProvider { fun getValue(featureFlag: FeatureFlag): Boolean }
class FirebaseFeatureFlagProvider: FeatureFlagProvider { private val remoteCon g = FirebaseRemoteCon
g.getInstance() override fun getValue(featureFlag: FeatureFlag): Boolean { return remoteCon g.getBoolean(featureFlag.key) } }
class RemoteCon gManager( private val featureFlagProvider: FeatureFlagProvider ) { fun
isFeatureEnabled(featureFlag: FeatureFlag) = featureFlagProvider.getValue(featureFlag) }
if (remoteCon gManager.isFeatureEnabled(NEW_CHECKOUT_FLOW)) { // allow access to shiny new
feature } else { // prevent access to shiny new feature }
Using Feature Flags effectively
Using Feature Flags effectively • De ne success metrics
Using Feature Flags effectively • • De ne success metrics
Less Crashes?
Using Feature Flags effectively • • • De ne success
metrics Less Crashes? Smoother experience?
Using Feature Flags effectively • • • • De ne
success metrics Less Crashes? Smoother experience? Implement using your Analytics library (like Mixpanel)
Using Feature Flags effectively • • • • • De
ne success metrics Less Crashes? Smoother experience? Implement using your Analytics library (like Mixpanel) Create dashboards to compare
@iamsubhrajyoti https://calendly.com/subhrajyotisen
Credits: UC Davis