Introduction to Package
In Flutter, packages are reusable code modules that add functionality to your app. These can range from simple utility functions to advanced features like integrating third-party services, accessing device hardware, or designing beautiful user interfaces.
1:Key Points About Flutter Packages
Types of Packages
In Flutter, packages are categorized into two main types based on their purpose and how they interact with the app and platform.
1. Dart Packages
These are written entirely in Dart and do not rely on platform-specific (Android/iOS) code. They are cross-platform and work seamlessly on both Android and iOS without any additional native integration.
Features
- Focus on pure Dart logic (e.g., utility functions, state management).
- Do not include platform-specific code or dependencies.
- Ideal for tasks like working with data structures, handling HTTP requests, or managing app state.
Examples
Dart package
import 'package:http/http.dart' as http;
Future<void> fetchData() async {
final response = await http.get(Uri.parse('https://example.com'));
print(response.body);
}
2. Plugin Packages
These packages include both Dart and platform-specific code (Java/Kotlin for Android and Objective-C/Swift for iOS). They allow you to access platform-specific features like device hardware, sensors, and system services.
Features
- Combine Dart code with native Android/iOS code.
- Useful for accessing features that cannot be achieved using Dart alone.
- Flutter uses platform channels to communicate between Dart and native code in these packages.
Example
- url_launcher:Opens a URL in the device's default browser.
- camera: Accesses the device's camera for capturing photos or videos.
- geolocator: Fetches the device's location using GPS.
- firebase_auth: Provides Firebase authentication services for both Android and iOS.
Plugin Package
import 'package:url_launcher/url_launcher.dart';
void launchURL() async {
final url = 'https://flutter.dev';
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
Differences Between Dart and Plugin Packages
Feature | Dart Packages | Plugin Packages |
---|---|---|
Code | Written purely in Dart | Combines Dart with native platform code |
Platform-Specific | No | Yes |
Cross-Platform | Yes | Mostly (some may have platform limitations) |
Examples | provider, http, intl | url_launcher, camera, geolocator |
2: Using a Package
To use a package in your Flutter app, follow these steps:
Add the Dependency:
Open your pubspec.yaml file and add the package under dependencies. For example:
dependencies:
http: ^1.0.0
Then run
Import the Package
Add the necessary import statement to your Dart file
import 'package:http/http.dart' as http;
Use the Package
Call its methods to add functionality to your app. For example:
final response = await http.get(Uri.parse('https://example.com')); print(response.body);
3: Finding Packages
Explore packages on the official pub.dev site, which lists thousands of packages for Flutter and Dart.
4: Creating Custom Packages
You can build your own package if none exist for your needs. Follow these steps:
Run:
flutter create --template=package my_package
Add your code, define dependencies, and publish to pub.dev.
Develop a Flutter Plugin Package
Creating a Flutter plugin package involves several steps, where you'll write both Dart and platform-specific code for Android and iOS. A Flutter plugin is typically used when you need to implement functionality that requires native code to interact with device features like camera, GPS, sensors, etc.
Steps to Develop a Flutter Plugin Package
1:Set Up Your Environment- Ensure that you have Flutter installed and set up on your machine.
- You’ll need Xcode (for iOS development) and Android Studio (or any IDE with Flutter plugin) to create and test plugins on both platforms.
- Use the flutter create command to generate a plugin project with Dart and native code for both Android and iOS.
Open your terminal and run:
flutter create --template=plugin flutter_plugin_example
This will create a new directory named flutter_plugin_example, which contains a Flutter plugin template with example code for both Android and iOS.
Structure of the Plugin Project
After running the flutter create command, the project structure will look like this:
flutter_plugin_example
- lib/
- flutter_plugin_example.dart # Dart API code (for users of your plugin)
- android/
- src/
- main/
- java/
- com/
- example/
- flutter_plugin_example/
- FlutterPluginExamplePlugin.java # Android native code
- flutter_plugin_example/
- example/
- com/
- java/
- main/
- src/
- ios/
- Classes/
- FlutterPluginExamplePlugin.h # iOS native header file
- FlutterPluginExamplePlugin.m # iOS native implementation
- Classes/
- pubspec.yaml # Plugin package data and dependencies
- README.md # Documentation for your plugin
Modify Dart Code for Plugin API
The file lib/flutter_plugin_example.dart contains the public Dart API that users of your plugin will interact with. This is where you'll define methods that invoke platform-specific code (Android/iOS).
For example, let’s create a method to get the platform version:
import 'dart:async';
import 'package:flutter/services.dart';
class FlutterPluginExample {
static const MethodChannel _channel = MethodChannel('flutter_plugin_example');
// Method to get platform version
static Future<String?> getPlatformVersion() async {
final String? version = await _channel.invokeMethod('getPlatformVersion');
return version;
}
}
In the Android part of your plugin, open the file android/src/main/java/com/example/flutter_plugin_example/FlutterPluginExamplePlugin.java and implement the native functionality.
For example, to get the platform version for Android:
package com.example.flutter_plugin_example;
import android.os.Build;
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;
public class FlutterPluginExamplePlugin implements FlutterPlugin, MethodCallHandler {
private MethodChannel channel;
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
channel = new MethodChannel(binding.getBinaryMessenger(), "flutter_plugin_example");
channel.setMethodCallHandler(this);
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
if (call.method.equals("getPlatformVersion")) {
result.success("Android " + Build.VERSION.RELEASE);
} else {
result.notImplemented();
}
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
channel.setMethodCallHandler(null);
}
}
Write Native Code (iOS)
In the iOS part of your plugin, open the file ios/Classes/FlutterPluginExamplePlugin.m and implement the native functionality.
For example, to get the platform version for iOS:
#import "FlutterPluginExamplePlugin.h"
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
@implementation FlutterPluginExamplePlugin
+ (void) registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"flutter_plugin_example"
binaryMessenger:[registrar messenger]];
FlutterPluginExamplePlugin* instance = [[FlutterPluginExamplePlugin alloc] init];
[registrar addMethodCallDelegate:instance channel:channel];
}
- (void) handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
if ([@"getPlatformVersion" isEqualToString:call.method]) {
result([NSString stringWithFormat:@"iOS %@", [[UIDevice currentDevice] systemVersion]]);
} else {
result(FlutterMethodNotImplemented);
}
}
@end
Configure the Plugin for Publication (Optional)
Update the pubspec.yaml file to include necessary metadata like name, description, and version.
Example pubspec.yaml configuration:
name: flutter_plugin_example
description: A new Flutter plugin
version: 0.0.1
homepage: https://example.com/flutter_plugin_example
author: Your Name <your.email@example.com>
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
Testing the Plugin
To test your plugin, you can create a sample Flutter app or use the example directory (if provided) within the plugin project
To test your plugin within the example app:
- Go to the example folder in your plugin project.
- Add your plugin as a dependency in the pubspec.yaml of the example app:
dependencies:
flutter:
sdk: flutter
flutter_plugin_example:
path: ../
Publish the Plugin (Optional)
If you want to share your plugin with the Flutter community, you can publish it on pub.dev. For this, ensure your plugin works correctly, write proper documentation, and follow pub.dev publishing instructions.
The complete code of the main.dart is as follows −
import 'package:flutter/material.dart';
import 'package:my_browser/my_browser.dart';
void main() => runApp(MyAppWidget());
class MyAppWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Example',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: HomeScreen(
pageTitle: 'Flutter Example Home Page',
),
);
}
}
class HomeScreen extends StatelessWidget {
HomeScreen({Key key, this.pageTitle}) : super(key: key);
final String pageTitle;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(this.pageTitle),
),
body: Center(
child: ElevatedButton(
child: Text('Launch Browser'),
onPressed: () => MyBrowser().openBrowser("https://flutter.dev"),
),
),
);
}
}