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

Flutter 与 NDK 集成实现

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

基本步骤

1. 创建 Flutter 项目

bash 复制代码
flutter create flutter_ndk_example
cd flutter_ndk_example

2. 添加 Android NDK 支持

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

gradle 复制代码
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 复制代码
cmake_minimum_required(VERSION 3.4.1)

add_library(
        native-lib
        SHARED
        src/main/cpp/native-lib.cpp
)

find_library(
        log-lib
        log
)

target_link_libraries(
        native-lib
        ${log-lib}
)

4. 创建 C++ 源文件

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

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 中:

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}'.";
    }
  }

  @override
  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 中:

kotlin 复制代码
package com.example.flutterndkexample

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class 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(): String

    companion object {
        init {
            System.loadLibrary("native-lib")
        }
    }
}

更复杂的 NDK 功能示例

1. 添加数学计算函数

native-lib.cpp 中添加:

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 代码

kotlin 复制代码
external fun addNumbers(a: Int, b: Int): Int

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

3. 更新 Dart 代码

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 编写的原生代码集成,实现高性能的计算或访问特定的原生功能。

相关推荐
氦客1 小时前
Android Compose : 传统View在Compose组件中的等价物
android·compose·jetpack·对比·传统view·等价物·compose组件
神话20092 小时前
Rust 初体验与快速上手指南
android·rust
CheungChunChiu2 小时前
Linux 内核动态打印机制详解
android·linux·服务器·前端·ubuntu
kirk_wang3 小时前
Flutter艺术探索-Flutter调试工具:DevTools使用指南
flutter·移动开发·flutter教程·移动开发教程
aidou13144 小时前
Android中设置Dialog和自定义布局相同高度
android·dialog·弹窗高度·getwindow
氦客4 小时前
UI编程的发展史 : 结合命令式UI和声明式UI
android·compose·声明式ui·ui编程·命令式ui·ui编程发展史·标记语言
小雨下雨的雨5 小时前
Flutter 框架跨平台鸿蒙开发 —— SingleChildScrollView 控件之长内容滚动艺术
flutter·ui·华为·harmonyos·鸿蒙
牛马1115 小时前
Flutter 多语言
前端·flutter
aidou13146 小时前
Android中RecyclerView实现多级列表
android·recyclerview·多级列表·layoutmanager
青风行6 小时前
Android从入门到进阶
android