Android Dynamic Feature Modules: My Experience
In Google I/O 2018, a new publishing format was introduced by Google, Android App Bundle(.aab). Everyone is so excited about this feature because of its advantages and the size reduction of the APK.
Recently, in one of my app, we felt a perfect use of this feature but we were not sure about the flow of the dynamic delivery. We were still not sure about how the popup of the download of the additional feature will be visible to the user. How easy would it be for the developer and what are the things the developer needs to keep in mind while using it. I tried to Google these questions but no luck as this feature is still in beta and not many developers have used it. In this article, will walk you through my experience with dynamic delivery along with the screenshot of the popup for download.
Our use case was very simple. We need to integrate FFMPEG library in our app to play with Audio, Video and much more features provided by FFMPEG.
For those who don’t know what FFMPEG is, FFMPEG is a universal multimedia framework able to decode, encode, transcode, mux, demux, stream, filter and play almost any type of content. It is used for professional image and video processing and much more.
The only reason we never thought of adding this library to our main module was that of its size. The size of this library depends on the features you need. FFMPEG is written in C++ but it can be compiled for Android and can be used. The minimum size of the FFMPEG library with minimal features for Android is around 10 MB. In our case it was even more. We could not afford to increase the APK size with that huge difference.
Initially we decided to create a separate app for FFMPEG features, ask the user to download another app and do the functionality but later on researching, I get to know about the Dynamic Modules Delivery from Google. After spending a fair amount of time on researching, I decided to make a demo app with a ‘Camera’ module as a dynamic module in that app which will pick an audio from the local file system, record the video and merge both and give the output as a “.mp4” format file.
With the help of the sample app and the instructions provided by Google here, I was able to implement the dynamic module into the demo app in no time.
The things I noticed in the while coding the dynamic module were,
- I was able to reuse the code of my main module into the dynamic module (Classes, Resources, and almost everything) which is not possible in a normal module. As I was following MVP structure, I reused the same base classes. For resources also, there was no need to add them separately but to reuse from the main module.
- I was able to implement Dependency injection and maintain it in the dynamic module separately.
- As I planned to create a separate CameraActivity in my dynamic module, which was supposed to be launched from the main module, I didn’t get the reference of my dynamic modules classes in the main module classes. This was understandable as my main module was not dependant on the dynamic module but the other way around. To fix this issue and start my activity present in the Camera module I used the classpath to start the activity.
val intent = Intent().setClassName(packageName,
"<complete class path of camera activity>")startActivity(intent)
Now was the time to test it. We tried to test it locally first using Bundle Tools. Testing it with Bundle Tool was very easy. I downloaded the Bundle Tool’s jar file from here. After downloading the Bundle Tool jar file, I generated the .aab file from Android Studio and generated the possible APKs using the jar from below command.
java -jar <jar file path> build-apks --bundle=<aab file path> --output=<output file path>
As I put everything inside a single folder on Desktop my final command was
java -jar ~/Desktop/release/bundletool-all-0.7.2.jar build-apks --bundle=~/Desktop/release/app.aab --output=~/Desktop/release/out.apks
This gave me a zip with the name out.apks in the same release folder on the Desktop. To extract different APKs from that zip, I used the below command inside that folder.
unzip out.apks -d apks
This gave me all the possible APKs.
I tried to install the base one on my device and it worked fine and on top of it I tried to install the Camera APK which gave me the additional functionality of Camera features.
Later I tried to generate signed APKs from bundle using below command on the same Bundle tools and it worked like a charm.
java -jar ~/Desktop/release/bundletool-all-0.7.2.jar build-apks --bundle=~/Desktop/release/app.aab --output=~/Desktop/release/out.apks --ks <keytore file path> --ks-key-alias <alias>
This prompted me for the password. One can have a look at all the possible attributes here.
Now was the time to test it through the Play store. As the dynamic module requires “Google Play App Signing”, we enabled the same and provided the Exported encrypted key (“.pepk” file) from Android studio to Play console for the same.
Once this was done, we were ready to upload the app bundle to the beta channel for testing. There was no major change while uploading the bundle from the flow of normal APK upload. The publishing was straightforward.
It took a while to get available in play store. Once I downloaded the new version from the play store, it installed the base APK on my device. I put the download of addition Camera feature on the camera Button click, On clicking the same, it showed the below popup from Google Play within my app as an overlay,
The first black part was the app name and the other one was the feature name.
I tried to “No Thanks” option first, and it dismissed the popup. On clicking the Download option next time, it started downloading the feature and triggered a notification for the progress of the download. This experience after the download click was similar to an app download from play store. Once the download was finished, it installed the module (similar to an app). Please note that this doesn’t close my app. Once the install was done, my Camera Activity opened in no time and I was able to use the features of that activity.
I tired with closing and opening the again, This time it directly opened the Camera Activity on Camera button click as the module was already present.
My overall experience was amazing with the dynamic modules. It was easy to implement and saved us from developing and managing a separate app. Although our Camera feature is still in beta but will be releasing it soon to Production. The only thing lacking with dynamic modules is proper documents. Eventually, this problem will be solved when more developers will start using it.