Just recently we have one project which has 2 apps, one for consumer and the other one is for partner. During planning, we decided that: the app for consumer should be as small as possible in size. Thus we follow guide from Google using dynamic feature modules.
The grand design of the app architectures is of course modularisation, and each module should be able to fit in both apps. After some discussions, we decided the following should be presented in our architectures:
View Modeland can be used in either dynamic feature modules or main app,
Common Codeto be used both in Dynamic Feature Modules and both main apps,
Below are full diagrams
Diagram C, D, and B are standard android library modules, which means we can easily import them on the main app and use it directly, however diagram A and B is a bit different, you can’t access feature modules from the main app, it works the other way around.
In this article, we’re going to focus more on part A and B and how we can reuse feature modules in both apps.
As mentioned above, the way Google design dynamic feature module is different than standard library, as mentioned here:
In the standard project structure that uses libraries, the base
com.android.applicationmodule depends on
com.android.librarymodules, which means you can use any classes defined in the library from the base module freely.
With DFMs however, the base
com.android.applicationis a dependency of
com.android.dynamic-featuremodules, which means you can use any classes defined in the base module and its libraries in the DFM, but you can’t reference any code defined in the DFM from the base application at compile time.
Now this is fine if you only have one app, however in our project, this DFM design is forcing us to do something creative 😌. A naive approach to this problem is to copy Activity/Fragment from consumer project and paste in partner app, but that’s not what we want, right?
Make sure when creating dynamic feature module, avoid creating dependency with main apps as much as possible, by doing the followings:
android.Ron main apps, if use by both, put it inside Common UI module,
BuildConfig.ApplicationIDas an intent to dynamic feature module instead of using it directly.
BuildConfig.ApplicationIDare mostly use to call another feature module,
.ideaevery time you change project from consumer to partner app,
Let’s try by creating first app called
consumer, create new android module called
common, and dynamic feature module called
Now open forgotpassword feature module’s manifest, and make sure you put
If we run the app through internal app sharing, we will see the downloading process of feature module like this:
Note: running the app directly from Android Studio will not show “downloading module” screen. You have to use internal app sharing to test dynamic feature module.
So far so good, now close the consumer app, and let’s create another app, called
settings.gradle to include
Next, we also update partner’s
build.gradle similar to consumer’s
Pay attention to
include ‘:app’ in partner’s settings.gradle, my recommendation is that you should use the same name as in consumer app, but if something or other things force you to use different name, don’t worry you still can reuse the module which i’ll explain later.
Now if you check forgotpassword’s
AndroidManifest.xml you will see warning/errors because it can’t find its parent that is
com.adrena.dfm.consumer.MainActivity, and because of that, clicking home button in
Forgot Password Activity won’t do anything.
Lets fix this by creating flavor. Create a new file called
flavors.gradle and put it inside
consumer and partner directory.
Note: when adding flavor, all of your dynamic feature modules should also implement the same flavor.
Update all your consumer, partner and feature module’s
Now navigate to Project, go to
forgotpassword, and create a new folder called
partner, and create
AndroidManifest.xml in each directory
AndroidManifest.xml file in
main directory, remove all except manifest tag.
As you can see above we’re using different
partner, we also updated parent activity to point to consumer/partner package name
Now try changing Build Variants to
partnerDebug and run the app, you should be able to go back to main activity now.
Don’t forget to remove
.idea directory (hidden), inside consumer app / partner app if you want to switch project, otherwise AndroidStudio might still pointing to wrong project.
And last, if you’re using different app name, you can use
flavorImplementation to point to different app name, e.g.:
By using flavor, we’re able to reuse feature module in 2 apps. This tutorial is pretty simple because we only change AndroidManifest.xml file. In real life project, you can use this approach if you’re using dependency injection and need AppComponent (if you are using Dagger 2) in feature modules.
Source code available here: