Flutter (84): Packages and plugins

Time: Column:Mobile & Frontend views:204

This section will introduce packages and plugins in Flutter, along with some commonly used packages, but will not cover specific implementations.

1 Packages

In Chapter 2, we discussed how to use packages. We know that packages allow for the reuse of modular code. A minimal package includes:

  • A pubspec.yaml file: This metadata file declares the package’s name, version, author, etc.

  • A lib folder: This contains the public code in the package, which must include at least one <package-name>.dart file.

Flutter packages are divided into two categories:

  • Dart Packages: Some may include features specific to Flutter and depend on the Flutter framework. These packages are only for Flutter, such as the fluro package.

  • Plugin Packages: A specialized Dart package that includes APIs written in Dart, along with specific implementations for Android (using Java or Kotlin) and iOS (using Objective-C or Swift). This means plugins include native code, such as the battery plugin package.

2 Plugins

Flutter is essentially a UI framework that runs on top of the host platform. It cannot provide certain system capabilities, such as using Bluetooth, the camera, or GPS. Therefore, to access these capabilities in Flutter, communication with the native platform is necessary. Currently, Flutter supports numerous platforms, including iOS, Android, Web, macOS, Windows, and Linux, and calling specific platform APIs requires writing plugins. A plugin is a special type of package, with the main difference being that it contains not only Dart code but also platform-specific code. For example, the image_picker plugin can access the photo library and camera on both iOS and Android devices.

2-1. Plugin Implementation Principle

A complete Flutter application actually consists of both native code and Flutter code. Flutter provides platform channels for communication between Flutter and the native platform. The platform channel serves as a bridge for communication between Flutter and native, and it is also the underlying infrastructure for Flutter plugins.

Communication between Flutter and native is essentially a remote procedure call (RPC) that is implemented through message passing:

  1. The Flutter part of the application sends a call message to the host application via the platform channel.

  2. The host listens to the platform channel and receives the message. It then calls the platform's API and sends the response back to Flutter.

Since writing a plugin involves knowledge of specific platform development, for example, the image_picker plugin requires developers to implement image picking and capturing functionalities separately on iOS and Android, developers need to be familiar with native development. However, this book primarily focuses on Flutter, so we won’t delve too deeply into this topic. Interested readers can refer to the official plugin development examples.

2-2. How to Obtain Platform Information

Sometimes, in Flutter, we want to add differentiated features based on the host platform. Therefore, Flutter provides a global variable defaultTargetPlatform to obtain the current platform information. defaultTargetPlatform is defined in platform.dart and is of type TargetPlatform, which is an enumeration defined as follows:

enum TargetPlatform {
  android,
  fuchsia,
  iOS,
  ...
}

Currently, Flutter only supports these three platforms. We can determine the platform with the following code:

if (defaultTargetPlatform == TargetPlatform.android) {
  // This is an Android system, do something
  ...
}

Due to different platforms having their own interaction specifications, some components in the Flutter Material library have been adapted for the respective platforms. For example, the routing component MaterialPageRoute applies the respective platform's transition animations for Android and iOS. If we want our app to behave consistently across all platforms—such as wishing for all platform transition animations to follow the left-to-right swipe style consistent with iOS—Flutter provides a mechanism to override the default platform. We can explicitly specify the value of the global variable debugDefaultTargetPlatformOverride to set the application platform. For example:

debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
print(defaultTargetPlatform); // Outputs TargetPlatform.iOS

The above code will make the Flutter app believe it is running on iOS, even when run on Android. All component interactions in the Material component library will align with iOS platform specifications, and the value of defaultTargetPlatform will change to TargetPlatform.iOS.

2-3. Commonly Used Plugins

Flutter provides a series of commonly used plugins, such as for accessing the camera/photo library, local storage, playing videos, etc. For a complete list, see: Flutter Plugins. Readers can check it out for themselves. In addition to the plugins maintained by the official team, the Flutter community also has many ready-made plugins, which can be found at pub.dev.