In our last article, “A Detailed Description of the Structure of the Flutter project (Android Perspective)”, we described the overall structure of the Flutter project and the role of several important documents in the Flutter project. In this article, we will focus on how the Flutter project is integrated with Android.

Here, we will focus on the analysis of the Android directory under some important files, we first take a look at the Android folder have those things.

App is our final module to generate APK files. In the app module, You can still write native Android code (Java or Kotlin) that you already know to implement the functionality that you want to implement natively. This should be understood. What is the Flutter folder? Let’s take a look at his build.gradle file to see what it has.

// I deleted some of the code that does not affect the understanding of the types of checks to apply plugin: 'com.android.library' // indicates that the Flutter project is an Android library // introduces a Flutter. Gradle file from the Flutter SDK. "$flutterRoot/packages/flutter_tools/gradle/flutter gradle" / / specifies the directory in which the flutter engineering, second difference. flutter { source '.. /.. '}Copy the code

Gradle file, and the extension of a flutter{} file. This helps us complete all the functions that the Flutter project has added to this library. In particular, the first one is to release the flutter. Gradle file from the Flutter SDK. See how he can help us package the contents of the Flutter project into our Flutter library project as follows:

// The core is a custom plugin and automatically helps us introduce the apply plugin: FlutterPlugin class FlutterPlugin implements Plugin<Project> {// The core method of this Plugin. @override void apply(Project Project) { Jar flutterJar = paths.get (engineout.absolutePath, "flutter.jar").tofile () if (! flutterJar.isFile()) { throw new GradleException('Local engine build does not contain flutter.jar') } localEngine = engineOut.name localEngineSrcPath = engineOut.parentFile.parent project.dependencies { if (project. GetConfigurations (.) findByName (" API ")) {API project. The files (flutterJar)/API/plugin3.0 above way on} else {the compile Project. Files (flutterJar) // compile dependencies on plugin3.0}} // Create the flutter extension and FluterTask Task mentioned above. For a while we watch a task to a specific project. The effect of extensions. Create (" flutter ", AfterEvaluate this. &addflutterTask Read all dependencies in the.flutter-plugins File and add File pluginsFile to build.gradle dependencies in the flutter project = new File(project.projectDir.parentFile.parentFile, '.flutter-plugins') Properties plugins = readPropertiesIfExist(pluginsFile) plugins.each { name, _ -> def pluginProject = project.rootProject.findProject(":$name") if (pluginProject ! = null) { project.dependencies { if (project.getConfigurations().findByName("implementation")) { implementation pluginProject } else { compile pluginProject } } pluginProject.afterEvaluate { pluginProject.android.buildTypes { profile { initWith debug } } } pluginProject.afterEvaluate this.&addFlutterJarCompileOnlyDependency } else { Project.logger. error("Plugin project :$name not found. Please update settings.gradle.")}}} // Create FlutterTask method mentioned in the second point Dart String target = project.flutter. Target if private void addFlutterTask(Project Project) {// Find the entry to the flutter Project lib (target == null) {target = 'lib/main.dart'} def addFlutterDeps = {variant -> FlutterTask flutterTask = project.tasks.create(name: "${flutterBuildPrefix}${variant.name.capitalize()}", type: FlutterTask) { flutterRoot this.flutterRoot flutterExecutable this.flutterExecutable buildMode flutterBuildMode localEngine this.localEngine localEngineSrcPath this.localEngineSrcPath targetPath target verbose verboseValue fileSystemRoots fileSystemRootsValue fileSystemScheme fileSystemSchemeValue trackWidgetCreation trackWidgetCreationValue  compilationTraceFilePath compilationTraceFilePathValue buildHotUpdate buildHotUpdateValue buildSharedLibrary buildSharedLibraryValue targetPlatform targetPlatformValue sourceDir project.file(project.flutter.source) intermediateDir project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}") extraFrontEndOptions extraFrontEndOptionsValue extraGenSnapshotOptions extraGenSnapshotOptionsValue } FindByPath (":flutter:package${varie.name.capitalize ()}Assets")  Task cleanPackageAssets = project.tasks.findByPath(":flutter:cleanPackage${variant.name.capitalize()}Assets") Task copyFlutterAssetsTask = project.tasks.create(name: "copyFlutterAssets${variant.name.capitalize()}", type: Copy) { dependsOn flutterTask dependsOn packageAssets ? packageAssets : variant.mergeAssets dependsOn cleanPackageAssets ? cleanPackageAssets : "clean${variant.mergeAssets.name.capitalize()}" into packageAssets ? packageAssets.outputDir : variant.mergeAssets.outputDir with flutterTask.assets } if (packageAssets) { // Only include configurations that exist in parent project. Task mergeAssets = project.tasks.findByPath(":app:merge${variant.name.capitalize()}Assets") if (mergeAssets) { mergeAssets.dependsOn(copyFlutterAssetsTask) } } else { variant.outputs[0].processResources.dependsOn(copyFlutterAssetsTask) } } } }Copy the code

By studying the code for the Flutter library and the Flutter. Gradle file in the Flutter SDK, we can find that the Flutter Module itself does not have any specific logic. His only role is to automatically package all the code in lib and assets of the Flutter project into the Flutter SDK by importing the flutter. Gradle. This allows the Flutter Android Module to eventually generate an AAR with Flutter code and resources that can be used by other apps.

In my demo project, how does app use the AAR package containing the Flutter code? Let’s open the build.gradle file in app to see.

Build /host buildDir = new File(rootProject.projectdir, ".. // build/host") dependencies { Implementation Project (': Flutter ') implementation fileTree(dir: Flutter) 'libs', include: [' *. Jar']) implementation 'com. Squareup. Okhttp3: okhttp: 3.3.0'Copy the code

There is a problem here. Our library module is called Flutter, but our app build.gradle uses Flutter. This one is much simpler. The key codes are as follows:

/ / include we create Flutter project and name it Flutter def scriptFile = getClass (). The protectionDomain. CodeSource. Location. The path def flutterProjectRoot = new File(scriptFile).parentFile.parentFile gradle.include ':flutter' Gradle.project (':flutter').projectdir = new File(flutterProjectRoot, '.android/ flutter') Def plugins = new Properties() def pluginsFile = new File(flutterProjectRoot, '.flutter-plugins') if (pluginsFile.exists()) { pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } } plugins.each { name, path -> def pluginDirectory = flutterProjectRoot.toPath().resolve(path).resolve('android').toFile() gradle.include ":$name" gradle.project(":$name").projectDir = pluginDirectory }Copy the code

Ok, now you should know how our Android project introduces things from the Flutter project to package them into the same APK. After understanding how they merge at the engineering level, how to call them at the code level, This plugin finally allows Flutter to communicate with Android native. Finally, let’s summarize what we have talked about today with a picture:

Collected from |The original address

Welcome to:

Download and install Flutter Mac/Flutter Windows

Flutter development practice: high imitation wechat (a) home page

Flutter development practice: high imitation wechat (ii) discovery page