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
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
, MethodCallHandler
These 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:
registerWith
The static method is flutter's old way of loading plugins, loaded through reflection.onAttachedToEngine
The andonDetachedFromEngine
yesFlutterPlugin
interface methods are flutter's new way of loading plugins.onAttachedToActivity
The andonDetachedFromActivity
yesActivityAware
interface methods are mainly used to get the Activity where the current flutter page is located.onMethodCall
YesMethodCallHandler
, 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
, Map
these 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 packageCHANGELOG.md
Record the changes in each versionLICENSE
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 publish
command, 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:
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 privoxy
tools 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
- Flutter Chinese Network Development Flutter Plug-in Tutorial
- flutter_xupdate realizes Flutter application version update with one click