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

相关推荐
WordPress学习笔记7 分钟前
wordpress根据页面别名获取该页面的链接
android·wordpress
2501_9160074724 分钟前
iOS 崩溃日志的分析方法,将崩溃日志与运行过程结合分析
android·ios·小程序·https·uni-app·iphone·webview
音浪豆豆_Rachel38 分钟前
Flutter鸿蒙化之深入解析Pigeon可空返回与参数设计:nullable_returns.dart全解
flutter·harmonyos
浅箬1 小时前
Taro3的H5项目在Android、IOS 中因为兼容性问题导致的白屏问题
android·团队开发·taro
技术摆渡人1 小时前
Android 全栈架构终极指南:从 Linux 内核、Binder 驱动到 Framework 源码实战
android·linux·架构
音浪豆豆_Rachel1 小时前
Flutter鸿蒙跨平台测试策略解析:从基础Widget测试到平台集成验证
flutter·harmonyos
音浪豆豆_Rachel1 小时前
Flutter鸿蒙跨平台通信协议解析:Pigeon生成的Dart端桥接艺术
flutter·华为·harmonyos
00后程序员张1 小时前
苹果应用商店上架App流程,签名证书、IPA 校验、上传
android·ios·小程序·https·uni-app·iphone·webview
2501_916007471 小时前
iOS 上架需要哪些准备,围绕证书、描述文件和上传方式等关键环节展开分析
android·ios·小程序·https·uni-app·iphone·webview
QING6181 小时前
Kotlin Flow 的 emit 和 tryEmit 有什么区别 ?
android·kotlin·android jetpack