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
24
Updated Lessons from a KMP Developer's Toolkit
subhrajyotisen
0
54
Building Mobile Apps and Scaling them
subhrajyotisen
0
58
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
230
Demystifying Styles and Themes
subhrajyotisen
0
270
Other Decks in Programming
See All in Programming
AWS re:Invent 2025の少し振り返り + DevOps AgentとBacklogを連携させてみた
satoshi256kbyte
3
160
10年分の技術的負債、完済へ ― Claude Code主導のAI駆動開発でスポーツブルを丸ごとリプレイスした話
takuya_houshima
0
2.4k
Codex CLIのSubagentsによる並列API実装 / Parallel API Implementation with Codex CLI Subagents
takatty
2
890
Vibe하게 만드는 Flutter GenUI App With ADK , 박제창, BWAI Incheon 2026
itsmedreamwalker
0
550
ドメインイベントでビジネスロジックを解きほぐす #phpcon_odawara
kajitack
2
140
VueエンジニアがReactを触って感じた_設計の違い
koukimiura
0
170
Cache-moi si tu peux : patterns et pièges du cache en production - Devoxx France 2026 - Conférence
slecache
0
140
Swift Concurrency Type System
inamiy
0
480
「効かない!」依存性注入(DI)を活用したAPI Platformのエラーハンドリング奮闘記
mkmk884
0
320
「速くなった気がする」をデータで疑う
senleaf24
0
170
年間50登壇、単著出版、雑誌寄稿、Podcast出演、YouTube、CM、カンファレンス主催……全部やってみたので面白さ等を比較してみよう / I’ve tried them all, so let’s compare how interesting they are.
nrslib
4
770
Feature Toggle は捨てやすく使おう
gennei
0
570
Featured
See All Featured
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
260
Fireside Chat
paigeccino
42
3.9k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
340
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
1
2k
Why Our Code Smells
bkeepers
PRO
340
58k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.6k
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
430
What's in a price? How to price your products and services
michaelherold
247
13k
Statistics for Hackers
jakevdp
799
230k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
5.9k
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