As we can see in current Mobile Application Development trends, Flutter has gain rapid growth in short span of time compared to any other mobile application development frameworks. Having ready-to-deploy or ready-to-release strategy is one of the best practices that an organization follows. In technical terms, this is called Continues-Integration & Continues-Deployment (CI-CD). In this 4 part series, we’ll be telling you how you can setup CI-CD pipeline on Gitlab for your Flutter Application.
We’ll walk you through the following processes:
Creating individual flavors for a Flutter Application is the practice that every organization follows to keeps development and production safe for end user. Here we’ll be creating two different flavors: ‘develop’ and ‘production’.
Flavor named ‘develop’ is the one that will be used during development of a Flutter Application. ‘Production’ will be used when we go live to end users. So, let’s see how we can setup these two flavors for both Android and iOS module of our freshly-created Flutter Application.
To setup two different flavor for Android module, a few lines need to be added in app’s build.gradle file right after buildTypes inside Android node. Check below code snippet:
Now our Android app module is ready with two different flavors: ‘develop’ and ‘production’. Now we’ll see how we can set this to iOS module of our Flutter Application.
Setting up flavor for iOS is bit tricky, but once you understand how it works, you will be amazed. We’ll go step by step for this whole procedure.
Create two schemes develop and production with xCode:
When you complete this step, you should have schemes as shown in below image:
Now, for every scheme created, we have to add a new build configuration combined with each different build mode type (Debug, Release).
When you complete this step, you should have Configurations as show in below image:
Now we’re done setting up schemes and configuration, so we’ll pair them together to enable for which scheme and build type combination and which configuration will be picked. Here we’ll be setting up for Run and Archive as of now.
We’ve to do this for our other scheme, also. Once we’re done, we’ll get configuration setup like below images:
Finally, we’re done setting up flavors for Android and iOS modules for our Flutter application. But one main thing is remaining: how our dart Flutter Application will inform native (Android or iOS) module about which flavor it’s executing right now.
So, for this we’ll be writing a communicating method at both sides, in Dart and as well as in Native (for Android and iOS modules) which we’ll cover now in next module.
In previous section we’ve configured flavors in Android and iOS modules of our Flutter Application. Now we will be configuring Dart side of our Flutter Application so it will communicate with native module to which flavor it is executing or building. For this, we’ll be using Platform Channels to make communication bridge between Dart and Native code our application.
Step 1
Create a file with name app_config.dart in lib folder of our application where main.dart resides. This file will be used to configure or we can store API Base Endpoint and flavor based on our current Run Configurations.
First of all, import required packages as displayed in below image:
Then declare a user define function definition and declare enum Environment of values same as our definedflavors,
Next, we’ll be creating a class named AppConfig and declare parameters as displayed below:
We’ll be communicating with Native module via Method channel. This will notify our native modules which flavor we’re running so appropriate run configuration will be taken at the time of execution.
Next define a method based on our define function signature as below:
This static method will be called via an instance of AppConfig class which will perform several functions like:
Finally, we’ll add a method to setup environment as shown below:
This method will create an _instance by assigning values to apiBaseUrl and flavor parameters based in flavor that it retrieves.
At the end, we require some modification to our main.dart file as shown below:
Here at the beginning of our application start-up, we’ll be checking if Flutter Widgets are initialized or not by a single line call. Then we’ll make an await call to our AppConfig class configure method to get flavor according to run configuration and setting up environment according to it and send back result as true or false. If the result is true, we’ll be forwarding execution to start our application.
Step 2
In this step we’ll do modification to native modules, so they can handle method channel call from dart side. Let’s check that out one by one.
Android
Open MainActivity.kt file from folder android -> app -> src -> main -> kotlin -> PACKAGE -> MainActivity.ktand include the changes as displayed in below image:
As we require to handle method channel call here on Android native side, we’ll be importing a few required packages first. Then we’ll declare channel name and method name the same as we have taken for our Flutter Dart application.
Next, we’ll be adding handling part of this method call for which we have to override a function namedconfigureFlutterEngine. Inside which we’ll be declaring method channel handler using setMethodCallHandlemethod of MethodChannel class by passing a required parameter and channel name. Further, we’ll be checking which method call has been made and according to it, we’ll reply with an instance of result containing value of Flavor that our app is configuring as per Run Configuration.
iOS
Configuring iOS module is straight forward but require precise changes so take time to be accurate. First of all, open AppDelegate.swift file and make the changes same as displayed in below image. It’s the same thing that we have done to handle a method channel call for Android side. This one is the iOS side. But it requires a little bit more modification. We need to make the variable Flavor available in info.plist file.
So, in xCode open Runner/Info.plist file and add a new key named Flavor and assign value of ${PRODUCT_FLAVOR} to it. You can check below image for it.
Next, we have to define the new setting for PRODUCT_FLAVOR under Targets/Runner/BuildSettings/User-Defined. Here we’ll be adding a flavor name for each configuration that we have on left side. So, make the changes as displayed in below image.
Finally, we’ll be modifying the package name as per our flavor configuration. So, move to Packaging section under same BuildSettings and modify Product Bundle Identifier values for each run configuration as displayed below:
Now,we’re ready to run our application by specifying flavor name. To do that you can use command line code as:
Flutter run —flavor develop or flutter run —flavor production
Or you can Edit Run Configuration for all the time as shown in below images:
First go to Edit Configuration and then mention name of the flavor as displayed in below image for a Run Configuration. You can also name it Develop. For production, just duplicate Develop Configuration and modify its name and specified flavor as per our requirement.
Now, when you run your application by selecting a particular configuration you can also check in log whichFlavor it is executing and also you can check installed app bundle id or package id on iOS and Android device respectively. That’s it. We’re done setting up flavors for our Flutter Application.
Stay tuned for part 2!
Our team of experts will review your project and give you a quote at no cost.
In this episode of the The Lazy CEO Podcast,…
Join us for an enlightening episode of The CEO…
Creating multi-agent workflows is the future of AI development,…
How has sunflower lab's focus on integrating ai, data…
Businesses are quickly shifting towards optimized processes. And the…
Developers often make mistakes when using Power Automate, which…