從你的 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"
鍵的 Map。
在 Android 端
#您必須對產生的 Android 應用程式中的 4 個檔案進行變更,才能準備好啟動新的 Compose 活動。
第一個需要修改的檔案是 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
。在根應用程式區塊中,新增以下
<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
的變更中引用了該活動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。 檢視原始碼 或 回報問題。