Fluttering over mobile app deployment tools

Jason Brewer
Atlas
Published in
6 min readJun 1, 2018

New cross platform development tools generate lots of interest in the mobile community. Look! We can cut development costs in half by maintaining a single code base for both iOS and Android.

My expectations, while hopeful, stay more grounded:

  • What’s the learning curve to proficiency?
  • What is the toolset? How mature is it? What are its limitations vs my existing tools?
  • Can I see myself working faster?
  • Are there any barriers to extending/customizing or releasing production apps?
  • Finally, is it fun to use? Can I see team members enjoying it?

Flutter is a promising recent option.

It’s straightforward to walk through a new cross-platform tutorial and get it running on your platform of choice. Especially with a technology like Flutter, that’s been out now for some time and has Google behind it. And there are plenty of resources on the web to choose from to start your knowledge ramp.

But often, the early excitement of something new and promising crashes into a solid wall of operational constraints or production requirements. So let’s see if I’ll need air bags when I take Flutter for a ride through real production deployment.

Keeping native app expectations in check

Flutter: fly unsteadily or hover by flapping the wings quickly and lightly.

Hmmm… sounds like extra work and little motion — but that might be my bias from previous experience with cross platform development — still I start optimistically.

As mentioned above, rather than build some fun cross-platform demo, I worked backwards to see if I could adapt flutter to our existing Android and iOS Continuous Integration and Continuous Deployment (CI/CD) flow.

Through this approach, I found myself thinking differently about cross platform development. Rather than the inevitable frustration of using new tools to build the same native thing, I looked at it from the perspective of using new tools create a new thing.

Artists can create sculptures from marble or wood, but they use different tools and end up with different types of sculpture.

So why should I expect cross-platform tools to be better or more efficient than their native counterparts? It’s a new tool for a different medium. I should use it to create something unique — different from what I’ve done before.

So I forgot about trying to write a native Android and iOS app and instead set out to write a cross-platform app with a view to how much of an upheaval would be required to my whole tool suite from source development to build deployment.

Local Environment

I went through Flutter setup on two environments:

  • My work computer with both Android Studio and Xcode tools.
  • My personal computer, with only Xcode (bias disclaimer — I spend the majority of my time on iOS)

No issues on my work device. The Flutter doctor utility was sufficient to resolve all issues and get everything installed. I was surprised to find I could build on Android Studio and install to the running iOS simulator out of the box with no special steps required on my part. Hot reload worked as advertised. I did the same with Android Simulator, iOS device (iPhone 7 with 11.4 beta) and Android device (Galaxy Note 8 running 7.1.1). Enthused, I did the same from my Xcode environment (minus running on Android).

On my personal computer, I ran into typical conflicts with multiple python environments, but nothing that couldn’t be solved with some web sleuthing and a few trial and error iterations. Flutter doctor warned me of missing Android tools, but I ignored and built and deployed to my iOS platforms just fine.

Android Studio is a nicer Dart editor due to the plug-in support, but I was OK with adding a Dart file grouping in Xcode and bringing the Dart files into the workspace Flutter created for me (via CocoaPods). I expect someone will develop a Dart formatting plug-in for Xcode if one doesn’t already exist.

Source Control

Great — I have a Flutter app running on multiple platforms and I can build from the tool of my choice. Let’s look at source control.

Really the only question is what should I commit/ignore from all these project and generated files I’m not familiar with? Fortunately, by giving Flutter a little time to evolve before I tackled this task, the answer was readily available:

Flutter .gitignore

Build Server

The first potential roadblock I hit was with our build servers. Android and iOS builds are isolated from each other on different machines.

My initial thought had been to set up a new build job that would generate both iOS and Android. I could have setup a custom build server environment on a new machine, but that went against my goal of minimal changes to existing production flow. I needed to configure jobs on the existing build environments.

That meant two build jobs, but at least by sticking with existing deployment environments, I reduced the risk of my Flutter build environment diverging significantly from our standard platform environments over time.

Android went smoothly and though I had never setup an Android Jenkins build before, it was straightforward enough to grab the configuration of a project I was familiar with and tweak it to build a Flutter APK. Yay, command line build tools!

# <Standard Android Jenkins build config stuff>
# Code from Bitbucket...
if [ ! -d "flutter" ]; then
echo "Get flutter..."
git clone https://github.com/flutter/flutter.git -b beta --depth 1
flutter doctor --android-licenses
fi
export PATH=`pwd`/flutter/bin:$PATH
flutter doctor
echo "Building..."
flutter build apk

iOS builds use Fastlane and that took a bit longer to figure out the right sequence of flutter package commands, CocoaPods, Fastlane, and build operations to get right with provisioning profiles, certs, etc.…

But eventually, that too was solved.

# <Standard iOS env setup, provisioning, certs, etc…>
if [ ! -d "flutter" ]; then
echo "Get flutter..."
git clone https://github.com/flutter/flutter.git -b master --depth 1
fi
export PATH=`pwd`/flutter/bin:$PATH
flutter doctor
echo "Get Packages..."
flutter packages get
echo "Building..."
cd ios
pod install
cd ..
flutter -v build ios --no-codesign
echo "Completed flutter build. Archiving..."
cd ios
# <Fastlane build scripts with signing>

I think this can probably be optimized. I see some redundancies here, but above is what finally worked for me.

Deployment

Now since we used our standard build server flow, there was minimal to do here. Our build server output is a native app for iOS and a native app for Android. These get pushed to Artifactory via our standard plug-in setup.

Integration

Another nice thing I found with the Flutter tool set was it generated a unit test infrastructure along with an initial test. So there’s really no excuse not to consider that from the start.

I updated the test code so it was consistent with the tweaks I made experimenting with the Flutter generated app starting point. After confirming the test passed, I added the Flutter test step to my Jenkins configuration.

I did this as time allowed over the course of a couple of weeks, but I figure I spent somewhere between 1 and 2 days overall, and I have our standard build work flows churning out an Android and iOS app from (an admittedly simple) Flutter code repo. I never would have expected that — hence the inspiration to share this experience.

Recap

In most cases, Flutter documentation is excellent. Unless you’re starting from scratch or have a dev ops unicorn with time to spare, you will probably need to do some digging and invest some time to adapt it into your CI flow, but official Flutter documentation is still a good place to start.

The sequencing below will give you a full survey of the platform and arm you with everything you may need before branching off in domain specific areas to write something really compelling.

Still Invested?

Conclusion

Flutter: A state of nervous excitement — a flutter of anticipation.

That definition seems more appropriate.

How does your experience integrating and deploying Flutter compare to that of other cross-platform tools?

--

--

Jason Brewer
Atlas
Writer for

Sr Engineering Manager, Cross-Platform, Bottle Rocket Studios