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