跳至主要內容

支援新的 Android 外掛程式 API

如果您沒有撰寫或維護 Android Flutter 外掛程式,您可以跳過此頁面。

在 1.12 版本中,Android 平台提供了新的外掛程式 API。舊的 API 基於 PluginRegistry.Registrar,雖然不會立即停用,但我們鼓勵您遷移到基於 FlutterPlugin 的新 API。

相較於舊的 API,新的 API 優勢在於為生命週期相關的組件提供更清晰的存取器。例如,如果 Flutter 沒有附加到任何 Activity,PluginRegistry.Registrar.activity() 可能會回傳 null。

換句話說,當把 Flutter 嵌入到 Android 應用程式中時,使用舊 API 的外掛程式可能會產生未定義的行為。 flutter.dev 團隊提供的大多數 Flutter 外掛程式 都已遷移。(了解如何在 pub.dev 上成為已驗證的發布者!)有關使用新 API 的外掛程式範例,請參閱 battery plus 套件

升級步驟

#

以下說明如何支援新的 API。

  1. 更新主外掛程式類別 (*Plugin.java) 以實作 FlutterPlugin 介面。對於更複雜的外掛程式,您可以將 FlutterPluginMethodCallHandler 分成兩個類別。有關使用最新版本 (v2) 的嵌入來存取應用程式資源的更多詳細資訊,請參閱下一節:基本外掛程式

    此外,請注意外掛程式仍應包含靜態 registerWith() 方法,以保持與未使用 v2 Android 嵌入的應用程式相容。(有關詳細資訊,請參閱升級 1.12 之前的 Android 專案。)最簡單的方法(如果可以的話)是將邏輯從 registerWith() 移至 registerWith()onAttachedToEngine() 都可以呼叫的私有方法。只會呼叫 registerWith()onAttachedToEngine() 其中一個,而不是兩者都呼叫。

    此外,您應該記錄外掛程式中所有未覆寫的公開成員。在「新增至應用程式」的情境中,開發人員可以存取這些類別,因此需要文件說明。

  2. (選用)如果您的外掛程式需要 Activity 參照,也請實作 ActivityAware 介面。

  3. (選用)如果您的外掛程式預期在任何時間點都保留在背景 Service 中,請實作 ServiceAware 介面。

  4. 更新範例應用程式的 MainActivity.java 以使用 v2 嵌入 FlutterActivity。有關詳細資訊,請參閱升級 1.12 之前的 Android 專案。如果您的外掛程式類別先前不存在公開建構函式,您可能需要為它建立一個。例如:

    MainActivity.java
    java
     package io.flutter.plugins.firebasecoreexample;
    
     import io.flutter.embedding.android.FlutterActivity;
     import io.flutter.embedding.engine.FlutterEngine;
     import io.flutter.plugins.firebase.core.FirebaseCorePlugin;
    
     public class MainActivity extends FlutterActivity {
       // You can keep this empty class or remove it. Plugins on the new embedding
       // now automatically registers plugins.
     }
  5. (選用)如果您移除了 MainActivity.java,請更新 <外掛程式名稱>/example/android/app/src/main/AndroidManifest.xml 以使用 io.flutter.embedding.android.FlutterActivity。例如:

    AndroidManifest.xml
    xml
     <activity android:name="io.flutter.embedding.android.FlutterActivity"
            android:theme="@style/LaunchTheme"
    android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
            android:hardwareAccelerated="true"
            android:exported="true"
            android:windowSoftInputMode="adjustResize">
            <meta-data
                android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
                android:value="true" />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
  6. (選用)在與 MainActivity 相同的資料夾中建立一個 EmbeddingV1Activity.java 檔案,以針對範例專案使用 v1 嵌入,以持續測試 v1 嵌入與您外掛程式的相容性。請注意,您必須手動註冊所有外掛程式,而不是使用 GeneratedPluginRegistrant。例如:

    EmbeddingV1Activity.java
    java
    package io.flutter.plugins.batteryexample;
    
    import android.os.Bundle;
    import io.flutter.app.FlutterActivity;
    import io.flutter.plugins.battery.BatteryPlugin;
    
    public class EmbeddingV1Activity extends FlutterActivity {
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        BatteryPlugin.registerWith(registrarFor("io.flutter.plugins.battery.BatteryPlugin"));
      }
    }
  7. <meta-data android:name="flutterEmbedding" android:value="2"/> 新增至 <外掛程式名稱>/example/android/app/src/main/AndroidManifest.xml。這會將範例應用程式設定為使用 v2 嵌入。

  8. (選用)如果您在上一個步驟中建立了一個 EmbeddingV1Activity,請將 EmbeddingV1Activity 新增至 <外掛程式名稱>/example/android/app/src/main/AndroidManifest.xml 檔案中。例如:

    AndroidManifest.xml
    xml
    <activity
        android:name=".EmbeddingV1Activity"
        android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
        android:hardwareAccelerated="true"
        android:exported="true"
        android:windowSoftInputMode="adjustResize">
    </activity>

測試您的外掛程式

#

其餘步驟說明如何測試您的外掛程式,我們鼓勵您進行測試,但並非必要。

  1. 更新 <外掛程式名稱>/example/android/app/build.gradle,以將對 android.support.test 的參照取代為 androidx.test

    build.gradle
    groovy
    defaultConfig {
      ...
      testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
      ...
    }
    build.gradle
    groovy
    dependencies {
    ...
    androidTestImplementation 'androidx.test:runner:1.2.0'
    androidTestImplementation 'androidx.test:rules:1.2.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    ...
    }
  2. <外掛程式名稱>/example/android/app/src/androidTest/java/<外掛程式路徑>/ 中新增 MainActivityEmbeddingV1Activity 的測試檔案。您需要建立這些目錄。例如:

    MainActivityTest.java
    java
    package io.flutter.plugins.firebase.core;
    
    import androidx.test.rule.ActivityTestRule;
    import io.flutter.plugins.firebasecoreexample.MainActivity;
    import org.junit.Rule;
    import org.junit.runner.RunWith;
    
    @RunWith(FlutterRunner.class)
    public class MainActivityTest {
      // Replace `MainActivity` with `io.flutter.embedding.android.FlutterActivity` if you removed `MainActivity`.
      @Rule public ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(MainActivity.class);
    }
    EmbeddingV1ActivityTest.java
    java
    package io.flutter.plugins.firebase.core;
    
    import androidx.test.rule.ActivityTestRule;
    import io.flutter.plugins.firebasecoreexample.EmbeddingV1Activity;
    import org.junit.Rule;
    import org.junit.runner.RunWith;
    
    @RunWith(FlutterRunner.class)
    public class EmbeddingV1ActivityTest {
      @Rule
      public ActivityTestRule<EmbeddingV1Activity> rule =
          new ActivityTestRule<>(EmbeddingV1Activity.class);
    }
  3. integration_testflutter_driver 開發依賴項新增至 <外掛程式名稱>/pubspec.yaml<外掛程式名稱>/example/pubspec.yaml

    pubspec.yaml
    yaml
    integration_test:
      sdk: flutter
    flutter_driver:
      sdk: flutter
  4. 更新 <外掛程式名稱>/pubspec.yaml 中環境的最低 Flutter 版本。所有外掛程式未來都會將最低版本設定為 1.12.13+hotfix.6,這是我們可以保證支援的最低版本。例如:

    pubspec.yaml
    yaml
    environment:
      sdk: ">=2.16.1 <3.0.0"
      flutter: ">=1.17.0"
  5. <外掛程式名稱>/test/<外掛程式名稱>_test.dart 中建立一個簡單的測試。為了測試新增 v2 嵌入支援的 PR,我們嘗試測試外掛程式的一些基本功能。這是一個冒煙測試,以確保外掛程式能正確向新嵌入器註冊。例如:

    dart
    import 'package:flutter_test/flutter_test.dart';
    import 'package:integration_test/integration_test.dart';
    
    void main() {
      IntegrationTestWidgetsFlutterBinding.ensureInitialized();
    
      testWidgets('Can get battery level', (tester) async {
        final Battery battery = Battery();
        final int batteryLevel = await battery.batteryLevel;
        expect(batteryLevel, isNotNull);
      });
    }
  6. 在本地測試執行 integration_test 測試。在終端機中,執行以下操作:

    flutter test integration_test/app_test.dart

基本外掛程式

#

若要開始使用程式碼中的 Flutter Android 外掛程式,請先實作 FlutterPlugin

java
public class MyPlugin implements FlutterPlugin {
  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
    // TODO: your plugin is now attached to a Flutter experience.
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    // TODO: your plugin is no longer attached to a Flutter experience.
  }
}

如上所示,您的外掛程式在任何給定時間點都可能(或可能不會)與給定的 Flutter 體驗相關聯。您應該謹慎地在 onAttachedToEngine() 中初始化外掛程式的行為,然後在 onDetachedFromEngine() 中清理外掛程式的參照。

FlutterPluginBinding 為您的外掛程式提供了一些重要的參照:

binding.getFlutterEngine()
回傳您的外掛程式所附加的 FlutterEngine,可讓您存取 DartExecutorFlutterRenderer 等元件。
binding.getApplicationContext()
回傳正在執行應用程式的 Android 應用程式的 Context

UI/活動外掛程式

#

如果您的外掛程式需要與 UI 互動,例如要求權限或變更 Android UI 裝飾,則您需要執行額外步驟來定義您的外掛程式。您必須實作 ActivityAware 介面。

java
public class MyPlugin implements FlutterPlugin, ActivityAware {
  //...normal plugin behavior is hidden...

  @Override
  public void onAttachedToActivity(ActivityPluginBinding activityPluginBinding) {
    // TODO: your plugin is now attached to an Activity
  }

  @Override
  public void onDetachedFromActivityForConfigChanges() {
    // TODO: the Activity your plugin was attached to was
    // destroyed to change configuration.
    // This call will be followed by onReattachedToActivityForConfigChanges().
  }

  @Override
  public void onReattachedToActivityForConfigChanges(ActivityPluginBinding activityPluginBinding) {
    // TODO: your plugin is now attached to a new Activity
    // after a configuration change.
  }

  @Override
  public void onDetachedFromActivity() {
    // TODO: your plugin is no longer associated with an Activity.
    // Clean up references.
  }
}

若要與 Activity 互動,您的 ActivityAware 外掛程式必須在 4 個階段實作適當的行為。首先,您的外掛程式會附加到 Activity。您可以透過提供的 ActivityPluginBinding 存取該 Activity 及其一些回呼。

由於 Activity 可能會在組態變更期間被銷毀,因此您必須在 onDetachedFromActivityForConfigChanges() 中清理對給定 Activity 的任何參照,然後在 onReattachedToActivityForConfigChanges() 中重新建立這些參照。

最後,在 onDetachedFromActivity() 中,您的外掛程式應該清除所有與 Activity 行為相關的參照,並返回非 UI 設定。