android-showcase icon indicating copy to clipboard operation
android-showcase copied to clipboard

Add Dynamic-delivery

Open igorwojda opened this issue 5 years ago • 3 comments

It would be nice to convert one of the module to on-demand-delivery so it will be downloaded when it is needed https://developer.android.com/guide/app-bundle/on-demand-delivery

Additionally we could have custom Progress fragment https://developer.android.com/guide/navigation/navigation-dynamic#customize

igorwojda avatar May 05 '20 19:05 igorwojda

The latest repository was cloned and built successfully. When a new dynamic module was created with Android Studio, (i.e. File->New->New Module...->Dynamic Feature Module->...-> Install-time inclusion: Do not include module at install-time(on-demand only), but failed to build it.

➜android-showcase git:(main) ✗ ./gradlew build   
Type-safe dependency accessors is an incubating feature.

> Configure project :app
WARNING: API 'BaseVariant.getApplicationIdTextResource' is obsolete and has been replaced with 'VariantProperties.applicationId'.
It will be removed in version 5.0 of the Android Gradle plugin.
For more information, see TBD.
To determine what is calling BaseVariant.getApplicationIdTextResource, use -Pandroid.debug.obsoleteApi=true on the command line to display more information.

FAILURE: Build failed with an exception.

* What went wrong:
Could not determine the dependencies of task ':app:lintVitalRelease'.
> Could not resolve all artifacts for configuration ':app:debugUnitTestCompileClasspath'.
   > Did not resolve 'org.jetbrains.kotlin:kotlin-test-common:1.3.50' which is part of the dependency lock state
   > Did not resolve 'org.jetbrains.kotlin:kotlin-test:1.3.50' which is part of the dependency lock state

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 13s

The dynamic module was named as 'feature_publish'. Here is the related file build.gradle:

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.3"

    defaultConfig {
      applicationId "com.igorwojda.showcase.feature.publish"
      minSdkVersion 26
      targetSdkVersion 30
      versionCode 1
      versionName "1.0"

      testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
       release {
           minifyEnabled false
           proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
       }
    }
    }

dependencies {
    implementation project(":app")
}

How to fix it?

yuwiggin avatar Feb 26 '21 17:02 yuwiggin

It looks like the module is using an older version of Kotlin and Gradle can't resolve it because of dependency locks. You could run ./gradlew test --write-locks to update dependency versions (this actually saves dependencies in various gradle.lockfile files, but I would make sure that your new module is using the same Kotlin version as other modules.

If you want to be consistent with the rest of the app you need to know that this project has a bit of config for each module, so the fastest way to add a new module is to do a bit of work:

  1. copy module folder
  2. rename it feature_album -> feature_whatever
  3. add a new module to settings.gradle.kts
  4. Run sync project with gradle action (you should see module in AS project view)
  5. Rename packages com.igorwojda.showcase.feature.album -> com.igorwojda.showcase.feature.whatever
  6. Rename navgraph file feature_album_nav_graph.xml -> feature_whatever_nav_graph.xml
  7. Include new navgraph in app navgraph (app\res\app_nav_graph.xml)
  8. Set name in Kodein module FeatureKodeinModule.kt (internal const val MODULE_NAME = "Whatever")
  9. Add new module to buildSrc\java\ModuleDependency -> const val FEATURE_WHATEVER = ":feature_whatever"

BTW It would be ideal to write a script in the future to do all of this

igorwojda avatar Feb 26 '21 17:02 igorwojda

Thank you for your reply. Following your step to create a new dynamic module: feature_cool, I build the app successfully, but failed to run it.

02/28 22:10:04: Launching 'app' on Nexus 4 API 30.
Install successfully finished in 1 s 477 ms.
$ adb shell am start -n "com.igorwojda.showcase/com.igorwojda.showcase.app.presentation.NavHostActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 10088 on device 'Nexus_4_API_30 [emulator-5554]'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
I/LoadedApk: No resource references to update in package com.igorwojda.showcase.feature_profile
    No resource references to update in package com.igorwojda.showcase.feature_favourite
I/LoadedApk: No resource references to update in package com.igorwojda.showcase.feature_album
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
I/stetho: Listening on @stetho_com.igorwojda.showcase_devtools_remote
D/libEGL: loaded /vendor/lib64/egl/libEGL_emulation.so
D/libEGL: loaded /vendor/lib64/egl/libGLESv1_CM_emulation.so
D/libEGL: loaded /vendor/lib64/egl/libGLESv2_emulation.so
W/rwojda.showcas: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
    Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
V/BaseActivity: onCreate NavHostActivity
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.igorwojda.showcase, PID: 10088
    java.lang.ExceptionInInitializerError
        at com.igorwojda.showcase.app.ShowcaseApplication$kodein$1.invoke(ShowcaseApplication.kt:25)
        at com.igorwojda.showcase.app.ShowcaseApplication$kodein$1.invoke(ShowcaseApplication.kt:20)
        at org.kodein.di.internal.KodeinImpl$Companion.newBuilder(KodeinImpl.kt:22)
        at org.kodein.di.internal.KodeinImpl$Companion.access$newBuilder(KodeinImpl.kt:21)
        at org.kodein.di.internal.KodeinImpl.<init>(KodeinImpl.kt:19)
        at org.kodein.di.Kodein$Companion$lazy$1.invoke(Kodein.kt:447)
        at org.kodein.di.Kodein$Companion$lazy$1.invoke(Kodein.kt:429)
        at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
        at org.kodein.di.LazyKodein.getBaseKodein(Unknown Source:2)
        at org.kodein.di.LazyKodein.getContainer(lateinit.kt:31)
        at org.kodein.di.internal.KodeinMainBuilderImpl.extend(KodeinBuilderImpl.kt:80)
        at org.kodein.di.Kodein$MainBuilder$DefaultImpls.extend$default(Kodein.kt:384)
        at com.igorwojda.showcase.base.presentation.activity.InjectionActivity$kodein$2.invoke(InjectionActivity.kt:23)
        at com.igorwojda.showcase.base.presentation.activity.InjectionActivity$kodein$2.invoke(InjectionActivity.kt:14)
        at org.kodein.di.internal.KodeinImpl$Companion.newBuilder(KodeinImpl.kt:22)
        at org.kodein.di.internal.KodeinImpl$Companion.access$newBuilder(KodeinImpl.kt:21)
        at org.kodein.di.internal.KodeinImpl.<init>(KodeinImpl.kt:19)
        at org.kodein.di.Kodein$Companion.invoke(Kodein.kt:438)
        at org.kodein.di.android.RetainedKt$retainedKodein$1.invoke(retained.kt:34)
        at org.kodein.di.android.RetainedKt$retainedKodein$1.invoke(Unknown Source:0)
        at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
        at com.igorwojda.showcase.base.presentation.activity.InjectionActivity.getKodein(Unknown Source:2)
        at org.kodein.di.android.ClosestKt.kodein(closest.kt:21)
        at org.kodein.di.android.ClosestKt.access$kodein(closest.kt:1)
        at org.kodein.di.android.LazyContextKodeinPropertyDelegateProvider$provideDelegate$1.invoke(closest.kt:43)
        at org.kodein.di.android.LazyContextKodeinPropertyDelegateProvider$provideDelegate$1.invoke(closest.kt:42)
        at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
        at com.igorwojda.showcase.base.presentation.fragment.InjectionFragment.getKodein(Unknown Source:7)
        at org.kodein.di.KodeinAwareKt$Instance$1.invoke(KodeinAware.kt:176)
        at org.kodein.di.KodeinAwareKt$Instance$1.invoke(Unknown Source:4)
        at org.kodein.di.KodeinProperty$provideDelegate$1.invoke(properties.kt:42)
        at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
        at com.igorwojda.showcase.feature.album.presentation.albumlist.AlbumListFragment.getAlbumAdapter(Unknown Source:7)
        at com.igorwojda.showcase.feature.album.presentation.albumlist.AlbumListFragment.onViewCreated(AlbumListFragment.kt:36)
        at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2974)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:543)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
        at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1636)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3112)
        at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3049)
        at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2975)
        at androidx.fragment.app.FragmentStateManager.ensureInflatedView(FragmentStateManager.java:389)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:281)
        at androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(FragmentLayoutInflaterFactory.java:141)
        at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:135)
        at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:313)
E/AndroidRuntime:     at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:292)
        at android.view.LayoutInflater.tryCreateView(LayoutInflater.java:1067)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:995)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:1121)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:680)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:532)
        at com.igorwojda.showcase.databinding.ActivityNavHostBinding.inflate(ActivityNavHostBinding.java:44)
        at com.igorwojda.showcase.databinding.ActivityNavHostBinding.inflate(ActivityNavHostBinding.java:38)
        at com.igorwojda.showcase.app.presentation.NavHostActivity$$special$$inlined$viewBinding$1.invoke(AppCompatActivityExt.kt:10)
        at com.igorwojda.showcase.app.presentation.NavHostActivity$$special$$inlined$viewBinding$1.invoke(Unknown Source:0)
        at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:81)
        at com.igorwojda.showcase.app.presentation.NavHostActivity.getBinding(Unknown Source:2)
        at com.igorwojda.showcase.app.presentation.NavHostActivity.onCreate(NavHostActivity.kt:23)
        at android.app.Activity.performCreate(Activity.java:8000)
        at android.app.Activity.performCreate(Activity.java:7984)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
     Caused by: java.lang.ClassNotFoundException: Kodein module class not found com.igorwojda.showcase.feature.cool.FeatureKodeinModule
        at com.igorwojda.showcase.app.feature.FeatureManager.<clinit>(FeatureManager.kt:19)
        	... 77 more
I/Process: Sending signal. PID: 10088 SIG: 9

It seemed that the new module com.igorwojda.showcase.feature.cool could not be found. The version of Android Studio is 4.1.2. Any suggestion?

yuwiggin avatar Feb 28 '21 14:02 yuwiggin

The project is being upgraded to version 2.0 (WiP). I am closing this issue as it is most likely obsolete - in 2.0 I had to drop dynamic feature modules as they are not supported by the ANDROID_TEST_USES_UNIFIED_TEST_PLATFORM yet.

igorwojda avatar Sep 22 '22 06:09 igorwojda