Slide 1

Slide 1 text

既存アプリへの
 Instant Apps導入 荒谷 光 あらたに あきら @_a_akira - Introduce Instant Apps -

Slide 2

Slide 2 text

About me @_a_akira AAkira CyberAgent, Inc. Akira Aratani

Slide 3

Slide 3 text

• 生放送配信プラットフォーム • ライブファンディング • 4K配信対応, 低遅延配信 • M11の頃からFull Kotlinで開発
 サーバサイドも1年前からKotlinを使用 About 3

Slide 4

Slide 4 text

Agenda • About Instant Apps • Develop Instant Apps • Tools • Modularize • Modularize by Dagger Injection • Summary 4

Slide 5

Slide 5 text

About Instant Apps

Slide 6

Slide 6 text

https://youtu.be/862r3XS2YB0?t=5993 Google I/O 2016 (1:39:50頃) 6

Slide 7

Slide 7 text

About Instant Apps • Google I/O 2016で発表 • Google I/O 2017の当日から使用可能に • Android 6.0+
 (将来的には5.0+) 7

Slide 8

Slide 8 text

8

Slide 9

Slide 9 text

Purpose • URLベースでアクセス可能なので、
 最初のキッカケを与えられる • ネイティブアプリと同じ経験を 9

Slide 10

Slide 10 text

Use case • 将来的には、
 位置情報, QRCode, ビーコン、NFC
 をキッカケにすることも考えている • Text baseのurlで起動出来るので、
 広告での使用も可能 10

Slide 11

Slide 11 text

Use case • 検索結果から
 InstantAppsを直接起動
 11 © RED BULL

Slide 12

Slide 12 text

Use case • Slack等の
 メッセージアプリからも
 InstantAppsを直接起動 12 © Vimeo, Inc.

Slide 13

Slide 13 text

Use case Web Pageでの表示 Storeでの表示 13 sharethemeal.org © RED BULL

Slide 14

Slide 14 text

Use case • Instant Appsは
 端末にDLされる 14

Slide 15

Slide 15 text

Use case • Instant Appsは
 端末にDLされる 15

Slide 16

Slide 16 text

APIs • Smart Lock
 → ログインがスムーズに • Google Payment API
 → 購入がスムーズに 16 Wish © ContextLogic, Inc.

Slide 17

Slide 17 text

APIs • Play Install API
 → インストールまでが
   スムーズに 17 © Vimeo, Inc.

Slide 18

Slide 18 text

About Instant Apps • ユーザへの障壁を出来るだけ減らす • UXを上げる各種APIが揃っている 18

Slide 19

Slide 19 text

About Instant Apps • ユーザへの障壁を出来るだけ減らす • UXを上げる各種APIが揃っている Googleの目指している未来 19

Slide 20

Slide 20 text

Develop
 Instant Apps

Slide 21

Slide 21 text

Development tools Android Studio 3.0+ Emulator Support App Links include SDK 21

Slide 22

Slide 22 text

App links • Marshmallow(6.0)から導入 • Manifestにを追加 • サーバにjsonファイルを配置すれば
 リンクをクリックした時にアプリを起動可能
 AndroidManifestに
 android:autoVerify=“true”を指定する 22

Slide 23

Slide 23 text

App links assistant • Tools > App links assistant 23

Slide 24

Slide 24 text

Develop instant apps 1つのコードベースで
 instant apps, installed appの開発が可能 24

Slide 25

Slide 25 text

Develop instant apps 1つのコードベースで
 instant apps, installed appの開発が可能 25

Slide 26

Slide 26 text

Modularization Feature three Feature one Feature two Source code Installed app 26

Slide 27

Slide 27 text

Modularization Feature three Feature one Feature two Source code 4MB Installed app 27

Slide 28

Slide 28 text

Source code Modularization Base module Feature one module Feature two module Instant apps Installed app 28

Slide 29

Slide 29 text

Source code Modularization Base module Feature one module Feature two module Instant apps Installed app 4MB 29

Slide 30

Slide 30 text

Source code Modularization Base module Feature one module Feature two module Installed app Instant apps 30

Slide 31

Slide 31 text

Reduce app size 4MB 制限が一番大変 31

Slide 32

Slide 32 text

Reduce app size • webP • Vector drawable 32

Slide 33

Slide 33 text

Reduce app size android { ... buildTypes { release { minifyEnabled true
 shrinkResources true proguardFiles getDefaultProguardFile( 
 'proguard-android.txt'), 'proguard-rules.pro' } } } 33

Slide 34

Slide 34 text

Reduce app size android { ... buildTypes { release { minifyEnabled true
 shrinkResources true
 useProguard false proguardFiles getDefaultProguardFile( 
 'proguard-android.txt'), 'proguard-rules.pro' } } } 34

Slide 35

Slide 35 text

Modularize

Slide 36

Slide 36 text

Modularization • リポジトリの一覧リスト • リポジトリ詳細 • プルリクエスト一覧 • Issue一覧 GitHubクライアント 36

Slide 37

Slide 37 text

Modularization • リポジトリの一覧リスト ← Installed • リポジトリ詳細 ← Instant, Installed • プルリクエスト一覧 ← Installed • Issue一覧 ← Installed • 通信等の共通部分 ← Base, Instant, Installed GitHubクライアント 37

Slide 38

Slide 38 text

Structure Base module Feature one module Feature two module Instant Installed 38

Slide 39

Slide 39 text

Structure Base module Feature one module Feature two module Instant Installed API通信等の
 共通処理 39

Slide 40

Slide 40 text

Structure Base module Feature one module Feature two module Instant Installed リポジトリ詳細 API通信等の
 共通処理 40

Slide 41

Slide 41 text

Structure Base module Feature one module Feature two module Instant Installed リポジトリ詳細 PR
 Issue
 リポジトリ一覧 API通信等の
 共通処理 41

Slide 42

Slide 42 text

Step by Step -Gradle -

Slide 43

Slide 43 text

Package structure • installed → app • instant → instantapp 43

Slide 44

Slide 44 text

1. Apply plugin • Installed module apply plugin: 'com.android.application' apply plugin: 'com.android.instantapp' apply plugin: 'com.android.feature' • Instant module • Base, Feature module 44

Slide 45

Slide 45 text

2. Specify baseFeature • Base module android { ... buildToolsVersion "26.0.1" ... defaultConfig { ... } Base module Feature one Feature two Instant Installed 45

Slide 46

Slide 46 text

2. Specify baseFeature • Base module android { ... buildToolsVersion "26.0.1" baseFeature true ... defaultConfig { ...
 } Base module Feature one Feature two Instant Installed 46

Slide 47

Slide 47 text

3. Dependencies • Installed module dependencies { implementation project(":base") implementation project(":featureone") implementation project(":featuretwo") } Base module Feature one Feature two Instant Installed 47

Slide 48

Slide 48 text

3. Dependencies • Instant module dependencies { implementation project(":base") implementation project(":featureone") } Base module Feature one Feature two Instant Installed 48

Slide 49

Slide 49 text

3. Dependencies • Feature one module dependencies { implementation project(":base") } Base module Feature one Feature two Instant Installed 49

Slide 50

Slide 50 text

3. Dependencies • Feature two module dependencies { implementation project(":base") } Base module Feature one Feature two Instant Installed 50

Slide 51

Slide 51 text

3. Dependencies • Base module dependencies { application project(":app") feature project(":featureone") feature project(":featuretwo") } Base module Feature one Feature two Instant Installed 51

Slide 52

Slide 52 text

Installed module.gradle apply plugin: 'com.android.application' android { ... } dependencies { implementation project(':base') implementation project(':featureone') implementation project(':featuretwo') } 52 Base module Feature one Feature two Instant Installed

Slide 53

Slide 53 text

Instant module.gradle apply plugin: 'com.android.instantapp' android { ... } dependencies { implementation project(':base') implementation project(':featureone') } 53 Base module Feature one Feature two Instant Installed

Slide 54

Slide 54 text

Feature module.gradle apply plugin: 'com.android.feature' ... android { ... } dependencies { implementation project(':base') } 54 Base module Feature one Feature two Instant Installed

Slide 55

Slide 55 text

Base module.gradle apply plugin: 'com.android.feature' ... android { ... baseFeature true ... } dependencies { application project(':app') feature project(':featureone') feature project(':featuretwo') } 55 Base module Feature one Feature two Instant Installed

Slide 56

Slide 56 text

Step by Step -App links -

Slide 57

Slide 57 text

App links Base module Feature one module Feature two module Instant Installed 57

Slide 58

Slide 58 text

App links module間の参照は? 58

Slide 59

Slide 59 text

App links 通常:各Activityにstaticなメソッド companion object { private const val KEY_HOGE = "hoge" fun createIntent(context: Context, hoge: Int): Intent = Intent(context, MainActivity::class.java).apply { putExtra(KEY_HOGE, hoge) } } 59

Slide 60

Slide 60 text

App links Feature one module Feature two module リポジトリ詳細 リポジトリ一覧 60

Slide 61

Slide 61 text

App links Feature one module Feature two module リポジトリ詳細 リポジトリ一覧 61 参照不可 ɹ

Slide 62

Slide 62 text

App links Feature one module Feature two module リポジトリ詳細 リポジトリ一覧 https://hoge.com/repository/hoge App links 62

Slide 63

Slide 63 text

App links • AndroidManifestにintent filterを追加 63

Slide 64

Slide 64 text

App links • data属性にhost, path, schemeを指定 64

Slide 65

Slide 65 text

App links • priorityは大きいほど優先 65

Slide 66

Slide 66 text

App links • base module/Navigator.kt const val KEY_REPO_GITHUB_REPO = "key_repo_github_repo" fun Activity.startRepoActivity(githubRepo: GithubRepo) { startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(
 "https://github.com/aakira/DaggerInstantApps")).apply { `package` = packageName addCategory(Intent.CATEGORY_BROWSABLE) putExtra(KEY_REPO_GITHUB_REPO, githubRepo) }) } 66

Slide 67

Slide 67 text

App links Feature one module Feature two module リポジトリ詳細 Search Intent リポジトリ一覧 Google検索 自他アプリから 67

Slide 68

Slide 68 text

Step by Step -Dagger -

Slide 69

Slide 69 text

Sample Project 69 AAkira/DaggerInstantApps https://goo.gl/7xqb5M @_a_akira

Slide 70

Slide 70 text

Gradle • Dagger android support(2.10.0+)
 今回は2.14.1を使う implementation dagger "com.google.dagger:dagger:2.14.1" implementation daggerAndroid "com.google.dagger:dagger-android:2.14.1" implementation daggerAndroidSupport "com.google.dagger:dagger-android-support:2.14.1" implementation daggerCompiler "com.google.dagger:dagger-compiler:2.14.1" implementation daggerAndroidProcessor "com.google.dagger:dagger-android-processor:2.14.1" 70

Slide 71

Slide 71 text

App structure • リポジトリの一覧リスト (RepoList) • リポジトリ詳細 (Repo) • プルリクエスト一覧 (PullRequestList) • Issue一覧 (IssueList) GitHubクライアント 71

Slide 72

Slide 72 text

App structure • Scope 72 Repo PR Issue Base module (App Scope) Repo
 List

Slide 73

Slide 73 text

App structure • Scope 73 Repo PR Issue Repo
 List Base module (App Scope) App Scope PerUi Scope PerUi Scope PerUi Scope PerUi Scope

Slide 74

Slide 74 text

App structure Base module Feature one module Feature two module Instant Installed 74

Slide 75

Slide 75 text

App structure Base module Feature one module Feature two module Instant Installed 75 Base moduleから Feature moduleへの参照は出来ない

Slide 76

Slide 76 text

App structure • Scope 76 Repo PR Issue Module One Base module (App Scope) Repo
 List Module Two App Scope PerModule Scope PerModule Scope PerUi Scope PerUi Scope PerUi Scope PerUi Scope

Slide 77

Slide 77 text

Base/AppComponent 77 @Singleton @Component(modules = [ AndroidSupportInjectionModule::class, AppModule::class, ActivityBuilder::class ]) interface AppComponent : AndroidInjector, AppComponentProviders { override fun inject(instance: App) @Component.Builder interface Builder { @BindsInstance fun application(application: Application): Builder fun build(): AppComponent } }

Slide 78

Slide 78 text

Base/AppComponent 78 @Singleton @Component(modules = [ AndroidSupportInjectionModule::class, AppModule::class, ActivityBuilder::class ]) interface AppComponent : AndroidInjector, AppComponentProviders { override fun inject(instance: App) @Component.Builder interface Builder { @BindsInstance fun application(application: Application): Builder fun build(): AppComponent } }

Slide 79

Slide 79 text

Base/Application 79 class App : DaggerApplication() { companion object { fun appComponent(context: Context) = 
 (context.applicationContext as App).appComponent } private val appComponent = DaggerAppComponent.builder()
 .application(this)
 .build() override fun applicationInjector(): AndroidInjector = appComponent.apply { inject(this@App) } }

Slide 80

Slide 80 text

Base/Application 80 class App : DaggerApplication() { companion object { fun appComponent(context: Context) = 
 (context.applicationContext as App).appComponent } private val appComponent = DaggerAppComponent.builder()
 .application(this)
 .build() override fun applicationInjector(): AndroidInjector = appComponent.apply { inject(this@App) } }

Slide 81

Slide 81 text

Base/Application 81 class App : DaggerApplication() { companion object { fun appComponent(context: Context) = 
 (context.applicationContext as App).appComponent } private val appComponent = DaggerAppComponent.builder()
 .application(this)
 .build() override fun applicationInjector(): AndroidInjector = appComponent.apply { inject(this@App) } }

Slide 82

Slide 82 text

Feature/Component 82 @PerModuleScope @Component( dependencies = [AppComponent::class], modules = [ AndroidSupportInjectionModule::class, FeatureOneUiBuilder::class, FeatureOneModule::class ] ) interface FeatureOneComponent : AndroidInjector

Slide 83

Slide 83 text

Feature/Component 83 @PerModuleScope @Component( dependencies = [AppComponent::class], modules = [ AndroidSupportInjectionModule::class, FeatureOneUiBuilder::class, FeatureOneModule::class ] ) interface FeatureOneComponent : AndroidInjector

Slide 84

Slide 84 text

Feature/Component 84 @PerModuleScope @Component( dependencies = [AppComponent::class], modules = [ AndroidSupportInjectionModule::class, FeatureOneUiBuilder::class, FeatureOneModule::class ] ) interface FeatureOneComponent : AndroidInjector

Slide 85

Slide 85 text

Feature/FeatureModuleInjector 85 object FeatureOneModuleInjector : BaseModuleInjector() { override fun moduleInjector(appComponent: AppComponent): AndroidInjector { return DaggerFeatureOneComponent.builder() .appComponent(appComponent) .build() } }

Slide 86

Slide 86 text

Feature/FeatureModuleInjector 86 object FeatureOneModuleInjector : BaseModuleInjector() { override fun moduleInjector(appComponent: AppComponent): AndroidInjector { return DaggerFeatureOneComponent.builder() .appComponent(appComponent) .build() } }

Slide 87

Slide 87 text

Feature/FeatureModuleInjector 87 object FeatureOneModuleInjector : BaseModuleInjector() { override fun moduleInjector(appComponent: AppComponent): AndroidInjector { return DaggerFeatureOneComponent.builder() .appComponent(appComponent) .build() } }

Slide 88

Slide 88 text

Base/BaseModuleInjector 88 abstract class BaseModuleInjector : HasActivityInjector, HasFragmentInjector,
 HasSupportFragmentInjector, HasServiceInjector,
 HasBroadcastReceiverInjector, HasContentProviderInjector { @Inject lateinit var activityInjector: DispatchingAndroidInjector ... private var needToInject = true abstract fun moduleInjector(appComponent: AppComponent):
 AndroidInjector fun inject(dependerContext: Context) { injectIfNecessary(App.appComponent(dependerContext)) ... } private fun injectIfNecessary(appComponent: AppComponent) { ...
 } ... override fun activityInjector(): DispatchingAndroidInjector = activityInjector ... }

Slide 89

Slide 89 text

Base/BaseModuleInjector 89 abstract class BaseModuleInjector : HasActivityInjector, HasFragmentInjector,
 HasSupportFragmentInjector, HasServiceInjector,
 HasBroadcastReceiverInjector, HasContentProviderInjector { @Inject lateinit var activityInjector: DispatchingAndroidInjector ... private var needToInject = true abstract fun moduleInjector(appComponent: AppComponent):
 AndroidInjector fun inject(dependerContext: Context) { injectIfNecessary(App.appComponent(dependerContext)) ... } private fun injectIfNecessary(appComponent: AppComponent) { ...
 } ... override fun activityInjector(): DispatchingAndroidInjector = activityInjector ... }

Slide 90

Slide 90 text

Feature/UiBuilder 90 @Module abstract class FeatureOneUiBuilder { @PerUiScope @ContributesAndroidInjector(modules = [RepoModule::class]) internal abstract fun bindRepoActivity(): RepoActivity }

Slide 91

Slide 91 text

Feature/Activity 91 class RepoActivity : AbstractActivity() { @Inject lateinit var repoAction: RepoAction @Inject lateinit var repoStore: RepoStore
 ... override fun onCreate(savedInstanceState: Bundle?) { FeatureOneModuleInjector.inject(this) super.onCreate(savedInstanceState) setContentView(R.layout.activity_repo) } }

Slide 92

Slide 92 text

Feature/Activity 92 class RepoActivity : AbstractActivity() { @Inject lateinit var repoAction: RepoAction @Inject lateinit var repoStore: RepoStore
 ... override fun onCreate(savedInstanceState: Bundle?) { FeatureOneModuleInjector.inject(this) super.onCreate(savedInstanceState) setContentView(R.layout.activity_repo) } }

Slide 93

Slide 93 text

App structure 93 Repo PR Issue Module One Base module (App Scope) Repo
 List Module Two App Scope PerModule Scope PerModule Scope PerUi Scope PerUi Scope PerUi Scope PerUi Scope

Slide 94

Slide 94 text

App structure 94 Repo PR Issue Module One Repo
 List Module Two App Scope PerModule Scope PerModule Scope PerUi Scope PerUi Scope PerUi Scope PerUi Scope Base module (App Scope) App Component

Slide 95

Slide 95 text

App structure 95 PR Issue Repo
 List Module Two App Scope PerModule Scope PerModule Scope PerUi Scope PerUi Scope PerUi Scope PerUi Scope Base module (App Scope) App Component Repo Module One ModuleOne
 Component
 * Repo

Slide 96

Slide 96 text

App structure 96 App Scope PerModule Scope PerModule Scope PerUi Scope PerUi Scope PerUi Scope PerUi Scope Base module (App Scope) App Component Repo Module One ModuleOne
 Component
 * Repo PR Issue Repo
 List Module Two ModuleTwo 
 Component
 * PR
 * Issue
 * RepoList

Slide 97

Slide 97 text

Summary

Slide 98

Slide 98 text

Summary • Instant Appsは
 Googleの目指すモバイルの未来 • 対応はそこまで難しくは無いが、
 4MB制限が一番大変 • Module分けしても今まで通りDaggerを
 用いてDIする事が可能 98

Slide 99

Slide 99 text

@_a_akira AAkira Thanks