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

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

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

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