從 Flutter 應用啟動 Jetpack Compose Activity
原生 Android Activity 允許您啟動完全由 Android 平臺執行的全屏 UI。您只需在這些檢視中編寫 Kotlin 程式碼(儘管它們可能會與您的 Dart 程式碼傳遞訊息和接收訊息),並且您將能夠訪問所有原生的 Android 功能。
要新增此功能,需要對您的 Flutter 應用及其內部生成的 Android 應用進行多項更改。在 Flutter 端,您需要建立一個新的平臺方法通道並呼叫其 invokeMethod 方法。在 Android 端,您需要註冊一個匹配的原生 MethodChannel 來接收來自 Dart 的訊號,然後啟動一個新的 Activity。請記住,所有 Flutter 應用(在 Android 上執行時)都存在於一個完全由 Flutter 應用佔用的 Android Activity 中。因此,正如您將在程式碼示例中看到的,原生 MethodChannel 回撥的任務是啟動第二個 Activity。
並非所有 Android Activity 都使用 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 Activity 做好準備。
需要修改的第一個檔案是 android/app/build.gradle。
將以下內容新增到現有的
android塊中android/app/build.gradlegroovyandroid { // Begin adding here buildFeatures { compose true } composeOptions { // https://developer.android.com/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。在根
application塊中,新增以下<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修改生成的
MainActivity類,新增CHANNEL欄位和configureFlutterEngine方法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更改中已引用了該 ActivityMainActivity.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 Activity,這有時是連線到特定 Android 功能的便捷方法。