当前位置: 首页 > news >正文

Flutter 与 Android NDK 集成实战:实现高性能原生功能

Flutter 与 NDK 集成实现

Flutter 可以通过 Platform Channels 与原生代码(包括使用 NDK 编写的 C/C++ 代码)进行交互。以下是实现 Flutter 与 NDK 集成的步骤:

基本步骤

1. 创建 Flutter 项目

flutter create flutter_ndk_example
cd flutter_ndk_example

2. 添加 Android NDK 支持

android/app/build.gradle 中添加 NDK 配置:

android {// ...defaultConfig {// ...externalNativeBuild {cmake {cppFlags "-std=c++17"}}ndk {abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'}}externalNativeBuild {cmake {path "CMakeLists.txt"}}
}

3. 创建 CMakeLists.txt 文件

android/app 目录下创建 CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1)add_library(native-libSHAREDsrc/main/cpp/native-lib.cpp
)find_library(log-liblog
)target_link_libraries(native-lib${log-lib}
)

4. 创建 C++ 源文件

android/app/src/main/cpp 目录下创建 native-lib.cpp

#include <jni.h>
#include <string>extern "C" JNIEXPORT jstring JNICALL
Java_com_example_flutterndkexample_MainActivity_stringFromJNI(JNIEnv* env,jobject /* this */) {std::string hello = "Hello from C++";return env->NewStringUTF(hello.c_str());
}

5. 创建 Method Channel 接口

lib/main.dart 中:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';void main() {runApp(MyApp());
}class MyApp extends StatelessWidget {static const platform = MethodChannel('com.example.flutterndkexample/channel');Future<String> _getNativeString() async {try {return await platform.invokeMethod('getNativeString');} on PlatformException catch (e) {return "Failed to get string: '${e.message}'.";}}Widget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: Text('Flutter NDK Example')),body: Center(child: FutureBuilder<String>(future: _getNativeString(),builder: (BuildContext context, AsyncSnapshot<String> snapshot) {if (snapshot.hasData) {return Text(snapshot.data!);} else if (snapshot.hasError) {return Text("Error: ${snapshot.error}");}return CircularProgressIndicator();},),),),);}
}

6. 实现 Android 端的 Method Channel

android/app/src/main/kotlin/.../MainActivity.kt 中:

package com.example.flutterndkexampleimport io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannelclass MainActivity: FlutterActivity() {private val CHANNEL = "com.example.flutterndkexample/channel"override fun configureFlutterEngine(flutterEngine: FlutterEngine) {super.configureFlutterEngine(flutterEngine)MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {call, result ->if (call.method == "getNativeString") {result.success(stringFromJNI())} else {result.notImplemented()}}}external fun stringFromJNI(): Stringcompanion object {init {System.loadLibrary("native-lib")}}
}

更复杂的 NDK 功能示例

1. 添加数学计算函数

native-lib.cpp 中添加:

extern "C" JNIEXPORT jint JNICALL
Java_com_example_flutterndkexample_MainActivity_addNumbers(JNIEnv* env,jobject /* this */,jint a,jint b) {return a + b;
}

2. 更新 Kotlin 代码

external fun addNumbers(a: Int, b: Int): Int// 在 MethodCallHandler 中添加
if (call.method == "addNumbers") {val a = call.argument<Int>("a") ?: 0val b = call.argument<Int>("b") ?: 0result.success(addNumbers(a, b))
}

3. 更新 Dart 代码

Future<int> _addNumbers(int a, int b) async {try {return await platform.invokeMethod('addNumbers', {'a': a, 'b': b});} on PlatformException catch (e) {print("Failed to add numbers: '${e.message}'.");return 0;}
}

iOS 平台的 NDK 实现(使用 Objective-C/Swift 调用 C++)

对于 iOS,Flutter 可以直接与 Objective-C/Swift 交互,后者可以调用 C++ 代码:

  1. ios/Runner 目录下创建 C++ 文件
  2. 创建对应的头文件
  3. AppDelegate.swift 中实现 Method Channel

最佳实践

  1. 尽量减少平台通道的调用次数(批量处理数据)
  2. 对于性能敏感的操作使用 NDK
  3. 错误处理要完善
  4. 考虑不同 Android ABI 的兼容性
  5. 对于复杂的 C++ 代码,考虑使用 FFI(Dart 2.12+ 支持)

通过以上步骤,你可以成功地将 Flutter 应用与 NDK 编写的原生代码集成,实现高性能的计算或访问特定的原生功能。

http://www.dtcms.com/a/323774.html

相关文章:

  • 结构化记忆、知识图谱与动态遗忘机制在医疗AI中的应用探析(上)
  • 随机向量正交投影定理(Orthogonal Projection Theorem, OPT)_学习笔记
  • LLaMA-Adapter Efficient Fine-tuning of Language Models with Zero-init Attention
  • C++高频知识点(二十)
  • 数据库删除术:逻辑删除 vs 物理删除,选错毁所有
  • Flink提交流程全解析:从模式到实践
  • Java高并发场景下的缓存穿透问题定位与解决方案
  • 计算机网络:子网的起始地址就是默认的网络地址吗?
  • Flink SQL 中的水印机制
  • 26.Scikit-learn实战:机器学习的工具箱
  • Unity笔记(四)——Camera、碰撞检测函数、刚体加力、音频
  • CSDN 五周年创作纪念日(PS:vnjohn)
  • C++设计模式单例模式(饿汉、懒汉模式)
  • 基于 RabbitMQ 死信队列+TTL 实现延迟消息+延迟插件基本使用
  • 检索召回率优化探究五(BGE-M3 混合检索):基于LangChain0.3 集成Milvu2.5 向量数据库构建的智能问答系统
  • 【Matplotlib】中文显示问题
  • Vue3 组件化开发
  • 第4章 程序段的反复执行1 for语句P115练习题(题及答案)
  • 堆----3.数据流的中位数
  • 第4章 程序段的反复执行2 while语句P128练习题(题及答案)
  • 2025AI颠覆认知!解锁智能新纪元
  • Kubernetes 无法识别你定义的 `CronJob` 资源*逐步解决方案
  • AI推理的“灵魂五问”:直面2025算力鸿沟与中国的破局之路
  • PowerShell 入门系列(五):运行命令与命令剖析详解
  • 面试题-----Spring Cloud
  • n8n 入门指南:更适合跨境出海搞钱的AI智能体
  • 7天精通Coze智能体实操手册(Day 1)
  • 健全性测试(Sanity Testing):你软件的快速“体检” ✅(省时避坑,确保核心!)
  • 【三个数绝对值排序】2022-10-10
  • 心灵笔记:思考三部曲