Flutter native plug-in - Android

Flutter native plug-in

1, What is the Flutter plug-in

1. Four engineering types of Flutter
a,Flutter Application

The new APP, the standard shuttle APP project, includes the standard Dart layer and Native platform layer

b,Flutter Module

Mix into existing Android / iOS projects

c,Flutter Plugin

The fluent platform plug-in project includes the implementation of Dart layer and Native platform layer. Plugin is actually a special Package. Flutter Plugin provides the underlying packaging of Android or iOS, and provides component functions in the flutter layer, so that flutter can easily access Native modules. Many platform dependencies or complex parts of the implementation of fluent can be encapsulated into plugin. Its principle is as follows

d,Flutter Package

The fluent pure Dart plug-in project only includes the implementation of Dart layer, and often defines some public widgets

2, Create a shuttle plugin project

1. ide creation
a. Select File - > New - > new shuttle project from the menu bar
b. In the pop-up window, select fluent plugin and then Next all the way

This is the directory structure created by IDE, including ios and Android directories

The main directories included in the figure are Android, example, ios and lib: - Android directory is a complete Android project to develop Android plug-in functions - example directory is used to test Android or ios plug-in functions - ios directory is a complete ios project to develop ios plug-in functions - files in lib directory are responsible for interaction with Android or ios

2. Command line creation (problems found after trying, no ios and Android directories)
flutter create -t plugin flutter_plugin_demo

There are no Android and ios directories created on this command line, but this is the creation command line on the official website of flutter. I don't know whether it is the reason for the update of flutter SDK, so I still use IDE to create it

3, Pre run configuration of Android native plug-ins

Environment: fluent SDK: 1.20.3

**1. * * for the code of remote pull, first configure the path of the fluent SDK in Perfrences (Mac) / Settings (Windows)

**2. * * enter Android / src.exe under project main. java. com. xxx. XXX directory, open the FlutterPlugin directory and find that all flutter related classes are red. This is because the sdk of flutter is not configured in the plug-in. The solution is as follows:

In android.src/ Create a new libs folder under the main directory, and copy the jar package of any Android platform under the bin/cache/artifacts/engine folder under the fluttersdk directory to the libs directory just created (I use the flutter.jar package of Android arm);

After copying, right-click on the shuttle in as Jar package, select Add As Library

Then open the android project under the project in as - > file - > Open... And you will find that the relevant imports of fluent are normal. The reference of NonNull is still red. You can directly import the dependency from alt+enter.

Finally, in the android directory of project, build In the gradle file, in dependencies:

implementation files('src/main/libs/flutter.jar')

Change to:

compileOnly files('src/main/libs/flutter.jar')

**3. * * the Android project under the project directory is a plug-in and cannot be run alone. It can only be run in the example project under the project (the dependency on this plug-in was added when the example project was created. It is a sample program specially used to test the operation of the plug-in.

Since it can't run, why open the Android project under project? Because in example, although you can modify the code of the java file in the plugin, you can't see build Gradle and setting Profile for gradle

**4. * * after completing the development of the bridge interface between fluent and native in the Android project under project, open the Android project under example in as - > file - > Open... And the project can be run at this time.

Note: you can also run the plug-in directly in the project. You can import the plug-in by configuring the plug-in path in the yaml file of the project

4, Development of FlutterPlugin

1. Introduction

Starting from Flutter 1.12, the Flutter team adjusted the implementation code of Android plug-in. After 1.12, Android began to use the new plug-in API based on the old pluginregistry Registrar will not be abandoned immediately, but the official suggests that it be migrated to the new API FlutterPlugin based on. In addition, the new version of the official suggests that the plug-ins directly use Androidx support, and the plug-ins provided by the official have been fully upgraded to Androidx.

Compared with the old API, the advantage of the new API is that it provides a more decoupled use method for the life cycle on which the plug-in depends, such as the previous pluginregistry Registrar. When using Activity (), if the fluent has not been added to the Activity, it may return null. At the same time, the plug-in does not know when it will be loaded and used by the engine, and these problems have been optimized in the new API.

2. Use of FlutterPlugin

The following is the plug-in code automatically generated when creating the shuttle plugin:

package com.example.flutter_plugin;

import androidx.annotation.NonNull;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;

/** FlutterPlugin */
public class FlutterDemoPlugin implements FlutterPlugin, MethodCallHandler {
  /// The MethodChannel that will the communication between Flutter and native Android
  ///
  /// This local reference serves to register the plugin with the Flutter Engine and unregister it
  /// when the Flutter Engine is detached from the Activity
  private MethodChannel channel;

  @Override
  public void onAttachedToEngine(@NonNull io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding flutterPluginBinding) {
    channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "flutter_plugin");
    channel.setMethodCallHandler(this);
  }

  // This static function is optional and equivalent to onAttachedToEngine. It supports the old
  // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting
  // plugin registration via this function while apps migrate to use the new Android APIs
  // post-flutter-1.12 via https://flutter.dev/go/android-project-migration.
  //
  // It is encouraged to share logic between onAttachedToEngine and registerWith to keep
  // them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called
  // depending on the user's project. onAttachedToEngine or registerWith must both be defined
  // in the same class.
  //Methods of compatibility support for old versions
  public static void registerWith(Registrar registrar) {
    final MethodChannel channel = new MethodChannel(registrar.messenger(), "flutter_plugin");
    channel.setMethodCallHandler(new FlutterDemoPlugin());
  }

  //flutter bridging interface method
  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    if (call.method.equals("getPlatformVersion")) {
      result.success("Android " + android.os.Build.VERSION.RELEASE);
    } else {
      result.notImplemented();
    }
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    channel.setMethodCallHandler(null);
  }
}

On the new API, the Android plug-in needs to be implemented by using FlutterPlugin and MethodCallHandler. At the same time, it also provides ActivityAware for the life cycle management and acquisition of Activity and ServiceAware for the life cycle management and acquisition of Service.

The previous fluent plug-ins directly inherited MethodCallHandler and then provided registerWith static methods; After the upgrade, as shown in the following code, the registerWith static method is retained here because it also needs compatibility support for the old version.

 public WxLoginPlugin initPlugin(MethodChannel channel, Registrar registrar) {
    this.channel = channel;
    mApplication = (Application) registrar.context().getApplicationContext();
    mActivity = new WeakReference<>( registrar.activity());
    return this;
  }

  //Old plug-in loading method
  public static void registerWith(Registrar registrar) {
    MethodChannel methodChannel = new MethodChannel(registrar.messenger(), PLUGIN_NAME);
    methodChannel.setMethodCallHandler(new WxLoginPlugin().initPlugin(methodChannel, registrar));
  }

The following four methods are the interface methods of * * ActivityAware * * to initialize and release mmactivity in attach and detach:

  @Override
  public void onAttachedToActivity(@NonNull ActivityPluginBinding activityPluginBinding) {
    mActivity = new WeakReference<>(activityPluginBinding.getActivity());
  }

  @Override
  public void onDetachedFromActivityForConfigChanges() {

  }

  @Override
  public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding activityPluginBinding) {

  }

  @Override
  public void onDetachedFromActivity() {
    mActivity = null;
  }

5, Call of fluent plugin

1. On the new API, the Activity should inherit from Io flutter. embedding. android. Flutteractivity, so that the plug-in can register automatically;
2. If the condition is not allowed, you cannot inherit io flutter. embedding. android. For flutteractivity, you need to manually call generatedpluginregistration Registerwith method, and configure androidmanifest XML file:

Add configuration under the Activity node:

						<!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <!-- Displays an Android View that continues showing the launch screen
                 Drawable until Flutter paints its first frame, then this splash
                 screen fades out. A splash screen is useful to avoid any visual
                 gap between the end of Android's launch screen and the painting of
                 Flutter's first frame. -->
            <meta-data
              android:name="io.flutter.embedding.android.SplashScreenDrawable"
              android:resource="@drawable/launch_background"
              />

Add configuration under the Application node:

				<!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
3. After that, you can execute fluent packages get to generate a new generatedpluginregistration file. As shown in the following code, the new fluent plugin will be generated by fluent engine getPlugins(). Add is loaded directly, and the old plug-in implementation method will be compatible loaded into the v2 implementation through ShimPluginRegistry.
@Keep
public final class GeneratedPluginRegistrant {
  public static void registerWith(@NonNull FlutterEngine flutterEngine) {
    flutterEngine.getPlugins().add(new com.example.flutter_plugin.FlutterDemoPlugin());
  }
}
4. Configure pubspec Yaml file to introduce plug-ins into the project:
  # Login plug-in
  wx_login:
#    path: ../Plugin/wx_login/
    git:
      url: http://git.wangxutech.com/mobile/flutter/plugins/wxlogin.git

Path refers to the introduction of local plug-in code. You can write the relative path of the code

Git is the code of introducing git warehouse. The default is the master branch

Reference link: Flutter upgrade 1.12 adaptation tutorial

Tags: Android Design Pattern Flutter

Posted by AshleyByrom on Thu, 05 May 2022 15:21:25 +0300