Merge pull request #87 from dart-lang/3_0
rev to 3.0.0-dev
diff --git a/.analysis_options b/.analysis_options
index 19c7129..a10d4c5 100644
--- a/.analysis_options
+++ b/.analysis_options
@@ -1,4 +1,2 @@
analyzer:
strong-mode: true
- exclude:
- - lib/src/usage_impl_flutter.dart
diff --git a/.travis.yml b/.travis.yml
index 35def79..9e27d1f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,11 +1,3 @@
language: dart
-dart:
- - dev
sudo: false
-
-# before_install:
-# - "export CHROME_ARGS=--no-sandbox"
-# - "export DISPLAY=:99.0"
-# - "sh -e /etc/init.d/xvfb start"
-
script: ./tool/travis.sh
diff --git a/changelog.md b/changelog.md
index 4379c44..f62e4dd 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,7 +1,9 @@
# Changelog
-## unreleased
-- updated the Flutter example pubspec to use the newer Flutter sdk reference style
+## 3.0.0
+- removed the use of configurable imports
+- removed the Flutter specific entry-point; Flutter apps can now use the
+ regular `dart:io` entrypoint (AnalyticsIO)
## 2.2.2
- adjust the Flutter usage client to Flutter API changes
diff --git a/example/example.dart b/example/example.dart
index 27fb5fc..06578c3 100644
--- a/example/example.dart
+++ b/example/example.dart
@@ -5,10 +5,9 @@
/// A simple web app to hand-test the usage library.
library usage_example;
-import 'dart:async';
import 'dart:html';
-import 'package:usage/usage.dart';
+import 'package:usage/usage_html.dart';
Analytics _analytics;
String _lastUa;
@@ -22,28 +21,28 @@
String _ua() => (querySelector('#ua') as InputElement).value.trim();
-Future<Analytics> getAnalytics() async {
+Analytics getAnalytics() {
if (_analytics == null || _lastUa != _ua()) {
_lastUa = _ua();
- _analytics = await Analytics.create(_lastUa, 'Test app', '1.0');
+ _analytics = new AnalyticsHtml(_lastUa, 'Test app', '1.0');
_analytics.sendScreenView(window.location.pathname);
}
return _analytics;
}
-Future _handleFoo() async {
- Analytics analytics = await getAnalytics();
+void _handleFoo() {
+ Analytics analytics = getAnalytics();
analytics.sendEvent('main', 'foo');
}
-Future _handleBar() async {
- Analytics analytics = await getAnalytics();
+void _handleBar() {
+ Analytics analytics = getAnalytics();
analytics.sendEvent('main', 'bar');
}
-Future _changePage() async {
- Analytics analytics = await getAnalytics();
+void _changePage() {
+ Analytics analytics = getAnalytics();
window.history.pushState(null, 'new page', '${++_count}.html');
analytics.sendScreenView(window.location.pathname);
}
diff --git a/example/flutter_example/.gitignore b/example/flutter_example/.gitignore
deleted file mode 100644
index 14c7d4c..0000000
--- a/example/flutter_example/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-.DS_Store
-.atom/
-.idea
-.packages
-.pub/
-build/
-ios/.generated/
-packages
-pubspec.lock
diff --git a/example/flutter_example/README.md b/example/flutter_example/README.md
deleted file mode 100644
index 7608a60..0000000
--- a/example/flutter_example/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Example of usage package with Flutter
-
-To run the Flutter example, ensure that the pubspec.yaml points to your Flutter
-path. Then run:
-
-```
-pub get
-flutter run
-```
diff --git a/example/flutter_example/android/AndroidManifest.xml b/example/flutter_example/android/AndroidManifest.xml
deleted file mode 100644
index 2e28bb3..0000000
--- a/example/flutter_example/android/AndroidManifest.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.yourcompany.flutterExample"
- android:versionCode="1"
- android:versionName="0.0.1">
-
- <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="21" />
- <uses-permission android:name="android.permission.INTERNET"/>
-
- <application android:name="org.domokit.sky.shell.SkyApplication" android:label="flutter_example" android:icon="@mipmap/ic_launcher">
- <activity android:name="org.domokit.sky.shell.SkyActivity"
- android:launchMode="singleTask"
- android:theme="@android:style/Theme.Black.NoTitleBar"
- android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
- android:hardwareAccelerated="true"
- android:windowSoftInputMode="adjustResize">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
- </application>
-</manifest>
diff --git a/example/flutter_example/android/res/mipmap-hdpi/ic_launcher.png b/example/flutter_example/android/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index f0a55cd..0000000
--- a/example/flutter_example/android/res/mipmap-hdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/example/flutter_example/android/res/mipmap-mdpi/ic_launcher.png b/example/flutter_example/android/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index eb98dc4..0000000
--- a/example/flutter_example/android/res/mipmap-mdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/example/flutter_example/android/res/mipmap-xhdpi/ic_launcher.png b/example/flutter_example/android/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index f1783db..0000000
--- a/example/flutter_example/android/res/mipmap-xhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/example/flutter_example/android/res/mipmap-xxhdpi/ic_launcher.png b/example/flutter_example/android/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index 46828a2..0000000
--- a/example/flutter_example/android/res/mipmap-xxhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/example/flutter_example/android/res/mipmap-xxxhdpi/ic_launcher.png b/example/flutter_example/android/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index a527671..0000000
--- a/example/flutter_example/android/res/mipmap-xxxhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/example/flutter_example/flutter.yaml b/example/flutter_example/flutter.yaml
deleted file mode 100644
index 2f6cd44..0000000
--- a/example/flutter_example/flutter.yaml
+++ /dev/null
@@ -1,2 +0,0 @@
-name: flutter_example
-uses-material-design: true
diff --git a/example/flutter_example/lib/main.dart b/example/flutter_example/lib/main.dart
deleted file mode 100644
index eceae54..0000000
--- a/example/flutter_example/lib/main.dart
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2016, the Flutter project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:flutter/material.dart';
-import 'package:usage/usage.dart';
-
-Future main() async {
- runApp(new Container());
- Analytics ga = await Analytics.create('UA-67589403-4', 'ga_test', '1.0');
- runApp(new MaterialApp(
- title: 'Usage Example',
- theme: new ThemeData.dark(),
- routes: <String, WidgetBuilder>{
- '/': (BuildContext context) => new FlutterDemo(ga)
- },
- ));
-}
-
-class FlutterDemo extends StatefulWidget {
- FlutterDemo(this.ga);
- Analytics ga;
- @override
- State createState() => new _FlutterDemoState();
-}
-
-class _FlutterDemoState extends State<FlutterDemo> {
- int _times = 0;
-
- void _handleButtonPressed() {
- config.ga.sendEvent('button', 'pressed');
- setState(() {
- _times++;
- });
- }
-
- void _handleOptIn(bool value) {
- setState(() {
- config.ga.enabled = value;
- });
- }
-
- @override
- Widget build(BuildContext context) {
- return new Scaffold(
- appBar: new AppBar(
- title: new Text('Usage Example'),
- ),
- body: new Column(
- children: <Widget>[
- new Center(
- child: new Text("Button pressed $_times times."),
- ),
- new ListItem(
- onTap: () => _handleOptIn(!config.ga.enabled),
- leading: new Checkbox(
- value: config.ga.enabled,
- onChanged: _handleOptIn,
- ),
- title: new Text("Opt in to analytics"),
- ),
- ],
- mainAxisAlignment: MainAxisAlignment.spaceAround,
- ),
- floatingActionButton: new FloatingActionButton(
- child: new Icon(Icons.add),
- onPressed: _handleButtonPressed,
- ),
- );
- }
-}
diff --git a/example/flutter_example/pubspec.yaml b/example/flutter_example/pubspec.yaml
deleted file mode 100644
index 52d5cb7..0000000
--- a/example/flutter_example/pubspec.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-name: flutter_example
-description: Create a new Flutter project.
-
-environment:
- sdk: ">=1.19.0 <2.0.0"
- flutter: ^0.0.1
-
-dependencies:
- usage:
- path: ../..
- flutter:
- sdk: flutter
diff --git a/example/ga.dart b/example/ga.dart
index e905ea6..51546fc 100644
--- a/example/ga.dart
+++ b/example/ga.dart
@@ -5,11 +5,9 @@
/// A simple command-line app to hand-test the usage library.
library usage_ga;
-import 'dart:async';
+import 'package:usage/usage_io.dart';
-import 'package:usage/usage.dart';
-
-Future main(List args) async {
+void main(List args) {
final String DEFAULT_UA = 'UA-55029513-1';
if (args.isEmpty) {
@@ -21,7 +19,7 @@
String ua = args.isEmpty ? DEFAULT_UA : args.first;
- Analytics ga = await Analytics.create(ua, 'ga_test', '1.0');
+ Analytics ga = new AnalyticsIO(ua, 'ga_test', '3.0');
ga.sendScreenView('home').then((_) {
return ga.sendScreenView('files');
diff --git a/lib/src/usage_impl_flutter.dart b/lib/src/usage_impl_flutter.dart
deleted file mode 100644
index 58f90a3..0000000
--- a/lib/src/usage_impl_flutter.dart
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:convert' show JSON;
-import 'dart:io';
-
-import 'package:flutter/http.dart' as http;
-import 'package:flutter/services.dart';
-import 'package:path/path.dart' as path;
-
-import '../usage.dart';
-import 'usage_impl.dart';
-
-Future<Analytics> createAnalytics(
- String trackingId,
- String applicationName,
- String applicationVersion, {
- String analyticsUrl
-}) async {
- Directory dataDirectory = await PathProvider.getTemporaryDirectory();
-
- String fileName = '.${applicationName.replaceAll(' ', '_')}';
- File file = new File(path.join(dataDirectory.path, fileName));
- await file.create();
- String contents = await file.readAsString();
- if (contents.isEmpty) contents = '{}';
- Map map = JSON.decode(contents);
-
- return new AnalyticsImpl(
- trackingId,
- new FlutterPersistentProperties(applicationName, file, map),
- new FlutterPostHandler(),
- applicationName: applicationName,
- applicationVersion: applicationVersion,
- analyticsUrl: analyticsUrl
- );
-}
-
-String _createUserAgent() {
- // Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en)
- // Dart/1.8.0-edge.41170 (macos; macos; macos; null)
- String os = Platform.operatingSystem;
- String locale = Platform.environment['LANG'];
- return "Dart/${_dartVersion()} (${os}; ${os}; ${os}; ${locale})";
-}
-
-String _dartVersion() {
- String ver = Platform.version;
- int index = ver.indexOf(' ');
- if (index != -1) ver = ver.substring(0, index);
- return ver;
-}
-
-class FlutterPostHandler extends PostHandler {
- final String _userAgent;
- final HttpClient mockClient;
-
- FlutterPostHandler({HttpClient this.mockClient}) : _userAgent = _createUserAgent();
-
- Future sendPost(String url, Map<String, dynamic> parameters) {
- // Add custom parameters for OS and the Dart version.
- parameters['cd1'] = Platform.operatingSystem;
- parameters['cd2'] = 'dart ${_dartVersion()}';
-
- String data = postEncode(parameters);
-
- Map<String, String> headers = <String, String>{ 'User-Agent': _userAgent };
-
- return http.post(url, body: data, headers: headers);
- }
-}
-
-class FlutterPersistentProperties extends PersistentProperties {
- File _file;
- Map _map;
- FlutterPersistentProperties(String name, this._file, this._map) : super(name);
-
- dynamic operator[](String key) => _map[key];
-
- void operator[]=(String key, dynamic value) {
- if (value == null) {
- _map.remove(key);
- } else {
- _map[key] = value;
- }
-
- _file.writeAsString(JSON.encode(_map) + '\n');
- }
-}
diff --git a/lib/src/usage_impl_html.dart b/lib/src/usage_impl_html.dart
index 6a5922c..184eaa6 100644
--- a/lib/src/usage_impl_html.dart
+++ b/lib/src/usage_impl_html.dart
@@ -6,23 +6,8 @@
import 'dart:convert' show JSON;
import 'dart:html';
-import '../usage.dart';
import 'usage_impl.dart';
-Future<Analytics> createAnalytics(
- String trackingId,
- String applicationName,
- String applicationVersion, {
- String analyticsUrl
-}) {
- return new Future.value(new AnalyticsHtml(
- trackingId,
- applicationName,
- applicationVersion,
- analyticsUrl: analyticsUrl
- ));
-}
-
class AnalyticsHtml extends AnalyticsImpl {
AnalyticsHtml(String trackingId, String applicationName, String applicationVersion, {
String analyticsUrl
diff --git a/lib/src/usage_impl_io.dart b/lib/src/usage_impl_io.dart
index fff224a..1a5c73e 100644
--- a/lib/src/usage_impl_io.dart
+++ b/lib/src/usage_impl_io.dart
@@ -8,29 +8,23 @@
import 'package:path/path.dart' as path;
-import '../usage.dart';
import 'usage_impl.dart';
-Future<Analytics> createAnalytics(
- String trackingId,
- String applicationName,
- String applicationVersion, {
- String analyticsUrl
-}) {
- return new Future.value(new AnalyticsIO(
- trackingId,
- applicationName,
- applicationVersion,
- analyticsUrl: analyticsUrl
- ));
-}
-
+/// Create a new Analytics instance.
+///
+/// `trackingId`, `applicationName`, and `applicationVersion` values should be supplied.
+/// `analyticsUrl` is optional, and lets user's substitute their own analytics URL for
+/// the default. `documentDirectory` is where the analytics settings are stored. It
+/// defaults to the user home directory. For regular `dart:io` apps this doesn't need to
+/// be supplied. For Flutter applications, you should pass in a value like
+/// `PathProvider.getApplicationDocumentsDirectory()`.
class AnalyticsIO extends AnalyticsImpl {
AnalyticsIO(String trackingId, String applicationName, String applicationVersion, {
- String analyticsUrl
+ String analyticsUrl,
+ Directory documentDirectory
}) : super(
trackingId,
- new IOPersistentProperties(applicationName),
+ new IOPersistentProperties(applicationName, documentDirPath: documentDirectory?.path),
new IOPostHandler(),
applicationName: applicationName,
applicationVersion: applicationVersion,
@@ -39,18 +33,22 @@
}
String _createUserAgent() {
- if (Platform.isMacOS) {
- return 'Mozilla/5.0 (Macintosh; Intel Mac OS X)';
+ final String locale = getPlatformLocale() ?? '';
+
+ if (Platform.isAndroid) {
+ return 'Mozilla/5.0 (Android; Mobile; ${locale})';
+ } else if (Platform.isIOS) {
+ return 'Mozilla/5.0 (iPhone; U; CPU iPhone OS like Mac OS X; ${locale})';
} else if (Platform.isMacOS) {
- return 'Mozilla/5.0 (Windows; Windows)';
+ return 'Mozilla/5.0 (Macintosh; Intel Mac OS X; Macintosh; ${locale})';
+ } else if (Platform.isWindows) {
+ return 'Mozilla/5.0 (Windows; Windows; Windows; ${locale})';
} else if (Platform.isLinux) {
- return 'Mozilla/5.0 (Linux; Linux)';
+ return 'Mozilla/5.0 (Linux; Linux; Linux; ${locale})';
} else {
- // Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en)
- // Dart/1.8.0-edge.41170 (macos; macos; macos; null)
+ // Dart/1.8.0 (macos; macos; macos; en_US)
String os = Platform.operatingSystem;
- String locale = Platform.environment['LANG'];
- return "Dart/${_dartVersion()} (${os}; ${os}; ${os}; ${locale})";
+ return "Dart/${getDartVersion()} (${os}; ${os}; ${os}; ${locale})";
}
}
@@ -60,7 +58,7 @@
return value == null ? '.' : value;
}
-String _dartVersion() {
+String getDartVersion() {
String ver = Platform.version;
int index = ver.indexOf(' ');
if (index != -1) ver = ver.substring(0, index);
@@ -74,10 +72,6 @@
IOPostHandler({HttpClient this.mockClient}) : _userAgent = _createUserAgent();
Future sendPost(String url, Map<String, dynamic> parameters) async {
- // Add custom parameters for OS and the Dart version.
- parameters['cd1'] = Platform.operatingSystem;
- parameters['cd2'] = 'dart ${_dartVersion()}';
-
String data = postEncode(parameters);
HttpClient client = mockClient != null ? mockClient : new HttpClient();
@@ -98,9 +92,10 @@
File _file;
Map _map;
- IOPersistentProperties(String name) : super(name) {
+ IOPersistentProperties(String name, { String documentDirPath }) : super(name) {
String fileName = '.${name.replaceAll(' ', '_')}';
- _file = new File(path.join(_userHomeDir(), fileName));
+ documentDirPath ??= _userHomeDir();
+ _file = new File(path.join(documentDirPath, fileName));
try {
if (!_file.existsSync()) _file.createSync();
@@ -129,3 +124,22 @@
} catch (_) { }
}
}
+
+/// Return the string for the platform's locale; return's `null` if the locale
+/// can't be determined.
+String getPlatformLocale() {
+ String locale = Platform.environment['LANG'];
+ if (locale == null) return null;
+
+ if (locale != null) {
+ // Convert `en_US.UTF-8` to `en_US`.
+ int index = locale.indexOf('.');
+ if (index != null) locale = locale.substring(0, index);
+
+ // Convert `en_US` to `en`.
+ index = locale.indexOf('_');
+ if (index != null) locale = locale.substring(0, index);
+ }
+
+ return locale;
+}
diff --git a/lib/usage.dart b/lib/usage.dart
index 53f1812..0d0a5ca 100644
--- a/lib/usage.dart
+++ b/lib/usage.dart
@@ -3,15 +3,17 @@
// BSD-style license that can be found in the LICENSE file.
/**
- * `usage` is a wrapper around Google Analytics for both command-line, web, and
- * Flutter apps.
+ * `usage` is a wrapper around Google Analytics for both command-line apps
+ * and web apps.
*
- * In order to use this library, call the [Analytics.create] static method.
- * You'll get either the command-line, web, or Flutter implementation based on
- * the current platform.
+ * In order to use this library as a web app, import the `analytics_html.dart`
+ * library and instantiate the [AnalyticsHtml] class.
*
- * When creating a new Analytics instance, you need to provide a Google
- * Analytics tracking ID, the application name, and the application version.
+ * In order to use this library as a command-line app, import the
+ * `analytics_io.dart` library and instantiate the [AnalyticsIO] class.
+ *
+ * For both classes, you need to provide a Google Analytics tracking ID, the
+ * application name, and the application version.
*
* Your application should provide an opt-in option for the user. If they
* opt-in, set the [optIn] field to `true`. This setting will persist across
@@ -24,40 +26,19 @@
import 'dart:async';
-import 'src/usage_impl_default.dart'
- if (dart.library.js) 'src/usage_impl_html.dart'
- if (dart.library.ui) 'src/usage_impl_flutter.dart'
- if (dart.library.io) 'src/usage_impl_io.dart'
- as impl;
-
// Matches file:/, non-ws, /, non-ws, .dart
final RegExp _pathRegex = new RegExp(r'file:/\S+/(\S+\.dart)');
/**
- * An interface to a Google Analytics session. You'll get the correct one for
- * your platform by calling the [Analytics.create] static method.
- * [AnalyticsMock] can be used for testing or for some variants of an opt-in
- * workflow.
+ * An interface to a Google Analytics session. [AnalyticsHtml] and [AnalyticsIO]
+ * are concrete implementations of this interface. [AnalyticsMock] can be used
+ * for testing or for some varients of an opt-in workflow.
*
- * The analytics information is sent on a best-effort basis. Failures to send
- * the GA information will not result in errors from the asynchronous `send`
- * methods.
+ * The analytics information is sent on a best-effort basis. So, failures to
+ * send the GA information will not result in errors from the asynchronous
+ * `send` methods.
*/
abstract class Analytics {
- static Future<Analytics> create(
- String trackingId,
- String applicationName,
- String applicationVersion, {
- String analyticsUrl
- }) {
- return impl.createAnalytics(
- trackingId,
- applicationName,
- applicationVersion,
- analyticsUrl: analyticsUrl
- );
- }
-
/**
* Tracking ID / Property ID.
*/
diff --git a/lib/usage_html.dart b/lib/usage_html.dart
new file mode 100644
index 0000000..f3dd555
--- /dev/null
+++ b/lib/usage_html.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * In order to use this library import the `usage_html.dart` file and
+ * instantiate the [AnalyticsHtml] class.
+ *
+ * You'll need to provide a Google Analytics tracking ID, the application name,
+ * and the application version.
+ */
+library usage_html;
+
+import 'dart:html';
+
+import 'src/usage_impl.dart';
+import 'src/usage_impl_html.dart';
+
+export 'usage.dart';
+
+/**
+ * An interface to a Google Analytics session, suitable for use in web apps.
+ *
+ * [analyticsUrl] is an optional replacement for the default Google Analytics
+ * URL (`https://www.google-analytics.com/collect`).
+ */
+class AnalyticsHtml extends AnalyticsImpl {
+ AnalyticsHtml(String trackingId, String applicationName, String applicationVersion, {
+ String analyticsUrl
+ }) : super(
+ trackingId,
+ new HtmlPersistentProperties(applicationName),
+ new HtmlPostHandler(),
+ applicationName: applicationName,
+ applicationVersion: applicationVersion,
+ analyticsUrl: analyticsUrl
+ ) {
+ int screenWidth = window.screen.width;
+ int screenHeight = window.screen.height;
+
+ setSessionValue('sr', '${screenWidth}x$screenHeight');
+ setSessionValue('sd', '${window.screen.pixelDepth}-bits');
+ setSessionValue('ul', window.navigator.language);
+ }
+}
diff --git a/lib/usage_io.dart b/lib/usage_io.dart
new file mode 100644
index 0000000..61accf7
--- /dev/null
+++ b/lib/usage_io.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * In order to use this library import the `usage_io.dart` file and
+ * instantiate the [AnalyticsIO] class.
+ *
+ * You'll need to provide a Google Analytics tracking ID, the application name,
+ * and the application version.
+ */
+library usage_io;
+
+import 'src/usage_impl.dart';
+import 'src/usage_impl_io.dart';
+
+export 'usage.dart';
+
+/**
+ * An interface to a Google Analytics session, suitable for use in command-line
+ * applications.
+ *
+ * [analyticsUrl] is an optional replacement for the default Google Analytics
+ * URL (`https://www.google-analytics.com/collect`).
+ */
+class AnalyticsIO extends AnalyticsImpl {
+ AnalyticsIO(String trackingId, String applicationName, String applicationVersion, {
+ String analyticsUrl
+ }) : super(
+ trackingId,
+ new IOPersistentProperties(applicationName),
+ new IOPostHandler(),
+ applicationName: applicationName,
+ applicationVersion: applicationVersion,
+ analyticsUrl: analyticsUrl
+ );
+}
diff --git a/pubspec.yaml b/pubspec.yaml
index 1584380..34dd640 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@
# BSD-style license that can be found in the LICENSE file.
name: usage
-version: 3.0.0-dev.1
+version: 3.0.0
description: A Google Analytics wrapper for both command-line, web, and Flutter apps.
homepage: https://github.com/dart-lang/usage
author: Dart Team <misc@dartlang.org>
diff --git a/readme.md b/readme.md
index e67dd88..9b2331f 100644
--- a/readme.md
+++ b/readme.md
@@ -7,17 +7,38 @@
[![Build Status](https://travis-ci.org/dart-lang/usage.svg)](https://travis-ci.org/dart-lang/usage)
[![Coverage Status](https://img.shields.io/coveralls/dart-lang/usage.svg)](https://coveralls.io/r/dart-lang/usage?branch=master)
-## Using this library
+## For web apps
-In order to use this library, call the `Analytics.create` static method.
-You'll get either the command-line, web, or Flutter implementation based on
-the current platform.
+To use this library as a web app, import the `usage_html.dart` library and
+instantiate the `AnalyticsHtml` class.
When you are creating a new property at [google analytics](https://www.google.com/analytics/)
make sure to select not the website option, but the **mobile app** option.
+## For Flutter apps
+
+Flutter applications can use the `AnalyticsIO` version of this library. They will need
+to specify the documents directory in the constructor, in order to tell the library where
+to save the analytics preferences:
+
+```dart
+import 'package:flutter/services.dart';
+import 'package:usage/usage_io.dart';
+
+void main() {
+ final String UA = ...;
+
+ Analytics ga = new AnalyticsIO(UA, 'ga_test', '3.0',
+ documentsDirectory: PathProvider.getApplicationDocumentsDirectory());
+ ...
+}
+```
+
## For command-line apps
+To use this library as a command-line app, import the `usage_io.dart` library
+and instantiate the `AnalyticsIO` class.
+
Note, for CLI apps, the usage library will send analytics pings asynchronously.
This is useful it that it doesn't block the app generally. It does have one
side-effect, in that outstanding asynchronous requests will block termination
@@ -39,10 +60,10 @@
## Using the API
-Import the package:
+Import the package (in this example we use the `dart:io` version):
```dart
-import 'package:usage/usage.dart';
+import 'package:usage/usage_io.dart';
```
And call some analytics code:
@@ -50,7 +71,8 @@
```dart
final String UA = ...;
-Analytics ga = await Analytics.create(UA, 'ga_test', '1.0');
+Analytics ga = new AnalyticsIO(UA, 'ga_test', '3.0');
+ga.optIn = true;
ga.sendScreenView('home');
ga.sendException('foo exception');
diff --git a/test/usage_impl_io_test.dart b/test/usage_impl_io_test.dart
index 31e8ac8..98da432 100644
--- a/test/usage_impl_io_test.dart
+++ b/test/usage_impl_io_test.dart
@@ -39,6 +39,16 @@
expect(props['foo'], null);
});
});
+
+ group('usage_impl_io', () {
+ test('getPlatformLocale', () {
+ expect(getPlatformLocale(), isNotNull);
+ });
+
+ test('getDartVersion', () {
+ expect(getDartVersion(), isNotNull);
+ });
+ });
}
class MockHttpClient implements HttpClient {
diff --git a/tool/travis.sh b/tool/travis.sh
index e6f3aca..a3f3082 100755
--- a/tool/travis.sh
+++ b/tool/travis.sh
@@ -15,11 +15,7 @@
test/all.dart
# Run the tests.
-dart --conditional_directives -c test/all.dart
-
-# Run the UI/web tests as well.
-#pub build test
-#pub run grinder:test build/test/web.html
+dart -c test/all.dart
# Measure the size of the compiled JS, for the dart:html version of the library.
dart tool/grind.dart build