从 Flutter 应用程序启动 Jetpack Compose 活动
原生 Android 活动允许您启动完全由 Android 平台运行和管理的全屏 UI。您只需在这些视图中编写 Kotlin 代码(尽管它们可能会传递消息到您的 Dart 代码并接收来自 Dart 代码的消息),并且您可以访问所有原生 Android 功能。
添加此功能需要对您的 Flutter 应用程序及其内部生成的 Android 应用程序进行一些更改。在 Flutter 端,您需要创建一个新的平台方法通道并调用其 invokeMethod
方法。在 Android 端,您需要注册一个匹配的原生 MethodChannel
来接收来自 Dart 的信号,然后启动一个新的活动。请记住,所有 Flutter 应用程序(在 Android 上运行时)都存在于一个完全由 Flutter 应用程序消耗的 Android 活动中。因此,正如您将在代码示例中看到的,原生 MethodChannel
回调的工作是启动第二个活动。
并非所有 Android 活动都使用 Jetpack Compose,但本教程假设您希望使用 Compose。
Dart 端
#在 Dart 端,创建一个方法通道并在特定的用户交互(例如点击按钮)中调用它。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
// SECTION 1: START COPYING HERE
const platformMethodChannel = MethodChannel(
// Note: You can change this string value, but it must match
// the `CHANNEL` attribute in the next step.
'com.example.flutter_android_activity',
);
// SECTION 1: END COPYING HERE
void main() {
runApp(const MainApp());
}
class MainApp extends StatelessWidget {
const MainApp({super.key});
// SECTION 2: START COPYING HERE
void _launchAndroidActivity() {
platformMethodChannel.invokeMethod(
// Note: You can change this value, but it must match
// the `call.method` value in the next section.
'launchActivity',
// Note: You can pass any primitive data types you like.
// To pass complex types, use package:pigeon to generate
// matching Dart and Kotlin classes that share serialization logic.
{'message': 'Hello from Flutter'},
);
}
// SECTION 2: END COPYING HERE
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: const Center(
child: Text('Hello World!'),
),
floatingActionButton: FloatingActionButton(
// SECTION 3: Call `_launchAndroidActivity` somewhere.
onPressed: _launchAndroidActivity,
// SECTION 3: End
tooltip: 'Launch Android activity',
child: const Icon(Icons.launch),
),
),
);
}
}
Dart 和 Kotlin 代码之间必须匹配 3 个重要的值
- 通道名称(在此示例中,值为
"com.example.flutter_android_activity"
)。 - 方法名称(在此示例中,值为
"launchActivity"
)。 - Dart 传递的数据结构和 Kotlin 期望接收的数据结构。在本例中,数据是一个具有单个
"message"
键的映射。
Android 端
#您必须在生成的 Android 应用程序中的 4 个文件中进行更改,以使其准备好启动新的 Compose 活动。
第一个需要修改的文件是 android/app/build.gradle
。
将以下内容添加到现有的
android
块中android/app/build.gradlegroovyandroid { // Begin adding here buildFeatures { compose true } composeOptions { // https://developer.android.com.cn/jetpack/androidx/releases/compose-kotlin kotlinCompilerExtensionVersion = "1.4.8" } // End adding here }
访问代码段中的 developer.android.com 链接并根据需要调整
kotlinCompilerExtensionVersion
。只有在您在flutter run
期间遇到错误并且这些错误告诉您机器上安装了哪些版本时,您才需要这样做。接下来,在文件的底部,根级别添加以下块
android/app/build.gradlegroovydependencies { implementation("androidx.core:core-ktx:1.10.1") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1") implementation("androidx.activity:activity-compose") implementation(platform("androidx.compose:compose-bom:2024.06.00")) implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.compose.material:material") implementation("androidx.compose.material3:material3") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") androidTestImplementation(platform("androidx.compose:compose-bom:2023.08.00")) androidTestImplementation("androidx.compose.ui:ui-test-junit4") debugImplementation("androidx.compose.ui:ui-tooling") debugImplementation("androidx.compose.ui:ui-test-manifest") }
第二个需要修改的文件是
android/build.gradle
。在文件的顶部添加以下 buildscript 块
android/build.gradlegroovybuildscript { dependencies { // Replace with the latest version. classpath 'com.android.tools.build:gradle:8.1.1' } repositories { google() mavenCentral() } }
第三个需要修改的文件是
android/app/src/main/AndroidManifest.xml
。在根应用程序块中,添加以下
<activity>
声明android/app/src/main/AndroidManifest.xmlxml<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application android:label="flutter_android_activity" android:name="${applicationName}" android:icon="@mipmap/ic_launcher"> // START COPYING HERE <activity android:name=".SecondActivity" android:exported="true" android:theme="@style/LaunchTheme"></activity> // END COPYING HERE <activity android:name=".MainActivity" …></activity> … </manifest>
第四个也是最后一个需要修改的代码是
android/app/src/main/kotlin/com/example/flutter_android_activity/MainActivity.kt
。在这里,您将为所需的 Android 功能编写 Kotlin 代码。在文件顶部添加必要的导入
MainActivity.ktkotlinpackage com.example.flutter_android_activity import android.content.Intent import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.Button import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.ui.Modifier import androidx.core.app.ActivityCompat import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.plugins.GeneratedPluginRegistrant
通过添加
CHANNEL
字段和configureFlutterEngine
方法来修改生成的MainActivity
类MainActivity.ktkotlinclass MainActivity: FlutterActivity() { // This value must match the `MethodChannel` name in your Dart code. private val CHANNEL = "com.example.flutter_android_activity" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { GeneratedPluginRegistrant.registerWith(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call: MethodCall, result: MethodChannel.Result -> when (call.method) { // Note: This must match the first parameter passed to // `platformMethodChannel.invokeMethod` in your Dart code. "launchActivity" -> { try { // Takes an object, in this case a String. val message = call.arguments val intent = Intent(this@MainActivity, SecondActivity::class.java) intent.putExtra("message", message.toString()) startActivity(intent) } catch (e: Exception){} result.success(true) } else -> {} } } } }
在文件的底部添加第二个
Activity
,您在之前对AndroidManifest.xml
的更改中引用了它MainActivity.ktkotlinclass SecondActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { Column { Text(text = "Second Activity") // Note: This must match the shape of the data passed from your Dart code. Text("" + getIntent()?.getExtras()?.getString("message")) Button(onClick = { finish() }) { Text("Exit") } } } } } }
这些步骤展示了如何从 Flutter 应用程序启动原生 Android 活动,这有时可能是连接到特定 Android 功能的简单方法。
除非另有说明,否则本网站上的文档反映了 Flutter 的最新稳定版本。页面上次更新于 2024-10-14。 查看源代码 或 报告问题.