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

Android Makers - Everything They Don't Tell You...

Android Makers - Everything They Don't Tell You About Instant Apps

Avatar for Jamie Adkins

Jamie Adkins

April 20, 2020
Tweet

More Decks by Jamie Adkins

Other Decks in Programming

Transcript

  1. CWC19 Quiz Instant App • Find the ICC app on

    the Play Store, and click “try now”. • “CWC” -> “T20WC”
  2. What are Dynamic Features? • At Install Time ◦ Download

    this feature when the user installs my app from the Play Store. • Conditional ◦ Download this feature when the user installs my app from the Play Store if their device meets some conditions. • Instant enabled ◦ Download just this feature when the user clicks on a link. • On Demand ◦ Don’t download this feature at install time, download it later when the user wants to use that feature.
  3. What are Dynamic Features? • At Install Time ◦ Download

    this feature when the user installs my app from the Play Store. • Conditional ◦ Download this feature when the user installs my app from the Play Store if their device meets some conditions. • Instant enabled ◦ Download just this feature when the user clicks on a link. • On Demand ◦ Don’t download this feature at install time, download it later when the user wants to use that feature.
  4. 4MB • Android/AndroidX - 1.2MB • Material Design - 500KB

    • Firebase - 60KB ◦ Google Play Services - 750KB • Common ICC/CWC assets - 500KB • CWC Fonts - 200KB • Common ICC/CWC code - 500KB • Quiz code & assets - 250KB • Total - 3.95MB
  5. 4MB

  6. 4MB

  7. Application Class - Before class IccApplication : DaggerApplication() { override

    fun onCreate() { super.onCreate() Timber.plant(CrashlyticsTree()) Fabric.with(this, Crashlytics()) } override fun applicationInjector() : AndroidInjector<out DaggerApplication> { return DaggerAppComponent.builder().create(this) } }
  8. Application Class - Before class IccApplication : DaggerApplication() { override

    fun onCreate() { super.onCreate() Timber.plant(CrashlyticsTree()) Fabric.with(this, Crashlytics()) } override fun applicationInjector() : AndroidInjector<out DaggerApplication> { return DaggerAppComponent.builder().create(this) } }
  9. Application Class - Before class IccApplication : DaggerApplication() { override

    fun onCreate() { super.onCreate() Timber.plant(CrashlyticsTree()) Fabric.with(this, Crashlytics()) } override fun applicationInjector() : AndroidInjector<out DaggerApplication> { return DaggerAppComponent.builder().create(this) } }
  10. Conclusions • Don’t redo the Dagger Graph • Few dependencies

    actually need to be Singletons • We don’t need DaggerApplication
  11. Proposal • AppComponent would stay in :app • Application class

    would move to :base, and it would provide a Singleton scoped CoreComponent • AppComponent would depend on CoreComponent for any Singletons • AppComponent would be built and scoped to the Activities in :app
  12. Manifest Merging <activity android:name="com.icccricket.quiz.QuizActivity" android:theme="@style/QuizTheme"> • Move all styles to

    base module ◦ Breaks separations of concern ◦ Impacts the 4MB download size limit • Create stub styles in :base
  13. Stub Themes <!-- base/src/main/res/values/styles.xml --> <!-- Empty theme in base

    module --> <style name=”QuizTheme” /> https://github.com/android/plaid
  14. Stub Themes <!-- base/src/main/res/values/styles.xml --> <!-- Empty theme in base

    module --> <style name=”QuizTheme” /> <!-- quiz/src/main/res/values/styles.xml --> <!-- Actual implementation in quiz dynamic feature module --> <style name="QuizTheme" parent="Theme.MaterialComponents"> <item name="colorPrimary">@color/cwc_primary</item> <item name="colorAccent">@color/cwc_secondary</item> ... https://github.com/android/plaid
  15. Stub Themes Caveats • Must be shipping as an App

    Bundle ◦ APK builds will incorrectly use the stub style ◦ Distributing test builds as APKs? ◦ No split install support on < SDK 21 • We ended up moving all our styles to :base :( • But you don’t have to! Fixed in bundletool 0.13.4
  16. Stub Themes Caveats • Must be shipping as an App

    Bundle ◦ APK builds will incorrectly use the stub style ◦ Distributing test builds as APKs ◦ No split install support on < SDK 21 • We ended up moving all our styles to :base :( • But you don’t have to! Fixed in bundletool 0.13.4
  17. Bundletool 0.13.4 buildscript { repositories { google() jcenter() ... }

    dependencies { classpath "com.android.tools.build:bundletool:0.13.4" ... } ... }
  18. Bundletool 0.13.4 • brew upgrade bundletool • Wait for Play

    Store to upgrade to 0.13.4 (April 2020 ) • https://github.com/google/bundletool/releases/tag/0.13.4 • https://github.com/google/bundletool/issues/68
  19. Everything is a Dynamic Feature • Turn a feature into

    a dynamic feature only if it is going to be instant enabled/on demand • Feature on Feature Dependencies in AGP 4.0 • https://medium.com/@jamieadkins95/a-quick-look-at-feature-on-feat ure-dependencies-in-android-gradle-plugin-4-0-0-5828915d02d3 • 15MB download size limit is much more forgiving
  20. Permissions • Smaller set of permissions for Instant Apps •

    Can’t access external storage • Can’t share from internal storage either • You should share images using backend and a web url • For CWC we dropped the image • Scoped storage in Android 10/11?
  21. Quick Fire Tips • Double check your proguard rules! •

    Use AGP 3.5 or higher (or 4.0 for feature-on-feature) • Use the APK Analyser in Android Studio • Test against the download size limit using xxxhdpi • Use the internal test track • Indexing may take 24 hours!
  22. Further Reading • Plaid Sample App - Google https://github.com/android/plaid •

    Ben Weiss https://medium.com/@keyboard surfer • Android Docs https://developer.android.com/to pic/google-play-instant @jamieadkins95 @jamieadkins95
  23. R.java Files • In normal project you can use the

    same R.java file to reference everything • In dynamic features, you need to use the base application module’s R.java file for common resources • Otherwise you’ll get an ‘unresolved reference’ error at compile time • IDE doesn’t see the error • Can use Kotlin aliases to neaten this up
  24. Groups/Barriers • Programatically set the view ids group.setReferencedIds(arrayOf(R.id.button4, R.id.button9)) Fixed

    in Constraint Layout 2.0.0-beta2 https://androidstudio.googleblog.com/2019/06/constraintlayout-200-be ta-2.html