You might be one of the people interested in using Flutter in your daily job, but unfortunately, you cannot use it as you already have a native application that you cannot just rewrite now with Flutter.

Luckily, Flutter can be integrated into an already existing application — at Groupon, we have been using it in Merchant application since May.

In the next three articles I would like to tell you:

How we have done the integration — Flutter with submodules

What are alternative ways to include it — Flutter with “attach”

Challenges we’ve faced with Flutter integration (coming soon)

Flutter with submodules

The approach that I will be describing here is called with submodules as it’s done with help of git submodules.

Flutter project structure is heavily opinionated, it should look like this:

└── FlutterApplication

├── android

├── ios

└── lib

When having already both Android and iOS repositories for your existing native project, you do not want to put everything into one mega-repository.

The solution to this is to have separate Android, iOS and Flutter repository. Your native Android repo would be submoduled into android folder and iOS repo into ios folder.

Project structure

First, let’s assume this is your project structure and AwesomeApp is your existing Android application:

└── MyProjects

├── AwesomeApp

│ └── AndroidAwesomeApp [1]

│ ├── mainModule [2]

│ │ └── build.gradle [3]

│ ├── build.gradle [4]

│ └── settings.gradle [5]

└── Flutter

Required steps to add include Flutter into your apk:

Rename your applications folder name AndroidAwesomeApp [1] to android Rename your main Android module to app Update build.gradle [3] in the app folder Update build.gradle [4] in the root folder Update settings.gradle [5] Create pubspec.yaml and lib Run flutter run

1. Rename your applications folder name

Flutter expects your Android code to be located in android folder:

└── MyProjects

├── AwesomeApp

│ └── android <=============== [1]

│ ├── mainModule [2]

│ │ └── build.gradle [3]

│ ├── build.gradle [4]

│ └── settings.gradle [5]

└── Flutter

2. Rename your main Android module to app

Flutter build tool is really opinionated and has to have iOS code in ios folder and Android in android . Furthermore, the main module of the Android project has to be named app otherwise it won’t be found.

Make sure your project structure looks now like this:

└── MyProjects

├── AwesomeApp

│ └── android [1]

│ ├── app <=============== [2]

│ │ └── build.gradle [3]

│ ├── build.gradle [4]

│ └── settings.gradle [5]

└── Flutter

3. Update build.gradle [3] in the root folder

// build.gradle [3] // Where should output folder for binaries be

rootProject.buildDir = '../build'

subprojects {

project.buildDir = "${rootProject.buildDir}/${project.name}"

} // All subprojects need to be dependent of the main module

subprojects {

project.evaluationDependsOn(':app')

} // Flutter cleanup task

task clean(type: Delete) {

delete rootProject.buildDir

}

4. Configuring app build.gradle

Make sure you put this code at the beginning of your app/build.gradle [4]

// build.gradle [4] def localProperties = new Properties()

def localPropertiesFile = rootProject.file('local.properties')

if (localPropertiesFile.exists()) {

localPropertiesFile.withReader('UTF-8') { reader ->

localProperties.load(reader)

}

} def flutterRoot = localProperties.getProperty('flutter.sdk')

if (flutterRoot == null) {

throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")

} def flutterVersionCode = localProperties.getProperty('flutter.versionCode')

if (flutterVersionCode == null) {

flutterVersionCode = '1'

} def flutterVersionName = localProperties.getProperty('flutter.versionName')if (flutterVersionName == null) {

flutterVersionName = '1.0'

} apply plugin: 'com.android.application'

// Applying flutter.gradle has to be after com.android.application pluggin

apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

// Path to flutter folder

flutter {

source '../..'

}

5. Configure settings.gradle [5] —adding plugin support

Flutter android plugins are normal Android modules — because those will be added in pubspec.yaml we need to add dynamic loading:

// settings.gradle[5] def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()

def plugins = new Properties()

def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') if (pluginsFile.exists()) {

pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }

} plugins.each { name, path ->

def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() include ":$name"

project(":$name").projectDir = pluginDirectory

}

6. Create pubspec.yaml and lib

To successfully run flutter build command pubspec.yaml file is required. To create a basic .yaml file, just run flutter create <project name> in a temporary folder and copy both pubspec.yaml and lib . into AwesomeApp folder:

└── MyProjects

├── AwesomeApp

│ ├── android [1]

│ │ ├── app [2]

│ │ │ └── build.gradle [3]

│ │ ├── build.gradle [4]

│ │ └── settings.gradle [5]

│ ├── lib <================== [6]

│ │ └── main.dart <======== [6]

│ └── pubspec.yaml <========= [6]

└── Flutter

7. Run flutter run

Now you can run the app with: