普通视图

发现新文章,点击刷新页面。
昨天 — 2025年12月14日首页

将flutter打成aar包嵌入到安卓

2025年12月14日 17:44

Flutter Module 打包成 AAR 并集成到 Android 项目

一、创建 Flutter Module

如果你 还没有 Flutter Module

flutter create -t module flutter_module

二、构建 Flutter AAR

执行 AAR 构建命令

flutter build aar

构建产物位置

flutter_module/build/host/outputs/repo/

构建控制台输出

在下面的配置中会用到

  1. Open <host>\app\build.gradle
  2. Ensure you have the repositories configured, otherwise add them:

      String storageUrl = System.env.FLUTTER_STORAGE_BASE_URL ?: "https://storage.googleapis.com"
      repositories {
        maven {
            url 'E:\lumosproject\module\lumos\build\host\outputs\repo'
        }
        maven {
            url "$storageUrl/download.flutter.io"
        }
      }

  3. Make the host app depend on the Flutter module:

    dependencies {
      debugImplementation 'com.example.lumos:flutter_debug:1.0'
      profileImplementation 'com.example.lumos:flutter_profile:1.0'
      releaseImplementation 'com.example.lumos:flutter_release:1.0'
    }


  4. Add the `profile` build type:

    android {
      buildTypes {
        profile {
          initWith debug
        }
      }
    }


三、Android 宿主项目集成 AAR

1. 修改MyApp/app/build.gradle

你目前现有的 Android 项目可能支持 mips 或 x86 之类的架构,然而,Flutter 当前仅支持 为 x86_64armeabi-v7a 和 arm64-v8a 构建预编(AOT)的库。

可以考虑使用 abiFilters 这个 Android Gradle 插件 API 来指定 APK 中支持的架构,从而避免 libflutter.so 无法生成而导致应用运行时崩溃,具体操作如下:

Groovy 版
android {
    defaultConfig {
        ndk {
            // Filter for architectures supported by Flutter
            abiFilters "armeabi-v7a", "arm64-v8a", "x86_64"
        }
    }
}
Kotlin DSL
android {
    defaultConfig {
        ndk {
            // Filter for architectures supported by Flutter
            abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86_64")
        }
    }
}

2. 配置 settings.gradle(.kts)

在国内,需要使用镜像站点代替 storage.googleapis.com。有关镜像的详细信息,参见 在中国网络环境下使用 Flutter 页面。

Groovy 版
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    String storageUrl = System.env.FLUTTER_STORAGE_BASE_URL ?: "https://storage.flutter-io.cn"
    repositories {

        google()
        mavenCentral()
        maven {
            url 'E:/lumosproject/module/lumos/build/host/outputs/repo'
        }
        maven {
            url "$storageUrl/download.flutter.io"
        }
    }
}
Kotlin DSL
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
    repositories {
        google()
        mavenCentral()
        maven("https://storage.googleapis.com/download.flutter.io")
    }
}

3. 添加依赖(app/build.gradle)

这里添加的依赖都是build aar 控制台输出的内容

groovy版
dependencies {
   debugImplementation 'com.example.untitled:flutter_debug:1.0'
   profileImplementation 'com.example.untitled:flutter_profile:1.0'
   releaseImplementation 'com.example.untitled:flutter_release:1.0'
}
Kotlin DSL
dependencies {
debugImplementation("com.example.flutter_module:flutter_debug:1.0")    
releaseImplementation("com.example.flutter_module:flutter_release:1.0")   
add("profileImplementation", "com.example.flutter_module:flutter_profile:1.0") 
}

4. 添加profile build type(app/build.gradle)

buildTypes中添加

groovy版
profile {
    initWith debug
}
Kotlin DSL
create("profile") { initWith(getByName("debug")) }

四、Android 启动 Flutter 页面

1.在 AndroidManifest.xml 中添加 FlutterActivity

Flutter 提供了 FlutterActivity,用于在 Android 应用内部展示一个 Flutter 的交互界面。和其他的 Activity 一样,FlutterActivity 必须在项目的 AndroidManifest.xml 文件中注册。将下边的 XML 代码添加到你的 AndroidManifest.xml 文件中的 application 标签内

<activity
  android:name="io.flutter.embedding.android.FlutterActivity"
  android:theme="@style/LaunchTheme"   android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
  android:hardwareAccelerated="true"
  android:windowSoftInputMode="adjustResize"
  />

2. 加载 FlutterActivity

确保使用如下的语句导入:

import io.flutter.embedding.android.FlutterActivity;
MyButton(onClick = {
    startActivity(
        FlutterActivity.createDefaultIntent(this)
    )
})

@Composable
fun MyButton(onClick: () -> Unit) {
    Button(onClick = onClick) {
        Text("Launch Flutter!")
    }
}

上述的例子假定了你的 Dart 代码入口是调用 main(),并且你的 Flutter 初始路由是 '/'。 Dart 代码入口不能通过 Intent 改变,但是初始路由可以通过 Intent 来修改。下面的例子讲解了如何打开一个自定义 Flutter 初始路由的 FlutterActivity

MyButton(onClick = {
  startActivity(
    FlutterActivity
      .withNewEngine()
      .initialRoute("/my_route")
      .build(this)
  )
})

@Composable
fun MyButton(onClick: () -> Unit) {
    Button(onClick = onClick) {
        Text("Launch Flutter!")
    }
}

3. 使用缓存 Engine(推荐)

每一个 FlutterActivity 默认会创建它自己的 FlutterEngine。每一个 FlutterEngine 会有一个明显的预热时间。这意味着加载一个标准的 FlutterActivity 时,在你的 Flutter 交互页面可见之前会有一个短暂的延迟。想要最小化这个延迟时间,你可以在抵达你的 FlutterActivity 之前,初始化一个 FlutterEngine,然后使用这个已经预热好的 FlutterEngine

class MyApplication : Application() {
  lateinit var flutterEngine : FlutterEngine

  override fun onCreate() {
    super.onCreate()

    // Instantiate a FlutterEngine.
    flutterEngine = FlutterEngine(this)

    // Start executing Dart code to pre-warm the FlutterEngine.
    flutterEngine.dartExecutor.executeDartEntrypoint(
      DartExecutor.DartEntrypoint.createDefault()
    )

    // Cache the FlutterEngine to be used by FlutterActivity.
    FlutterEngineCache
      .getInstance()
      .put("my_engine_id", flutterEngine)
  }
}
使用
myButton.setOnClickListener {
  startActivity(
    FlutterActivity
      .withCachedEngine("my_engine_id")
      .build(this)
  )
}
为缓存的 FlutterEngine 设置初始路由
class MyApplication : Application() {
  lateinit var flutterEngine : FlutterEngine
  override fun onCreate() {
    super.onCreate()
    // Instantiate a FlutterEngine.
    flutterEngine = FlutterEngine(this)
    // Configure an initial route.
    flutterEngine.navigationChannel.setInitialRoute("your/route/here");
    // Start executing Dart code to pre-warm the FlutterEngine.
    flutterEngine.dartExecutor.executeDartEntrypoint(
      DartExecutor.DartEntrypoint.createDefault()
    )
    // Cache the FlutterEngine to be used by FlutterActivity or FlutterFragment.
    FlutterEngineCache
      .getInstance()
      .put("my_engine_id", flutterEngine)
  }
}
通过设置路由的方式可以配置缓存引擎在执行 Dart 入口点之前使用自定义初始路由

五、Flutter 与 Android 通信

MethodChannel方式

Flutter

添加到合适的地方

static const methodChannel = MethodChannel('com.bluetoothCharacteristic');
methodChannel.setMethodCallHandler(_handleMethod);
Future<dynamic> _handleMethod(MethodCall call) async {
  switch (call.method) {
    case 'bluetoothCharacteristic':
      // 设置设备写入特征
      _device.setWriteCharacteristic(
        call.arguments as BluetoothCharacteristic,
      );
      break;
    default:
      throw PlatformException(code: 'Unrecognized Method');
  }
}

Android


private lateinit var methodChannel: MethodChannel
methodChannel = MethodChannel(
    flutterEngine.dartExecutor.binaryMessenger,
    "com.bluetoothCharacteristic"
)
使用
Button(
    onClick = {
        val intent = FlutterActivity
            .withCachedEngine("my_engine_id")
            .build(activity)
        methodChannel.invokeMethod(
            "bluetoothCharacteristic",
            "00002a37-0000-1000-8000-00805f9b34fb"
        );
        activity.startActivity(intent)
    },
    modifier = Modifier.padding(16.dp)
) {
    Text("跳转到flutter页面")
}

MethodChannel 中的 com.bluetoothCharacteristic 和methodChannel.invokeMethod中的bluetoothCharacterstic必须和 Flutter 中保持一致,否则接收不到数据。

EventChannel方式

EventChannel的使用方式大致和MethodChannel相同,我这里就把主要代码复制下来了。

class MainActivity : ComponentActivity() {
    private lateinit var flutterEngine: FlutterEngine
    private lateinit var eventChannel: EventChannel
    private var eventDataSink: EventChannel.EventSink? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        // 创建 FlutterEngine
        flutterEngine = FlutterEngine(this)
        //设置初始路由
        flutterEngine.navigationChannel.setInitialRoute("/settings")
        // 启动 Flutter 引擎
        flutterEngine.dartExecutor.executeDartEntrypoint(
            DartExecutor.DartEntrypoint.createDefault()
        )
        // 设置 EventChannel 用于实时数据传输
        eventChannel = EventChannel(flutterEngine.dartExecutor, "com.example.flutter_aar_demo/event_channel")
        eventChannel.setStreamHandler(object : EventChannel.StreamHandler {
            override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
                eventDataSink = events
                startRealTimeDataTransmission()
            }
            override fun onCancel(arguments: Any?) {
                eventDataSink = null
            }
        })
        // 缓存 FlutterEngine
        FlutterEngineCache.getInstance().put("my_engine_id", flutterEngine)
    }

我这里的安卓使用的是groovy的创建方式Kotlin DSL的方式是我直接从官网复制的代码可能有不正确的地方具体请查看将 Flutter module 集成到 Android 项目

❌
❌