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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Subhrajyoti Sen
November 06, 2021
Programming
150
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
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
55
Updated Lessons from a KMP Developer's Toolkit
subhrajyotisen
0
71
Building Mobile Apps and Scaling them
subhrajyotisen
0
75
Compose Previews as a Power User
subhrajyotisen
1
240
Understanding WindowInsets
subhrajyotisen
0
270
Exploring a KMM Developer’s Toolkit
subhrajyotisen
1
280
Understanding WindowInsets - Android Worldwide
subhrajyotisen
0
400
Understanding WindowInsets
subhrajyotisen
1
240
Demystifying Styles and Themes
subhrajyotisen
0
290
Other Decks in Programming
See All in Programming
為什麼你並不需要ViewModel / No, you don't need a ViewModel
lovee
1
500
仕様駆動開発へのトライを機に チームに適合する手法を模索し続けている話
freee
PRO
0
580
AI Engineeringは、AIプロダクトだけのものか? 〜AIがソフトウェアを作る時代の新しい当たり前〜 / No AI in your product. AI Engineering in your development.
rkaga
4
490
リアルな遅延を測る仕様
kota_yata
1
120
KotlinConf Extended South Korea 2026 Keynote
l2hyunwoo
0
110
レビュー履歴をAIに食わせて、 Compose移行を加速するs
shihochan
0
150
Detecting Compromised CI with eBPF and Cilium Tetragon
lizrice
0
220
【デモ】Kiroで体験する仕様駆動開発|設計からコーディングまでAIと進める開発フロー
cmkudo
0
250
いまどきの Codex で開発する visionOS アプリの開発スタイルについて
karad
0
150
Building a Meta Ray-Ban display app
akkeylab
0
170
言葉の格闘技のススメ~紙とペンと言葉から始める、キャリアの描き方~
progresscicada
2
160
yield再入門 #phpcon
o0h
PRO
0
1.2k
Featured
See All Featured
Navigating Team Friction
lara
192
16k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
990
Site-Speed That Sticks
csswizardry
13
1.5k
KATA
mclloyd
PRO
35
15k
We Have a Design System, Now What?
morganepeng
55
8.3k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
470
4 Signs Your Business is Dying
shpigford
187
23k
Testing 201, or: Great Expectations
jmmastey
46
8.2k
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
500
Ruling the World: When Life Gets Gamed
codingconduct
0
300
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
260
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2k
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