What is the Flutter plugin package?

The Flutter plugin package has the same meaning as the dependencies in Android Gradle. Packages developed by official or open source organizations can significantly improve our development efficiency and reduce development costs. We can also learn a lot from some of the best open source frameworks, and as a programmer, you can get a lot of improvement by visiting Github and looking at projects, or by forking out open source projects and contributing code.

Flutter packages fall into two categories.

  1. Dart package: Independent of a particular platform and dependent on the Flutter framework, this package is only used for Flutter.
  2. Plug-in package: Platform-specific, a dedicated Dart package that contains apis written in Dart code and specific implementations for Android (using Java or Kotlin) and iOS (using OC or Swift) platforms, meaning plug-ins include native code.

This article only introduces the development and release process of the Flutter plugin package. For the Dart package, the process is similar. You can refer to the related articles for more information.

Create the Flutter plugin package project

Before the start of the body, the reader need to know what Flutter platform channel, if you still don’t know, you can read the written before I Flutter | how to grace the invocation of the Android native method? And then come back to continue the study of this article. If you already know about platform channels, follow my lead and continue

This article will take you through the implementation of a volume adjustment plug-in package project on the Android platform and publish it to the Dart repository. First open Android Studio and create the Flutter Plugin project as follows.

After the whole project is created, the directory structure looks like this, similar to the Flutter project. The system automatically generates two classes in the Android and lib directories based on the package name you created (cn.blogss.volume_control is my package name). The values are volumecontrolplugin. kt and volume_control.dart.

Volumecontrolplugin.kt implements the FlutterPlugin and MethodCallHandler interfaces. You can see that this is basically the same code we wrote for the Android platform channel. A platform channel named volume_control is instantiated, and then we simply process the messages from the platform according to the business logic in the onMethodCall method and return the results.

/** VolumeControlPlugin */
class VolumeControlPlugin: FlutterPlugin.MethodCallHandler {
  private lateinit var channel : MethodChannel

  This method is automatically called when the Flutter Engine starts to instantiate the platform channel
  override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    channel = MethodChannel(flutterPluginBinding.binaryMessenger, "volume_control")
    channel.setMethodCallHandler(this)}override fun onMethodCall(@NonNull call: MethodCall.@NonNull result: Result) {  // This is where messages from the platform are processed
    if (call.method == "getPlatformVersion") {
      result.success("Android ${android.os.Build.VERSION.RELEASE}")}else {
      result.notImplemented()
    }
  }

// When the Flutter Engine is closed, memory is freed
  override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
    channel.setMethodCallHandler(null)}}Copy the code

Volume_control. dart is basically the same code we wrote for the Flutter terminal channel. Instantiate a platform channel internally, and you can then write various asynchronous methods internally to communicate with a particular platform and receive the results returned by the platform.

class VolumeControl {
  static const MethodChannel _channel =
      const MethodChannel('volume_control');

  static Future<String> get platformVersion async {
    final String version = await _channel.invokeMethod('getPlatformVersion');
    returnversion; }}Copy the code

This is the whole process of creating the Flutter plugin project. It introduces the reader to two important classes that the system automatically generates for us. Then we focused our development around these two classes.

Write code to adjust volume and test it

The Android client code

Start by writing the methods you want to implement in volumecontrolplugin.kt. As follows, I have written four corresponding method names for the Flutter side to call. Set the maximum volume range, obtain the current power, change the media volume, change the system volume. VolumeManager internal implementation of the specific logic of the four methods, due to the length of the relationship, and the purpose of this article is to take readers familiar with the whole Flutter plug-in development process, here does not post the source code of VolumeManager class, nor explain its implementation details. The code is placed in volume_flutter for interested readers to look at.

/** VolumeControlPlugin */
class VolumeControlPlugin: FlutterPlugin.MethodCallHandler {
  private lateinit var channel : MethodChannel
  private lateinit var volumeManager: VolumeManager

  override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    channel = MethodChannel(flutterPluginBinding.binaryMessenger, "volume_control")
    channel.setMethodCallHandler(this)

    volumeManager = VolumeManager(flutterPluginBinding.applicationContext)
  }

  override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
    channel.setMethodCallHandler(null)}override fun onMethodCall(@NonNull call: MethodCall.@NonNull result: Result) {
    when(call.method){
      "setMaxVol"- > {// Set the maximum volume range
        volumeManager.setMaxVol(call.arguments as Double);
      }
      "getCurrentVol"- > {// Get the current volume
        volumeManager.setAudioType(call.arguments as Int)
        result.success(volumeManager.currentVolume);
      }
      "changeMediaVoice"- > {// Change the media volume
        volumeManager.setAudioType(VolumeManager.TYPE_MUSIC)
        val curVoice = volumeManager.setVoice(call.arguments as Double);
        result.success(curVoice)
      }
      "changeSysVoice"- > {// Change the system volume
        volumeManager.setAudioType(VolumeManager.TYPE_SYSTEM)
        val curVoice = volumeManager.setVoice(call.arguments as Double);
        result.success(curVoice)
      }
      else -> {
        result.notImplemented()
      }
    }
  }
}
Copy the code

Flutter server-side code

Dart (); dart (); volume_control.dart ();

class VolumeControl {
  static const MethodChannel _channel = const MethodChannel('volume_control');

  /// Set the maximum volume range
  /// The setMaxVol method allows the maximum volume to be set freely. If this method is not used, the default maximum volume is 100
  static Future<void> setMaxVol(double num) async{
    await _channel.invokeMethod("setMaxVol".num);
  }

  /// Get current volume
  static Future<double> getCurrentVol(AudioType audioType) async{
    return await _channel.invokeMethod("getCurrentVol",_getStreamInt(audioType)) as double;
  }

  /// Changing media Volume
  static Future<double> changeMediaVoice(double num) async{
    return await _channel.invokeMethod("changeMediaVoice".num) as double;
  }

  /// Change system volume
  static Future<double> changeSysVoice(double num) async{
    return await _channel.invokeMethod("changeSysVoice".num) as double; }}enum AudioType {
  /// Controls the Voice Call volume
  STREAM_VOICE_CALL,
  /// Controls the system volume
  STREAM_SYSTEM,
  /// Controls the ringer volume
  STREAM_RING,
  /// Controls the media volume
  STREAM_MUSIC,
  // Controls the alarm volume
  STREAM_ALARM,
  /// Controls the notification volume
  STREAM_NOTIFICATION
}

int _getStreamInt(AudioType audioType) {
  switch (audioType) {
    case AudioType.STREAM_VOICE_CALL:
      return 0;
    case AudioType.STREAM_SYSTEM:
      return 1;
    case AudioType.STREAM_RING:
      return 2;
    case AudioType.STREAM_MUSIC:
      return 3;
    case AudioType.STREAM_ALARM:
      return 4;
    case AudioType.STREAM_NOTIFICATION:
      return 5;
    default:
      return null; }}Copy the code

Check out the effect on the Flutter page

Dart, the example directory generated by the project, is now used to write sample page code to show the functionality of the plugin. Note that the Example is a Flutter project written by the developer to tell users how to use the plugin. It is a help document, which I think is great. It has greatly accelerated our learning process.

Dart uses a Slider component to illustrate the effect. Follow these steps to code.

  1. When entering the page, the getCurrentVol method is called to get the current media volume and display the initial state.
  2. The slider calls the changeMediaVoice method to change the media volume.

The main.dart page code is as simple as the following.

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  double _musicVoice;

  @override
  void initState() {
    super.initState();
    ///1. Obtain the current media volume
    initCurrentVol();
  }

  /// Gets the current media volume
  Future<void> initCurrentVol () async{
    _musicVoice = await VolumeControl.getCurrentVol(AudioType.STREAM_MUSIC);
    if(! mounted)return;
    setState(() {});
  }

  /// Changing media Volume
  Future<void> changeMediaVoice(double vol) async{
    await VolumeControl.changeMediaVoice(vol);
    _musicVoice = vol;
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'), ), body: Center( child: (_musicVoice ! =null)? Slider( value: _musicVoice, min:0,
            max: 100,
            inactiveColor: Colors.grey,
            activeColor: Colors.blue,
            onChanged: (vol){
              /// 2.Slide to change media volumechangeMediaVoice(vol); }, ): Container(), ), ), ); }}Copy the code

The effect is as follows: when you slide the slider, the system media volume changes. My test model is MI 6X. Other models may have differences, please note.

Upload the developed plug-in package to the Dart repository

This is the end of our development process for the Flutter plugin package. Now upload it to the Dart repository so that other developers can use the plug-in package. Before publishing, check the LICENSE, pubspec.yaml, readme. md, and Changelog. md files.

Selecting an Open Source LICENSE

There are probably hundreds of open source licenses for software. Six of the most popular – GPL, BSD, MIT, Mozilla, Apache, and LGPL. Readers can Choose their own certificate from the Choose an Open Source License. In this case, I Choose MIT.

Paste the copied content into the LICENSE file, replace [year] with the current year, and replace [fullname] with the copyright owner. As shown below, the certificate is finished.

Modify pubspec yaml

name: volume_control
description: A new Flutter plugin.
version: 0.01.
author:
homepage:
Copy the code

In this section, the brief description of the description plug-in, version version of the plug-in, and the homepage of the homepage project are modified according to the actual situation. In this section, the author is no longer supported. Readers need to delete it directly, otherwise it will fail the following check.

name: volume_control
description: A Flutter plugin which can control android volume.
version: 0.01.
homepage: https://github.com/liqvip/volume_control
Copy the code

Modify readme. md and Changelog. md

The readme. md file goes without saying, leaving the reader free to play around with what the plugin does, what it does, how to use it, and so on. The Changelog. md file is used to record changes for each version. Also fill in according to the actual situation.

# # 0.0.1 initial commitCopy the code

Very simple, for version 0.0.1 I only filled in one sentence, hee hee ~

To upload

  1. First, enter the following command in Android Studio Termial to check whether the above file we have written meets the requirements for distribution.
flutter pub publish --dry-run
Copy the code
  1. If no problem is found, the console displays the following information.
Package has 0 warnings.
Copy the code
  1. Then enter the following command to start uploading
flutter pub publish --server=https://pub.dartlang.org
Copy the code

You will be prompted that once published, it is permanent and cannot be cancelled. Type y to continue

Publishing is forever; packages cannot be unpublished.
Policy details are available at https://pub.dev/policy

Do you want to publish volume_control 0.0.1 (y/N)?
Copy the code

The console will then output a link, which we will copy to the browser to open, and it will prompt you to log in and verify Gmail. If not, you will need to use a VPN to sign up for Gmail.

Do you want to publish volume_control 0.0.1 (y/N)? y Pub needs your authorization to upload packages on your behalf. In a web browser, go to https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force&response_type=code&client_id=8183688 55108-8grd2eg9tj9f38os6f1urbcvsq399u8n.apps.googleusercontent.com&redirect_uri=http%3A %2F%2Flocalhost%3A55779&code_challenge=t9GweRvzHgPt6F1-1I42-3e8eg1MeA7xovsNLCsDHks&code_challenge_method=S256&scope=open id+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email Then click "Allow access". Waiting for your authorization...Copy the code

The following is the result that I verified with my own mailbox.

Back to the console, you may see the following error message. An error message tells us that we received the authentication message and are processing it but we can’t go to the next step and have to time out. This is obviously a network problem.

Waiting for your authorization... Authorization received, processing... It looks like accounts.google.com is having some trouble. Pub will wait for a while before trying to connect again. OS Error: The semaphor timeout has expired. Errno = 121, address = accounts.google.com, port = 56479 pub finished with exit code 69Copy the code

This is because even if you set the proxy, HTTP and HTTPS in the terminal will not be proxy, so we need to set the terminal proxy. According to the command provided below, readers can set the terminal agent on different operating systems, note that HTTP and HTTPS should be set, and my SSR agent port is 1080, readers need to fill in according to your actual agent port.

Set http_proxy=http://127.0.0.1:1080 set https_proxy=http://127.0.0.1:1080 http://www.google.com # delete proxy set http_proxy= set https_proxy= Linux export http_proxy=http://127.0.0.1:1080; Export https_proxy = http://127.0.0.1:1080;Copy the code

According to the command provided above, after setting up terminal agent in Windows, test whether the agent is set up successfully, just ask Google. If the following information is displayed, the proxy is successfully configured.

After the agent is set up, proceed with the publish command.

flutter pub publish --server=https://pub.dartlang.org
Copy the code

It turns out that the network problem has obviously been resolved this time, but there is a plug-in package with the same name on the Dart repository. So we changed the volume_control to volume_flutter, changed the names of other related classes, and continued publishing. The project name here had better go to the Dart warehouse to check whether it is occupied. Give it a different name if it’s occupied. Otherwise, it’s going to be hard in here. 555

Ten minutes later, I’ve changed my name. Boys, go ahead and issue orders. Upload success, excited to fly, hee hee ~

Check in the Dart warehouse

As a final step, go to Dart repository Volume_flutter to check the final result. Note that there will be a delay in the repository. It will take a few minutes to find the plugin you just uploaded. As a result, we completed the plug-in development and release process.

Write in the last

This article takes readers through a plugin project to adjust Android volume in Flutter and publishes it to the Dart repository. If a developer wants to use the plugin later, simply add the following dependencies to pubspec.yaml. Use the same method as the sample code we wrote in the Exmaple directory.

dependencies:
  volume_flutter: ^ 0.0.1
Copy the code

With this article, you should be able to fully understand how to develop a plug-in package and publish it to the Dart repository. There were a lot of bumps and bumps along the way, especially in the final release phase. But they all worked out one by one.

If you are interested in me, please go to blogss.cn or follow programmer Xiabei to learn more.

  • If this article helped you, please like it and follow ❤️
  • Due to the author’s limited level, if there are any mistakes in this article, please correct them in the comments section ✔️
  • This article was first published in nuggets. Reprint is prohibited without permission ©️