Flutter 1.20 — What you should know before you upgrade your project that uses compile-time variables

Denis Beketsky
4 min readAug 2, 2020

Update 05/08/2020: Article updated with new stable Flutter release

This article is an addition to the main article about compile-time variables. If you don’t know how to define and use them, I would recommend you to read the main article before you continue:

Update 11/08/2020: Added explanation regarding grep command in XCode pre-action

So new Flutter 1.20 is here and it’s time to talk about breaking changes 😉

If you using Flutter 1.17 with compile-time variables on the board and decided to upgrade your Flutter up to version 1.20 (which is the current stable version) you may face some problems with compile-time variables usage in the native layers. In this article, we will go through needed changes in order to make your project compatible with Flutter 1.20.

In fact, if you using compile-time variables exclusively in the Dart code you probably nothing to worry about. Since Flutter Tool decodes defined key-value pairs before it builds the Dart code. So you’re safe here.

But if your project uses Dart Defines in the native code, you may need to provide some changes in your parsing logic for Android and iOS builds.

The reason why your build may fail is actually a quite trivial: fix for // usage in the dart-define variables, that was fixed with this PR.

What was changed in the flutter tools?

The fix is quite straightforward — the Flutter team added URI encode to all Dart Define variables that are passed to the build process. Delimiter for variables still remains , , but the key name, value, as well as equality operator, will be encoded. This means that before you will try to create key-value pair by splitting a string by = char, you need to decode each Dart Define item.

Let’s start with changes in the Gradle config.

In order to fix Android build, you need to decode each Dart Define item before it assigned to the result HashMap. So in the original GitHub project, you just need to change 1 line in the Gradle config and add URLDecoder.decode before you split dart define item on key and value pair (line 5 in the following code snippet):

And that’s pretty much it for the Android.

Fix for iOS pre-build action

With iOS it will be a little bit trickier.

Since the purpose of the pre-build action is to create *.xcconfig file, you need to take into account that as soon as you decode key/value pair, you need to take into account *.xcconfig limitation for the result values. So if you want to pass something like API URL, that contains //, you need to find a solution that fits for your project.

So in order to parse new dart-define value in Xcode, you need to update the pre-action script.

Open your flutter project in XCode and Edit Scheme.

Select Build > Pre-action section:

And update your script with the following variant.

I’m not a bash expert, so if you have a more elegant solution, please let me know)

First, it splits Dart Defines by ,. Then it decodes each array item. And then it joins the array with a newline.

You also may notice grep '^DEFINEEXAMPLE_' line. The reason why it’s needed is to filter all key/value pairs except keys that start with DEFINEEXAMPLE_ , because the Flutter tool can pass its own keys with dart defines. For example like flutter.inspector.structuredErrors (you can find it in Generated.xcconfig) and if don’t filter such keys, your output Defineexample.xcconfig will be invalid and iOS will simply ignore it.

So if you going to have other key names, make sure that you changed this grep line and put there your credentials for filtering.

And that’s all.

Now your project is ready to work with a Flutter 1.19 and higher.

Example project with all changes is placed as usual here, use master branch for Flutter version 1.20 or flutter-1.17 branch for Flutter before 1.17:

Thank you for your time and happy coding!

--

--