Android原生项目集成Flutter解决方案

了解一下如何在 Android 原生项目中集成 Flutter

生成配置

在原生项目根目录执行命令

flutter create -t module --org {package_name} {module_name}

// 此处 module_name 的命令遵循 Android 子 module 的命名即可。不能有中划线。

// 比如, 

flutter create -t module --org com.engineer.mini.flutter flutter_sub

// 此处 module_name 的命令遵循 Android 子 module 的命名即可。不能有中划线。

// 比如, 

flutter create -t module --org com.engineer.mini.flutter flutter_sub
</pre>

结果

Creating project sub_flutter...
sub_flutter/test/widget_test.dart (created)
sub_flutter/sub_flutter.iml (created)
sub_flutter/.gitignore (created)
sub_flutter/.metadata (created)
sub_flutter/pubspec.yaml (created)
sub_flutter/README.md (created)
sub_flutter/lib/main.dart (created)
sub_flutter/sub_flutter_android.iml (created)
sub_flutter/.idea/libraries/Dart_SDK.xml (created)
sub_flutter/.idea/modules.xml (created)
sub_flutter/.idea/workspace.xml (created)
Running "flutter pub get" in sub_flutter... 1,054ms
Wrote 11 files.

最终生成了以上文件,注意这里最后 自动执行了 flutter pub get 的命令。关于 flutter pub get 具体做了什么,可以参考后面的。

这里在项目根目录创建子 module 只是为了把代码放在一个仓库,方便维护,理论上可以放在硬盘的任何位置。

配置原生项目 settings.gradle

在配置 settings.gradle 之前先来简单回顾一下关于 Gradle 的一些基础知识。

如果你了解过 Gradle 相关的配置的话,一定会看到一个概念,就是 约定优于配置 ,什么意思呢,按照面向对象的思路来理解,每一个工程是一个巨大的 Project 类,整个类里有很多的属性。而我们创建的每一个项目其实就是一个具体的 Project 对象(也就是实例).约定优于配置的意思,就是在 project 实例化的时候,其内部的属性已经有了默认值。那么我们怎么知道有哪些默认值呢?在项目根目录执行

./gradlew properties

就可以得到整个 Project 的一些默认配置,比如(此处节选部分结果)

------------------------------------------------------------
Root project
------------------------------------------------------------

allprojects: [root project 'MiniApp', project ':app', project ':thirdlib']
android.agp.version.check.performed: true
android.enableJetifier: true
android.enableR8: true
android.enableR8.libraries: true
android.useAndroidX: true
buildDir: /Users/username/Documents/mygithub/MinApp/build
buildFile: /Users/username/Documents/mygithub/MinApp/build.gradle
projectDir: /Users/username/Documents/mygithub/MinApp
rootDir: /Users/username/Documents/mygithub/MinApp
rootProject: root project 'MiniApp'

这里当前有一些是我们配置的,比如 useAndroidX,但也有一些是约定的,比如 对于整个 project 来说 buildDir 就是项目根目录的 build 文件夹等。

执行

./gradlew :app:properties

节选部分结果

buildDir: /Users/username/Documents/mygithub/MinApp/app/build
buildFile: /Users/username/Documents/mygithub/MinApp/app/build.gradle

就会得到关于 app 整个 module 现阶段的一些配置信息,当然这些配置信息除了约定的,还有你自己配置的,比如 buildToolsVersion ,签名等相关信息。可以看到 buildDir 和整个 project 的是不一样的。

回到主题, 看看如何把我们刚才创建的 sub_flutter 模块集成到项目中。(严格来说并不是集成 sub_flutter 模块,因为他只是一个 flutter 的模块,而在 Android 主项目只能集成子 Android module,那么具体改怎么做呢,下面就来看看其中的奥秘)

按照官方的操作方法,会要求我们添加以下配置到 settings.gradle 中。

// Include the host app project.
include ':app'                                    // assumed existing content
setBinding(new Binding([gradle: this]))                                // new
evaluate(new File(                                                     // new
  settingsDir.parentFile,                                              // new
  'my_flutter/.android/include_flutter.groovy'                         // new
))                                                                     // new

首先看看 这里的 settingsDir 的值。在 settings.gradle 中直接添加

println "settings.dir=" + settingsDir
println "settings.dir.parent=" + settingsDir.parent

sync 之后就会看到输出

settings.dir=/Users/username/Documents/mygithub/MinApp
settings.dir.parent=/Users/username/Documents/mygithub

所以,上面的配置信息,就是说结合 settings 所在目录的父目录和我们配置的目录结合,找到一个名为 include_flutter.groovy 的文件,然后去执行他。

前面说了,创建子 module 的时候,可以是在项目根目录,也可以是在其他位置,如果是在其他位置,这里的 my_flutter 可以替换为你创建目录的绝对路劲。

这里是在根目录直接创建的,那么以上的配置就可以简化为

setBinding(new Binding([gradle: this]))
evaluate(new File(settingsDir, 'sub_flutter/.android/include_flutter.groovy'))
include ':sub_flutter'
#### 关于 include_flutter.groovy

上面说了,settings.gradle 的配置,其实就是去执行 include_flutter.groovy 这个文件,可以简单看一下这个文件

def scriptFile = getClass().protectionDomain.codeSource.location.toURI()
def flutterProjectRoot = new File(scriptFile).parentFile.parentFile

gradle.include ":flutter"
gradle.project(":flutter").projectDir = new File(flutterProjectRoot, ".android/Flutter")

def localPropertiesFile = new File(flutterProjectRoot, ".android/local.properties")
def properties = new Properties()

assert localPropertiesFile.exists(), ":exclamation:️The Flutter module doesn't have a `$localPropertiesFile` file." +
                                     "\nYou must run `flutter pub get` in `$flutterProjectRoot`."
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }

def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
gradle.apply from: "$flutterSdkPath/packages/flutter_tools/gradle/module_plugin_loader.gradle"

.android 其实就是一个 Android 项目,他包含一个 Flutter 文件夹,这 Flutter 是一个 library 类型的 Android module ,这个一点从他的 build.gradle 文件就可以看出。 include_flutter.groovy 所做的事情,就是将当前 library 命名为 flutter 的一个 moudle。然后检查项目中 local.properties 中 sdk 的相关配置,最后去执行 FlutterSDK 的中 gradle 脚本,这里具体的分析就不再展开了。

也就是说,现在有一个名为 flutter 的 Android Library Module 。这个 module 包含 flutter 的所有配置。我们如果依赖了这个 module ,那么就相当于是依赖了 Flutter .

依赖 flutter

最后在原生项目的 application-module 的 build.gradle 的 dependencies 闭包中添加

implementation project(':flutter')

至此,原生项目已经有了 Flutter 的依赖,可以使用 Flutter 的 View 了。

至此,现在的原生项目就包含 Flutter SDK 的所有依赖了,UI 相关的内容,改怎么写还是用 dart 在 main.dart 中写,然后我们就可以把这个 dart 渲染出来的内容按照 Activity 、Fragment 或 View 的形式添加到已有的项目中了。

flutter pub get

flutter pub get 或者 pub get 是在做 flutter 的时候在使用第三方 lib 或版本更新的时候经常会使用一个命令,通过这个命令会拉取相关的依赖,其实这个命令还会自动生成 Android 和 iOS 的原生项目。比如在我们创建就的 sub_flutter 模块中,均自动生成了 .android 和 .ios 的原生项目目录。同时这两个目录都是点打头的,那么一般情况下就是隐藏文件,同时通过 .gitignore 文件也可以看到,对于 flutter module 形式来说,这两个文件夹都是被忽略的,毕竟 flutter module 的核心,还是为了方便以 module 的形式集成到原生的项目中,内部的两个原生目录,一方面是为了方便集成,另一方面是便于直接运行执行 hot-reload 的调试。

以上就是Android原生项目集成Flutter解决方案的详细内容,更多关于Android集成Flutter的资料请关注我们其它相关文章!

(0)

相关推荐

  • Flutter深色模式适配的实现

    一.简介 Flutter的深色模式以及跟随系统设置比较简单,我感觉需要注意的是开发过程中尽量使用Theme中的颜色与样式,开发过程中遇到的比较大的坑就是provider的一些问题,可能是因为我用的版本新一些,网上找了很多文章,总会遇到一些问题.本文的深色模式适配是通过修改themeMode来实现的,供诸位有缘人参考. 二.环境介绍 1. Flutter: 2.0.3 2. Dart: 2.12.0 3. provider: 5.0.0 状态管理,用于运行时切换主题 4. shared_prefe

  • 详解Flutter的路由导航

    Flutter 的路由导航 路由管理或导航管理:从一个页面平滑地过渡到另一个页面,我们需要有一个统一的机制来管理页面之间的跳转.在原生的Android 开发,是通过startActivity或startActivityForResult 来完成页面的跳转的,在Flutter 中如何实现呢? 在 Flutter 中,页面之间的跳转是通过 Route 和 Navigator 来管理的: Route 是页面的抽象,主要负责创建对应的界面,接收参数,响应 Navigator 打开和关闭: 而 Navig

  • Flutter实现图片滤镜效果

    本着学习的态度,研究了一下flutter里面的ColorFilter,字面意思翻译颜色过滤器,学习就是要举一反三,拓展思考就把这个功能做了一个简单的图片滤镜效果.(ps:图片有点没控制住,有点长) 效果如下: ColorFilter 介绍 两种使用方式 const ColorFilter.mode(Color color, BlendMode blendMode) const ColorFilter.matrix(List<double> matrix) 实现效果主要通过第一种方式, 首先创建

  • Flutter网络请求库DIO的基本使用

    1. 导入dio包 目前dio库的最新版本是3.0.1,同使用其他三方库一样,Flutter中使用dio库同样需要配置pubspec.yaml文件. dependencies: flutter: sdk: flutter dio: ^3.0.10 2. 导入并创建实例 dio包引入成功之后就可以创建dio实例了,一个实例可以发起多个请求,APP中如果只有一个数据源的情况下就可以考虑将dio实例创建成单例模式,这样可以节省系统资源,减少不必要的开销. //htpp.dart import 'pac

  • 详解Flutter 调用 Android Native 的方法

    Flutter 调用 Android Native 的方法,是通过MethodChannel的方式来实现的: 在Android端: 创建一个Class,实现FlutterPlugin和MethodCallHandler接口 重写onAttachedToEngine(),onDetachedFromEngine(),onMethodCall() onAttachedToEngine()中,根据自定义的CHANNEL_NAME创建MethodChannel, onDetachedFromEngine

  • 浅谈Flutter解析JSON三种方式

    Dart实体类格式 class CategoryMo { String name; int count; CategoryMo({this.name, this.count}); //将map转成mo CategoryMo.fromJson(Map<String, dynamic> json) { name = json['name']; count = json['count']; } //将mo转成map,可缺省 Map<String, dynamic> toJson() {

  • 新版Flutter集成到已有Android项目的实现

    FlutterSDK升级后,我们发现不能按照原来的方式集成到已有Android项目中了,因为没有了Flutter这个类,通过阅读源码我找到了新的使用方式. 一.创建Flutter Module 在已有Android工程中集成flutter,可以使用AndroidStudio的new Flutter Module实现,方便快捷. 找到FlutterModule,一连串的next操作即可 创建完成后我们的项目中会多一个叫做flutter的module 并且在项目的setting.gradle文件中会

  • 详解Flutter点击空白隐藏键盘的全局做法

    开发原生页面的时候,在处理键盘事件上,通常的需求是,点击输入框外屏幕,要隐藏键盘,同样的,这样的需求也需要在 Flutter 上实现, Android 上的实现方式是在基类 Activity 里实现事件分发,判断触摸位置是否在输入框内. /** * 获取点击事件 */ @CallSuper @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.MotionEv

  • 详解Flutter混排瀑布流解决方案

    背景 流式布局,这是一种当前无论是前端,还是Native都比较流行的一种页面布局.特别是对于商品这样的Feeds流,无论是淘宝,京东,美团,还是闲鱼.都基本上以多列瀑布流进行呈现,容器列数固定,然后每个卡片高度不一,形成参差不齐的多栏布局. 对于Native来说,无论是iOS还是Android,CollectionView和RecyclerView都能满足我们的绝大部分场景了.不过目前闲鱼很多业务场景都是在Flutter上进行实现的,当时Flutter官方只提供了ListView和GridVie

  • Android原生项目集成Flutter解决方案

    了解一下如何在 Android 原生项目中集成 Flutter 生成配置 在原生项目根目录执行命令 flutter create -t module --org {package_name} {module_name} // 此处 module_name 的命令遵循 Android 子 module 的命名即可.不能有中划线. // 比如, flutter create -t module --org com.engineer.mini.flutter flutter_sub // 此处 mod

  • Android原生项目集成React Native的方法

    开发环境准备 首先按照开发环境搭建教程来安装React Native在安卓平台上所需的一切依赖软件(比如npm). 在应用中添加JS代码 在项目的根目录中运行: $ npm init $ npm install --save react react-native $ curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig npm init创建了一个空的node模块

  • Android 集成Flutter

    目录 Android 集成Flutter 1, Hello Flutter 2, 引入 Flutter 模块 3,使用Flutter 3.1 添加依赖 3.2 运行Flutter页面 3.2.1 添加Flutter页面 4,Flutter APK 解析 5,踩过的坑 Android 集成Flutter Flutter 作为 Google 开源的新一代跨平台.高性能 UI 框架,旨在帮助开发者高效地构建出跨平台的.UI 与交互体验一致的精美应用,推出后一直倍受开发者的青睐. 当需要开发一个全新的应

  • Android集成Flutter

    目录 Android 集成Flutter 1, Hello Flutter 2, 引入 Flutter 模块 3,使用Flutter 3.1 添加依赖 3.2 运行Flutter页面 4,Flutter APK 解析 5,踩过的坑 Android 集成Flutter Flutter 作为 Google 开源的新一代跨平台.高性能 UI 框架,旨在帮助开发者高效地构建出跨平台的.UI 与交互体验一致的精美应用,推出后一直倍受开发者的青睐. 当需要开发一个全新的应用时,我们可以很方便地从零开始,完全

  • Android插件化-RePlugin项目集成与使用详解

    前言:前一段时间新开源了一种全面插件化的方案-- RePlugin,之前一种都在关注 DroidPlugin 并且很早也在项目中试用了,但最终没有投入到真正的生产环节,一方面是项目中没有特别需要插件化的需求,另一方面也考虑到 DroidPlugin 不是特别稳定,Android系统每更新一次 DroidPlugin 可能就会出现一些 Bug,毕竟 Hook 了 Android 原生的太多东西,系统一旦更新引发 Bug 是在所难免的.当然,这些并不能否认 DroidPlugin 的优秀,它的原理和

  • Flutter中嵌入Android 原生TextView实例教程

    前言 本篇文章 中写到的是 flutter 调用了Android 原生的 TextView 案例 添加原生组件的流程基本上可以描述为: 1 android 端实现原生组件PlatformView提供原生view 2 android 端创建PlatformViewFactory用于生成PlatformView 3 android 端创建FlutterPlugin用于注册原生组件 4 flutter 平台嵌入 原生view 1 创建原生组件 创建在fLutter工程时会生成几个文件夹,lib是放fl

  • Eclipse新建Android项目报错解决方案详细汇总

    本文记录刚接触Android开发搭建环境后新建工程各种可能的报错,并亲身经历漫长的解决过程(╥╯^╰╥),寻找各种偏方,避免大家采坑,希望能帮助到大家. 出错一:The import android.support cannot be resolved类型解决 如图,如果报The import android.support cannot be resolved或者android.support.v7.app.ActionBarActivity类似的错误. 解决方案一 :缺少相关依赖包,这里提供

  • Flutter使用Android原生播放器详解

    接上篇:播放器-IOS(Swift)篇 安卓端原生播放器的接入思路与ios基本一致,所以本篇就不废话了,直接上代码: 创建插件VideoViewPlugin实现FlutterPlugin: package io.flutter.plugins.videoplayer; import android.util.Log; import androidx.annotation.NonNull; import io.flutter.embedding.engine.plugins.FlutterPlug

  • Android原生嵌入React Native详解

    1.首先集成的项目目录 我使用的是直接按照react-native init Project 的格式来导入的,也就是说,我的Android项目目录是跟node_modules是在一个目录下的. 我们init完项目之后,项目初始化完成了,这时候我们可以用命令react-native run-android直接运行项目,至于怎么调试,之前已经说过. 说一下我们怎么开发和运行分开吧,我们开发一般会选择webstrom,开发后我们会Android和ios的编译分开. 启动npm 下面说一下android

  • 解决Android原生定位的坑

    Android原生定位的代码网上已经很多了,就不贴出来. 简单了解下: GPS_PROVIDER:通过手机内置的GPS芯片,利用卫星获取定位信息.位置监听.卫星状态监听很耗电且室内定位很不准确. NETWORK_PROVIDER:网络定位通过基站和WiFi节点,利用节点id在定位数据服务器查询位置信息.但是国内网络不允许,且有消息称Google已不提供该服务.so网上出现的此种方式获取定位信息不可用,也就是说NETWORK_PROVIDER在国内不可用. PASSIVE_PROVIDER:被动定

随机推荐