Android app is on a diet: Dynamic Features — Next Steps

Last, but not least, the end of this series of stories. We want to share the strawberry on the ice-cream. The results and a few things we’re planning next.

Rodrigo Pintos
Mercado Libre Tech
7 min readNov 23, 2022

--

Read this story in Spanish.

Welcome, it’s nice to see you back! This will be the last post of our story with Dynamic Features. Remember that for a better understanding and to get the full picture, we recommend that you read the two previous stories.

In our first article, we saw the definition of Dynamic Features, what we can achieve with this tool, and what types of dynamic installations Google offers us, among other things.

In our second story, we saw how we apply Dynamic Features at Mercado Libre, what changes we’ve made at the architecture level, and what analysis we’ve made of general issues such as external navigation, dependency management and their coexistence across their dynamic modules and the base application. In addition, we’ve seen different compilation modes with assembly and bundle and how to know when a module should be dynamic.

We’d like to thank those who have reached this far in the reading, and hope that they have been able to profit from this experience we are sharing that is coming to an end with the present article. So, let’s begin with the last lap.

What results did we obtain in this first experience with a module in production?

The first thing we could verify was the weight reduced by having this small module as a dynamic module. We learned that in the bundles section of Google store, we get the download weight of the Base application and the download weight assigned to the dynamic module.

Although they were few KB, our focus was on seeing the stability of this module as used by end users and on collecting, from their experience, the possible errors that they had faced in the entire download and installation flow that we were coding within our wrapper.

As we made headway in this process, we could begin to see how we had more and more tracks referenced to the different states of the download and installation of the module. Thus, we defined the UX experience accordingly, changing or adapting it to actual use.

At first, we handled a message where we showed the download percentage while the user waited to start the dynamic flow. Later, we made adaptations since as it weighed so little, the download was almost immediate with the percentage almost flying from 0 to 100.

At this point, we began analyzing our applications internally to define which modules met the criteria to become dynamic, and we began to meet with the teams to share this initiative, always focusing on giving the best possible experience to end users.

What were our next steps and the overall result?

The first thing we did was advance with several PoCs (in the different types of installations, but with a focus on the type of download in install time, which does not require major changes or migrations on the modules in question. This allows us to define a certain type of filters, our main focus being the filters by country.

As you know, in our applications there are different configurations depending on the country where the user is located which allow many features to be turned off for certain countries. Yet, the code the user downloads from the store is the same for all. This means, therefore, that my package has embedded features that as a user from a certain country, I cannot access, but those same features generate download and installation weight in my packaging. Thus, having modules with an install time proved beneficial in terms of time and effort saved since it does not require significant changes within the dynamic module that will be dynamic.

After making several PoCs with this feature, we brought even more devices to production that met the requirements to become dynamic modules.

We ended 2021 having reduced the download weight of our Mercado Libre and Mercado Pago applications by 8% as we’ve mainly worked with modules shared between apps. In parallel with the analyzes to define which modules had to include the Dynamic Features flow, we needed to place a lot of focus on our developers’ experience when testing the flows — mainly those that had become dynamic.

Getting to know Meli Store: our internal store

In case you didn’t know, at Mercado Libre we have an internal application store called Meli Store, similar to PlayStore and AppStore, which mainly allows us to share the early stages of our developments with any company sector. Meli Store serves the purpose of improving our tests and showing results.

Let’s explore how we’ve had to adapt this tool once we released Dynamic Feature into production and which needs spearheaded this adaptation.

In short, Meli Store allows us to upload apps to an internal storage which makes them available to be consumed from an internal app that anyone at Mercado Libre can install.

What was the problem with Dynamic Features and our tests with apk?

The main problem that arose is that for the correct functioning of the dynamic modules, we need the package to be generated as an .aab, i.e. an Android App Bundle. Otherwise, as in the .apk package the module is not part of the base app, it is excluded. This makes the flow break when trying to access these modules.

In order to be able to integrate our apps with Dynamic Features, we first had to support .aab uploading. Afterwards, we moved on with an official Google account to start integrating the apps by means of Internal App Sharing. This was the Google’s api that we linked up with, creating the necessary token.

What is Internal App Sharing?

Internal app sharing is the latest progression in PlayStore developer tools that allows us to upload an app and receive a URL in return. With this shareable URL, we are able to install the app on our device. Of course, there are some security measures worth mentioning: we can restrict who can upload applications to share internal apps as well as limit who can download them.

If you wish to know more about internal app sharing, you can access the following links:

Our main focus is to integrate this tool with our Meli Store so as to share our packages with the embedded dynamic module.

How do we communicate our backend with Internal App Sharing?

For this purpose, we use Fastline actions; here is the guide we follow with the official documentation.

The last step was to create a variant of our productive app such as an mds, i.e. a buildtype that allows us to generate a package with certain configurations to publish on our Meli Store. The app is registered as part of a new application within our PlayStore account so we can test the dynamic feature without affecting production.

As a result and thanks to the integration we’ve carried out, we can now access each package of our internal application and act on the URL provided by Internal App Sharing. In this way, we are directly connected to PlayStore to download our package as .aab within the new application for MDS, created in the same Store.

It should be noted that for this, it’s been necessary to expand the architecture that we had defined for our client at the time of generating these packages, a task which required many tests at the level of our Store. For such an accomplishment, I would like to acknowledge the efforts made by the great team that participated in this initiative; they managed to take it to the next level by giving an integrated experience to the tools we already had in a super scalable way.

How do we go on from here?

In order to understand user experience better, we will be adding some performance metrics to what we already have such as the download time of dynamic modules, among other data.

What we in the architecture team have mainly sought to achieve with all this work is to raise awareness in other teams that the DF wrapper is a good tool to incorporate in order to keep the weight of the app under control, provided the apps meet the requirements to use Dynamic Features.

After sharing our lessons learned with other teams internally today the initiative is practically in auto-run mode, with our participation focused on offering support to the teams and on improving our documentation.

In parallel, we go on improving and giving visibility to our metrics, keeping ourselves updated on new versions of PlayCore being released by Google. Regarding migrations, our active work has dropped significantly since we have already transferred our knowhow to the teams.

Each team should be made aware of the importance of looking after our native applications, ensuring both stability and minimum weight. This awareness raising has been a challenge even to us, the architecture team, but today we’ve reached a point where other teams come along to consult about the tool and are integrating Dynamic Features extremely easily.

With our own DF wrapper running practically independently, we can now count on a tool with good stability and adoption which allows us to render sustainable results at the weight level of the app, improving user experience significantly.

Our gratitude

If you have read this far, we thank you for the time you’ve invested. We hope that you will make the most of our experience on the integration process of Dynamic Features within our Mercado Libre and Mercado Pago applications.

Thank you very much.

--

--