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
0
82
Shipping Apps Confidently with Firebase
Subhrajyoti Sen
November 06, 2021
Tweet
Share
More Decks by Subhrajyoti Sen
See All by Subhrajyoti Sen
Updated Lessons from a KMP Developer's Toolkit
subhrajyotisen
0
30
Building Mobile Apps and Scaling them
subhrajyotisen
0
34
Compose Previews as a Power User
subhrajyotisen
1
170
Understanding WindowInsets
subhrajyotisen
0
200
Exploring a KMM Developer’s Toolkit
subhrajyotisen
1
230
Understanding WindowInsets - Android Worldwide
subhrajyotisen
0
330
Understanding WindowInsets
subhrajyotisen
1
200
Demystifying Styles and Themes
subhrajyotisen
0
240
Journey Of Time
subhrajyotisen
0
250
Other Decks in Programming
See All in Programming
Denoのセキュリティに関する仕組みの紹介 (toranoana.deno #23)
uki00a
0
200
Implementation Patterns
denyspoltorak
0
140
Grafana:建立系統全知視角的捷徑
blueswen
0
260
Basic Architectures
denyspoltorak
0
150
AI時代を生き抜く 新卒エンジニアの生きる道
coconala_engineer
1
480
Patterns of Patterns
denyspoltorak
0
400
Combinatorial Interview Problems with Backtracking Solutions - From Imperative Procedural Programming to Declarative Functional Programming - Part 2
philipschwarz
PRO
0
130
Claude Codeの「Compacting Conversation」を体感50%減! CLAUDE.md + 8 Skills で挑むコンテキスト管理術
kmurahama
1
680
ローカルLLMを⽤いてコード補完を⾏う VSCode拡張機能を作ってみた
nearme_tech
PRO
0
210
公共交通オープンデータ × モバイルUX 複雑な運行情報を 『直感』に変換する技術
tinykitten
PRO
0
170
Canon EOS R50 V と R5 Mark II 購入でみえてきた最近のデジイチ VR180 事情、そして VR180 静止画に活路を見出すまで
karad
0
140
HTTPプロトコル正しく理解していますか? 〜かわいい猫と共に学ぼう。ฅ^•ω•^ฅ ニャ〜
hekuchan
2
570
Featured
See All Featured
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
150
How to build a perfect <img>
jonoalderson
0
4.8k
Code Reviewing Like a Champion
maltzj
527
40k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
1
99
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
680
Build your cross-platform service in a week with App Engine
jlugia
234
18k
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
140
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
0
1k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
0
2.3k
Imperfection Machines: The Place of Print at Facebook
scottboms
269
13k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
10
770
How To Stay Up To Date on Web Technology
chriscoyier
791
250k
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