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. Agenda • About Instant Apps • Develop Instant Apps •

    Tools • Modularize • Modularize by Dagger Injection • Summary 4
  2. About Instant Apps • Google I/O 2016で発表 • Google I/O

    2017の当日から使用可能に • Android 6.0+
 (将来的には5.0+) 7
  3. 8

  4. APIs • Smart Lock
 → ログインがスムーズに • Google Payment API


    → 購入がスムーズに 16 Wish © ContextLogic, Inc.
  5. Reduce app size android { ... buildTypes { release {

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

    minifyEnabled true
 shrinkResources true
 useProguard false proguardFiles getDefaultProguardFile( 
 'proguard-android.txt'), 'proguard-rules.pro' } } } 34
  7. Modularization • リポジトリの一覧リスト ← Installed • リポジトリ詳細 ← Instant, Installed

    • プルリクエスト一覧 ← Installed • Issue一覧 ← Installed • 通信等の共通部分 ← Base, Instant, Installed GitHubクライアント 37
  8. Structure Base module Feature one module Feature two module Instant

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

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

    Installed リポジトリ詳細 PR
 Issue
 リポジトリ一覧 API通信等の
 共通処理 41
  11. 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
  12. 2. Specify baseFeature • Base module android { ... buildToolsVersion

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

    "26.0.1" baseFeature true ... defaultConfig { ...
 } Base module Feature one Feature two Instant Installed 46
  14. 3. Dependencies • Installed module dependencies { implementation project(":base") implementation

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

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

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

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

    project(":featureone") feature project(":featuretwo") } Base module Feature one Feature two Instant Installed 51
  19. 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
  20. 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
  21. Feature module.gradle apply plugin: 'com.android.feature' ... android { ... }

    dependencies { implementation project(':base') } 54 Base module Feature one Feature two Instant Installed
  22. 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
  23. 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
  24. App links • AndroidManifestにintent filterを追加 <activity android:name=".ui.repo.RepoActivity"> <intent-filter android:priority="1"> <action

    android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:host="aakira.github.com" android:pathPattern="/.*" android:scheme="https" /> </intent-filter> </activity> 63
  25. App links • data属性にhost, path, schemeを指定 <activity android:name=".ui.repo.RepoActivity"> <intent-filter android:priority="1">

    <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:host="aakira.github.com" android:pathPattern="/.*" android:scheme="https" /> </intent-filter> </activity> 64
  26. App links • priorityは大きいほど優先 <activity android:name=".ui.repo.RepoActivity"> <intent-filter android:priority="1"> <action android:name="android.intent.action.VIEW"

    /> <category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:host="aakira.github.com" android:pathPattern="/.*" android:scheme="https" /> </intent-filter> </activity> 65
  27. 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
  28. App links Feature one module Feature two module リポジトリ詳細 Search

    Intent リポジトリ一覧 Google検索 自他アプリから 67
  29. 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
  30. App structure • Scope 73 Repo PR Issue Repo
 List

    Base module (App Scope) App Scope PerUi Scope PerUi Scope PerUi Scope PerUi Scope
  31. App structure Base module Feature one module Feature two module

    Instant Installed 75 Base moduleから Feature moduleへの参照は出来ない
  32. 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
  33. Base/AppComponent 77 @Singleton @Component(modules = [ AndroidSupportInjectionModule::class, AppModule::class, ActivityBuilder::class ])

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

    interface AppComponent : AndroidInjector<App>, AppComponentProviders { override fun inject(instance: App) @Component.Builder interface Builder { @BindsInstance fun application(application: Application): Builder fun build(): AppComponent } }
  35. 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<out DaggerApplication> = appComponent.apply { inject(this@App) } }
  36. 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<out DaggerApplication> = appComponent.apply { inject(this@App) } }
  37. 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<out DaggerApplication> = appComponent.apply { inject(this@App) } }
  38. Feature/Component 82 @PerModuleScope @Component( dependencies = [AppComponent::class], modules = [

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

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

    AndroidSupportInjectionModule::class, FeatureOneUiBuilder::class, FeatureOneModule::class ] ) interface FeatureOneComponent : AndroidInjector<FeatureOneModuleInjector>
  41. Feature/FeatureModuleInjector 85 object FeatureOneModuleInjector : BaseModuleInjector() { override fun moduleInjector(appComponent:

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

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

    AppComponent): AndroidInjector<out BaseModuleInjector> { return DaggerFeatureOneComponent.builder() .appComponent(appComponent) .build() } }
  44. Base/BaseModuleInjector 88 abstract class BaseModuleInjector : HasActivityInjector, HasFragmentInjector,
 HasSupportFragmentInjector, HasServiceInjector,


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


    HasBroadcastReceiverInjector, HasContentProviderInjector { @Inject lateinit var activityInjector: DispatchingAndroidInjector<Activity> ... private var needToInject = true abstract fun moduleInjector(appComponent: AppComponent):
 AndroidInjector<out BaseModuleInjector> fun inject(dependerContext: Context) { injectIfNecessary(App.appComponent(dependerContext)) ... } private fun injectIfNecessary(appComponent: AppComponent) { ...
 } ... override fun activityInjector(): DispatchingAndroidInjector<Activity> = activityInjector ... }
  46. Feature/UiBuilder 90 @Module abstract class FeatureOneUiBuilder { @PerUiScope @ContributesAndroidInjector(modules =

    [RepoModule::class]) internal abstract fun bindRepoActivity(): RepoActivity }
  47. 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) } }
  48. 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) } }
  49. 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
  50. 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
  51. 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
  52. 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