Slide 1

Slide 1 text

Introduction to Android Instant Apps by Cyril Mottier

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

>

Slide 4

Slide 4 text

> >

Slide 5

Slide 5 text

> > >

Slide 6

Slide 6 text

Find Install Start Setup Use Installing & using a mobile app is a long and steep path

Slide 7

Slide 7 text

Reduce friction as much as possible

Slide 8

Slide 8 text

Instant apps Native apps, without installation

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

>

Slide 11

Slide 11 text

> >

Slide 12

Slide 12 text

You may only need 10% of an app’s features So why download 100%?

Slide 13

Slide 13 text

Application

Slide 14

Slide 14 text

Application Feature 1 Feature 2 Feature 3 Common

Slide 15

Slide 15 text

The build output now depends on the targeted run mode

Slide 16

Slide 16 text

installable.apk Feature 1 Feature 2 Feature 3 Common

Slide 17

Slide 17 text

instant_app.zip Feature 1 APK Feature 2 APK Feature 3 APK Base APK

Slide 18

Slide 18 text

What about the on-device behaviour?

Slide 19

Slide 19 text

Installable app

Slide 20

Slide 20 text

Feature 1 Feature 2 Feature 3 Base Installable app

Slide 21

Slide 21 text

Instant app

Slide 22

Slide 22 text

Feature 1 Base Instant app Using feature 1

Slide 23

Slide 23 text

Feature 2 Base Instant app Using feature 2

Slide 24

Slide 24 text

Feature 1 Base Instant app Using feature 1 then 2

Slide 25

Slide 25 text

Feature 1 Feature 2 Base Instant app Using feature 1 then 2

Slide 26

Slide 26 text

Feature 1 Feature 2 Feature 3 Base Instant app Using all features

Slide 27

Slide 27 text

Lollipop+

Slide 28

Slide 28 text

Android Studio 3.0+ with Instant Apps Development SDK

Slide 29

Slide 29 text

Runtime permissions introduced in Android 6.0 (API level 23)

Slide 30

Slide 30 text

App links Associate your app with your domain

Slide 31

Slide 31 text

android:autoVerify="true"

Slide 32

Slide 32 text

android:autoVerify="true"

Slide 33

Slide 33 text

android:autoVerify="true"

Slide 34

Slide 34 text

https:///.well-known/assetlinks.json

Slide 35

Slide 35 text

https:///.well-known/assetlinks.json [ { "relation": [ "delegate_permission/common.handle_all_urls" ], "target": { "namespace": "android_app", "package_name": "com.gdgnantes.devfest.android", "sha256_cert_fingerprints": [ "1A:24:9C:B5:69:5F:B5:21:CD:80:45:7A:06:20:C5:78:DB: 07:A8:CA:A0:8F:E9:47:B9:F6:A5:60:6B:78:DB:32" ] } } ]

Slide 36

Slide 36 text

https:///.well-known/assetlinks.json [ { "relation": [ "delegate_permission/common.handle_all_urls" ], "target": { "namespace": "android_app", "package_name": "com.gdgnantes.devfest.android", "sha256_cert_fingerprints": [ "1A:24:9C:B5:69:5F:B5:21:CD:80:45:7A:06:20:C5:78:DB: 07:A8:CA:A0:8F:E9:47:B9:F6:A5:60:6B:78:DB:32" ] } } ] "relation": [ "delegate_permission/common.handle_all_urls" ]

Slide 37

Slide 37 text

https:///.well-known/assetlinks.json [ { "relation": [ "delegate_permission/common.handle_all_urls" ], "target": { "namespace": "android_app", "package_name": "com.gdgnantes.devfest.android", "sha256_cert_fingerprints": [ "1A:24:9C:B5:69:5F:B5:21:CD:80:45:7A:06:20:C5:78:DB: 07:A8:CA:A0:8F:E9:47:B9:F6:A5:60:6B:78:DB:32" ] } } ] "namespace": "android_app" "target": { }

Slide 38

Slide 38 text

https:///.well-known/assetlinks.json [ { "relation": [ "delegate_permission/common.handle_all_urls" ], "target": { "namespace": "android_app", "package_name": "com.gdgnantes.devfest.android", "sha256_cert_fingerprints": [ "1A:24:9C:B5:69:5F:B5:21:CD:80:45:7A:06:20:C5:78:DB: 07:A8:CA:A0:8F:E9:47:B9:F6:A5:60:6B:78:DB:32" ] } } ] "package_name": "com.gdgnantes.devfest.android" "target": { }

Slide 39

Slide 39 text

https:///.well-known/assetlinks.json [ { "relation": [ "delegate_permission/common.handle_all_urls" ], "target": { "namespace": "android_app", "package_name": "com.gdgnantes.devfest.android", "sha256_cert_fingerprints": [ "1A:24:9C:B5:69:5F:B5:21:CD:80:45:7A:06:20:C5:78:DB: 07:A8:CA:A0:8F:E9:47:B9:F6:A5:60:6B:78:DB:32" ] } } ] "sha256_cert_fingerprints": [ "1A:24:9C:B5:69:5F:B5:21:CD:80:45:7A:06:20:C5:78:DB: 07:A8:CA:A0:8F:E9:47:B9:F6:A5:60:6B:78:DB:32" ] "target": { }

Slide 40

Slide 40 text

https:///.well-known/assetlinks.json [ { "relation": [ "delegate_permission/common.handle_all_urls" ], "target": { "namespace": "android_app", "package_name": "com.gdgnantes.devfest.android", "sha256_cert_fingerprints": [ "1A:24:9C:B5:69:5F:B5:21:CD:80:45:7A:06:20:C5:78:DB: 07:A8:CA:A0:8F:E9:47:B9:F6:A5:60:6B:78:DB:32" ] } } ]

Slide 41

Slide 41 text

Modularise your code Break the app into features

Slide 42

Slide 42 text

Pointing out features

Slide 43

Slide 43 text

Licenses :features:licenses module Installable app :app module About :features:about module

Slide 44

Slide 44 text

What about the base APK? contains code/resources used in all modules

Slide 45

Slide 45 text

Application icon Custom font management Common styles, dimens, colors, … Base Activity/Fragment implementation Utilities etc. What about the base APK? contains code/resources used in all modules

Slide 46

Slide 46 text

Modularize action in Android Studio

Slide 47

Slide 47 text

./settings.gradle include ':app', ':features:about', ':features:base', ':features:licenses', ':instant'

Slide 48

Slide 48 text

include ':app', ':features:about', ':features:base', ':features:licenses', ':instant' ./settings.gradle ':app'

Slide 49

Slide 49 text

include ':app', ':features:about', ':features:base', ':features:licenses', ':instant' ':features:base' ./settings.gradle

Slide 50

Slide 50 text

include ':app', ':features:about', ':features:base', ':features:licenses', ':instant' ':features:about' ./settings.gradle

Slide 51

Slide 51 text

include ':app', ':features:about', ':features:base', ':features:licenses', ':instant' ':instant' ./settings.gradle

Slide 52

Slide 52 text

apply plugin: 'com.android.feature' android { //... baseFeature true } dependencies { application project(':app') feature project(':features:about') feature project(':features:licenses') } ./features/base/build.gradle

Slide 53

Slide 53 text

apply plugin: 'com.android.feature' android { //... baseFeature true } dependencies { application project(':app') feature project(':features:about') feature project(':features:licenses') } ./features/base/build.gradle apply plugin: 'com.android.feature'

Slide 54

Slide 54 text

apply plugin: 'com.android.feature' android { //... baseFeature true } dependencies { application project(':app') feature project(':features:about') feature project(':features:licenses') } ./features/base/build.gradle baseFeature true

Slide 55

Slide 55 text

apply plugin: 'com.android.feature' android { //... baseFeature true } dependencies { application project(':app') feature project(':features:about') feature project(':features:licenses') } ./features/base/build.gradle application project(':app') feature project(':features:about') feature project(':features:licenses')

Slide 56

Slide 56 text

apply plugin: 'com.android.feature' android { //... baseFeature true } dependencies { application project(':app') feature project(':features:about') feature project(':features:licenses') } ./features/base/build.gradle

Slide 57

Slide 57 text

apply plugin: 'com.android.feature' //... dependencies { implementation project(':features:base') } ./features/about/build.gradle

Slide 58

Slide 58 text

apply plugin: 'com.android.application' //... dependencies { implementation project(':features:base') implementation project(':features:about') implementation project(':features:licenses') } ./app/build.gradle

Slide 59

Slide 59 text

apply plugin: ‘com.android.instantapp' //... dependencies { implementation project(':features:base') implementation project(':features:about') implementation project(':features:licenses') } ./instant/build.gradle

Slide 60

Slide 60 text

apply plugin: ‘com.android.instantapp' //... dependencies { implementation project(':features:base') implementation project(':features:about') implementation project(':features:licenses') } ./instant/build.gradle apply plugin: ‘com.android.instantapp'

Slide 61

Slide 61 text

apply plugin: ‘com.android.instantapp' //... dependencies { implementation project(':features:base') implementation project(':features:about') implementation project(':features:licenses') } ./instant/build.gradle

Slide 62

Slide 62 text

where Function returning the binary size of Total download bundle binary size

Slide 63

Slide 63 text

where Function returning the binary size of Maximum download bundle binary size

Slide 64

Slide 64 text

Maximum download bundle size (i.e. that weird “ ” constant)

Slide 65

Slide 65 text

During development ∞ Maximum download bundle size (i.e. that weird “ ” constant)

Slide 66

Slide 66 text

Play Store dev tracks 10MB During development ∞ Maximum download bundle size (i.e. that weird “ ” constant)

Slide 67

Slide 67 text

4MB Play Store production Play Store dev tracks 10MB During development ∞ Maximum download bundle size (i.e. that weird “ ” constant)

Slide 68

Slide 68 text

The smaller, the better (not specific to Android only)

Slide 69

Slide 69 text

Slim down your APK size

Slide 70

Slide 70 text

Slim down your APK size Resource shrinking

Slide 71

Slide 71 text

Slim down your APK size Code minification Resource shrinking

Slide 72

Slide 72 text

Slim down your APK size Code minification Vector graphics Resource shrinking

Slide 73

Slide 73 text

Slim down your APK size Code minification Vector graphics Resource shrinking

Slide 74

Slide 74 text

Slim down your APK size Dependencies reduction Code minification Vector graphics Resource shrinking Downloadable fonts Resources de-duplication Remote fetching Images optimisation WebP format Granular dependencies Density bucket removal Native code architecture removal Wear 2.0 APK distribution Sparse translation elimination Version collapsing

Slide 75

Slide 75 text

APK Analyser

Slide 76

Slide 76 text

APK Analyser

Slide 77

Slide 77 text

Still not enough? Configuration split to the rescue

Slide 78

Slide 78 text

android { //... generatePureSplits true splits { abi { enable true } density { enable true } language { enable true include "en", "fr" } } } ./base.build.gradle

Slide 79

Slide 79 text

Installation prompts

Slide 80

Slide 80 text

dependencies { //... implementation 'com.google.android.instantapps:instantapps:1.1.0' } ./features/base/build.gradle

Slide 81

Slide 81 text

if (InstantApps.isInstantApp(this)) { val postInstallIntent = MainActivity.newIntent() InstantApps.showInstallPrompt(this, postInstallIntent, INSTALL_PROMPT_REQUEST_CODE, "Referrer") }

Slide 82

Slide 82 text

Keep user state after app installation

Slide 83

Slide 83 text

Cookie API // Instant app with(packageManager) { if (cookie.size <= instantAppCookieMaxBytes) { updateInstantAppCookie(cookie) } }

Slide 84

Slide 84 text

// Installable app val cookie = packageManager.instantAppCookie // ... (i.e. restore user data) packageManager.clearInstantAppCookie() Cookie API

Slide 85

Slide 85 text

Instant App Data dependencies { //... implementation 'com.google.android.gms:play-services-instantapps:11.4.2' } ./features/base/build.gradle

Slide 86

Slide 86 text

Instant App Data val client = InstantApps.getInstantAppsClient(this) val fileTask = client.instantAppData fileTask .addOnCompleteListener { readData(it.result) } .addOnFailureListener { handleException(it) }

Slide 87

Slide 87 text

Instant App Data Shared Preferences getFilesDir() getDir(String, int) Databases ParcelFileDescriptor to the caller's Instant App's data

Slide 88

Slide 88 text

Instant Apps in the real world aka the pros and cons

Slide 89

Slide 89 text

VS Instant apps Progressive Web apps

Slide 90

Slide 90 text

Thank you! cyrilmottier.com @cyrilmottier