flutter-android混合编译,原生接入

关于作者: CSDN内容合伙人、技术专家, 从零开始做日活千万级APP ,带领团队单日营收超千万。

专注于分享各领域原创系列文章 ,擅长java后端、移动开发、商业化变现、人工智能等,希望大家多多支持。

目录

一、导读

我们继续总结学习flutter基础知识,温故知新。

二、概览

本文主要讲解原生Android工程接入Flutter ,进行混合编程。

首先,需要开发者按照原生Android、iOS的搭建流程搭建好开发环境。

然后,去Flutter官网下载最新的SDK,下载完毕后解压到自定义目录即可。

下载完后,还需要配置好环境,具体可参考 上一篇的 flutter配置的文章。

我们讲解一下三种方式;

Flutter 可以作为源代码 Gradle 子项目或 AAR 嵌入到现有的 Android 应用程序中。

集成流程可以使用带有Flutter 插件的Android Studio IDE或手动完成。

现有的 Android 应用可能支持mips或 等架构x86。Flutter 目前仅支持x86_64为、armeabi-v7a和构建预先 (AOT) 编译库arm64-v8a。

考虑使用abiFiltersAndroid Gradle 插件 API 来限制 APK 中支持的架构。这样做可以避免缺失libflutter.so运行时崩溃,例如:

groovy 复制代码
android {
    // ...
    defaultConfig {
        ndk {
            // Filter for architectures supported by Flutter
            abiFilters "armeabi-v7a", "arm64-v8a", "x86_64"
        }
    }
}

三、以原生module依赖

创建flutter module,然后以原生module那样依赖

自行参考
参考文档
参考文档

四、以aar方式依赖一

另一种方式是将flutter module打包成aar,然后在原生工程中依赖aar包,官方推荐aar的方式接入。

参考文档
参考文档

创建一个flutter module,然后打包成aar,这个过程就省略一下。

在 /flutter_module/.android/Flutter/build/outputs 目录下生成对应的aar包。

groovy 复制代码
stuff@ddddeMacBook-Pro loktar % flutter build aar

Running Gradle task 'assembleAarDebug'...                           7.1s
✓ Built build/host/outputs/repo
Running Gradle task 'assembleAarProfile'...                      1,714ms
✓ Built build/host/outputs/repo
Running Gradle task 'assembleAarRelease'...                      1,642ms
✓ Built build/host/outputs/repo

Consuming the Module
  1. Open <host>/app/build.gradle
  2. Ensure you have the repositories configured, otherwise add them:

      String storageUrl = System.env.FLUTTER_STORAGE_BASE_URL ?: "https://storage.googleapis.com"
      repositories {
        maven {
            // 本地仓库,也是创建的 flutter工程目录, 也可以是自己创建的一个目录,然后把编译后的产物拷贝过来
            url '/Users/stuff/dddd/working/flutter_pro/loktar/build/host/outputs/repo'
        }
        maven {
            url "$storageUrl/download.flutter.io"
        }
      }

  3. Make the host app depend on the Flutter module:

    dependencies {
      debugImplementation 'com.ddd:flutter_debug:1.0'
      profileImplementation 'com.ddd:flutter_profile:1.0'
      releaseImplementation 'com.ddd:flutter_release:1.0'
    }


  4. Add the `profile` build type:

    android {
      buildTypes {
        profile {
          initWith debug
        }
      }
    }

To learn more, visit https://flutter.dev/go/build-aar

接下来,就是在原生Android工程中集成aar即可。

第一,在build.gradle中添加如下配置。

groovy 复制代码
android {
    ...
 
buildTypes {
        profile {
          initWith debug
        }
      } 
 
    String storageUrl = System.env.FLUTTER_STORAGE_BASE_URL ?:
      "https://storage.googleapis.com"
      repositories {
        maven {
            // 本地仓库,也即是创建的 flutter工程目录
            url '/Users/mac/Flutter/module_flutter/build/host/outputs/repo'
        }
        maven {
            url "$storageUrl/download.flutter.io"
        }
      }
}

repositories {
    flatDir {
        dirs 'libs'
    }
}
dependencies {
      debugImplementation 'com.ddd.module_flutter:flutter_debug:1.0'
      profileImplementation 'com.ddd.module_flutter:flutter_profile:1.0'
      releaseImplementation 'com.ddd.module_flutter:flutter_release:1.0'
    }

第二、在AndroidManifest.xml中注册FlutterActivity实现

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:theme="@style/AppTheme"
            android:windowSoftInputMode="adjustResize" />
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />

第三、启动FlutterActivity

java 复制代码
context.startActivity(FlutterActivity.withNewEngine().build(context));

// 
Intent intent = FlutterActivity.withCachedEngine(FlutterHelper.FLUTTER_ENGINE).build(context);
//重新设置一下目标class到子类BridgeActivity.class
intent.setClass(context, FlutterActivity.class);
context.startActivity(intent);

五、以aar方式依赖二

将flutter module打包成aar,然后在原生工程中依赖aar包, 但这种方式跟前一种有少许区别。

在新建的flutter工程中,可以看一下.android 目录下Flutter/build.gradle文件。

groovy 复制代码
apply plugin: "com.android.library"
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
想来,这就是flutter 相关的依赖,
我们在进入到目录下看看其他的gradle文件,发现有个依赖相关的文件,后面用到。

创建一个flutter module,然后打包成aar,这个过程就省略一下。

在 /flutter_module/.android/Flutter/build/outputs 目录下生成对应的aar包。

groovy 复制代码
stuff@ddddeMacBook-Pro loktar % flutter build aar

Running Gradle task 'assembleAarDebug'...                           7.1s
✓ Built build/host/outputs/repo
Running Gradle task 'assembleAarProfile'...                      1,714ms
✓ Built build/host/outputs/repo
Running Gradle task 'assembleAarRelease'...                      1,642ms
✓ Built build/host/outputs/repo

Consuming the Module
  1. Open <host>/app/build.gradle
  2. Ensure you have the repositories configured, otherwise add them:

      String storageUrl = System.env.FLUTTER_STORAGE_BASE_URL ?: "https://storage.googleapis.com"
      repositories {
        maven {
            url '/Users/stuff/dddd/working/flutter_pro/loktar/build/host/outputs/repo'
        }
        maven {
            url "$storageUrl/download.flutter.io"
        }
      }

  3. Make the host app depend on the Flutter module:

    dependencies {
      debugImplementation 'com.ddd:flutter_debug:1.0'
      profileImplementation 'com.ddd:flutter_profile:1.0'
      releaseImplementation 'com.ddd:flutter_release:1.0'
    }


  4. Add the `profile` build type:

    android {
      buildTypes {
        profile {
          initWith debug
        }
      }
    }

To learn more, visit https://flutter.dev/go/build-aar

接下来,就是在原生Android工程中集成aar即可。

第一,在app的目录下新建libs文件夹,然后将生成aar包放入libs文件夹中

第二、新建一个flutter依赖文件

首先,在local.properties 目录新增flutter目录

groovy 复制代码
sdk.dir=/Users/sd/Library/Android/sdk
flutter.sdk=/Users/sd/development/flutter

然后在 "$flutter sdk目录/packages/flutter_tools/gradle/" 中找到resolve_dependencies.gradle文件,复制到app目录下。

然后进行修改如下:

groovy 复制代码
// This script is used to warm the Gradle cache by downloading the Flutter dependencies
// used during the build. This script is invoked when `flutter precache` is run.
//
// Command:
//  gradle -b <flutter-sdk>packages/flutter_tools/gradle/resolve_dependencies.gradle
//      resolveDependencies
//
// This way, Gradle can run with the `--offline` flag later on to eliminate any
// network request during the build process.
//
// This includes:
//   1. The embedding
//   2. libflutter.so

import java.nio.file.Paths


///add
//获取local.properties配置文件
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')

if (localPropertiesFile.exists()) {
    localPropertiesFile.withReader('UTF-8') {
        reader -> localProperties.load(reader)
    }
}

//获取flutter的sdk路径
def flutterRootPath = localProperties.getProperty('flutter.sdk')

if (flutterRootPath == null) {
    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

 end


String storageUrl = System.getenv('FLUTTER_STORAGE_BASE_URL') ?: "https://storage.googleapis.com"

//File flutterRoot = projectDir.parentFile.parentFile.parentFile
File flutterRoot = new File(flutterRootPath)


String engineRealm = Paths.get(flutterRoot.absolutePath, "bin", "internal", "engine.realm")
        .toFile().text.trim()
if (engineRealm) {
    engineRealm = engineRealm + "/"
}

repositories {
    google()
    mavenCentral()
    maven {
        url "$storageUrl/${engineRealm}download.flutter.io"
    }
}


assert flutterRoot.isDirectory()
String engineVersion = Paths.get(flutterRoot.absolutePath, "bin", "internal", "engine.version")
        .toFile().text.trim()

System.out.println("hrl Resolving dependencies for Flutter $engineVersion")

configurations {
    flutterRelease.extendsFrom releaseImplementation
    flutterDebug.extendsFrom debugImplementation
    flutterProfile.extendsFrom debugImplementation
}

dependencies {
    flutterRelease "io.flutter:flutter_embedding_release:1.0.0-$engineVersion"
    flutterRelease "io.flutter:armeabi_v7a_release:1.0.0-$engineVersion"
    flutterRelease "io.flutter:arm64_v8a_release:1.0.0-$engineVersion"

    flutterProfile "io.flutter:flutter_embedding_profile:1.0.0-$engineVersion"
    flutterProfile "io.flutter:armeabi_v7a_profile:1.0.0-$engineVersion"
    flutterProfile "io.flutter:arm64_v8a_profile:1.0.0-$engineVersion"

    flutterDebug "io.flutter:flutter_embedding_debug:1.0.0-$engineVersion"
    flutterDebug "io.flutter:armeabi_v7a_debug:1.0.0-$engineVersion"
    flutterDebug "io.flutter:arm64_v8a_debug:1.0.0-$engineVersion"
    flutterDebug "io.flutter:x86_debug:1.0.0-$engineVersion"
    flutterDebug "io.flutter:x86_64_debug:1.0.0-$engineVersion"

//    compileOnly "io.flutter:flutter_embedding_debug:1.0.0-$engineVersion"
//    compileOnly "io.flutter:armeabi_v7a_debug:1.0.0-$engineVersion"
//    compileOnly "io.flutter:arm64_v8a_debug:1.0.0-$engineVersion"
//    compileOnly "io.flutter:x86_debug:1.0.0-$engineVersion"
//    compileOnly "io.flutter:x86_64_debug:1.0.0-$engineVersion"

    debugImplementation "io.flutter:flutter_embedding_debug:1.0.0-$engineVersion"
    debugImplementation "io.flutter:armeabi_v7a_debug:1.0.0-$engineVersion"
    debugImplementation "io.flutter:arm64_v8a_debug:1.0.0-$engineVersion"
    debugImplementation "io.flutter:x86_debug:1.0.0-$engineVersion"
    debugImplementation "io.flutter:x86_64_debug:1.0.0-$engineVersion"


    releaseImplementation "io.flutter:flutter_embedding_release:1.0.0-$engineVersion"
    releaseImplementation "io.flutter:armeabi_v7a_release:1.0.0-$engineVersion"
    releaseImplementation "io.flutter:arm64_v8a_release:1.0.0-$engineVersion"
}

第三、在build.gradle中添加如下配置。

groovy 复制代码
allprojects {
    repositories {

        maven {
            url "https://storage.googleapis.com/download.flutter.io"
        }
    }
}

然后在app的build.gradle中添加如下配置。

groovy 复制代码
apply from: "${rootDir}/resolve_dependencies.gradle"

repositories {
    flatDir {
        dirs 'libs'
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')

    releaseImplementation(name:'flutter_release-1.0', ext:'aar')
    debugImplementation(name:'flutter_debug-1.0', ext:'aar')
}

第四、在AndroidManifest.xml中注册FlutterActivity实现

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:theme="@style/AppTheme"
    android:windowSoftInputMode="adjustResize" />
<meta-data
    android:name="flutterEmbedding"
    android:value="2" />

第五、启动FlutterActivity

java 复制代码
context.startActivity(FlutterActivity.withNewEngine().build(context));

// 
Intent intent = FlutterActivity.withCachedEngine(FlutterHelper.FLUTTER_ENGINE).build(context);
//重新设置一下目标class到子类BridgeActivity.class
intent.setClass(context, FlutterActivity.class);
context.startActivity(intent);

如此即可

六、 推荐阅读

Java 专栏

SQL 专栏

数据结构与算法

Android学习专栏

未经允许,不得转载。

相关推荐
龙之叶1 小时前
Android13源码下载和编译过程详解
android·linux·ubuntu
闲暇部落3 小时前
kotlin内联函数——runCatching
android·开发语言·kotlin
大渔歌_4 小时前
软键盘显示/交互问题
android
LuiChun5 小时前
webview_flutter 4.10.0 技术文档
flutter
ssslar5 小时前
FLUTTER 开发资料集(持续更新)
flutter
LuiChun6 小时前
webview_flutter_wkwebview 3.17.0使用指南
flutter
愿天深海10 小时前
Flutter TextPainter 计算文本高度和行数
flutter
LuiChun11 小时前
webview_flutter_android 4.3.0使用
android·flutter
Tanecious.11 小时前
C语言--分支循环实践:猜数字游戏
android·c语言·游戏
闲暇部落13 小时前
kotlin内联函数——takeIf和takeUnless
android·kotlin