前言
在 flutter
中可以通过 method channel
的方式来调用 opencv api
,那么就会有较长的调用链flutter -> java jni -> c++
。
假如我们要传递一个参数,这个参数将会在 java、C++
堆各拷贝一次,这样容易造成内存抖动,且效率较低。
本文将讲述如何在 flutter android
项目中接入 opencv sdk
,通过 FFI 调用 opencv c++ api
来实现高斯模糊效果。
版本提示: Dart 2.12.0 版本之后 (同时包含在 Flutter 2.0 和以后的版本里), FFI 已经作为稳定版本发布。
一、FFI 介绍
Flutter
移动版可以使用 dart:ffi
库来调用本地的 C API
。 FFI
代表 外部功能接口。类似功能的其他术语包括本地接口和语言绑定。
您必须首先确保本地代码已加载,并且其符号对 Dart
可见,然后才能在库或程序使用 FFI
库绑定本地代码。
二、环境搭建
2.1 下载 SDK
解压后包含以下内容:
2.2 导入文件
创建一个 flutter
插件名为opencv_plugin
,在 main
目录下新建 cpp
目录。
-
创建
native-lib.cpp
文件在cpp
目录下。 -
复制
OpenCv
的include
文件到cpp
目录下。indlue
文件在sdk -> native -> jni -> include
-
新建
jniLibs
文件,并复制libs
到jniLibs
indlue
文件在sdk -> native -> libs
复制完成后的目录:
2.3 配置 CmakeLists.txt
新建 CmakeLists.txt
到 Android
目录下,内容如下:
cmake_minimum_required(VERSION 3.4.1)
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include)
add_library(libopencv_java4 SHARED IMPORTED)
set_target_properties(libopencv_java4 PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/libs/${ANDROID_ABI}/libopencv_java4.so)
add_library( # Sets the name of the library.
native-lib # Sets the library as a shared library.
SHARED # Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
find_library( # Sets the name of the path variable.
log-lib # Specifies the name of the NDK library that
# you want CMake to locate.
log )
target_link_libraries( # Specifies the target library.
native-lib libopencv_java4 # Links the target library to the log library
android
# included in the NDK.
${log-lib} )
CmakeLists.txt
文件位置:
注:
include_directories
与set_target_properties
一定要使用${CMAKE_SOURCE_DIR}
配置绝对路径,不然编译过程中会报找不到.so
的问题。
2.4 配置 Gradle 编译
将 opencv_plugin
下的 Gradle
文件添加一下内容
- 引入
c++_shared.so
库 - 配置
CmakeLists.txt
路径
android {
compileSdkVersion 30
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
minSdkVersion 16
### 引入 c++_shared.so 库
externalNativeBuild {
cmake {
cppFlags ""
arguments "-DANDROID_STL=c++_shared"
}
}
}
### 配置 CmakeLists.txt 路径
externalNativeBuild {
cmake {
path file('CMakeLists.txt')
}
}
}
2.5 检查是否配置成功
在 flutter
调用 DynamicLibrary.open("libnative-lib.so")
观察日志是否报错。
final DynamicLibrary _opencvLib =
Platform.isAndroid ? DynamicLibrary.open("libnative-lib.so") : DynamicLibrary.process();