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

IntroduceInstantApps(DroidKaigi2018)

AAkira
February 07, 2018

 IntroduceInstantApps(DroidKaigi2018)

Introduce Instant Apps in your existing project.
This is talked in https://droidkaigi.jp/2018/

Sample project on github : https://github.com/AAkira/DaggerInstantApps

AAkira

February 07, 2018
Tweet

More Decks by AAkira

Other Decks in Technology

Transcript

  1. 既存アプリへの

    Instant Apps導入
    荒谷 光
    あらたに あきら
    @_a_akira
    - Introduce Instant Apps -

    View full-size slide

  2. About me
    @_a_akira
    AAkira
    CyberAgent, Inc.
    Akira Aratani

    View full-size slide

  3. • 生放送配信プラットフォーム
    • ライブファンディング
    • 4K配信対応, 低遅延配信
    • M11の頃からFull Kotlinで開発

    サーバサイドも1年前からKotlinを使用
    About
    3

    View full-size slide

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

    View full-size slide

  5. About Instant Apps

    View full-size slide

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

    View full-size slide

  7. About Instant Apps
    • Google I/O 2016で発表
    • Google I/O 2017の当日から使用可能に
    • Android 6.0+

    (将来的には5.0+)
    7

    View full-size slide

  8. Purpose
    • URLベースでアクセス可能なので、

    最初のキッカケを与えられる
    • ネイティブアプリと同じ経験を
    9

    View full-size slide

  9. Use case
    • 将来的には、

    位置情報, QRCode, ビーコン、NFC

    をキッカケにすることも考えている
    • Text baseのurlで起動出来るので、

    広告での使用も可能
    10

    View full-size slide

  10. Use case
    • 検索結果から

    InstantAppsを直接起動

    11
    © RED BULL

    View full-size slide

  11. Use case
    • Slack等の

    メッセージアプリからも

    InstantAppsを直接起動
    12
    © Vimeo, Inc.

    View full-size slide

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

    View full-size slide

  13. Use case
    • Instant Appsは

    端末にDLされる
    14

    View full-size slide

  14. Use case
    • Instant Appsは

    端末にDLされる
    15

    View full-size slide

  15. APIs
    • Smart Lock

    → ログインがスムーズに
    • Google Payment API

    → 購入がスムーズに
    16
    Wish © ContextLogic, Inc.

    View full-size slide

  16. APIs
    • Play Install API

    → インストールまでが

      スムーズに
    17
    © Vimeo, Inc.

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  19. Develop

    Instant Apps

    View full-size slide

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

    View full-size slide

  21. App links
    • Marshmallow(6.0)から導入
    • Manifestにを追加
    • サーバにjsonファイルを配置すれば

    リンクをクリックした時にアプリを起動可能

    AndroidManifestに

    android:autoVerify=“true”を指定する
    22

    View full-size slide

  22. App links assistant
    • Tools > App links assistant
    23

    View full-size slide

  23. Develop instant apps
    1つのコードベースで

    instant apps, installed appの開発が可能
    24

    View full-size slide

  24. Develop instant apps
    1つのコードベースで

    instant apps, installed appの開発が可能
    25

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  31. Reduce app size
    • webP
    • Vector drawable
    32

    View full-size slide

  32. Reduce app size
    android {
    ...
    buildTypes {
    release {
    minifyEnabled true

    shrinkResources true
    proguardFiles getDefaultProguardFile( 

    'proguard-android.txt'),
    'proguard-rules.pro'
    }
    }
    }
    33

    View full-size slide

  33. Reduce app size
    android {
    ...
    buildTypes {
    release {
    minifyEnabled true

    shrinkResources true

    useProguard false
    proguardFiles getDefaultProguardFile( 

    'proguard-android.txt'),
    'proguard-rules.pro'
    }
    }
    }
    34

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  37. Structure
    Base module
    Feature one module Feature two module
    Instant Installed
    API通信等の

    共通処理
    39

    View full-size slide

  38. Structure
    Base module
    Feature one module Feature two module
    Instant Installed
    リポジトリ詳細
    API通信等の

    共通処理
    40

    View full-size slide

  39. Structure
    Base module
    Feature one module Feature two module
    Instant Installed
    リポジトリ詳細
    PR

    Issue

    リポジトリ一覧
    API通信等の

    共通処理
    41

    View full-size slide

  40. Step by Step
    -Gradle -

    View full-size slide

  41. Package structure
    • installed → app
    • instant → instantapp
    43

    View full-size slide

  42. 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

    View full-size slide

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

    View full-size slide

  44. 2. Specify baseFeature
    • Base module
    android {
    ...
    buildToolsVersion "26.0.1"
    baseFeature true
    ...
    defaultConfig {
    ...

    }
    Base module
    Feature one Feature two
    Instant Installed
    46

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  50. 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

    View full-size slide

  51. 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

    View full-size slide

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

    View full-size slide

  53. 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

    View full-size slide

  54. Step by Step
    -App links -

    View full-size slide

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

    View full-size slide

  56. App links
    module間の参照は?
    58

    View full-size slide

  57. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  61. App links
    • AndroidManifestにintent filterを追加





    android:host="aakira.github.com"
    android:pathPattern="/.*"
    android:scheme="https"
    />


    63

    View full-size slide

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





    android:host="aakira.github.com"
    android:pathPattern="/.*"
    android:scheme="https"
    />


    64

    View full-size slide

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





    android:host="aakira.github.com"
    android:pathPattern="/.*"
    android:scheme="https"
    />


    65

    View full-size slide

  64. 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

    View full-size slide

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

    View full-size slide

  66. Step by Step
    -Dagger -

    View full-size slide

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

    View full-size slide

  68. 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

    View full-size slide

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

    View full-size slide

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

    List

    View full-size slide

  71. App structure
    • Scope
    73
    Repo PR Issue
    Repo

    List
    Base module (App Scope)
    App Scope
    PerUi Scope PerUi Scope PerUi Scope PerUi Scope

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  74. 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

    View full-size slide

  75. 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
    }
    }

    View full-size slide

  76. 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
    }
    }

    View full-size slide

  77. 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) }
    }

    View full-size slide

  78. 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) }
    }

    View full-size slide

  79. 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) }
    }

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  86. 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
    ...
    }

    View full-size slide

  87. 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
    ...
    }

    View full-size slide

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

    View full-size slide

  89. 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)
    }
    }

    View full-size slide

  90. 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)
    }
    }

    View full-size slide

  91. 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

    View full-size slide

  92. 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

    View full-size slide

  93. 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

    View full-size slide

  94. 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

    View full-size slide

  95. Summary
    • Instant Appsは

    Googleの目指すモバイルの未来
    • 対応はそこまで難しくは無いが、

    4MB制限が一番大変
    • Module分けしても今まで通りDaggerを

    用いてDIする事が可能
    98

    View full-size slide

  96. @_a_akira
    AAkira
    Thanks

    View full-size slide