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++ 代码:
- 在
ios/Runner
目录下创建 C++ 文件 - 创建对应的头文件
- 在
AppDelegate.swift
中实现 Method Channel
最佳实践
- 尽量减少平台通道的调用次数(批量处理数据)
- 对于性能敏感的操作使用 NDK
- 错误处理要完善
- 考虑不同 Android ABI 的兼容性
- 对于复杂的 C++ 代码,考虑使用 FFI(Dart 2.12+ 支持)
通过以上步骤,你可以成功地将 Flutter 应用与 NDK 编写的原生代码集成,实现高性能的计算或访问特定的原生功能。