Flutter Module

Integrate a Flutter module into your iOS and Android project

HUA YU TSENG
3 min readFeb 25, 2021

If we have a native project both on iOS and Android platform, now we need implement some new feature to this project, We can write flutter module to implement it and add to native project, so we don’t need implement the new feature with separate iOS and Android native code.

For Flutter module

flutter create --template module my_flutter

For iOS

Flutter can be incrementally added into your existing iOS application as embedded frameworks, we embed with CocoaPods and the Flutter SDK.

  1. Add lines of code in Podfile
# Uncomment the next line to define a global platform for your project
platform :ios, '10.0' //for flutter module
flutter_application_path = '../my_flutter' //for flutter module
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')target 'Native_iOS' do# Comment the next line if you don't want to use dynamic frameworksuse_frameworks!# Pods for Native_iOSinstall_all_flutter_pods(flutter_application_path)post_install do |installer| installer.pods_project.targets.each do |target| if target.name =="App" || target.name =="Flutter" target.build_configurations.each do |config| config.build_settings['ENABLE_BITCODE'] ='NO'
end
end
end
end
end

2. $ pod install
3. Make a flutter view entrance with pre-warmFlutterEngine for your application

import UIKit
import Flutter
import FlutterPluginRegistrant // Used to connect plugins (only if you have plugins with iOS platform code).
class ViewController: UIViewController { lazy var flutterEngine = FlutterEngine(name: "my_engine_id")
override func viewDidLoad() {
super.viewDidLoad()
initFlutterEngine()

let myButton: UIButton = UIButton()
myButton.setTitle("To Flutter View", for: .normal)
myButton.backgroundColor = .red
myButton.frame = CGRect(x: 50, y: 100, width: 200, height: 50)
myButton.addTarget(self, action: #selector(presentFlutterView), for: .touchUpInside)
self.view.addSubview(myButton);
}

private func initFlutterEngine(){
// Runs the default Dart entrypoint with a default Flutter route.
flutterEngine.run()
// Used to connect plugins (only if you have plugins with iOS platform code).
GeneratedPluginRegistrant.register(with: self.flutterEngine)
}

@objc func presentFlutterView() {
let vc = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
self.present(vc, animated: true, completion: nil)
}
}

For Android

Flutter can be embedded into your existing Android application piecemeal, as a source code Gradle subproject or as AARs.

  1. Add couple lines of code to build.gradle
apply plugin: 'com.android.application'

android {
compileSdkVersion 30
buildToolsVersion "30.0.2"

defaultConfig {
applicationId "com.example.native_android"
minSdkVersion 16
targetSdkVersion 30
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

//for flutter module
ndk {
// Filter for architectures supported by Flutter.
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64'
}

}

//for flutter module
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
//for flutter module
implementation project(':flutter')

}

2. Add lines of code in setting.gradle

include ':app'
rootProject.name = "Native_android"

setBinding(new Binding([gradle: this]))
evaluate(new File(
settingsDir.parentFile,
'my_flutter/.android/include_flutter.groovy'
))
include ':my_flutter'
project(':my_flutter').projectDir = new File('../my_flutter')

3. Add activity for flutter view in AndroidManifest.xml

<activity
android:name="io.flutter.embedding.android.FlutterActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"
/>

4. Make a flutter view entrance with pre-warmFlutterEngine for your application

public class MainActivity extends AppCompatActivity {

private Button myButton;
private FlutterEngine flutterEngine;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

initFlutterEngine();

myButton = (Button) findViewById(R.id.button);
myButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d("asd","my button click");

startActivity(
FlutterActivity
.withCachedEngine("my_engine_id")
.build(MainActivity.this)
);
}
});
}

private void initFlutterEngine(){
// Instantiate a FlutterEngine.
flutterEngine = new FlutterEngine(this);
// Start executing Dart code to pre-warm the FlutterEngine.
flutterEngine.getDartExecutor().executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
);

// Cache the FlutterEngine to be used by FlutterActivity.
FlutterEngineCache
.getInstance()
.put("my_engine_id", flutterEngine);
}

}

--

--

HUA YU TSENG

I am Red, an iOS developer, I have hands on experience in iOS, Flutter, familiar with RxSwift Moya Unit/UI testing and Gitlab-CI.