Flutter Plugin plug-in development and filling guide

Preface

Recently I developed a Flutter plugin in my spare time to update the version of the Android app: flutter_xupdate , I found that I did not encounter any pits during the development process, but I encountered a lot of problems when publishing to the flutter plugin platform , here I record Let me give some advice to those who follow me.

Flutter Plugin plugin development

1. Create a Flutter Plugin plugin project

It is recommended to use Android Studio to create a project here. Follow the prompts step by step. The screenshot is as follows: The
Insert picture description here
generated project directory mainly contains the following contents:

  • The "android" directory is the implementation of the plug-in API on the Android platform.
  • The "ios" directory is the implementation of the plug-in API on the iOS platform.
  • The "example" directory is an example project using plugins.
  • Files in the "lib" directory are mainly used to create "MethodChannel", and then receive and process messages from the native platform

2. Implement plug-in functions

Here I mainly introduce the API implementation on the Android side.

Pit 1: There are two versions of Flutter plugin loading

Since there are two versions (Registrar and FlutterPluginBinding) of the way that Flutter automatically relies on plugins, when we implement Android plugins, in order to improve compatibility, it is best to implement both of these. Therefore, Android plugins need to be implemented FlutterPlugin, ActivityAware, MethodCallHandlerThese three interfaces, taking my flutter_xupdate plugin as an example, are implemented as follows:

public class FlutterXUpdatePlugin implements FlutterPlugin, ActivityAware, MethodCallHandler {
    private static final String PLUGIN_NAME = "com.xuexiang/flutter_xupdate";

    private MethodChannel mMethodChannel;
    private Application mApplication;
    private WeakReference<Activity> mActivity;

	//此处是新的插件加载注册方式
    @Override
    public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
        mMethodChannel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), PLUGIN_NAME);
        mApplication = (Application) flutterPluginBinding.getApplicationContext();
        mMethodChannel.setMethodCallHandler(this);
    }

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

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

    @Override
    public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
        switch (call.method) {
            case "getPlatformVersion":
                result.success("Android " + android.os.Build.VERSION.RELEASE);
                break;
            case "initXUpdate":
                initXUpdate(call, result);
                break;
			...
            default:
                result.notImplemented();
                break;
        }
    }

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

    @Override
    public void onDetachedFromActivityForConfigChanges() {

    }

    @Override
    public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) {

    }

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

	//此处是旧的插件加载注册方式
    public static void registerWith(Registrar registrar) {
        final MethodChannel channel = new MethodChannel(registrar.messenger(), PLUGIN_NAME);
        channel.setMethodCallHandler(new FlutterXUpdatePlugin().initPlugin(channel, registrar));
    }
}

The above code needs to pay attention to:

  • registerWithThe static method is flutter's old way of loading plugins, loaded through reflection.
  • onAttachedToEngineThe and onDetachedFromEngineyes FlutterPlugininterface methods are flutter's new way of loading plugins.
  • onAttachedToActivityThe and onDetachedFromActivityyes ActivityAwareinterface methods are mainly used to get the Activity where the current flutter page is located.
  • onMethodCallYes MethodCallHandler, the interface method is mainly used to receive the implementation of native method calls from Flutter.

Pit 2: There are restrictions on the type of data interaction between native and flutter

When developing a plug-in, it must involve data interaction between native and flutter. It should be noted here that just like when we are developing react-native and JNI, not all types of data are supported Interactive. Below I give the interactive data types between native and flutter:

Dart Android iOS
null null nil (NSNull when nested)
bool java.lang.Boolean NSNumber numberWithBool:
int java.lang.Integer NSNumber numberWithInt:
int, if 32 bits not enough java.lang.Long NSNumber numberWithLong:
double java.lang.Double NSNumber numberWithDouble:
String java.lang.String NSString
Uint8List byte[] FlutterStandardTypedData typedDataWithBytes:
Int32List int[] FlutterStandardTypedData typedDataWithInt32:
Int64List long[] FlutterStandardTypedData typedDataWithInt64:
Float64List double[] FlutterStandardTypedData typedDataWithFloat64:
List java.util.ArrayList NSArray
Map java.util.HashMap NSDictionary

Here we use the most is the bool, int, String, Mapthese types of

3. Plug-in release

The plug-in release encounters the most pits and requires additional attention.

Improve documentation

It is recommended to add the following documents to the plug-in project:

  • README.md: File introducing the package
  • CHANGELOG.mdRecord the changes in each version
  • LICENSE File containing the software package license terms
  • API documentation for all public APIs

Publish plugin

Run the following command to publish:

flutter packages pub publish

Do you think it's over? No, no, there are too many pits below!!

Pit point three: permission authentication requires access to the google account

Since we want to publish the plug-in to the flutter plug-in platform , we need to know that this platform is built by Google. If we need to publish, we must log in to our Google account for authentication. After we enter the flutter packages pub publishcommand, we will receive an authentication link, which is what we need We log in to the google account.

To know that Google is inaccessible in China, here we need to find a way (what method you know) to log in to the Google account and authenticate.

Pit 4: Flutter Chinese network construction documents are poisonous

Do you think you are done after logging in to your google account? Thinking too much! There is a big pit here is the environment configuration problem of Flutter Chinese online, as shown in the following figure:
Insert picture description here
Here, the official let us configure the temporary mirror of Flutter, and most people have just contacted I always follow the official documentation step by step, and I believe this step is definitely indispensable. But it is such an inconspicuous step that makes me stuck in the certification step. It is useless to find a solution for a long time on the Internet. There are also some in between. People say that it is because of the problem of mirroring. I dare not believe that it is caused by this problem.

Here we can pass the authentication by removing the mirror configuration.

Pit point five: scientific Internet tools do not work on the command terminal

I thought it was difficult to pass the authentication, but the upload will always be successful now, but the accident Uploading...happened again.I have been stuck , and the upload failed.

Uploading...
Failed to upload the package.

On Baidu on the Internet, it is said that scientific Internet tools do not work on the command terminal, and it is necessary to set a proxy for the command line.

export https_proxy=http://127.0.0.1:1087
export http_proxy=http://127.0.0.1:1087
set https_proxy=https://127.0.0.1:1087
set http_proxy=http://127.0.0.1:1087

Because I am using the Mac version of the scientific Internet tool, the small plane, so my proxy port is 1087.

However, it is impossible to upload successfully with this setting directly. We need to use privoxytools to complete the proxy of the terminal. The operation is as follows:

  • Install privoxy
brew install privoxy
  • Modify privoxy configuration
vim /usr/local/etc/privoxy/config

Add these two configurations (note that the port number in the first line should be based on your scientific Internet proxy, I did not change it here, it defaults to 1087), and be careful not to forget a space and dot at the end.

listen-address 0.0.0.0:1087
forward-socks5 / localhost:1080 .
  • Start privoxy
sudo /usr/local/sbin/privoxy /usr/local/etc/privoxy/config

After starting, let's check if it is started:

netstat -na | grep 1087

If a result similar to the following appears, the startup is successful.

tcp4 0 0 127.0.0.1.1087 *.* LISTEN

Re-execute at this time:

export https_proxy=http://127.0.0.1:1087
export http_proxy=http://127.0.0.1:1087
set https_proxy=https://127.0.0.1:1087
set http_proxy=http://127.0.0.1:1087

Finally, execute the release command:

flutter packages pub publish

If the following results appear, it proves that the release was successful!

Waiting for your authorization...

Authorization received, processing...

Successfully authorized.

Uploading...

Successfully uploaded package.

Related Links

No public

Insert picture description here

Exchange group

Insert picture description here

Guess you like

Origin blog.csdn.net/xuexiangjys/article/details/104351616