diff --git a/README.md b/README.md
index 0b2c763f..8fec3c9c 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,5 @@
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
-⚠️ ⚠️
-We are no longer mantaining this library. Feel free to fork it and work on your own branch.
-⚠️ ⚠️
-
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
-
# Segment plugin
+
[](https://pub.dev/packages/flutter_segment)
[](https://pub.dev/packages/lint)
@@ -16,35 +8,40 @@ This library was created by our friends at [claimsforce-gmbh](https://github.com
Flutter plugin to support iOS, Android and Web sources at https://segment.com.
### Future development
+
We want to prepare flutter-segment for the future!
Please have a look at [this issue](https://github.com/claimsforce-gmbh/flutter-segment/issues/46) and let us know what you think.
## Usage
+
To use this plugin, add `flutter_segment` as a [dependency in your pubspec.yaml file](https://flutter.io/platform-plugins/).
### Important note for iOS usage
+
Since version `3.5.0` we are forcing all users to use `use_frameworks!` within the [`Podfile`](https://github.com/claimsforce-gmbh/flutter-segment/blob/master/example/ios/Podfile#L31) due to import issues of some 3rd party dependencies.
### Supported methods
+
| Method | Android | iOS | Web | MacOS | Windows | Linux |
-|------------------|---|---|---|---|---|---|
-| `identify` | X | X | X | | | |
-| `track` | X | X | X | | | |
-| `screen` | X | X | X | | | |
-| `group` | X | X | X | | | |
-| `alias` | X | X | X | | | |
-| `getAnonymousId` | X | X | X | | | |
-| `reset` | X | X | X | | | |
-| `disable` | X | X | | | | |
-| `enable` | X | X | | | | |
-| `flush` | X | X | | | | |
-| `debug` | X* | X | X | | | |
-| `setContext` | X | X | | | | |
+| ---------------- | ------- | --- | --- | ----- | ------- | ----- |
+| `identify` | X | X | X | | | |
+| `track` | X | X | X | | | |
+| `screen` | X | X | X | | | |
+| `group` | X | X | X | | | |
+| `alias` | X | X | X | | | |
+| `getAnonymousId` | X | X | X | | | |
+| `reset` | X | X | X | | | |
+| `disable` | X | X | | | | |
+| `enable` | X | X | | | | |
+| `flush` | X | X | | | | |
+| `debug` | X\* | X | X | | | |
+| `setContext` | X | X | | | | |
\* Debugging must be set as a configuration parameter in `AndroidManifest.xml` (see below). The official segment library does not offer the debug method for Android.
### Example
-``` dart
+
+```dart
import 'package:flutter/material.dart';
import 'package:flutter_segment/flutter_segment.dart';
@@ -85,25 +82,27 @@ class MyApp extends StatelessWidget {
}
```
-
## Migration from `v2.x` to `v3.x`
+
In `v3.x` we removed branch io integration as the package is in the the maintenance mode and uses outdated dependencies.
If you don't use `ENABLE_BRANCH_IO_INTEGRATION` you are good to go.
If you want to continue using `ENABLE_BRANCH_IO_INTEGRATION` then use `v2.x` of this package.
## Installation
+
Setup your Android, iOS and/or web sources as described at Segment.com and generate your write keys.
Set your Segment write key and change the automatic event tracking (only for Android and iOS) on if you wish the library to take care of it for you.
Remember that the application lifecycle events won't have any special context set for you by the time it is initialized.
### Via Dart Code
+
```dart
void main() {
/// Wait until the platform channel is properly initialized so we can call
/// `setContext` during the app initialization.
WidgetsFlutterBinding.ensureInitialized();
-
+
String writeKey;
if(Platform.isAndroid){
writeKey = "ANDROID_WRITE_KEY";
@@ -122,7 +121,8 @@ void main() {
}
```
-### Android _(Deprecated*)_
+### Android _(Deprecated\*)_
+
```xml
@@ -137,7 +137,8 @@ void main() {
```
-### iOS _(Deprecated*)_
+### iOS _(Deprecated\*)_
+
```xml
@@ -156,27 +157,29 @@ void main() {
```
### Web
+
```html
-
- [...]
-
-
-
-
-
+
+ [...]
+
+
+
+
+
-
```
+
For more informations please check: https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/quickstart/
## Sending device tokens strings for push notifications
+
Segment integrates with 3rd parties that allow sending push notifications.
In order to do that you will need to provide it with the device token string - which can be obtained using one of the several Flutter libraries.
@@ -199,17 +202,20 @@ await Segment.track(eventName: 'Application Opened');
```
A few important points:
+
- The token is propagated as-is to Segment through the context field, without any manipulation or intermediate calls to Segment's libraries. Strucutred data - such as APNs - need to be properly converted to its string representation beforehand
-- On iOS, once the `device.token` is set, calling `setContext({})` will *not* clean up its value. This occurs due to the existence of another method from segment's library that sets the device token for Apple Push Notification service (APNs )
+- On iOS, once the `device.token` is set, calling `setContext({})` will _not_ clean up its value. This occurs due to the existence of another method from segment's library that sets the device token for Apple Push Notification service (APNs )
- `setContext` always overrides any previous values that were set in a previous call to `setContext`
- `setContext` is not persisted after the application is closed
## Setting integration options
+
If you intend to use any specific integrations with third parties, such as custom Session IDs for Amplitude, you'll need to set it using options for each call, or globally when the application was started.
### Setting the options in every call
The methods below support `options` as parameters:
+
- `identify({@required userId, Map traits, Map options})`
- `track({@required String eventName, Map properties, Map options})`
- `screen({@required String screenName, Map properties, Map options})`
@@ -231,8 +237,8 @@ Segment.screen(
```
### Setting the options globally
-You can also set the default options to be used in every method call, if the call omits the options parameter. Just set `SegmentDefaultOptions.instance.options`. For example:
+You can also set the default options to be used in every method call, if the call omits the options parameter. Just set `SegmentDefaultOptions.instance.options`. For example:
```dart
SegmentDefaultOptions.instance.options = {
@@ -245,9 +251,11 @@ SegmentDefaultOptions.instance.options = {
```
## Issues
+
Please file any issues, bugs, or feature requests in the [GitHub repo](https://github.com/claimsforce-gmbh/flutter-segment/issues/new).
## Contributing
+
If you wish to contribute a change to this repo, please send a [pull request](https://github.com/claimsforce-gmbh/flutter-segment/pulls).
-_*This installation method will be removed, please use the [Installation via Dart Code](#via-dart-code) instructions._
+_\*This installation method will be removed, please use the [Installation via Dart Code](#via-dart-code) instructions._
diff --git a/android/build.gradle b/android/build.gradle
index ad7e38e2..c9d5269c 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -1,4 +1,4 @@
-group 'com.example.flutter_segment'
+group 'io.draftea.flutter_segment'
version '3.12.1'
buildscript {
@@ -24,7 +24,7 @@ apply plugin: 'com.android.library'
android {
if (project.android.hasProperty("namespace")) {
- namespace 'com.example.flutterSegment'
+ namespace 'io.draftea.flutterSegment'
}
compileSdk 33
diff --git a/android/src/main/java/com/example/flutter_segment/FlutterSegmentOptions.java b/android/src/main/java/io/draftea/flutter_segment/FlutterSegmentOptions.java
similarity index 74%
rename from android/src/main/java/com/example/flutter_segment/FlutterSegmentOptions.java
rename to android/src/main/java/io/draftea/flutter_segment/FlutterSegmentOptions.java
index 2c0975d9..9b4a3376 100644
--- a/android/src/main/java/com/example/flutter_segment/FlutterSegmentOptions.java
+++ b/android/src/main/java/io/draftea/flutter_segment/FlutterSegmentOptions.java
@@ -1,4 +1,4 @@
-package com.example.flutter_segment;
+package io.draftea.flutter_segment;
import android.os.Bundle;
@@ -11,13 +11,12 @@ public class FlutterSegmentOptions {
private final Boolean appsflyerIntegrationEnabled;
private final Boolean debug;
- public FlutterSegmentOptions(
+ public FlutterSegmentOptions(
String writeKey,
Boolean trackApplicationLifecycleEvents,
Boolean amplitudeIntegrationEnabled,
Boolean appsflyerIntegrationEnabled,
- Boolean debug
- ) {
+ Boolean debug) {
this.writeKey = writeKey;
this.trackApplicationLifecycleEvents = trackApplicationLifecycleEvents;
this.amplitudeIntegrationEnabled = amplitudeIntegrationEnabled;
@@ -47,11 +46,15 @@ public Boolean getDebug() {
static FlutterSegmentOptions create(Bundle bundle) {
String writeKey = bundle.getString("com.claimsforce.segment.WRITE_KEY");
- Boolean trackApplicationLifecycleEvents = bundle.getBoolean("com.claimsforce.segment.TRACK_APPLICATION_LIFECYCLE_EVENTS");
- Boolean isAmplitudeIntegrationEnabled = bundle.getBoolean("com.claimsforce.segment.ENABLE_AMPLITUDE_INTEGRATION", false);
- Boolean isAppsflyerIntegrationEnabled = bundle.getBoolean("com.claimsforce.segment.ENABLE_APPSFLYER_INTEGRATION", false);
+ Boolean trackApplicationLifecycleEvents = bundle
+ .getBoolean("com.claimsforce.segment.TRACK_APPLICATION_LIFECYCLE_EVENTS");
+ Boolean isAmplitudeIntegrationEnabled = bundle
+ .getBoolean("com.claimsforce.segment.ENABLE_AMPLITUDE_INTEGRATION", false);
+ Boolean isAppsflyerIntegrationEnabled = bundle
+ .getBoolean("com.claimsforce.segment.ENABLE_APPSFLYER_INTEGRATION", false);
Boolean debug = bundle.getBoolean("com.claimsforce.segment.DEBUG", false);
- return new FlutterSegmentOptions(writeKey, trackApplicationLifecycleEvents, isAmplitudeIntegrationEnabled, isAppsflyerIntegrationEnabled, debug);
+ return new FlutterSegmentOptions(writeKey, trackApplicationLifecycleEvents, isAmplitudeIntegrationEnabled,
+ isAppsflyerIntegrationEnabled, debug);
}
static FlutterSegmentOptions create(HashMap options) {
@@ -60,7 +63,8 @@ static FlutterSegmentOptions create(HashMap options) {
Boolean isAmplitudeIntegrationEnabled = orFalse((Boolean) options.get("amplitudeIntegrationEnabled"));
Boolean isAppsflyerIntegrationEnabled = orFalse((Boolean) options.get("appsflyerIntegrationEnabled"));
Boolean debug = orFalse((Boolean) options.get("debug"));
- return new FlutterSegmentOptions(writeKey, trackApplicationLifecycleEvents, isAmplitudeIntegrationEnabled, isAppsflyerIntegrationEnabled, debug);
+ return new FlutterSegmentOptions(writeKey, trackApplicationLifecycleEvents, isAmplitudeIntegrationEnabled,
+ isAppsflyerIntegrationEnabled, debug);
}
private static Boolean orFalse(Boolean value) {
diff --git a/android/src/main/java/com/example/flutter_segment/FlutterSegmentPlugin.java b/android/src/main/java/io/draftea/flutter_segment/FlutterSegmentPlugin.java
similarity index 85%
rename from android/src/main/java/com/example/flutter_segment/FlutterSegmentPlugin.java
rename to android/src/main/java/io/draftea/flutter_segment/FlutterSegmentPlugin.java
index 40b92236..fe76afd4 100644
--- a/android/src/main/java/com/example/flutter_segment/FlutterSegmentPlugin.java
+++ b/android/src/main/java/io/draftea/flutter_segment/FlutterSegmentPlugin.java
@@ -1,4 +1,4 @@
-package com.example.flutter_segment;
+package io.draftea.flutter_segment;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -51,7 +51,7 @@ private void setupChannels(Context applicationContext, BinaryMessenger messenger
try {
ApplicationInfo ai = applicationContext.getPackageManager()
- .getApplicationInfo(applicationContext.getPackageName(), PackageManager.GET_META_DATA);
+ .getApplicationInfo(applicationContext.getPackageName(), PackageManager.GET_META_DATA);
Bundle bundle = ai.metaData;
@@ -88,38 +88,38 @@ private void setupChannels(FlutterSegmentOptions options) {
// Here we build a middleware that just appends data to the current context
// using the [deepMerge] strategy.
analyticsBuilder.useSourceMiddleware(
- new Middleware() {
- @Override
- public void intercept(Chain chain) {
- try {
- if (appendToContextMiddleware == null) {
- chain.proceed(chain.payload());
- return;
- }
-
- BasePayload payload = chain.payload();
- Map originalContext = new LinkedHashMap<>(payload.context());
- Map mergedContext = FlutterSegmentPlugin.deepMerge(
- originalContext,
- appendToContextMiddleware
- );
-
- BasePayload newPayload = payload.toBuilder()
- .context(mergedContext)
- .build();
-
- chain.proceed(newPayload);
- } catch (Exception e) {
- Log.e("FlutterSegment", e.getMessage());
- chain.proceed(chain.payload());
- }
+ new Middleware() {
+ @Override
+ public void intercept(Chain chain) {
+ try {
+ if (appendToContextMiddleware == null) {
+ chain.proceed(chain.payload());
+ return;
}
+
+ BasePayload payload = chain.payload();
+ Map originalContext = new LinkedHashMap<>(payload.context());
+ Map mergedContext = FlutterSegmentPlugin.deepMerge(
+ originalContext,
+ appendToContextMiddleware);
+
+ BasePayload newPayload = payload.toBuilder()
+ .context(mergedContext)
+ .build();
+
+ chain.proceed(newPayload);
+ } catch (Exception e) {
+ Log.e("FlutterSegment", e.getMessage());
+ chain.proceed(chain.payload());
}
- );
+ }
+ });
// Set the initialized instance as globally accessible.
- // It may throw an exception if we are trying to re-register a singleton Analytics instance.
- // This state may happen after the app is popped (back button until the app closes)
+ // It may throw an exception if we are trying to re-register a singleton
+ // Analytics instance.
+ // This state may happen after the app is popped (back button until the app
+ // closes)
// and opened again from the TaskManager.
try {
Analytics.setSingletonInstance(analyticsBuilder.build());
@@ -205,14 +205,13 @@ private void identify(MethodCall call, Result result) {
}
private void callIdentify(
- String userId,
- HashMap traitsData,
- HashMap optionsData
- ) {
+ String userId,
+ HashMap traitsData,
+ HashMap optionsData) {
Traits traits = new Traits();
Options options = this.buildOptions(optionsData);
- for(Map.Entry trait : traitsData.entrySet()) {
+ for (Map.Entry trait : traitsData.entrySet()) {
String key = trait.getKey();
Object value = trait.getValue();
traits.putValue(key, value);
@@ -234,10 +233,9 @@ private void track(MethodCall call, Result result) {
}
private void callTrack(
- String eventName,
- HashMap propertiesData,
- HashMap optionsData
- ) {
+ String eventName,
+ HashMap propertiesData,
+ HashMap optionsData) {
Properties properties = propertiesMapper.buildProperties(propertiesData);
Options options = this.buildOptions(optionsData);
@@ -257,10 +255,9 @@ private void screen(MethodCall call, Result result) {
}
private void callScreen(
- String screenName,
- HashMap propertiesData,
- HashMap optionsData
- ) {
+ String screenName,
+ HashMap propertiesData,
+ HashMap optionsData) {
Properties properties = propertiesMapper.buildProperties(propertiesData);
Options options = this.buildOptions(optionsData);
@@ -280,14 +277,13 @@ private void group(MethodCall call, Result result) {
}
private void callGroup(
- String groupId,
- HashMap traitsData,
- HashMap optionsData
- ) {
+ String groupId,
+ HashMap traitsData,
+ HashMap optionsData) {
Traits traits = new Traits();
Options options = this.buildOptions(optionsData);
- for(Map.Entry trait : traitsData.entrySet()) {
+ for (Map.Entry trait : traitsData.entrySet()) {
String key = trait.getKey();
Object value = trait.getValue();
traits.putValue(key, value);
@@ -367,8 +363,10 @@ private void disable(MethodCall call, Result result) {
}
/**
- * Enables / disables / sets custom integration properties so Segment can properly
+ * Enables / disables / sets custom integration properties so Segment can
+ * properly
* interact with 3rd parties, such as Amplitude.
+ *
* @see https://segment.com/docs/connections/sources/catalog/libraries/mobile/android/#selecting-destinations
* @see https://github.com/segmentio/analytics-android/blob/master/analytics/src/main/java/com/segment/analytics/Options.java
*/
@@ -377,16 +375,17 @@ private Options buildOptions(HashMap optionsData) {
Options options = new Options();
if (optionsData != null &&
- optionsData.containsKey("integrations") &&
- (optionsData.get("integrations") instanceof HashMap)) {
- for (Map.Entry integration : ((HashMap)optionsData.get("integrations")).entrySet()) {
+ optionsData.containsKey("integrations") &&
+ (optionsData.get("integrations") instanceof HashMap)) {
+ for (Map.Entry integration : ((HashMap) optionsData.get("integrations"))
+ .entrySet()) {
String key = integration.getKey();
if (integration.getValue() instanceof HashMap) {
- HashMap values = ((HashMap)integration.getValue());
+ HashMap values = ((HashMap) integration.getValue());
options.setIntegrationOptions(key, values);
} else if (integration.getValue() instanceof Boolean) {
- Boolean value = ((Boolean)integration.getValue());
+ Boolean value = ((Boolean) integration.getValue());
options.setIntegration(key, value);
}
}
diff --git a/android/src/main/java/com/example/flutter_segment/PropertiesMapper.java b/android/src/main/java/io/draftea/flutter_segment/PropertiesMapper.java
similarity index 82%
rename from android/src/main/java/com/example/flutter_segment/PropertiesMapper.java
rename to android/src/main/java/io/draftea/flutter_segment/PropertiesMapper.java
index ec79cbc9..060a0510 100644
--- a/android/src/main/java/com/example/flutter_segment/PropertiesMapper.java
+++ b/android/src/main/java/io/draftea/flutter_segment/PropertiesMapper.java
@@ -1,4 +1,4 @@
-package com.example.flutter_segment;
+package io.draftea.flutter_segment;
import androidx.annotation.VisibleForTesting;
@@ -11,11 +11,11 @@ public class PropertiesMapper {
protected Properties buildProperties(Map map) {
Properties properties = new Properties();
- for(Map.Entry property : map.entrySet()) {
+ for (Map.Entry property : map.entrySet()) {
String key = property.getKey();
Object value = property.getValue();
- if (value instanceof Map){
+ if (value instanceof Map) {
Properties nestedProperties = buildProperties((Map) value);
properties.putValue(key, nestedProperties);
} else {
diff --git a/example/pubspec.lock b/example/pubspec.lock
index 0418fc69..fc006dec 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -68,7 +68,7 @@ packages:
path: ".."
relative: true
source: path
- version: "3.13.2"
+ version: "4.0.0"
flutter_test:
dependency: "direct dev"
description: flutter
diff --git a/ios/flutter_segment.podspec b/ios/flutter_segment.podspec
index 951c5acd..e16db850 100644
--- a/ios/flutter_segment.podspec
+++ b/ios/flutter_segment.podspec
@@ -3,15 +3,15 @@
#
Pod::Spec.new do |s|
s.name = 'flutter_segment'
- s.version = '3.13.1'
+ s.version = '4.0.0'
s.summary = 'Segment.io plugin for Flutter'
s.description = <<-DESC
Library to let Flutter apps use Segment.io
DESC
- s.homepage = 'https://github.com/la-haus/flutter-segment'
+ s.homepage = 'https://github.com/Drafteame/flutter-segment'
s.license = { :type => 'MIT', :file => '../LICENSE' }
- s.author = 'La Haus'
- s.source = { :git => "https://github.com/la-haus/flutter-segment.git", :tag => s.version.to_s }
+ s.author = 'Draftea'
+ s.source = { :git => "https://github.com/Drafteame/flutter-segment.git", :tag => s.version.to_s }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
diff --git a/pubspec.yaml b/pubspec.yaml
index 9abb576d..5978dafe 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,13 +1,13 @@
name: flutter_segment
description: Flutter implementation of Segment Analytics for iOS, Android and Web
-version: 3.13.2
+version: 4.0.0
homepage: https://lahaus.com
repository: https://github.com/la-haus/flutter-library-segment
issue_tracker: https://github.com/la-haus/flutter-library-segment/issues
documentation: https://github.com/la-haus/flutter-library-segment#readme
environment:
- sdk: '>=2.12.0 <3.0.0'
+ sdk: ">=2.12.0 <3.0.0"
flutter: ">=1.12.13+hotfix.4"
dependencies:
@@ -26,7 +26,7 @@ flutter:
plugin:
platforms:
android:
- package: com.example.flutter_segment
+ package: io.draftea.flutter_segment
pluginClass: FlutterSegmentPlugin
ios:
pluginClass: FlutterSegmentPlugin