├── .github └── workflows │ ├── flutter.yml │ └── release.yml ├── .gitignore ├── .metadata ├── .travis.yml ├── .vscode └── settings.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── settings.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── mixpanel │ └── mixpanel_flutter │ ├── MixpanelFlutterHelper.java │ ├── MixpanelFlutterPlugin.java │ └── MixpanelMessageCodec.java ├── assets └── mixpanel.js ├── docs ├── __404error.html ├── categories.json ├── index.html ├── index.json ├── mixpanel_flutter │ ├── Mixpanel-class.html │ ├── Mixpanel │ │ ├── Mixpanel.html │ │ ├── addGroup.html │ │ ├── alias.html │ │ ├── clearSuperProperties.html │ │ ├── deleteGroup.html │ │ ├── eventElapsedTime.html │ │ ├── flush.html │ │ ├── getDistinctId.html │ │ ├── getGroup.html │ │ ├── getPeople.html │ │ ├── getSuperProperties.html │ │ ├── hasOptedOutTracking.html │ │ ├── identify.html │ │ ├── init.html │ │ ├── optInTracking.html │ │ ├── optOutTracking.html │ │ ├── registerSuperProperties.html │ │ ├── registerSuperPropertiesOnce.html │ │ ├── removeGroup.html │ │ ├── reset.html │ │ ├── setGroup.html │ │ ├── setLoggingEnabled.html │ │ ├── setServerURL.html │ │ ├── setUseIpAddressForGeolocation.html │ │ ├── timeEvent.html │ │ ├── track.html │ │ ├── trackWithGroups.html │ │ └── unregisterSuperProperty.html │ ├── MixpanelGroup-class.html │ ├── MixpanelGroup │ │ ├── MixpanelGroup.html │ │ ├── remove.html │ │ ├── set.html │ │ ├── setOnce.html │ │ ├── union.html │ │ └── unset.html │ ├── People-class.html │ ├── People │ │ ├── People.html │ │ ├── append.html │ │ ├── clearCharges.html │ │ ├── deleteUser.html │ │ ├── increment.html │ │ ├── remove.html │ │ ├── set.html │ │ ├── setOnce.html │ │ ├── trackCharge.html │ │ ├── union.html │ │ └── unset.html │ └── mixpanel_flutter-library.html └── static-assets │ ├── favicon.png │ ├── github.css │ ├── highlight.pack.js │ ├── play_button.svg │ ├── readme.md │ ├── script.js │ ├── styles.css │ └── typeahead.bundle.min.js ├── example ├── .gitignore ├── .metadata ├── README.md ├── analysis_options.yaml ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── mixpanel_example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values-night │ │ │ │ └── styles.xml │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── Podfile.lock │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ ├── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ ├── Contents.json │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ │ └── LaunchImage.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ └── README.md │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h │ └── RunnerTests │ │ └── RunnerTests.swift ├── lib │ ├── analytics.dart │ ├── event.dart │ ├── gdpr.dart │ ├── group.dart │ ├── main.dart │ ├── profile.dart │ └── widget.dart ├── pubspec.lock ├── pubspec.yaml ├── test │ └── widget_test.dart └── web │ ├── favicon.png │ ├── icons │ ├── Icon-192.png │ ├── Icon-512.png │ ├── Icon-maskable-192.png │ └── Icon-maskable-512.png │ ├── index.html │ └── manifest.json ├── ios ├── .gitignore ├── Assets │ └── .gitkeep ├── Classes │ ├── MixpanelFlutterPlugin.h │ ├── MixpanelFlutterPlugin.m │ ├── MixpanelTypeHandler.swift │ └── SwiftMixpanelFlutterPlugin.swift └── mixpanel_flutter.podspec ├── lib ├── codec │ └── mixpanel_message_codec.dart ├── mixpanel_flutter.dart ├── mixpanel_flutter_web.dart └── web │ └── mixpanel_js_bindings.dart ├── local.properties ├── mixpanel_flutter.iml ├── pubspec.lock ├── pubspec.yaml ├── test ├── mixpanel_flutter_test.dart └── mixpanel_flutter_web_unit_test.dart └── tool └── release.py /.github/workflows/flutter.yml: -------------------------------------------------------------------------------- 1 | name: Mixpanel Flutter SDK CI 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | 9 | jobs: 10 | test-main-code: 11 | runs-on: macos-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - uses: actions/setup-java@v1 15 | with: 16 | java-version: "12.x" 17 | - uses: subosito/flutter-action@v1 18 | with: 19 | flutter-version: "3.16.0" 20 | - run: flutter pub get 21 | - run: flutter test 22 | - run: flutter analyze --no-pub --no-current-package lib 23 | 24 | test-android-integration: 25 | runs-on: macos-13 26 | steps: 27 | - uses: actions/checkout@v4 28 | - uses: actions/setup-java@v4 29 | with: 30 | java-version: "17" 31 | distribution: 'temurin' 32 | - uses: subosito/flutter-action@v1 33 | with: 34 | flutter-version: "3.16.0" 35 | - name: Test Android integration 36 | working-directory: example 37 | run: flutter build apk 38 | 39 | test-ios-integration: 40 | runs-on: macos-latest 41 | steps: 42 | - uses: actions/checkout@v4 43 | - uses: actions/setup-java@v4 44 | with: 45 | java-version: "17" 46 | distribution: 'temurin' 47 | - uses: subosito/flutter-action@v1 48 | with: 49 | flutter-version: "3.16.0" 50 | - name: Clean 51 | working-directory: example 52 | run: flutter clean 53 | - name: Flutter pub get 54 | working-directory: example 55 | run: flutter pub get 56 | - name: CocoaPods update 57 | working-directory: example/ios 58 | run: pod repo update 59 | - name: Test iOS integration 60 | working-directory: example 61 | run: flutter build ios --debug --simulator --no-codesign 62 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Create release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v*" # Push events to matching v*, i.e. v1.0, v20.15.10 7 | 8 | jobs: 9 | build: 10 | name: "🚀 Release" 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: "Check-out" 14 | uses: actions/checkout@v1 15 | - name: "Update Release CHANGELOG" 16 | id: update-release-changelog 17 | uses: heinrichreimer/github-changelog-generator-action@v2.2 18 | with: 19 | token: ${{ secrets.GITHUB_TOKEN }} 20 | onlyLastTag: true 21 | stripHeaders: false 22 | base: "CHANGELOG.md" 23 | headerLabel: "# Changelog" 24 | breakingLabel: '### Breaking' 25 | enhancementLabel: '### Enhancements' 26 | stripGeneratorNotice: true 27 | bugsLabel: '### Fixes' 28 | issues: false 29 | issuesWoLabels: false 30 | pullRequests: true 31 | prWoLabels: true 32 | author: false 33 | verbose: true 34 | - name: Commit CHANGELOG Changes 35 | run: | 36 | git add . 37 | git config user.name "zihe.jia" 38 | git config user.email "zihe.jia@mixpanel.com" 39 | git commit -m "Update CHANGELOG" 40 | - name: Push CHANGELOG changes 41 | uses: ad-m/github-push-action@v0.6.0 42 | with: 43 | github_token: ${{ secrets.GITHUB_TOKEN }} 44 | branch: main 45 | force: true 46 | - name: "Prepare for the Github Release" 47 | id: generate-release-changelog 48 | uses: heinrichreimer/github-changelog-generator-action@v2.2 49 | with: 50 | token: ${{ secrets.GITHUB_TOKEN }} 51 | output: "output.md" 52 | headerLabel: "# Changelog" 53 | onlyLastTag: true 54 | stripHeaders: false 55 | breakingLabel: '### Breaking' 56 | enhancementLabel: '### Enhancements' 57 | stripGeneratorNotice: true 58 | bugsLabel: '### Fixes' 59 | issues: false 60 | issuesWoLabels: false 61 | pullRequests: true 62 | prWoLabels: true 63 | author: false 64 | verbose: true 65 | - name: "🚀 Create GitHub Release" 66 | uses: actions/create-release@v1 67 | env: 68 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 69 | with: 70 | tag_name: ${{ github.ref }} 71 | release_name: Release ${{ github.ref }} 72 | body: ${{ steps.generate-release-changelog.outputs.changelog }} 73 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | .idea/workspace.xml 4 | .packages 5 | .pub/ 6 | .idea 7 | build/ 8 | .cxx 9 | CLAUDE.md -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 78910062997c3a836feee883712c241a5fd22983 8 | channel: stable 9 | 10 | project_type: plugin 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: dart 2 | dart: 3 | - stable 4 | os: 5 | - linux 6 | sudo: false 7 | addons: 8 | apt: 9 | sources: 10 | - ubuntu-toolchain-r-test 11 | packages: 12 | - libstdc++6 13 | - fonts-droid-fallback 14 | before_script: 15 | - git clone https://github.com/flutter/flutter.git -b beta 16 | - ./flutter/bin/flutter doctor 17 | script: 18 | - cd $TRAVIS_BUILD_DIR 19 | - flutter packages get 20 | - flutter analyze --no-pub --no-current-package lib 21 | - flutter test 22 | - flutter packages pub publish --dry-run 23 | branches: 24 | only: 25 | - master 26 | cache: 27 | directories: 28 | - $HOME/.pub-cache -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "java.compile.nullAnalysis.mode": "automatic", 3 | "java.configuration.updateBuildConfiguration": "interactive" 4 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | Mixpanel Flutter SDK 3 |
4 | 5 | # Table of Contents 6 | 7 | 8 | 9 | - [Introduction](#introduction) 10 | - [Quick Start Guide](#quick-start-guide) 11 | - [Install Mixpanel](#1-install-mixpanel) 12 | - [Initialize Mixpanel](#2-initialize-mixpanel) 13 | - [Send Data](#3-send-data) 14 | - [Check for Success](#4-check-for-success) 15 | - [I want to know more!](#i-want-to-know-more) 16 | 17 | 18 | 19 | # Introduction 20 | 21 | Welcome to the official Mixpanel Flutter SDK. 22 | The Mixpanel Flutter SDK is an open-source project, and we'd love to see your contributions! 23 | We'd also love for you to come and work with us! Check out **[Jobs](https://mixpanel.com/jobs/#openings)** for details 24 | 25 | # Quick Start Guide 26 | 27 | Check out our **[official documentation](https://developer.mixpanel.com/docs/flutter)** for more in depth information on installing and using Mixpanel on Flutter. 28 | 29 | ## 1. Install Mixpanel 30 | 31 | ### Prerequisites 32 | 33 | - [Setup development environment for Flutter](https://flutter.dev/docs/get-started/install) 34 | 35 | ### Steps 36 | 37 | 1. Depend on it \ 38 | Add this to your package's pubspec.yaml file: 39 | 40 | ``` 41 | dependencies: 42 | mixpanel_flutter: ^1.x.x # set this to your desired version 43 | ``` 44 | 45 | 2. Install it \ 46 | You can install packages from the command line: 47 | 48 | ``` 49 | $ flutter pub get 50 | ``` 51 | 52 | 3. Import it \ 53 | Now in your Dart code, you can use: 54 | 55 | ``` 56 | import 'package:mixpanel_flutter/mixpanel_flutter.dart'; 57 | ``` 58 | 59 | #### Flutter Web Support 60 | 61 | Please add the following snippet to your `web/index.html` inside `` in your Flutter project. 62 | 63 | ``` 64 | 65 | ``` 66 | 67 | ## 2. Initialize Mixpanel 68 | 69 | To start tracking with the SDK you must first initialize with your project token. To initialize the SDK, first add `import 'package:mixpanel_flutter/mixpanel_flutter.dart';` and call `Mixpanel.init(token, trackAutomaticEvents);` with your project token and automatic events setting as it's arguments. You can find your token in [project settings](https://mixpanel.com/settings/project). 70 | 71 | ```dart 72 | import 'package:mixpanel_flutter/mixpanel_flutter.dart'; 73 | ... 74 | class _YourClassState extends State { 75 | Mixpanel mixpanel; 76 | 77 | @override 78 | void initState() { 79 | super.initState(); 80 | initMixpanel(); 81 | } 82 | 83 | Future initMixpanel() async { 84 | mixpanel = await Mixpanel.init("Your Mixpanel Token", trackAutomaticEvents: false); 85 | } 86 | ... 87 | ``` 88 | 89 | Once you've called this method once, you can access `mixpanel` throughout the rest of your application. 90 | 91 | ## 3. Send Data 92 | 93 | Once you've initialized the SDK, Mixpanel will automatically collect common mobile events. You can enable/disable automatic collection through your project settings. 94 | With the `mixpanel` object created in [the last step](#2-initialize-mixpanel) a call to `track` is all you need to send additional events to Mixpanel. 95 | 96 | ```dart 97 | // Track with event-name 98 | mixpanel.track('Sent Message'); 99 | // Track with event-name and property 100 | mixpanel.track('Plan Selected', properties: {'Plan': 'Premium'}); 101 | ``` 102 | 103 | You're done! You've successfully integrated the Mixpanel Flutter SDK into your app. To stay up to speed on important SDK releases and updates, star or watch our repository on [GitHub](https://github.com/mixpanel/mixpanel-flutter). 104 | 105 | ## 4. Check for Success 106 | 107 | [Open up Events in Mixpanel](https://mixpanel.com/report/events) to view incoming events. 108 | Once data hits our API, it generally takes ~60 seconds for it to be processed, stored, and queryable in your project. 109 | 110 | 👋 👋 Tell us about the Mixpanel developer experience! [https://www.mixpanel.com/devnps](https://www.mixpanel.com/devnps) 👍 👎 111 | 112 | # FAQ 113 | 114 | **I want to stop tracking an event/event property in Mixpanel. Is that possible?** 115 | 116 | Yes, in Lexicon, you can intercept and drop incoming events or properties. Mixpanel won’t store any new data for the event or property you select to drop. [See this article for more information](https://help.mixpanel.com/hc/en-us/articles/360001307806#dropping-events-and-properties). 117 | 118 | **I have a test user I would like to opt out of tracking. How do I do that?** 119 | 120 | Mixpanel’s client-side tracking library contains the [optOutTracking()](https://mixpanel.github.io/mixpanel-flutter/mixpanel_flutter/Mixpanel/optOutTracking.html) method, which will set the user’s local opt-out state to “true” and will prevent data from being sent from a user’s device. More detailed instructions can be found in the section, [Opting users out of tracking](https://developer.mixpanel.com/docs/flutter#opting-users-out-of-tracking). 121 | 122 | **Why aren't my events showing up?** 123 | 124 | First, make sure your test device has internet access. To preserve battery life and customer bandwidth, the Mixpanel library doesn't send the events you record immediately. Instead, it sends batches to the Mixpanel servers every 60 seconds while your application is running, as well as when the application transitions to the background. You can call [flush()](https://mixpanel.github.io/mixpanel-flutter/mixpanel_flutter/Mixpanel/flush.html) manually if you want to force a flush at a particular moment. 125 | 126 | ``` 127 | mixpanel.flush(); 128 | ``` 129 | 130 | If your events are still not showing up after 60 seconds, check if you have opted out of tracking. You can also enable Mixpanel debugging and logging, it allows you to see the debug output from the Mixpanel library. To enable it, call [setLoggingEnabled](https://mixpanel.github.io/mixpanel-flutter/mixpanel_flutter/Mixpanel/setLoggingEnabled.html) to true, then run your iOS project with Xcode or android project with Android Studio. The logs should be available in the console. 131 | 132 | ``` 133 | mixpanel.setLoggingEnabled(true); 134 | ``` 135 | 136 | **Starting with iOS 14.5, do I need to request the user’s permission through the AppTrackingTransparency framework to use Mixpanel?** 137 | 138 | No, Mixpanel does not use IDFA so it does not require user permission through the AppTrackingTransparency(ATT) framework. 139 | 140 | **If I use Mixpanel, how do I answer app privacy questions for the App Store?** 141 | 142 | Please refer to our [Apple App Developer Privacy Guidance](https://mixpanel.com/legal/app-store-privacy-details/) 143 | 144 | # I want to know more! 145 | 146 | No worries, here are some links that you will find useful: 147 | 148 | - **[Sample app](https://github.com/mixpanel/mixpanel-flutter/tree/main/example)** 149 | - **[Full API Reference](https://developer.mixpanel.com/docs/flutter)** 150 | 151 | [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/mixpanel/mixpanel-flutter) 152 | 153 | Have any questions? Reach out to Mixpanel [Support](https://help.mixpanel.com/hc/en-us/requests/new) to speak to someone smart, quickly. 154 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | # Additional information about this file can be found at 4 | # https://dart.dev/guides/language/analysis-options 5 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | group 'com.mixpanel.mixpanel_flutter' 2 | version '1.0' 3 | 4 | buildscript { 5 | repositories { 6 | google() 7 | mavenCentral() 8 | } 9 | 10 | dependencies { 11 | // Use a compatible version of Gradle Plugin 12 | classpath 'com.android.tools.build:gradle:8.1.0' // Updated to 8.1.0 13 | } 14 | } 15 | 16 | rootProject.allprojects { 17 | repositories { 18 | google() 19 | mavenCentral() 20 | } 21 | } 22 | 23 | apply plugin: 'com.android.library' 24 | 25 | android { 26 | // Safely handle 'namespace' property for new Android Gradle plugin versions 27 | if (project.hasProperty("android") && project.android.hasProperty("namespace")) { 28 | namespace = "com.mixpanel.mixpanel_flutter" 29 | } 30 | 31 | compileSdkVersion 34 32 | buildToolsVersion '34.0.0' 33 | 34 | defaultConfig { 35 | minSdkVersion 21 36 | } 37 | 38 | compileOptions { 39 | sourceCompatibility JavaVersion.VERSION_17 40 | targetCompatibility JavaVersion.VERSION_17 41 | } 42 | 43 | lintOptions { 44 | disable 'InvalidPackage' 45 | } 46 | } 47 | 48 | dependencies { 49 | // Use the Mixpanel Android SDK 50 | implementation "com.mixpanel.android:mixpanel-android:8.2.0" 51 | } 52 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | android.defaults.buildfeatures.buildconfig=true 5 | android.nonTransitiveRClass=false 6 | android.nonFinalResIds=false 7 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip 6 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'mixpanel_flutter' 2 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelFlutterHelper.java: -------------------------------------------------------------------------------- 1 | package com.mixpanel.mixpanel_flutter; 2 | 3 | import org.json.JSONArray; 4 | import org.json.JSONException; 5 | import org.json.JSONObject; 6 | 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | import java.util.Iterator; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | public class MixpanelFlutterHelper { 14 | 15 | static public JSONObject getMergedProperties(JSONObject properties, JSONObject mixpanelProperties) throws JSONException { 16 | if (mixpanelProperties != null) { 17 | for (Iterator keys = mixpanelProperties.keys(); keys.hasNext(); ) { 18 | String key = keys.next(); 19 | properties.put(key, mixpanelProperties.get(key)); 20 | } 21 | } 22 | return properties; 23 | } 24 | 25 | static public Map toMap(JSONObject object) throws JSONException { 26 | Map map = new HashMap<>(); 27 | Iterator keys = object.keys(); 28 | while (keys.hasNext()) { 29 | String key = (String) keys.next(); 30 | map.put(key, fromJson(object.get(key))); 31 | } 32 | return map; 33 | } 34 | 35 | static public List toList(JSONArray array) throws JSONException { 36 | List list = new ArrayList<>(); 37 | for (int i = 0; i < array.length(); i++) { 38 | list.add(fromJson(array.get(i))); 39 | } 40 | return list; 41 | } 42 | 43 | static public Object fromJson(Object json) throws JSONException { 44 | if (json == JSONObject.NULL) { 45 | return null; 46 | } else if (json instanceof JSONObject) { 47 | return toMap((JSONObject) json); 48 | } else if (json instanceof JSONArray) { 49 | return toList((JSONArray) json); 50 | } else { 51 | return json; 52 | } 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /android/src/main/java/com/mixpanel/mixpanel_flutter/MixpanelMessageCodec.java: -------------------------------------------------------------------------------- 1 | package com.mixpanel.mixpanel_flutter; 2 | 3 | import io.flutter.plugin.common.StandardMessageCodec; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.net.URI; 7 | import java.net.URISyntaxException; 8 | import java.nio.ByteBuffer; 9 | import java.nio.charset.Charset; 10 | import java.util.Date; 11 | 12 | public class MixpanelMessageCodec extends StandardMessageCodec { 13 | static final MixpanelMessageCodec instance = new MixpanelMessageCodec(); 14 | static final Charset UTF8 = Charset.forName("UTF8"); 15 | static final int DATE_TIME = 128; 16 | static final int URI = 129; 17 | 18 | @Override 19 | protected void writeValue(ByteArrayOutputStream stream, Object value) { 20 | if (value instanceof Date) { 21 | stream.write(DATE_TIME); 22 | writeLong(stream, ((Date) value).getTime()); 23 | } else if (value instanceof java.net.URI) { 24 | stream.write(URI); 25 | writeBytes(stream, ((java.net.URI) value).toString().getBytes(UTF8)); 26 | } else { 27 | super.writeValue(stream, value); 28 | } 29 | } 30 | 31 | @Override 32 | protected Object readValueOfType(byte type, ByteBuffer buffer) { 33 | switch (type) { 34 | case (byte) DATE_TIME: 35 | return new Date(buffer.getLong()); 36 | case (byte) URI: 37 | final byte[] urlBytes = readBytes(buffer); 38 | final String url = new String(urlBytes, UTF8); 39 | try { 40 | return new URI(url); 41 | } catch (URISyntaxException e) { 42 | } 43 | default: 44 | return super.readValueOfType(type, buffer); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /assets/mixpanel.js: -------------------------------------------------------------------------------- 1 | (function(f,b){if(!b.__SV){var e,g,i,h;window.mixpanel=b;b._i=[];b.init=function(e,f,c){function g(a,d){var b=d.split(".");2==b.length&&(a=a[b[0]],d=b[1]);a[d]=function(){a.push([d].concat(Array.prototype.slice.call(arguments,0)))}}var a=b;"undefined"!==typeof c?a=b[c]=[]:c="mixpanel";a.people=a.people||[];a.toString=function(a){var d="mixpanel";"mixpanel"!==c&&(d+="."+c);a||(d+=" (stub)");return d};a.people.toString=function(){return a.toString(1)+".people (stub)"};i="disable time_event track track_pageview track_links track_forms track_with_groups add_group set_group remove_group register register_once alias unregister identify name_tag set_config reset opt_in_tracking opt_out_tracking has_opted_in_tracking has_opted_out_tracking clear_opt_in_out_tracking start_batch_senders people.set people.set_once people.unset people.increment people.append people.union people.track_charge people.clear_charges people.delete_user people.remove".split(" "); 2 | for(h=0;h 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | mixpanel_flutter - Dart API docs 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 28 |
29 | 30 |
31 | 32 | 35 |
mixpanel_flutter
36 | 39 |
40 | 41 |
42 | 43 | 44 |
45 |

404: Something's gone wrong :-(

46 | 47 |
48 |

You've tried to visit a page that doesn't exist. Luckily this site 49 | has other pages.

50 |

If you were looking for something specific, try searching: 51 |

54 |

55 | 56 |
57 |
58 | 59 | 78 | 79 | 81 | 82 |
83 | 84 |
85 | 86 | mixpanel_flutter 87 | 1.3.1 88 | 89 | 90 | 91 |
92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /docs/categories.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /docs/mixpanel_flutter/MixpanelGroup/MixpanelGroup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MixpanelGroup constructor - MixpanelGroup class - mixpanel_flutter library - Dart API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 |
28 | 29 |
30 | 31 | 37 |
MixpanelGroup
38 | 41 |
42 | 43 |
44 | 45 | 46 |
47 |
48 |

MixpanelGroup constructor 49 | Null safety 50 |

51 | 52 |
53 | MixpanelGroup(
  1. String token,
  2. 54 |
  3. String groupKey,
  4. 55 |
  5. dynamic groupID
  6. 56 |
) 57 |
58 | 59 | 60 | 61 | 62 | 63 |
64 |

Implementation

65 |
MixpanelGroup(String token, String groupKey, dynamic groupID)
 66 |     : _token = token,
 67 |       _groupKey = groupKey,
 68 |       _groupID = groupID;
69 |
70 | 71 | 72 |
73 | 74 | 120 | 121 | 123 | 124 |
125 | 126 |
127 | 128 | mixpanel_flutter 129 | 1.3.1 130 | 131 | 132 | 133 |
134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /docs/mixpanel_flutter/MixpanelGroup/remove.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | remove method - MixpanelGroup class - mixpanel_flutter library - Dart API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 |
28 | 29 |
30 | 31 | 37 |
remove
38 | 41 |
42 | 43 |
44 | 45 | 46 |
47 |
48 |

remove method 49 | Null safety 50 |

51 | 52 |
53 | 54 | 55 | void 56 | remove(
  1. String name,
  2. 57 |
  3. dynamic value
  4. 58 |
) 59 | 60 | 61 | 62 |
63 | 64 |
65 |

Remove value from a list-valued property only if it is already present in the list. 66 | If the property does not currently exist, the remove will be ignored. 67 | If the property exists and is not list-valued, the remove will be ignored.

68 |
    69 |
  • name the Group Analytics list-valued property that should have a value removed
  • 70 |
  • value the value that will be removed from the list
  • 71 |
72 |
73 | 74 | 75 | 76 |
77 |

Implementation

78 |
void remove(String name, dynamic value) {
 79 |   if (_MixpanelHelper.isValidString(name)) {
 80 |     _channel.invokeMethod<void>('groupRemovePropertyValue', <String, dynamic>{
 81 |       'token': this._token,
 82 |       'groupKey': this._groupKey,
 83 |       'groupID': this._groupID,
 84 |       'name': name,
 85 |       'value': value
 86 |     });
 87 |   } else {
 88 |     developer.log('`group remove` failed: name cannot be blank',
 89 |         name: 'Mixpanel');
 90 |   }
 91 | }
92 |
93 | 94 | 95 |
96 | 97 | 143 | 144 | 146 | 147 |
148 | 149 |
150 | 151 | mixpanel_flutter 152 | 1.3.1 153 | 154 | 155 | 156 |
157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /docs/mixpanel_flutter/MixpanelGroup/set.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | set method - MixpanelGroup class - mixpanel_flutter library - Dart API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 |
28 | 29 |
30 | 31 | 37 |
set
38 | 41 |
42 | 43 |
44 | 45 | 46 |
47 |
48 |

set method 49 | Null safety 50 |

51 | 52 |
53 | 54 | 55 | void 56 | set(
  1. String prop,
  2. 57 |
  3. String to
  4. 58 |
) 59 | 60 | 61 | 62 |
63 | 64 |
65 |

Sets a single property with the given name and value for this group. 66 | The given name and value will be assigned to the user in Mixpanel Group Analytics, 67 | possibly overwriting an existing property with the same name.

68 |
    69 |
  • prop The name of the Mixpanel property. This must be a String, for example "Zip Code"
  • 70 |
  • to The value to set on the given property name. For "Zip Code", this value might be the String "90210"
  • 71 |
72 |
73 | 74 | 75 | 76 |
77 |

Implementation

78 |
void set(String prop, String to) {
 79 |   if (_MixpanelHelper.isValidString(prop)) {
 80 |     Map<String, dynamic> properties = {prop: to};
 81 | 
 82 |     _channel.invokeMethod<void>('groupSetProperties', <String, dynamic>{
 83 |       'token': this._token,
 84 |       'groupKey': this._groupKey,
 85 |       'groupID': this._groupID,
 86 |       'properties': properties
 87 |     });
 88 |   } else {
 89 |     developer.log('`group set` failed: prop cannot be blank',
 90 |         name: 'Mixpanel');
 91 |   }
 92 | }
93 |
94 | 95 | 96 |
97 | 98 | 144 | 145 | 147 | 148 |
149 | 150 |
151 | 152 | mixpanel_flutter 153 | 1.3.1 154 | 155 | 156 | 157 |
158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /docs/mixpanel_flutter/MixpanelGroup/setOnce.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | setOnce method - MixpanelGroup class - mixpanel_flutter library - Dart API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 |
28 | 29 |
30 | 31 | 37 |
setOnce
38 | 41 |
42 | 43 |
44 | 45 | 46 |
47 |
48 |

setOnce method 49 | Null safety 50 |

51 | 52 |
53 | 54 | 55 | void 56 | setOnce(
  1. String prop,
  2. 57 |
  3. String to
  4. 58 |
) 59 | 60 | 61 | 62 |
63 | 64 |
65 |

Works just like groupSet() except it will not overwrite existing property values. This is useful for properties like "First login date".

66 |
    67 |
  • prop The name of the Mixpanel property. This must be a String, for example "Zip Code"
  • 68 |
  • to The value to set on the given property name. For "Zip Code", this value might be the String "90210"
  • 69 |
70 |
71 | 72 | 73 | 74 |
75 |

Implementation

76 |
void setOnce(String prop, String to) {
 77 |   if (_MixpanelHelper.isValidString(prop)) {
 78 |     Map<String, dynamic> properties = {prop: to};
 79 | 
 80 |     _channel.invokeMethod<void>('groupSetPropertyOnce', <String, dynamic>{
 81 |       'token': this._token,
 82 |       'groupKey': this._groupKey,
 83 |       'groupID': this._groupID,
 84 |       'properties': properties
 85 |     });
 86 |   } else {
 87 |     developer.log('`group setOnce` failed: prop cannot be blank',
 88 |         name: 'Mixpanel');
 89 |   }
 90 | }
91 |
92 | 93 | 94 |
95 | 96 | 142 | 143 | 145 | 146 |
147 | 148 |
149 | 150 | mixpanel_flutter 151 | 1.3.1 152 | 153 | 154 | 155 |
156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /docs/mixpanel_flutter/MixpanelGroup/unset.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | unset method - MixpanelGroup class - mixpanel_flutter library - Dart API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 |
28 | 29 |
30 | 31 | 37 |
unset
38 | 41 |
42 | 43 |
44 | 45 | 46 |
47 |
48 |

unset method 49 | Null safety 50 |

51 | 52 |
53 | 54 | 55 | void 56 | unset(
  1. String prop
  2. 57 |
) 58 | 59 | 60 | 61 |
62 | 63 |
64 |

Permanently removes the property with the given name from the group's profile

65 |
    66 |
  • prop name of a property to unset
  • 67 |
68 |
69 | 70 | 71 | 72 |
73 |

Implementation

74 |
void unset(String prop) {
 75 |   if (_MixpanelHelper.isValidString(prop)) {
 76 |     _channel.invokeMethod<void>('groupUnsetProperty', <String, dynamic>{
 77 |       'token': this._token,
 78 |       'groupKey': this._groupKey,
 79 |       'groupID': this._groupID,
 80 |       'propertyName': prop
 81 |     });
 82 |   } else {
 83 |     developer.log('`group unset` failed: prop cannot be blank',
 84 |         name: 'Mixpanel');
 85 |   }
 86 | }
87 |
88 | 89 | 90 |
91 | 92 | 138 | 139 | 141 | 142 |
143 | 144 |
145 | 146 | mixpanel_flutter 147 | 1.3.1 148 | 149 | 150 | 151 |
152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /docs/mixpanel_flutter/People/People.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | People constructor - People class - mixpanel_flutter library - Dart API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 |
28 | 29 |
30 | 31 | 37 |
People
38 | 41 |
42 | 43 |
44 | 45 | 46 |
47 |
48 |

People constructor 49 | Null safety 50 |

51 | 52 |
53 | People(
  1. String token
  2. 54 |
) 55 |
56 | 57 | 58 | 59 | 60 | 61 |
62 |

Implementation

63 |
People(String token) : _token = token;
64 |
65 | 66 | 67 |
68 | 69 | 120 | 121 | 123 | 124 |
125 | 126 |
127 | 128 | mixpanel_flutter 129 | 1.3.1 130 | 131 | 132 | 133 |
134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /docs/mixpanel_flutter/People/clearCharges.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | clearCharges method - People class - mixpanel_flutter library - Dart API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 |
28 | 29 |
30 | 31 | 37 |
clearCharges
38 | 41 |
42 | 43 |
44 | 45 | 46 |
47 |
48 |

clearCharges method 49 | Null safety 50 |

51 | 52 |
53 | 54 | 55 | void 56 | clearCharges() 57 | 58 | 59 | 60 |
61 | 62 |
63 |

Permanently clear the whole transaction history for the identified people profile.

64 |
65 | 66 | 67 | 68 |
69 |

Implementation

70 |
void clearCharges() {
 71 |   _channel.invokeMethod<void>(
 72 |       'clearCharges', <String, dynamic>{'token': this._token});
 73 | }
74 |
75 | 76 | 77 |
78 | 79 | 130 | 131 | 133 | 134 |
135 | 136 |
137 | 138 | mixpanel_flutter 139 | 1.3.1 140 | 141 | 142 | 143 |
144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /docs/mixpanel_flutter/People/deleteUser.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | deleteUser method - People class - mixpanel_flutter library - Dart API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 |
28 | 29 |
30 | 31 | 37 |
deleteUser
38 | 41 |
42 | 43 |
44 | 45 | 46 |
47 |
48 |

deleteUser method 49 | Null safety 50 |

51 | 52 |
53 | 54 | 55 | void 56 | deleteUser() 57 | 58 | 59 | 60 |
61 | 62 |
63 |

Permanently deletes the identified user's record from People Analytics.

64 |

Calling deleteUser deletes an entire record completely. Any future calls 65 | to People Analytics using the same distinct id will create and store new values.

66 |
67 | 68 | 69 | 70 |
71 |

Implementation

72 |
void deleteUser() {
 73 |   _channel.invokeMethod<void>(
 74 |       'deleteUser', <String, dynamic>{'token': this._token});
 75 | }
76 |
77 | 78 | 79 |
80 | 81 | 132 | 133 | 135 | 136 |
137 | 138 |
139 | 140 | mixpanel_flutter 141 | 1.3.1 142 | 143 | 144 | 145 |
146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /docs/mixpanel_flutter/People/remove.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | remove method - People class - mixpanel_flutter library - Dart API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 |
28 | 29 |
30 | 31 | 37 |
remove
38 | 41 |
42 | 43 |
44 | 45 | 46 |
47 |
48 |

remove method 49 | Null safety 50 |

51 | 52 |
53 | 54 | 55 | void 56 | remove(
  1. String name,
  2. 57 |
  3. dynamic value
  4. 58 |
) 59 | 60 | 61 | 62 |
63 | 64 |
65 |

Remove value from a list-valued property only if they are already present in the list. 66 | If the property does not currently exist, the remove will be ignored. 67 | If the property exists and is not list-valued, the remove will be ignored.

68 |
    69 |
  • name the People Analytics property that should have it's value removed from
  • 70 |
  • value the value that will be removed from the property's list
  • 71 |
72 |
73 | 74 | 75 | 76 |
77 |

Implementation

78 |
void remove(String name, dynamic value) {
 79 |   if (_MixpanelHelper.isValidString(name)) {
 80 |     _channel.invokeMethod<void>('remove', <String, dynamic>{
 81 |       'token': this._token,
 82 |       'name': name,
 83 |       'value': value
 84 |     });
 85 |   } else {
 86 |     developer.log('`people remove` failed: name cannot be blank',
 87 |         name: 'Mixpanel');
 88 |   }
 89 | }
90 |
91 | 92 | 93 |
94 | 95 | 146 | 147 | 149 | 150 |
151 | 152 |
153 | 154 | mixpanel_flutter 155 | 1.3.1 156 | 157 | 158 | 159 |
160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /docs/mixpanel_flutter/People/set.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | set method - People class - mixpanel_flutter library - Dart API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 |
28 | 29 |
30 | 31 | 37 |
set
38 | 41 |
42 | 43 |
44 | 45 | 46 |
47 |
48 |

set method 49 | Null safety 50 |

51 | 52 |
53 | 54 | 55 | void 56 | set(
  1. String prop,
  2. 57 |
  3. dynamic to
  4. 58 |
) 59 | 60 | 61 | 62 |
63 | 64 |
65 |

Sets a single property with the given name and value for this user. 66 | The given name and value will be assigned to the user in Mixpanel People Analytics, 67 | possibly overwriting an existing property with the same name.

68 |
    69 |
  • prop The name of the Mixpanel property. This must be a String, for example "Zip Code"
  • 70 |
  • to The value of the Mixpanel property. For "Zip Code", this value might be the String "90210"
  • 71 |
72 |
73 | 74 | 75 | 76 |
77 |

Implementation

78 |
void set(String prop, dynamic to) {
 79 |   if (_MixpanelHelper.isValidString(prop)) {
 80 |     Map<String, dynamic> properties = {prop: to};
 81 |     _channel.invokeMethod<void>('set',
 82 |         <String, dynamic>{'token': this._token, 'properties': properties});
 83 |   } else {
 84 |     developer.log('`people set` failed: prop cannot be blank',
 85 |         name: 'Mixpanel');
 86 |   }
 87 | }
88 |
89 | 90 | 91 |
92 | 93 | 144 | 145 | 147 | 148 |
149 | 150 |
151 | 152 | mixpanel_flutter 153 | 1.3.1 154 | 155 | 156 | 157 |
158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /docs/mixpanel_flutter/People/setOnce.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | setOnce method - People class - mixpanel_flutter library - Dart API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 |
28 | 29 |
30 | 31 | 37 |
setOnce
38 | 41 |
42 | 43 |
44 | 45 | 46 |
47 |
48 |

setOnce method 49 | Null safety 50 |

51 | 52 |
53 | 54 | 55 | void 56 | setOnce(
  1. String prop,
  2. 57 |
  3. dynamic to
  4. 58 |
) 59 | 60 | 61 | 62 |
63 | 64 |
65 |

Works just like set(), except it will not overwrite existing property values. This is useful for properties like "First login date".

66 |
    67 |
  • prop The name of the Mixpanel property. This must be a String, for example "Zip Code"
  • 68 |
  • to The value of the Mixpanel property. For "Zip Code", this value might be the String "90210"
  • 69 |
70 |
71 | 72 | 73 | 74 |
75 |

Implementation

76 |
void setOnce(String prop, dynamic to) {
 77 |   if (_MixpanelHelper.isValidString(prop)) {
 78 |     Map<String, dynamic> properties = {prop: to};
 79 |     _channel.invokeMethod<void>('setOnce',
 80 |         <String, dynamic>{'token': this._token, 'properties': properties});
 81 |   } else {
 82 |     developer.log('`people setOnce` failed: prop cannot be blank',
 83 |         name: 'Mixpanel');
 84 |   }
 85 | }
86 |
87 | 88 | 89 |
90 | 91 | 142 | 143 | 145 | 146 |
147 | 148 |
149 | 150 | mixpanel_flutter 151 | 1.3.1 152 | 153 | 154 | 155 |
156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /docs/mixpanel_flutter/People/unset.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | unset method - People class - mixpanel_flutter library - Dart API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 |
28 | 29 |
30 | 31 | 37 |
unset
38 | 41 |
42 | 43 |
44 | 45 | 46 |
47 |
48 |

unset method 49 | Null safety 50 |

51 | 52 |
53 | 54 | 55 | void 56 | unset(
  1. String name
  2. 57 |
) 58 | 59 | 60 | 61 |
62 | 63 |
64 |

permanently removes the property with the given name from the user's profile

65 |
    66 |
  • name name of a property to unset
  • 67 |
68 |
69 | 70 | 71 | 72 |
73 |

Implementation

74 |
void unset(String name) {
 75 |   if (_MixpanelHelper.isValidString(name)) {
 76 |     _channel.invokeMethod<void>(
 77 |         'unset', <String, dynamic>{'token': this._token, 'name': name});
 78 |   } else {
 79 |     developer.log('`people unset` failed: name cannot be blank',
 80 |         name: 'Mixpanel');
 81 |   }
 82 | }
83 |
84 | 85 | 86 |
87 | 88 | 139 | 140 | 142 | 143 |
144 | 145 |
146 | 147 | mixpanel_flutter 148 | 1.3.1 149 | 150 | 151 | 152 |
153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /docs/mixpanel_flutter/mixpanel_flutter-library.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | mixpanel_flutter library - Dart API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 |
28 | 29 |
30 | 31 | 35 |
mixpanel_flutter
36 | 39 |
40 | 41 |
42 | 43 | 44 |
45 |
46 |

mixpanel_flutter library 47 | Null safety 48 | 49 |

50 | 51 | 52 | 53 | 54 |
55 |

Classes

56 | 57 |
58 |
59 | Mixpanel 60 | 61 |
62 |
63 | The primary class for integrating Mixpanel with your app. 64 |
65 | 66 |
67 | MixpanelGroup 68 | 69 |
70 |
71 | Core class for using Mixpanel Group Analytics features. [...] 72 |
73 | 74 |
75 | People 76 | 77 |
78 |
79 | Core class for using Mixpanel People Analytics features. [...] 80 |
81 | 82 |
83 |
84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 |
94 | 95 | 115 | 116 | 134 | 135 |
136 | 137 |
138 | 139 | mixpanel_flutter 140 | 1.3.1 141 | 142 | 143 | 144 |
145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /docs/static-assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/docs/static-assets/favicon.png -------------------------------------------------------------------------------- /docs/static-assets/github.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | github.com style (c) Vasily Polovnyov 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | color: #333; 12 | background: #f8f8f8; 13 | } 14 | 15 | .hljs-comment, 16 | .hljs-quote { 17 | color: #998; 18 | font-style: italic; 19 | } 20 | 21 | .hljs-keyword, 22 | .hljs-selector-tag, 23 | .hljs-subst { 24 | color: #333; 25 | font-weight: bold; 26 | } 27 | 28 | .hljs-number, 29 | .hljs-literal, 30 | .hljs-variable, 31 | .hljs-template-variable, 32 | .hljs-tag .hljs-attr { 33 | color: #008080; 34 | } 35 | 36 | .hljs-string, 37 | .hljs-doctag { 38 | color: #d14; 39 | } 40 | 41 | .hljs-title, 42 | .hljs-section, 43 | .hljs-selector-id { 44 | color: #900; 45 | font-weight: bold; 46 | } 47 | 48 | .hljs-subst { 49 | font-weight: normal; 50 | } 51 | 52 | .hljs-type, 53 | .hljs-class .hljs-title { 54 | color: #458; 55 | font-weight: bold; 56 | } 57 | 58 | .hljs-tag, 59 | .hljs-name, 60 | .hljs-attribute { 61 | color: #000080; 62 | font-weight: normal; 63 | } 64 | 65 | .hljs-regexp, 66 | .hljs-link { 67 | color: #009926; 68 | } 69 | 70 | .hljs-symbol, 71 | .hljs-bullet { 72 | color: #990073; 73 | } 74 | 75 | .hljs-built_in, 76 | .hljs-builtin-name { 77 | color: #0086b3; 78 | } 79 | 80 | .hljs-meta { 81 | color: #999; 82 | font-weight: bold; 83 | } 84 | 85 | .hljs-deletion { 86 | background: #fdd; 87 | } 88 | 89 | .hljs-addition { 90 | background: #dfd; 91 | } 92 | 93 | .hljs-emphasis { 94 | font-style: italic; 95 | } 96 | 97 | .hljs-strong { 98 | font-weight: bold; 99 | } 100 | -------------------------------------------------------------------------------- /docs/static-assets/play_button.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/static-assets/readme.md: -------------------------------------------------------------------------------- 1 | # highlight.js 2 | 3 | Generated from https://highlightjs.org/download/ on 2021-03-07 4 | 5 | **Included languages:** 6 | 7 | * bash 8 | * c 9 | * css 10 | * dart 11 | * html, xml 12 | * java 13 | * javascript 14 | * json 15 | * kotlin 16 | * markdown 17 | * objective-c 18 | * plaintext 19 | * shell 20 | * swift 21 | * yaml 22 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 78910062997c3a836feee883712c241a5fd22983 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # Sample Flutter Application for Mixpanel Integration 2 | 3 | This folder contains a sample application demonstrating how you can use Mixpanel in your Flutter apps. 4 | 5 | ## Setup 6 | 7 | - You need to set up the Flutter development environment 8 | https://flutter.dev/docs/get-started/install 9 | - In the root folder of the sample application, run from the command line `$ flutter pub get` 10 | - To run the application, in the root folder of the sample application, run from the command line `$ flutter run` or in Android Studio, open `example/lib/main.dart` and run. 11 | 12 | ## Use your Mixpanel Token 13 | 14 | Replace `Your Mixpanel Token` value in `analytics.dart` that you'll need to update before you can send data to Mixpanel. 15 | 16 | ### For Your Mixpanel Token 17 | - Log in to your account at https://www.mixpanel.com 18 | - Select the project you'll be working with 19 | - Click the gear link at the top right to show the project settings dialog 20 | - Copy the "Token" string from the dialog 21 | 22 | Change the value of "token" in app.json to the value you copied from the web page. 23 | 24 | ## Getting More Information 25 | The Mixpanel Flutter integration API documentation is available on the Mixpanel website. 26 | https://developer.mixpanel.com/docs/flutter -------------------------------------------------------------------------------- /example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at https://dart.dev/lints. 17 | # 18 | # Instead of disabling a lint rule for the entire project in the 19 | # section below, it can also be suppressed for a single line of code 20 | # or a specific dart file by using the `// ignore: name_of_lint` and 21 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 22 | # producing the lint. 23 | rules: 24 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 25 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 26 | 27 | # Additional information about this file can be found at 28 | # https://dart.dev/guides/language/analysis-options 29 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | id "dev.flutter.flutter-gradle-plugin" 5 | } 6 | 7 | def localProperties = new Properties() 8 | def localPropertiesFile = rootProject.file('local.properties') 9 | if (localPropertiesFile.exists()) { 10 | localPropertiesFile.withReader('UTF-8') { reader -> 11 | localProperties.load(reader) 12 | } 13 | } 14 | 15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 16 | if (flutterVersionCode == null) { 17 | flutterVersionCode = '1' 18 | } 19 | 20 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 21 | if (flutterVersionName == null) { 22 | flutterVersionName = '1.0' 23 | } 24 | 25 | android { 26 | namespace "com.example.mixpanel_example" 27 | compileSdkVersion flutter.compileSdkVersion 28 | ndkVersion flutter.ndkVersion 29 | 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | 35 | kotlinOptions { 36 | jvmTarget = '1.8' 37 | } 38 | 39 | sourceSets { 40 | main.java.srcDirs += 'src/main/kotlin' 41 | } 42 | 43 | defaultConfig { 44 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 45 | applicationId "com.example.mixpanel_example" 46 | // You can update the following values to match your application needs. 47 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. 48 | minSdkVersion 21 49 | targetSdkVersion 34 50 | versionCode flutterVersionCode.toInteger() 51 | versionName flutterVersionName 52 | } 53 | 54 | buildTypes { 55 | release { 56 | // TODO: Add your own signing config for the release build. 57 | // Signing with the debug keys for now, so `flutter run --release` works. 58 | signingConfig signingConfigs.debug 59 | } 60 | } 61 | } 62 | 63 | flutter { 64 | source '../..' 65 | } 66 | 67 | dependencies {} 68 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 14 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 29 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/example/mixpanel_example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.mixpanel_example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.7.10' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 10 | } 11 | } 12 | 13 | allprojects { 14 | repositories { 15 | google() 16 | mavenCentral() 17 | } 18 | } 19 | 20 | rootProject.buildDir = '../build' 21 | subprojects { 22 | project.buildDir = "${rootProject.buildDir}/${project.name}" 23 | } 24 | subprojects { 25 | project.evaluationDependsOn(':app') 26 | } 27 | 28 | tasks.register("clean", Delete) { 29 | delete rootProject.buildDir 30 | } 31 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | android.defaults.buildfeatures.buildconfig=true 5 | android.nonTransitiveRClass=false 6 | android.nonFinalResIds=false 7 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | } 9 | settings.ext.flutterSdkPath = flutterSdkPath() 10 | 11 | includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") 12 | 13 | repositories { 14 | google() 15 | mavenCentral() 16 | gradlePluginPortal() 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false 21 | } 22 | } 23 | 24 | plugins { 25 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 26 | id "com.android.application" version '8.8.1' apply false 27 | } 28 | 29 | include ":app" 30 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | platform :ios, '12.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | target 'RunnerTests' do 36 | inherit! :search_paths 37 | end 38 | end 39 | 40 | post_install do |installer| 41 | installer.pods_project.targets.each do |target| 42 | flutter_additional_ios_build_settings(target) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - Mixpanel-swift (5.1.0): 4 | - Mixpanel-swift/Complete (= 5.1.0) 5 | - Mixpanel-swift/Complete (5.1.0) 6 | - mixpanel_flutter (2.4.1): 7 | - Flutter 8 | - Mixpanel-swift (= 5.1.0) 9 | 10 | DEPENDENCIES: 11 | - Flutter (from `Flutter`) 12 | - mixpanel_flutter (from `.symlinks/plugins/mixpanel_flutter/ios`) 13 | 14 | SPEC REPOS: 15 | trunk: 16 | - Mixpanel-swift 17 | 18 | EXTERNAL SOURCES: 19 | Flutter: 20 | :path: Flutter 21 | mixpanel_flutter: 22 | :path: ".symlinks/plugins/mixpanel_flutter/ios" 23 | 24 | SPEC CHECKSUMS: 25 | Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 26 | Mixpanel-swift: 7b26468fc0e2e521104e51d65c4bbf7cab8162f8 27 | mixpanel_flutter: 4498f84a45cee407d32a8bd893f7483afcbc2be4 28 | 29 | PODFILE CHECKSUM: 7be2f5f74864d463a8ad433546ed1de7e0f29aef 30 | 31 | COCOAPODS: 1.16.2 32 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 43 | 49 | 50 | 51 | 52 | 53 | 64 | 66 | 72 | 73 | 74 | 75 | 81 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @main 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Mixpanel Example 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | mixpanel_example 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | CADisableMinimumFrameDurationOnPhone 45 | 46 | UIApplicationSupportsIndirectInputEvents 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /example/lib/analytics.dart: -------------------------------------------------------------------------------- 1 | import 'package:mixpanel_flutter/mixpanel_flutter.dart'; 2 | 3 | class MixpanelManager { 4 | static Mixpanel? _instance; 5 | 6 | static Future init() async { 7 | if (_instance == null) { 8 | _instance = await Mixpanel.init("YOUR_PROJECT_TOKEN", 9 | optOutTrackingDefault: false, trackAutomaticEvents: true); 10 | _instance?.setLoggingEnabled(true); 11 | } 12 | return _instance!; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /example/lib/gdpr.dart: -------------------------------------------------------------------------------- 1 | import 'analytics.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:mixpanel_flutter_example/widget.dart'; 4 | import 'package:mixpanel_flutter/mixpanel_flutter.dart'; 5 | 6 | class GDPRScreen extends StatefulWidget { 7 | @override 8 | _GDPRScreenState createState() => _GDPRScreenState(); 9 | } 10 | 11 | class _GDPRScreenState extends State { 12 | late final Mixpanel _mixpanel; 13 | 14 | @override 15 | void initState() { 16 | // TODO: implement initState 17 | super.initState(); 18 | _initMixpanel(); 19 | } 20 | 21 | Future _initMixpanel() async { 22 | _mixpanel = await MixpanelManager.init(); 23 | } 24 | 25 | void showAlertDialog(BuildContext context, bool? result) { 26 | Widget okButton = TextButton( 27 | child: Text("OK"), 28 | onPressed: () { 29 | Navigator.of(context).pop(); 30 | }, 31 | ); 32 | 33 | AlertDialog alert = AlertDialog( 34 | title: Text("Result"), 35 | content: Text("${result}"), 36 | actions: [ 37 | okButton, 38 | ], 39 | ); 40 | 41 | // show the dialog 42 | showDialog( 43 | context: context, 44 | builder: (BuildContext context) { 45 | return alert; 46 | }, 47 | ); 48 | } 49 | 50 | @override 51 | Widget build(BuildContext context) { 52 | return Scaffold( 53 | appBar: AppBar( 54 | backgroundColor: Color(0xff4f44e0), 55 | title: Text("GDPR"), 56 | ), 57 | body: Center( 58 | child: ListView( 59 | children: [ 60 | SizedBox( 61 | height: 40, 62 | ), 63 | SizedBox( 64 | width: MediaQuery.of(context).size.width * 0.65, 65 | child: MixpanelButton( 66 | text: 'Opt In', 67 | onPressed: () { 68 | _mixpanel.optInTracking(); 69 | }, 70 | ), 71 | ), 72 | SizedBox( 73 | height: 20, 74 | ), 75 | SizedBox( 76 | width: MediaQuery.of(context).size.width * 0.65, 77 | child: MixpanelButton( 78 | text: 'Opt Out', 79 | onPressed: () { 80 | _mixpanel.optOutTracking(); 81 | }, 82 | ), 83 | ), 84 | SizedBox( 85 | height: 20, 86 | ), 87 | SizedBox( 88 | width: MediaQuery.of(context).size.width * 0.65, 89 | child: MixpanelButton( 90 | text: 'Has opted out', 91 | onPressed: () async { 92 | bool? optedOut = await _mixpanel.hasOptedOutTracking(); 93 | showAlertDialog(context, optedOut); 94 | }, 95 | ), 96 | ), 97 | ], 98 | )), 99 | ); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /example/lib/group.dart: -------------------------------------------------------------------------------- 1 | import 'analytics.dart'; 2 | import 'package:mixpanel_flutter/mixpanel_flutter.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:mixpanel_flutter_example/widget.dart'; 5 | 6 | class GroupScreen extends StatefulWidget { 7 | @override 8 | _GroupScreenState createState() => _GroupScreenState(); 9 | } 10 | 11 | class _GroupScreenState extends State { 12 | late final Mixpanel _mixpanel; 13 | late final MixpanelGroup _mixpanelGroup; 14 | 15 | @override 16 | void initState() { 17 | super.initState(); 18 | _initMixpanel(); 19 | } 20 | 21 | Future _initMixpanel() async { 22 | _mixpanel = await MixpanelManager.init(); 23 | _mixpanelGroup = _mixpanel.getGroup("company_id", 12346); 24 | } 25 | 26 | @override 27 | Widget build(BuildContext context) { 28 | return Scaffold( 29 | appBar: AppBar( 30 | backgroundColor: Color(0xff4f44e0), 31 | title: Text("Group"), 32 | ), 33 | body: Center( 34 | child: ListView( 35 | children: [ 36 | SizedBox( 37 | height: 40, 38 | ), 39 | SizedBox( 40 | width: MediaQuery.of(context).size.width * 0.65, 41 | child: MixpanelButton( 42 | text: 'Set One Property', 43 | onPressed: () { 44 | _mixpanelGroup.set("prop_key", "prop_value"); 45 | }, 46 | ), 47 | ), 48 | SizedBox( 49 | height: 20, 50 | ), 51 | SizedBox( 52 | width: MediaQuery.of(context).size.width * 0.65, 53 | child: MixpanelButton( 54 | text: 'Set Properties Once', 55 | onPressed: () { 56 | _mixpanelGroup.setOnce("prop_key_once", "prop_value"); 57 | }, 58 | ), 59 | ), 60 | SizedBox( 61 | height: 20, 62 | ), 63 | SizedBox( 64 | width: MediaQuery.of(context).size.width * 0.65, 65 | child: MixpanelButton( 66 | text: 'Unset Property', 67 | onPressed: () { 68 | _mixpanelGroup.unset("prop_key"); 69 | }, 70 | ), 71 | ), 72 | SizedBox( 73 | height: 20, 74 | ), 75 | SizedBox( 76 | width: MediaQuery.of(context).size.width * 0.65, 77 | child: MixpanelButton( 78 | text: 'Remove Property', 79 | onPressed: () { 80 | _mixpanelGroup.remove("prop_key2", "aaa"); 81 | }, 82 | ), 83 | ), 84 | SizedBox( 85 | height: 20, 86 | ), 87 | SizedBox( 88 | width: MediaQuery.of(context).size.width * 0.65, 89 | child: MixpanelButton( 90 | text: 'Union Properties', 91 | onPressed: () { 92 | _mixpanelGroup.union("prop_key2", ["aaa", "bbb"]); 93 | }, 94 | ), 95 | ), 96 | SizedBox( 97 | height: 20, 98 | ), 99 | SizedBox( 100 | width: MediaQuery.of(context).size.width * 0.65, 101 | child: MixpanelButton( 102 | text: 'Delete Group', 103 | onPressed: () { 104 | _mixpanel.deleteGroup("company_id", 12346); 105 | }, 106 | ), 107 | ), 108 | SizedBox( 109 | height: 20, 110 | ), 111 | SizedBox( 112 | width: MediaQuery.of(context).size.width * 0.65, 113 | child: MixpanelButton( 114 | text: 'Set Group', 115 | onPressed: () { 116 | _mixpanel.setGroup("company_id", 12346); 117 | }, 118 | ), 119 | ), 120 | SizedBox( 121 | height: 20, 122 | ), 123 | SizedBox( 124 | width: MediaQuery.of(context).size.width * 0.65, 125 | child: MixpanelButton( 126 | text: 'Add Group', 127 | onPressed: () { 128 | _mixpanel.addGroup("company_id", 12346); 129 | }, 130 | ), 131 | ), 132 | SizedBox( 133 | height: 20, 134 | ), 135 | SizedBox( 136 | width: MediaQuery.of(context).size.width * 0.65, 137 | child: MixpanelButton( 138 | text: 'Remove Group', 139 | onPressed: () { 140 | _mixpanel.removeGroup("company_id", 12346); 141 | }, 142 | ), 143 | ), 144 | SizedBox( 145 | height: 20, 146 | ), 147 | SizedBox( 148 | width: MediaQuery.of(context).size.width * 0.65, 149 | child: MixpanelButton( 150 | text: 'Track with Groups', 151 | onPressed: () { 152 | _mixpanel.trackWithGroups("tracked with groups", 153 | {"a": 1, "b": 2.3}, {"company_id": 12346}); 154 | }, 155 | ), 156 | ), 157 | SizedBox( 158 | height: 20, 159 | ), 160 | SizedBox( 161 | width: MediaQuery.of(context).size.width * 0.65, 162 | child: MixpanelButton( 163 | text: 'Flush', 164 | onPressed: () { 165 | _mixpanel.flush(); 166 | }, 167 | ), 168 | ), 169 | SizedBox( 170 | height: 40, 171 | ), 172 | ], 173 | )), 174 | ); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:mixpanel_flutter_example/widget.dart'; 3 | 4 | import 'event.dart'; 5 | import 'gdpr.dart'; 6 | import 'group.dart'; 7 | import 'profile.dart'; 8 | 9 | // This is the main page only, check out the example app in https://github.com/mixpanel/mixpanel-flutter/tree/main/example 10 | void main() { 11 | runApp(MyApp()); 12 | } 13 | 14 | class MyApp extends StatefulWidget { 15 | const MyApp(); 16 | 17 | @override 18 | State createState() => _MyAppState(); 19 | } 20 | 21 | class _MyAppState extends State { 22 | @override 23 | Widget build(BuildContext context) { 24 | return MaterialApp( 25 | debugShowCheckedModeBanner: false, 26 | initialRoute: '/', 27 | routes: { 28 | '/': (context) => FirstScreen(), 29 | '/event': (context) => EventScreen(), 30 | '/profile': (context) => ProfileScreen(), 31 | '/gdpr': (context) => GDPRScreen(), 32 | '/group': (context) => GroupScreen(), 33 | }, 34 | ); 35 | } 36 | } 37 | 38 | class FirstScreen extends StatelessWidget { 39 | @override 40 | Widget build(BuildContext context) { 41 | return Scaffold( 42 | appBar: AppBar( 43 | backgroundColor: Color(0xff4f44e0), 44 | title: Text('Mixpanel Demo'), 45 | ), 46 | body: Center( 47 | child: Column( 48 | children: [ 49 | SizedBox( 50 | height: 40, 51 | ), 52 | SizedBox( 53 | width: MediaQuery.of(context).size.width * 0.65, 54 | child: MixpanelButton( 55 | text: 'EVENT', 56 | onPressed: () { 57 | Navigator.pushNamed(context, '/event'); 58 | }, 59 | ), 60 | ), 61 | SizedBox( 62 | height: 20, 63 | ), 64 | SizedBox( 65 | width: MediaQuery.of(context).size.width * 0.65, 66 | child: MixpanelButton( 67 | text: 'PROFILE', 68 | onPressed: () { 69 | Navigator.pushNamed(context, '/profile'); 70 | }, 71 | ), 72 | ), 73 | SizedBox( 74 | height: 20, 75 | ), 76 | SizedBox( 77 | width: MediaQuery.of(context).size.width * 0.65, 78 | child: MixpanelButton( 79 | text: 'GDPR', 80 | onPressed: () { 81 | Navigator.pushNamed(context, '/gdpr'); 82 | }, 83 | ), 84 | ), 85 | SizedBox( 86 | height: 20, 87 | ), 88 | SizedBox( 89 | width: MediaQuery.of(context).size.width * 0.65, 90 | child: MixpanelButton( 91 | text: 'GROUP', 92 | onPressed: () { 93 | Navigator.pushNamed(context, '/group'); 94 | }, 95 | ), 96 | ), 97 | ], 98 | )), 99 | ); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /example/lib/profile.dart: -------------------------------------------------------------------------------- 1 | import 'analytics.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:mixpanel_flutter_example/widget.dart'; 4 | import 'package:mixpanel_flutter/mixpanel_flutter.dart'; 5 | 6 | class ProfileScreen extends StatefulWidget { 7 | @override 8 | _ProfileScreenState createState() => _ProfileScreenState(); 9 | } 10 | 11 | class _ProfileScreenState extends State { 12 | late final Mixpanel _mixpanel; 13 | 14 | @override 15 | void initState() { 16 | // TODO: implement initState 17 | super.initState(); 18 | _initMixpanel(); 19 | } 20 | 21 | Future _initMixpanel() async { 22 | _mixpanel = await MixpanelManager.init(); 23 | } 24 | 25 | @override 26 | Widget build(BuildContext context) { 27 | return Scaffold( 28 | appBar: AppBar( 29 | backgroundColor: Color(0xff4f44e0), 30 | title: Text("Profile"), 31 | ), 32 | body: Center( 33 | child: ListView( 34 | children: [ 35 | SizedBox( 36 | height: 40, 37 | ), 38 | SizedBox( 39 | width: MediaQuery.of(context).size.width * 0.65, 40 | child: MixpanelButton( 41 | text: 'Create Alias', 42 | onPressed: () { 43 | _mixpanel.alias("New Alias", "testDistinctId"); 44 | }, 45 | ), 46 | ), 47 | SizedBox( 48 | height: 20, 49 | ), 50 | SizedBox( 51 | width: MediaQuery.of(context).size.width * 0.65, 52 | child: MixpanelButton( 53 | text: 'Reset', 54 | onPressed: () { 55 | _mixpanel.reset(); 56 | }, 57 | ), 58 | ), 59 | SizedBox( 60 | height: 20, 61 | ), 62 | SizedBox( 63 | width: MediaQuery.of(context).size.width * 0.65, 64 | child: MixpanelButton( 65 | text: 'Set One Property', 66 | onPressed: () { 67 | _mixpanel.getPeople().set("ab", 34); 68 | }, 69 | ), 70 | ), 71 | SizedBox( 72 | height: 20, 73 | ), 74 | SizedBox( 75 | width: MediaQuery.of(context).size.width * 0.65, 76 | child: MixpanelButton( 77 | text: 'Set Properties Once', 78 | onPressed: () { 79 | _mixpanel.getPeople().setOnce("a", "a just once"); 80 | }, 81 | ), 82 | ), 83 | SizedBox( 84 | height: 20, 85 | ), 86 | SizedBox( 87 | width: MediaQuery.of(context).size.width * 0.65, 88 | child: MixpanelButton( 89 | text: 'Unset Properties', 90 | onPressed: () { 91 | _mixpanel.getPeople().unset("a"); 92 | }, 93 | ), 94 | ), 95 | SizedBox( 96 | height: 20, 97 | ), 98 | SizedBox( 99 | width: MediaQuery.of(context).size.width * 0.65, 100 | child: MixpanelButton( 101 | text: 'Increment Property', 102 | onPressed: () { 103 | _mixpanel.getPeople().increment("a", 2.1); 104 | }, 105 | ), 106 | ), 107 | SizedBox( 108 | height: 20, 109 | ), 110 | SizedBox( 111 | width: MediaQuery.of(context).size.width * 0.65, 112 | child: MixpanelButton( 113 | text: 'Remove Property Value', 114 | onPressed: () { 115 | _mixpanel.getPeople().remove("e", "Hello12"); 116 | }, 117 | ), 118 | ), 119 | SizedBox( 120 | height: 20, 121 | ), 122 | SizedBox( 123 | width: MediaQuery.of(context).size.width * 0.65, 124 | child: MixpanelButton( 125 | text: 'Append Properties', 126 | onPressed: () { 127 | _mixpanel.getPeople().append("e", "Hello12"); 128 | }, 129 | ), 130 | ), 131 | SizedBox( 132 | height: 20, 133 | ), 134 | SizedBox( 135 | width: MediaQuery.of(context).size.width * 0.65, 136 | child: MixpanelButton( 137 | text: 'Union Properties', 138 | onPressed: () { 139 | _mixpanel.getPeople().union("c", ["goodbye", "hi34"]); 140 | }, 141 | ), 142 | ), 143 | SizedBox( 144 | height: 20, 145 | ), 146 | SizedBox( 147 | width: MediaQuery.of(context).size.width * 0.65, 148 | child: MixpanelButton( 149 | text: 'Track Charge w/o Properties', 150 | onPressed: () { 151 | _mixpanel.getPeople().trackCharge(22.8); 152 | }, 153 | ), 154 | ), 155 | SizedBox( 156 | height: 20, 157 | ), 158 | SizedBox( 159 | width: MediaQuery.of(context).size.width * 0.65, 160 | child: MixpanelButton( 161 | text: 'Track Charge w Properties', 162 | onPressed: () { 163 | _mixpanel 164 | .getPeople() 165 | .trackCharge(22.8, properties: {"sandwich": 1}); 166 | }, 167 | ), 168 | ), 169 | SizedBox( 170 | height: 20, 171 | ), 172 | SizedBox( 173 | width: MediaQuery.of(context).size.width * 0.65, 174 | child: MixpanelButton( 175 | text: 'Clear Charges', 176 | onPressed: () { 177 | _mixpanel.getPeople().clearCharges(); 178 | }, 179 | ), 180 | ), 181 | SizedBox( 182 | height: 20, 183 | ), 184 | SizedBox( 185 | width: MediaQuery.of(context).size.width * 0.65, 186 | child: MixpanelButton( 187 | text: 'Delete User', 188 | onPressed: () { 189 | _mixpanel.getPeople().deleteUser(); 190 | }, 191 | ), 192 | ), 193 | SizedBox( 194 | height: 20, 195 | ), 196 | SizedBox( 197 | width: MediaQuery.of(context).size.width * 0.65, 198 | child: MixpanelButton( 199 | text: 'Flush', 200 | onPressed: () { 201 | _mixpanel.flush(); 202 | }, 203 | ), 204 | ), 205 | SizedBox( 206 | height: 40, 207 | ), 208 | ], 209 | )), 210 | ); 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /example/lib/widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class MixpanelButton extends StatelessWidget { 4 | MixpanelButton({required this.onPressed, required this.text}); 5 | final GestureTapCallback onPressed; 6 | final String text; 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return ElevatedButton( 11 | style: ElevatedButton.styleFrom( 12 | foregroundColor: Colors.white, 13 | backgroundColor: Color(0xff4f44e0), // foreground 14 | ), 15 | onPressed: onPressed, 16 | child: Text(text), 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.12.0" 12 | boolean_selector: 13 | dependency: transitive 14 | description: 15 | name: boolean_selector 16 | sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.1.2" 20 | characters: 21 | dependency: transitive 22 | description: 23 | name: characters 24 | sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "1.4.0" 28 | clock: 29 | dependency: transitive 30 | description: 31 | name: clock 32 | sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.1.2" 36 | collection: 37 | dependency: transitive 38 | description: 39 | name: collection 40 | sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.19.1" 44 | cupertino_icons: 45 | dependency: "direct main" 46 | description: 47 | name: cupertino_icons 48 | sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.0.6" 52 | fake_async: 53 | dependency: transitive 54 | description: 55 | name: fake_async 56 | sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "1.3.2" 60 | flutter: 61 | dependency: "direct main" 62 | description: flutter 63 | source: sdk 64 | version: "0.0.0" 65 | flutter_test: 66 | dependency: "direct dev" 67 | description: flutter 68 | source: sdk 69 | version: "0.0.0" 70 | flutter_web_plugins: 71 | dependency: transitive 72 | description: flutter 73 | source: sdk 74 | version: "0.0.0" 75 | leak_tracker: 76 | dependency: transitive 77 | description: 78 | name: leak_tracker 79 | sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec 80 | url: "https://pub.dev" 81 | source: hosted 82 | version: "10.0.8" 83 | leak_tracker_flutter_testing: 84 | dependency: transitive 85 | description: 86 | name: leak_tracker_flutter_testing 87 | sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 88 | url: "https://pub.dev" 89 | source: hosted 90 | version: "3.0.9" 91 | leak_tracker_testing: 92 | dependency: transitive 93 | description: 94 | name: leak_tracker_testing 95 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" 96 | url: "https://pub.dev" 97 | source: hosted 98 | version: "3.0.1" 99 | matcher: 100 | dependency: transitive 101 | description: 102 | name: matcher 103 | sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 104 | url: "https://pub.dev" 105 | source: hosted 106 | version: "0.12.17" 107 | material_color_utilities: 108 | dependency: transitive 109 | description: 110 | name: material_color_utilities 111 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec 112 | url: "https://pub.dev" 113 | source: hosted 114 | version: "0.11.1" 115 | meta: 116 | dependency: transitive 117 | description: 118 | name: meta 119 | sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c 120 | url: "https://pub.dev" 121 | source: hosted 122 | version: "1.16.0" 123 | mixpanel_flutter: 124 | dependency: "direct main" 125 | description: 126 | path: ".." 127 | relative: true 128 | source: path 129 | version: "2.4.3" 130 | path: 131 | dependency: transitive 132 | description: 133 | name: path 134 | sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" 135 | url: "https://pub.dev" 136 | source: hosted 137 | version: "1.9.1" 138 | sky_engine: 139 | dependency: transitive 140 | description: flutter 141 | source: sdk 142 | version: "0.0.0" 143 | source_span: 144 | dependency: transitive 145 | description: 146 | name: source_span 147 | sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" 148 | url: "https://pub.dev" 149 | source: hosted 150 | version: "1.10.1" 151 | stack_trace: 152 | dependency: transitive 153 | description: 154 | name: stack_trace 155 | sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" 156 | url: "https://pub.dev" 157 | source: hosted 158 | version: "1.12.1" 159 | stream_channel: 160 | dependency: transitive 161 | description: 162 | name: stream_channel 163 | sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" 164 | url: "https://pub.dev" 165 | source: hosted 166 | version: "2.1.4" 167 | string_scanner: 168 | dependency: transitive 169 | description: 170 | name: string_scanner 171 | sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" 172 | url: "https://pub.dev" 173 | source: hosted 174 | version: "1.4.1" 175 | term_glyph: 176 | dependency: transitive 177 | description: 178 | name: term_glyph 179 | sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" 180 | url: "https://pub.dev" 181 | source: hosted 182 | version: "1.2.2" 183 | test_api: 184 | dependency: transitive 185 | description: 186 | name: test_api 187 | sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd 188 | url: "https://pub.dev" 189 | source: hosted 190 | version: "0.7.4" 191 | vector_math: 192 | dependency: transitive 193 | description: 194 | name: vector_math 195 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 196 | url: "https://pub.dev" 197 | source: hosted 198 | version: "2.1.4" 199 | vm_service: 200 | dependency: transitive 201 | description: 202 | name: vm_service 203 | sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" 204 | url: "https://pub.dev" 205 | source: hosted 206 | version: "14.3.1" 207 | sdks: 208 | dart: ">=3.7.0-0 <4.0.0" 209 | flutter: ">=3.18.0-18.0.pre.54" 210 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: mixpanel_flutter_example 2 | description: Demonstrates how to use the mixpanel_flutter plugin. 3 | 4 | publish_to: 'none' 5 | 6 | environment: 7 | sdk: '>=2.12.0 <3.0.0' 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | 13 | mixpanel_flutter: 14 | path: ../ 15 | 16 | cupertino_icons: ^1.0.0 17 | 18 | dev_dependencies: 19 | flutter_test: 20 | sdk: flutter 21 | 22 | 23 | flutter: 24 | uses-material-design: true 25 | 26 | -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility in the flutter_test package. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | import 'package:mixpanel_flutter_example/main.dart'; 11 | 12 | void main() { 13 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 14 | // Build our app and trigger a frame. 15 | await tester.pumpWidget(const MyApp()); 16 | 17 | // Verify that our counter starts at 0. 18 | expect(find.text('0'), findsOneWidget); 19 | expect(find.text('1'), findsNothing); 20 | 21 | // Tap the '+' icon and trigger a frame. 22 | await tester.tap(find.byIcon(Icons.add)); 23 | await tester.pump(); 24 | 25 | // Verify that our counter has incremented. 26 | expect(find.text('0'), findsNothing); 27 | expect(find.text('1'), findsOneWidget); 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/web/favicon.png -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/example/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | mixpanel_example 33 | 34 | 35 | 39 | 40 | 41 | 44 | 45 | 46 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mixpanel_example", 3 | "short_name": "mixpanel_example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/Generated.xcconfig 37 | /Flutter/flutter_export_environment.sh -------------------------------------------------------------------------------- /ios/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mixpanel/mixpanel-flutter/360e096f7f258da71b38b883d4da02df446e16ab/ios/Assets/.gitkeep -------------------------------------------------------------------------------- /ios/Classes/MixpanelFlutterPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface MixpanelFlutterPlugin : NSObject 4 | @end 5 | -------------------------------------------------------------------------------- /ios/Classes/MixpanelFlutterPlugin.m: -------------------------------------------------------------------------------- 1 | #import "MixpanelFlutterPlugin.h" 2 | #if __has_include() 3 | #import 4 | #else 5 | // Support project import fallback if the generated compatibility header 6 | // is not copied when this plugin is created as a library. 7 | // https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 8 | #import "mixpanel_flutter-Swift.h" 9 | #endif 10 | 11 | @implementation MixpanelFlutterPlugin 12 | + (void)registerWithRegistrar:(NSObject*)registrar { 13 | [SwiftMixpanelFlutterPlugin registerWithRegistrar:registrar]; 14 | } 15 | @end 16 | -------------------------------------------------------------------------------- /ios/Classes/MixpanelTypeHandler.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Mixpanel 3 | 4 | class MixpanelTypeHandler { 5 | 6 | static func mixpanelTypeValue(_ object: Any) -> MixpanelType? { 7 | switch object { 8 | case let value as String: 9 | return value as MixpanelType 10 | 11 | case let value as NSNumber: 12 | if isBoolNumber(value) { 13 | return value.boolValue as MixpanelType 14 | } else if isInvalidNumber(value) { 15 | return String(describing: value) as MixpanelType 16 | } else { 17 | return value as MixpanelType 18 | } 19 | 20 | case let value as Int: 21 | return value as MixpanelType 22 | 23 | case let value as UInt: 24 | return value as MixpanelType 25 | 26 | case let value as Double: 27 | return value as MixpanelType 28 | 29 | case let value as Float: 30 | return value as MixpanelType 31 | 32 | case let value as Bool: 33 | return value as MixpanelType 34 | 35 | case let value as Date: 36 | return value as MixpanelType 37 | 38 | case let value as URL: 39 | return value 40 | 41 | case let value as NSNull: 42 | return value 43 | 44 | case let value as [Any]: 45 | return value.map { mixpanelTypeValue($0) } 46 | 47 | case let value as [String: Any]: 48 | return value.mapValues { mixpanelTypeValue($0) } 49 | 50 | case let value as MixpanelType: 51 | return value 52 | 53 | default: 54 | return nil 55 | } 56 | } 57 | 58 | private static func isBoolNumber(_ num: NSNumber) -> Bool 59 | { 60 | let boolID = CFBooleanGetTypeID() 61 | let numID = CFGetTypeID(num) 62 | return numID == boolID 63 | } 64 | 65 | private static func isInvalidNumber(_ num: NSNumber) -> Bool 66 | { 67 | return num.doubleValue.isInfinite || num.doubleValue.isNaN 68 | } 69 | 70 | static func mixpanelProperties(properties: Dictionary? = nil, mixpanelProperties: Dictionary? = nil) -> Dictionary { 71 | var properties = (properties != nil) ? properties : [:] 72 | 73 | if let mixpanelProperties = mixpanelProperties { 74 | properties?.merge(dict: mixpanelProperties) 75 | } 76 | 77 | var allProperties = Dictionary() 78 | 79 | for (key, value) in properties ?? [:] { 80 | allProperties[key] = mixpanelTypeValue(value) 81 | } 82 | 83 | return allProperties 84 | } 85 | } 86 | 87 | extension Dictionary { 88 | mutating func merge(dict: [Key: Value]){ 89 | for (k, v) in dict { 90 | updateValue(v, forKey: k) 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /ios/mixpanel_flutter.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. 3 | # Run `pod lib lint mixpanel_flutter.podspec' to validate before publishing. 4 | # 5 | Pod::Spec.new do |s| 6 | s.name = 'mixpanel_flutter' 7 | s.version = '2.4.4' 8 | s.summary = 'Official Flutter Tracking Library for Mixpanel Analytics' 9 | s.homepage = 'https://www.mixpanel.com' 10 | s.license = { :file => '../LICENSE' } 11 | s.author = { 'Mixpanel, Inc' => 'support@mixpanel.com' } 12 | s.source = { :path => '.' } 13 | s.source_files = 'Classes/**/*' 14 | s.dependency 'Flutter' 15 | s.dependency 'Mixpanel-swift', '5.1.0' 16 | s.platform = :ios, '12.0' 17 | 18 | # Flutter.framework does not contain a i386 slice. 19 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } 20 | s.swift_version = '5.0' 21 | end 22 | -------------------------------------------------------------------------------- /lib/codec/mixpanel_message_codec.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'package:flutter/services.dart'; 3 | 4 | /// The codec utilized to encode data back and forth between 5 | /// the Dart application and the native platform. 6 | class MixpanelMessageCodec extends StandardMessageCodec { 7 | /// Constructor. 8 | const MixpanelMessageCodec(); 9 | 10 | static const int _kDateTime = 128; 11 | static const int _kUri = 129; 12 | 13 | @override 14 | void writeValue(WriteBuffer buffer, dynamic value) { 15 | if (value is DateTime) { 16 | buffer.putUint8(_kDateTime); 17 | buffer.putInt64(value.millisecondsSinceEpoch); 18 | } else if (value is Uri) { 19 | buffer.putUint8(_kUri); 20 | final bytes = utf8.encoder.convert(value.toString()); 21 | writeSize(buffer, bytes.length); 22 | buffer.putUint8List(bytes); 23 | } else { 24 | super.writeValue(buffer, value); 25 | } 26 | } 27 | 28 | @override 29 | dynamic readValueOfType(int type, ReadBuffer buffer) { 30 | switch (type) { 31 | case _kDateTime: 32 | return DateTime.fromMillisecondsSinceEpoch(buffer.getInt64()); 33 | case _kUri: 34 | final int length = readSize(buffer); 35 | final String string = utf8.decoder.convert(buffer.getUint8List(length)); 36 | return Uri.parse(string); 37 | default: 38 | return super.readValueOfType(type, buffer); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/web/mixpanel_js_bindings.dart: -------------------------------------------------------------------------------- 1 | import 'dart:js_interop'; 2 | 3 | @JS('mixpanel') 4 | @staticInterop 5 | class Mixpanel {} 6 | 7 | @JS('MixpanelGroup') 8 | @staticInterop 9 | class MixpanelGroup {} 10 | 11 | extension MixpanelGroupMethods on MixpanelGroup { 12 | external void set(JSAny? properties); 13 | 14 | @JS('group.set_once') 15 | external void set_once(String prop, JSAny? to); 16 | 17 | external void unset(String prop); 18 | 19 | external void remove(String name, JSAny? value); 20 | 21 | external void union(String name, JSArray values); 22 | } 23 | 24 | @JS('mixpanel.init') 25 | external void init(String token, JSAny? config); 26 | 27 | @JS('mixpanel.set_config') 28 | external void set_config(JSAny? config); 29 | 30 | @JS('mixpanel.has_opted_out_tracking') 31 | external bool has_opted_out_tracking(); 32 | 33 | @JS('mixpanel.opt_in_tracking') 34 | external void opt_in_tracking(); 35 | 36 | @JS('mixpanel.opt_out_tracking') 37 | external void opt_out_tracking(); 38 | 39 | @JS('mixpanel.identify') 40 | external void identify(String distinctId); 41 | 42 | @JS('mixpanel.alias') 43 | external void alias(String alias, String distinctId); 44 | 45 | @JS('mixpanel.track') 46 | external void track(String name, JSAny? properties); 47 | 48 | @JS('mixpanel.track_with_groups') 49 | external void track_with_groups( 50 | String event_name, JSAny? properties, JSAny? groups); 51 | 52 | @JS('mixpanel.set_group') 53 | external void set_group(String group_key, JSAny? group_ids); 54 | 55 | @JS('mixpanel.add_group') 56 | external void add_group(String group_key, JSAny? group_id); 57 | 58 | @JS('mixpanel.remove_group') 59 | external void remove_group(String group_key, JSAny? group_id); 60 | 61 | @JS('mixpanel.get_group') 62 | external MixpanelGroup get_group(String group_key, JSAny? group_id); 63 | 64 | @JS('mixpanel.register') 65 | external void register(JSAny? properties); 66 | 67 | @JS('mixpanel.register_once') 68 | external void register_once(JSAny? properties); 69 | 70 | @JS('mixpanel.unregister') 71 | external void unregister(String property); 72 | 73 | @JS('mixpanel.time_event') 74 | external void time_event(String event_name); 75 | 76 | @JS('mixpanel.reset') 77 | external void reset(); 78 | 79 | @JS('mixpanel.get_distinct_id') 80 | external String get_distinct_id(); 81 | 82 | @JS('mixpanel.people.set') 83 | external void people_set(JSAny? properties); 84 | 85 | @JS('mixpanel.people.set_once') 86 | external void people_set_once(JSAny? properties); 87 | 88 | @JS('mixpanel.people.increment') 89 | external void people_increment(JSAny? properties); 90 | 91 | @JS('mixpanel.people.append') 92 | external void people_append(JSAny? properties); 93 | 94 | @JS('mixpanel.people.union') 95 | external void people_union(JSAny? properties); 96 | 97 | @JS('mixpanel.people.remove') 98 | external void people_remove(JSAny? properties); 99 | 100 | @JS('mixpanel.people.unset') 101 | external void people_unset(JSAny? properties); 102 | 103 | @JS('mixpanel.people.track_charge') 104 | external void people_track_charge(double amount, JSAny? properties); 105 | 106 | @JS('mixpanel.people.clear_charge') 107 | external void people_clear_charge(); 108 | 109 | @JS('mixpanel.people.delete_users') 110 | external void people_delete_users(); 111 | -------------------------------------------------------------------------------- /local.properties: -------------------------------------------------------------------------------- 1 | ## This file must *NOT* be checked into Version Control Systems, 2 | # as it contains information specific to your local configuration. 3 | # 4 | # Location of the SDK. This is only used by Gradle. 5 | # For customization when using a Version Control System, please read the 6 | # header note. 7 | #Thu Jan 28 14:11:03 PST 2021 8 | sdk.dir=/Users/zihejia/Library/Android/sdk 9 | -------------------------------------------------------------------------------- /mixpanel_flutter.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.12.0" 12 | boolean_selector: 13 | dependency: transitive 14 | description: 15 | name: boolean_selector 16 | sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.1.2" 20 | characters: 21 | dependency: transitive 22 | description: 23 | name: characters 24 | sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "1.4.0" 28 | clock: 29 | dependency: transitive 30 | description: 31 | name: clock 32 | sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.1.2" 36 | collection: 37 | dependency: transitive 38 | description: 39 | name: collection 40 | sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.19.1" 44 | fake_async: 45 | dependency: transitive 46 | description: 47 | name: fake_async 48 | sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.3.2" 52 | flutter: 53 | dependency: "direct main" 54 | description: flutter 55 | source: sdk 56 | version: "0.0.0" 57 | flutter_test: 58 | dependency: "direct dev" 59 | description: flutter 60 | source: sdk 61 | version: "0.0.0" 62 | flutter_web_plugins: 63 | dependency: "direct main" 64 | description: flutter 65 | source: sdk 66 | version: "0.0.0" 67 | leak_tracker: 68 | dependency: transitive 69 | description: 70 | name: leak_tracker 71 | sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec 72 | url: "https://pub.dev" 73 | source: hosted 74 | version: "10.0.8" 75 | leak_tracker_flutter_testing: 76 | dependency: transitive 77 | description: 78 | name: leak_tracker_flutter_testing 79 | sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 80 | url: "https://pub.dev" 81 | source: hosted 82 | version: "3.0.9" 83 | leak_tracker_testing: 84 | dependency: transitive 85 | description: 86 | name: leak_tracker_testing 87 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" 88 | url: "https://pub.dev" 89 | source: hosted 90 | version: "3.0.1" 91 | matcher: 92 | dependency: transitive 93 | description: 94 | name: matcher 95 | sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 96 | url: "https://pub.dev" 97 | source: hosted 98 | version: "0.12.17" 99 | material_color_utilities: 100 | dependency: transitive 101 | description: 102 | name: material_color_utilities 103 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec 104 | url: "https://pub.dev" 105 | source: hosted 106 | version: "0.11.1" 107 | meta: 108 | dependency: transitive 109 | description: 110 | name: meta 111 | sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c 112 | url: "https://pub.dev" 113 | source: hosted 114 | version: "1.16.0" 115 | path: 116 | dependency: transitive 117 | description: 118 | name: path 119 | sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" 120 | url: "https://pub.dev" 121 | source: hosted 122 | version: "1.9.1" 123 | sky_engine: 124 | dependency: transitive 125 | description: flutter 126 | source: sdk 127 | version: "0.0.0" 128 | source_span: 129 | dependency: transitive 130 | description: 131 | name: source_span 132 | sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" 133 | url: "https://pub.dev" 134 | source: hosted 135 | version: "1.10.1" 136 | stack_trace: 137 | dependency: transitive 138 | description: 139 | name: stack_trace 140 | sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" 141 | url: "https://pub.dev" 142 | source: hosted 143 | version: "1.12.1" 144 | stream_channel: 145 | dependency: transitive 146 | description: 147 | name: stream_channel 148 | sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" 149 | url: "https://pub.dev" 150 | source: hosted 151 | version: "2.1.4" 152 | string_scanner: 153 | dependency: transitive 154 | description: 155 | name: string_scanner 156 | sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" 157 | url: "https://pub.dev" 158 | source: hosted 159 | version: "1.4.1" 160 | term_glyph: 161 | dependency: transitive 162 | description: 163 | name: term_glyph 164 | sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" 165 | url: "https://pub.dev" 166 | source: hosted 167 | version: "1.2.2" 168 | test_api: 169 | dependency: transitive 170 | description: 171 | name: test_api 172 | sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd 173 | url: "https://pub.dev" 174 | source: hosted 175 | version: "0.7.4" 176 | vector_math: 177 | dependency: transitive 178 | description: 179 | name: vector_math 180 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 181 | url: "https://pub.dev" 182 | source: hosted 183 | version: "2.1.4" 184 | vm_service: 185 | dependency: transitive 186 | description: 187 | name: vm_service 188 | sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" 189 | url: "https://pub.dev" 190 | source: hosted 191 | version: "14.3.1" 192 | sdks: 193 | dart: ">=3.7.0-0 <4.0.0" 194 | flutter: ">=3.18.0-18.0.pre.54" 195 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: mixpanel_flutter 2 | description: Official Flutter Tracking SDK for Mixpanel Analytics developed and maintained by Mixpanel, Inc. 3 | version: 2.4.4 4 | homepage: https://mixpanel.com 5 | repository: https://github.com/mixpanel/mixpanel-flutter 6 | issue_tracker: https://github.com/mixpanel/mixpanel-flutter/issues 7 | documentation: https://developer.mixpanel.com/docs/flutter 8 | 9 | environment: 10 | sdk: '>=2.12.0 <4.0.0' 11 | flutter: ">=1.20.0" 12 | 13 | dependencies: 14 | flutter: 15 | sdk: flutter 16 | flutter_web_plugins: 17 | sdk: flutter 18 | 19 | dev_dependencies: 20 | flutter_test: 21 | sdk: flutter 22 | 23 | flutter: 24 | assets: 25 | - assets/mixpanel.js 26 | 27 | plugin: 28 | platforms: 29 | android: 30 | package: com.mixpanel.mixpanel_flutter 31 | pluginClass: MixpanelFlutterPlugin 32 | ios: 33 | pluginClass: MixpanelFlutterPlugin 34 | web: 35 | pluginClass: MixpanelFlutterPlugin 36 | fileName: mixpanel_flutter_web.dart 37 | -------------------------------------------------------------------------------- /tool/release.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import subprocess 3 | 4 | parser = argparse.ArgumentParser(description='Release Mixpanel Flutter SDK') 5 | parser.add_argument('--old', help='version for the release', action="store") 6 | parser.add_argument('--new', help='version for the release', action="store") 7 | args = parser.parse_args() 8 | 9 | def bump_version(): 10 | replace_version('pubspec.yaml', "version: " + args.old, "version: " + args.new) 11 | replace_version('lib/mixpanel_flutter.dart', "\'\\$lib_version\': \'" + args.old + "\'", "\'\\$lib_version\': \'" + args.new + "\'") 12 | replace_version('test/mixpanel_flutter_test.dart', "\'\\$lib_version\': \'" + args.old + "\'", "\'\\$lib_version\': \'" + args.new + "\'") 13 | replace_version('ios/mixpanel_flutter.podspec', "= \'" + args.old + "\'", "= \'" + args.new + "\'") 14 | subprocess.call('git add pubspec.yaml', shell=True) 15 | subprocess.call('git add lib/mixpanel_flutter.dart', shell=True) 16 | subprocess.call('git add test/mixpanel_flutter_test.dart', shell=True) 17 | subprocess.call('git add ios/mixpanel_flutter.podspec', shell=True) 18 | subprocess.call('git commit -m "Version {}"'.format(args.new), shell=True) 19 | subprocess.call('git push', shell=True) 20 | 21 | def replace_version(file_name, old_version, new_version): 22 | with open(file_name) as f: 23 | file_str = f.read() 24 | assert(old_version in file_str) 25 | file_str = file_str.replace(old_version, new_version) 26 | 27 | with open(file_name, "w") as f: 28 | f.write(file_str) 29 | 30 | def generate_docs(): 31 | subprocess.call('flutter analyze --no-pub --no-current-package lib', shell=True) 32 | subprocess.call('dartdoc --output docs', shell=True) 33 | subprocess.call('git add docs', shell=True) 34 | subprocess.call('git commit -m "Update docs"', shell=True) 35 | subprocess.call('git push', shell=True) 36 | 37 | def add_tag(): 38 | subprocess.call('git tag -a v{} -m "version {}"'.format(args.new, args.new), shell=True) 39 | subprocess.call('git push origin --tags', shell=True) 40 | 41 | def publish_dry_run(): 42 | subprocess.call('mv docs doc', shell=True) 43 | subprocess.call('dart pub publish --dry-run', shell=True) 44 | subprocess.call('mv doc docs', shell=True) 45 | 46 | def clean_up(): 47 | subprocess.call('flutter clean', shell=True) 48 | subprocess.call('cd example', shell=True) 49 | subprocess.call('flutter clean', shell=True) 50 | 51 | def main(): 52 | bump_version() 53 | generate_docs() 54 | add_tag() 55 | publish_dry_run() 56 | clean_up() 57 | print("Congratulations! " + args.new + " is now ready to be released!") 58 | 59 | if __name__ == '__main__': 60 | main() 61 | --------------------------------------------------------------------------------