How to create a Flutter plugin

24 Oct 2018 09:38   |   by Administrator   |    android development , flutter , dart , flutter plugin

Recently I had an opportunity to develop both Android and iOS applications for one of my clients. To make the development easier and faster, I decided to use flutter, which is Google's mobile app SDK for developing beautiful applications for both Android and iOS.


Working with flutter was pretty awesome and I was able to deliver the applications within a short amount of time. While developing the applications I realised that most of the functionalities that i was creating for the applications could be converted into plugins. So after i was done with the applications, I converted a few pieces of my code into plugins.


In this post we'll create and publish a flutter plugin for fetching the unique identifier serial number for Android(Android ID) and iOS(identifierForVendor).

Requirements


  1. Standard Flutter Setup : Flutter Getting Started

  2. Github account

  3. Android phone/android simulator

  4. iPhone/iOS simulator


I am using android studio with a Nexus 6p and iOS simulator for iPhone X.


Following are the steps that I followed while setting up the plugin


  1. Open android studio and click on 'Start a new Flutter project'.



2. Select 'Flutter plugin' as the project type and move on to the next step



3. Give the plugin a proper name and description. Choose an appropriate location for the project and select the correct flutter sdk path (which was used for setting up the environment).



4. Choose a correct package name i used my organisations default package(Example : com.myplugin) and select the checkbox : Include swift support for iOS code. Click on finish to create the default code for the plugin







Now the framework has created a default plugin for getting the platform version(OS version) in the created plugin. Now we have to remove the default code and add our own logic.


Use the following steps to change the plugin code and the example code:


  1. Open the created plugin file : lib > <PLUGIN NAME>.dart and modify the code. In my case the file name is unique_identifier.dart and the class name is 'UniqueIdentifier' . after removing the default code we have added a method Channel 'unique_identifier' and the method 'getUniqueIdentifier', this will trigger the respective platform code to fetch the serial number : ANDROID_ID for android and identifierForVendor for iOS.


import 'dart:async';

import 'package:flutter/services.dart';


class UniqueIdentifier {

static const MethodChannel _channel =

    const MethodChannel('unique_identifier');


static Future<String> get serial async {

  final String identifier = await _channel.invokeMethod('getUniqueIdentifier');

  return identifier;

}

}



2. Our next step is to handle the method call in android and iOS.


For Android : open  the generated Java class : android>src>main>java > <your package name> > <ClassName>Plugin.java and change the onMethodCall the following code :


@Override

public void onMethodCall(MethodCall call, Result result) {

if (call.method.equals("getUniqueIdentifier")) {

  String android_id = null;

  if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.CUPCAKE) {

    android_id = Secure.getString(context.getContentResolver(),

            Secure.ANDROID_ID);

  }


  result.success(android_id);

} else {

  result.notImplemented();

}

}


                            For iOS : Open the generated swift file :

ios > Classes > Swift<Class name>Plugin.swift  and change the handle method to


public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {

let device = UIDevice.current;

result(device.identifierForVendor?.uuidString);

}


This is the logic for getting the identifierForVendor in iOS and setting it in method call result.


3. Open the main.dart file located in example > lib . In the example the plugin is already getting used. Change the methods used in the example to the new methods created in the first step. Finally the file will look like:


import 'package:flutter/material.dart';

import 'dart:async';


import 'package:flutter/services.dart';

import 'package:unique_identifier/unique_identifier.dart';


void main() => runApp(new MyApp());


class MyApp extends StatefulWidget {

@override

_MyAppState createState() => new _MyAppState();

}


class _MyAppState extends State<MyApp> {

String _identifier = 'Unknown';


@override

void initState() {

  super.initState();

  initUniqueIdentifierState();

}


Future<void> initUniqueIdentifierState() async {

  String identifier;

  try {

    identifier = await UniqueIdentifier.serial;

  } on PlatformException {

    identifier = 'Failed to get Unique Identifier';

  }


  if (!mounted) return;


  setState(() {

    _identifier = identifier;

  });

}


@override

Widget build(BuildContext context) {

  return new MaterialApp(

    home: new Scaffold(

      appBar: new AppBar(

        title: const Text('Plugin example app'),

      ),

      body: new Center(

        child: new Text('Running on device with id: $_identifier\n'),

      ),

    ),

  );

}

}



4. Optionally you can add a new package test in the project directory with the name : <package_name>_test.dart

I have added an empty test case to the plugin but you can add your own test cases before deploying.

void main() {}


You can also remove the default test case present in example > test > widget_test.dart to avoid getting warnings while publishing the plugin

5. Connect your phone (android/iphone) and execute the main.dart by clicking on the play button




The output will look like :


Android :



iOS







The final step is to publish the plugin on https://pub.dartlang.org


  1. The first step is to create a github repository and add your code for source control. Goto your github account and create a new repository


You can optionally add license, i generally add it after the initial commit.


Open the project directory in terminal(powershell) and run the following command displayed on the new github repository

  • Git init
  • Git add .
  • Git remote add origin <your repository url>
  • Git push -u origin master




2. Open the pubspec.yaml on android studio located in the project directory (not from the example directory), add a meaningful description (this will be used by the search engines), author and specify the github repository as the homepage. Finally your pubspec file should look like this:


name: unique_identifier

description: A new Flutter plugin for fetching the unique identifier from android and ios.

version: 0.0.1

author: Karan Tanwar <karantanwar.nitd@gmail.com>

homepage: https://github.com/karantanwar/unique_identifier


environment:

sdk: ">=2.0.0-dev.68.0 <3.0.0"


dependencies:

flutter:

  sdk: flutter


flutter:

plugin:

  androidPackage: altercode.xyz.uniqueidentifier

  pluginClass: UniqueIdentifierPlugin



3. Now we need to start preparing for the publishing by running the publish command with --dry-run parameter


flutter packages pub publish --dry-run



This will display the errors and warnings if any before you actually publish the plugin. Just fix the issues and you are ready to publish the plugin.


4. You can optionally add the content to your README.md file and maintain the CHANGELOG.md file for maintenance purposes


CHANGELOG.md


## 0.0.1


* initial release.



README.md

# Flutter Search Panel


[![pub package](https://img.shields.io/badge/pub-0.0.1-green.svg)](https://pub.dartlang.org/packages/unique_identifier)


A Flutter plugin to get the ANDROID_ID for android and identifierForVendor for iOS platforms.


## Installing


```yaml

dependencies:

unique_identifier: ^0.0.1

```


### Import


```dart

import 'package:unique_identifier/unique_identifier.dart';

```


## How To Use


```

dart String _identifier = 'Unknown';


@override

void initState() {

 super.initState();

 initUniqueIdentifierState();

}


Future<void> initUniqueIdentifierState() async {

 String identifier;

 try {

   identifier = await UniqueIdentifier.serial;

 } on PlatformException {

   identifier = 'Failed to get Unique Identifier';

 }


 if (!mounted) return;


 setState(() {

   _identifier = identifier;

 });

}


@override

Widget build(BuildContext context) {

 return new MaterialApp(

   home: new Scaffold(

     appBar: new AppBar(

       title: const Text('Plugin example app'),

     ),

     body: new Center(

       child: new Text('Running on device with id: $_identifier\n'),

     ),

   ),

 );

}

FlutterSearchPanel(

padding: EdgeInsets.all(10.0),

selected: 'a',

title: 'Demo Search Page',

data: ['This', 'is', 'a', 'test', 'array'],

icon: new Icon(Icons.check_circle, color: Colors.white),

color: Colors.blue,

textStyle: new TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 20.0, decorationStyle: TextDecorationStyle.dotted),

onChanged: (value) {

  print(value);

},

),

```


## Bugs & Requests


If you encounter any bugs feel free to open an issue. Raise a ticket on github for suggestions. Pull request are also welcome.


### Flutter


For help getting started with Flutter, view our online

[documentation](https://flutter.io/).


For help on editing plugin code, view the [documentation](https://flutter.io/platform-plugins/#edit-code).


## License


MIT License





5. Open the project directory in termnial and run the following command to publish the plugin


flutter packages pub publish


Output:



Copy and paste the provided link on your browser and you are done. After the authorization is completed the plugin is successfully published.


Final output:






I hope this is useful to those who are looking to develop their own flutter plugins.



References :


You can view the entire code on github : unique_identifier_repo

And use the plugin from pub.dartlang.org : unique_identifier_pub