-
Notifications
You must be signed in to change notification settings - Fork 690
CACHET Flutter Plugins and Packages
The role of these packages and plugins is largely to allow the programmer to infer the user's state/context, using a high level of abstraction.
A Flutter project containing Dart source code exclusively. An example of this is the weather package which produces weather forecasts by querying a web server.
flutter create --org dk.cachet --template=package hello_world_package
A Flutter project containing Dart source code as well as native iOS and Android code. An example of this is the Health plugin which queries the native APIs (Apple HealthKit and Google Fit) to read the user's health data.
For plugins, the sensor data readings are performed natively and then sent to the Dart source code, where the results are processed afterward. Processing can include streamlining the sensor data such that the results and formats are the same on both platforms.
flutter create --org dk.cachet --template=plugin --platforms=android,ios -i swift -a java hello_world_plugin
Note, you can exchange kotlin for java if you want. I don't recommend using obj-c instead of swift, however.
Make src directory inside the lib directory which contains all the source code. Inside lib should also be a dart file named after the plugin/package, ex health
:
lib/
├── health.dart
├── src/
│ ├── data_types.dart
│ ├── functions.dart
│ ├── health_data_point.dart
│ ├── health_factory.dart
│ └── units.dart
This dart file is a library, which contains a reference to all the other files inside src
. The content of the file should look like so:
/// Library declaration
library health;
/// Other packages to import
import 'dart:async';
import 'package:flutter/services.dart';
import 'dart:io' show Platform;
import 'package:device_id/device_id.dart';
/// Files to include (use the part keyword)
part 'package:health/src/units.dart';
part 'package:health/src/data_types.dart';
part 'package:health/src/functions.dart';
part 'package:health/src/health_data_point.dart';
part 'package:health/src/health_factory.dart';
Each of the source code should have no imports, but should instead use the part of
keyword, to declare that it belongs to the library. Any imports made in the library will be available in the source code files.
Example:
part of health;
/// Source code below
String _enumToString(enumItem) => enumItem.toString().split('.').last;
enum PlatformType { IOS, ANDROID }
You must provide a description, version and webpage. See the example below
name: health
description: Wrapper for the iOS HealthKit and Android GoogleFit services.
version: 2.0.2
homepage: https://github.com/cph-cachet/flutter-plugins
It is sufficient to link to the root of this repository since the issue tracker is the same for all plugins.
State what has been done in the update you are publishing, example:
## 2.0.2
* Updated the API to take a list of types rather than a single type, when requesting health data.
You must provide an example to demonstrate how the package or plugin can be used. Often this is done by making a Flutter application which uses the plugin/package to produce some result. This example application is located in <package name>/example
. For plugins, this application is auto generated, but for packages you must do this yourself. This can be done with:
flutter create example
Run the following command in the root of the project:
flutter packages pub publish
This is hard to do, the best way is usually to make a native app that uses the sensors to verify that your native source code works, and then copy-pasting this source code into your Flutter project.
Use an editor such as vscode or the like, XCode won't give you syntax highlights. This is why you should make sure the source code works before copy pasting it into the Flutter project.
Open the <package name>/example/android
project in Android studio and in the file explorer on the left, navigate to the directory named after the package, ex health
, rather than the app
directory. This will give you syntax highlighting when you edit the native source code.
Permissions cannot be inherited from a package, this means that the programmer must specify permissions in their Flutter app, and you must specify this in the example
app as well.
On Android, permissions are specified inside the AndroidManifest.xml
file, found at android/app/src/main/AndroidManifest.xml
.
On iOS, permissions are specified inside the Info.plist
file, found at ios/Runner/Info.plist
This channel is used for simple 'get' calls, ex 'get the battery level'. A single result is produced.
Example:
/// Set parameters
Map<String, int> interval = {'start': start, 'end': end};
/// Get result and parse it as a Map of <String, double>
Map usage = await _methodChannel.invokeMethod('getUsage', interval);
This channel is used for listening to events, i.e. a stream is returned which produces one or more events, until canceled. Example:
static const EventChannel _noiseEventChannel = EventChannel(EVENT_CHANNEL_NAME);
Stream<List<double>> _stream;
StreamSubscription<List<dynamic>> _subscription;
Stream<List<double>> get audioStream {
if (_stream == null) {
_stream = _noiseEventChannel
.receiveBroadcastStream()
.map((buffer) => buffer as List<dynamic>)
.map((list) => list.map((e) => double.parse('$e')).toList());
}
return _stream;
}