diff --git a/.github/ISSUE_TEMPLATE/-------------------------.md b/.github/ISSUE_TEMPLATE/-------------------------.md
new file mode 100644
index 0000000..78430f5
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/-------------------------.md
@@ -0,0 +1,27 @@
+---
+name: "\U0001F680 اضافهکردن قابلیت جدید"
+about: در صورتی که درخواست دارید که قابلیتی جدید به لایبرری اضافه شود
+title: "\U0001F680 [FEATURE]: "
+labels: enhancement
+assignees: ''
+
+---
+
+
+
+[//]: # ([FEATURE] و اموجی در تیتر برای وضوح مشکل ترجیحا باقی بماند)
+[//]: # (لطفا حتما تمپلیت را رعایت کنید تا مشکل به خوبی توضیح داده شود و متون تمپلیت را پاک نکنید)
+
+
+**آیا این قابلیت مرتبط با مشکلی است؟ توضیح دهید**
+در صورتی که این قابلیت برگرفته از یک مشکل است لطفا مشکل را شرحدهید
+
+[//]: # (در صورتی که قصد دارید مشکلی را بیان کنید و درخواست قابلیتی را ندارید بایستی مشکل را بصورت خطا یا باگ مطرح کنید و نه قابلیت)
+
+**شرح قابلیت و کارکرد آن**
+این قابلیت چه استفادهای دارد و چه مشکلی را حل میکند یا چه امکانی را اضافه میکند
+
+**در حال حاضر جایگزینی برای این قابلیت وجود دارد؟**
+در صورتی که این قابلیت نباشد آیا راه جایگزینی وجود دارد؟
+
+
diff --git a/.github/ISSUE_TEMPLATE/-------------------.md b/.github/ISSUE_TEMPLATE/-------------------.md
new file mode 100644
index 0000000..247c2d7
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/-------------------.md
@@ -0,0 +1,38 @@
+---
+name: "❓: بیان سوال یا خطا"
+about: در صورتی که اروری در هر موردی رخداده که در سوالات و خطاهای مستندات ذکر نشدهاست
+title: "❓ [ERROR]: "
+labels: question
+assignees: ''
+
+---
+
+
+
+[//]: # ([ERROR] و اموجی در تیتر برای وضوح مشکل ترجیحا باقی بماند)
+[//]: # (لطفا حتما تمپلیت را رعایت کنید تا مشکل به خوبی توضیح داده شود و متون تمپلیت را پاک نکنید)
+
+**شرح خطا**
+خطایی که رخداده است را شرحدهید
+
+[//]: # (در صورتی که نصب شما ثبت نمیشود لطفا خطاهای مستندات را مطالعه کنید)
+[//]: # (برای اضافهکردن کد آن را از بلاک div خارج کنید تا سمت راست قرار نگیرد)
+
+**لاگ خطا**
+لاگی که در لاگکت هنگام رخدادن خطا چاپ میشود. متن کامل استکتریس را چاپ کنید.
+
+
+
+```
+paste log here
+```
+
+
+
+**اطلاعات محیط تست**
+- نسخهی پوشه یا پلاگین
+- نسخهی فریمورک
+- سیستمعامل (Android/iOS)
+- TargetSDK/CompileSDK (Android)
+
+
diff --git a/.github/ISSUE_TEMPLATE/----------------.md b/.github/ISSUE_TEMPLATE/----------------.md
new file mode 100644
index 0000000..408c9f1
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/----------------.md
@@ -0,0 +1,37 @@
+---
+name: "\U0001F41B باگ در پلاگین"
+about: وجود باگ یا مشکل در پلاگین
+title: "\U0001F41B [BUG]: "
+labels: bug
+assignees: ''
+
+---
+
+
+
+[//]: # ([BUG] و اموجی در تیتر برای وضوح مشکل ترجیحا باقی بماند)
+[//]: # (لطفا حتما تمپلیت را رعایت کنید تا مشکل به خوبی توضیح داده شود و متون تمپلیت را پاک نکنید)
+
+**شرح باگ**
+باگی که با آن مواجه شدید را شرح دهید
+
+[//]: # (در صورتی که نصب ثبت نمیشود لطفا به مستندات مراجعه کنید و خطاها را مطالعه نمایید)
+[//]: # (برای اضافهکردن کد آنرا خارج از بلاک div قرار دهید تا سمت راست قرار نگیرد)
+
+**تولید مجدد باگ**
+گامهای لازم را که برای تولید باگ بایستی طی کرد را لیست کنید
+
+
+**اطلاعات محیط تست**
+- سیستمعامل (iOS/Android)
+- نسخهی پوشه یا پلاگین پوشه
+- CompileSDK/TargetSDK (For Android)
+- اطلاعات دستگاهی که با آن تست کردید
+
+**لاگ خطا در لاگکت**
+لاگی که در لاگ کت وجود دارد (استکتریس کامل) را وارد کنید
+
+**اطلاعات اضافی**
+اطلاعاتی که میتواند به وضوح بیان مشکل کمک کند
+
+
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 0000000..a1fc228
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,42 @@
+name: Deploy
+
+on:
+ push:
+ branches:
+ - master
+
+jobs:
+ deploy-sample:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Setup git
+ run: |
+ echo "Initializing git"
+ git config --global user.name "Mahdi-Malv"
+ git config --global user.email "mmalvandi75@gmail.com"
+ - uses: webfactory/ssh-agent@v0.4.1
+ with:
+ ACTIONS_ALLOW_UNSECURE_COMMANDS: true
+ ssh-private-key: ${{ secrets.ACTION_PRIVATE_KEY }}
+ - name: Chaning local version to global version in sample
+ run: |
+ VERSION=$(cat pubspec.yaml | grep -i 'version:' | awk '{ print $2 }')
+ cd example
+ sed -i -e "s@path: ../@ @g" pubspec.yaml
+ var3='pushe_flutter:'; var4="pushe_flutter: $VERSION"
+ sed -i -e "s@$var3@$var4@g" pubspec.yaml
+ cd ..
+ - name: Push sample
+ run: |
+ VERSION=$(cat pubspec.yaml | grep -i 'version:' | awk '{ print $2 }')
+ rm -rf .git
+ cd example
+ git init
+ git remote add example git@github.com:pusheco/pushe-flutter-sample.git
+ git add -A
+ git commit -m "Update example with pushe:$VERSION"
+ git push -f example master
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e784e73
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,17 @@
+.DS_Store
+.dart_tool/
+
+.packages
+.pub/
+
+build/
+
+*.iml
+
+.idea/
+
+example/.metadata
+
+example/\.flutter-plugins-dependencies
+
+example/ios/Flutter/flutter_export_environment\.sh
diff --git a/.metadata b/.metadata
new file mode 100644
index 0000000..9e63b03
--- /dev/null
+++ b/.metadata
@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+ revision: f30b7f4db93ee747cd727df747941a28ead25ff5
+ channel: stable
+
+project_type: plugin
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..5eb5ff4
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,207 @@
+# ChangeLog
+
+## 2.5.2
+### Android
+- [fix] Bridge methods casting issue
+
+## 2.5.1
+### Android
+- [Breaking] **Huawei push support** android module is now optional and will not be added to classpath by default
+ In order to get benefits add it to your `build.gradle` file:
+
+ ```groovy
+ //dependencies {
+ implementation("co.pushe.plus:hms:2.5.1")
+ // }
+ ```
+
+
+- [Breaking] `PusheInAppMessaging` android module is now optional and will not be added to classpath by default
+ In order to get benefits add it to your `build.gradle` file:
+
+ ```groovy
+ //dependencies {
+ implementation("co.pushe.plus:inappmessaging:2.5.1")
+ // }
+ ```
+
+- **Feat**: Update `targetSDK` to 31. This update also fixes the `android:exported` service attribute issue
+
+### iOS
+- [**Breaking**]: iOS support is canceled temporarily until it is decided to bring it back. `Pushe.dart` method will ignore non-android calls and return default results
+
+
+## 2.5.1-nullsafety.1
+- Fix: Remove legacy preview remote for downloading native packages
+
+## 2.5.1-nullsafety.0
+- Migration to null-safety
+
+## 2.5.0
+### Android
+- Update native dependency to `2.5.0`
+ - **New**: Adds ability to ignore showing notification if app is open (either all notifications or individually using `show_foreground`)
+ - **New**: Location and Geofencing features are applied to `hms` module. Huawei devices can have location-related features
+ - Bug fixes and improvements
+- **Feat:** New APIs for notification foreground awareness
+ - `enableNotificationForceForegroundAware`: Force enable foreground awareness for all notifications
+ - `disableNotificationForceForegroundAware`: Disable what was enabled by above function
+ - `isForceForegroundAware`: Is enabled or not
+
+## 2.4.2
+- Fix null-safe issue in `PusheChandler.kt`
+
+## 2.4.1
+### Android
+- Update native module to `2.4.1` which includes:
+ - Bug fix for `hms` module
+ - Fix issues in registration
+- Add `getFcmToken` and `getHmsToken` to return module tokens if needed
+- Add `getActiveService` to return the currently chosen service to interact with (fcm,hms)
+- Deprecate `getGoogleAdvertisingId`. Use `getAdvertisingId` instead. New method returns Huawei `OAID` when hms is used
+
+### iOS
+- Unchanged
+
+## 2.4.0
+
+> **New**
+> - PusheFlutter now features iOS support
+> - Android supports Huawei push notifications using `hms` module
+
+### Android
+- Update native library to `2.4.1-beta05` which includes:
+ - `hms` module adding support for sending push notifications on Huawei devices (HMSCore)
+ - Improvements and bug fixes
+
+### iOS
+- Stable changes of `2.3.0-alpha01`
+
+## 2.3.0-alpha01
+
+> **New**
+> PusheFlutter now features iOS support
+
+- [change] Inner plugin classes are changed to respect iOS native classes
+- **Android**: Update native library to `2.2.1`
+
+
+## 2.2.0
+
+- Introducing **InAppMessaging** module added to plugin
+- Added APIs:
+ * `triggerEvent` for triggering local events.
+ * `disableInAppMessaging`/`EnableInAppMessaging`/`isInAppMessagingEnabled` to control whether message should be shown or not.
+ * `setInAppMessagingListener` to get a callback when a specific event occurred on InAppMessaging module
+ * `dismissShownInApp` to remove shown InApp message using code
+ * `testInAppMessage` for testing purposes using code
+- **Fix**: Bug in `sendNotificationToUser` when type was `DeviceId`
+- **Fix**: PlatformChannel crash after successful `sendNotificationToUser`
+
+## 2.1.1
+- Update Native Android dependency to `pushe:2.1.1`
+- Custom RxJava is used to avoid large size when not needed
+ - If developer or any library is using RxJava, `duplicate` error might be thrown
+ In that case you should exclude RxJava and instead implement a normal version
+- Added support for GDPR compliance
+- Native library has been migrated to AndroidX
+- Deprecate `getAndroidId`. Instead, `getDeviceId` should be used
+
+## 2.1.1-alpha01
+- Update native dependency to `pushe:2.1.1-beta08`
+
+## 2.1.0
+
+- Added Support for **Flutter Embedding V2**
+- Migrate native language to Kotlin
+- Added APIs:
+ * `createNotificationChannel`
+ * `removeNotificationChannel`
+ * `enableCustomSound`
+ * `DisableCustomSound`
+- Improvements on analytics methods `sendEvent` and `sendEcommerceData`
+- Added support for background execution to get the callbacks event when the app is fully killed
+- Fix bug when clearing `customId`, `userEmail` and `userPhoneNumber`. You can now set null to clear them.
+
+## 2.0.3
+
+- Fix bug in notification listeners
+- Improve `sendNotificationToUser` to support multiple IDs
+- Function callbacks will have no boolean status anymore, since there was no false status
+- Code style improvements
+- Example project improvements
+
+## 2.0.2
+
+- Fix issue with AndroidX
+
+## 2.0.1
+
+- Fix formatting of plugin
+- Minor improvements
+
+## 2.0.0
+
+* Migrate to the new Plus sdk of Pushe
+* Get used of new Plus features in the SDK
+* No initialization is needed for the library
+> Notice the `setNotificationListener` is not fully reliable yet, since it does not handle background
+
+## 1.1.0-alpha1
+
+* Fixed Battery usage issue
+* Added method `isNotificationOn`
+
+## 1.0.1
+
+* Fix problem with **AndroidX** projects.
+
+* Changed example package name.
+
+## 1.0.0
+
+* Release ready version.
+
+* New listener API for notification callbacks.
+
+* Removed extra files and APIs.
+
+* Remove extra Fcm service. Firebase and other services can now be added and supported natively.
+
+* Minor improvements and bug fixes.
+
+## 0.9.1
+
+* Recreating notification callbacks. Callbacks will return actual notification objects now.
+
+* From now on, Plugin can be used along with Firebase messaging plugin.
+
+* Minor improvements and bug fixes.
+
+## 0.2.1
+
+* Added better styled callbacks.
+
+* Minor improvements.
+
+## 0.0.2
+
+* Bug fixed on notification listeners not getting called.
+
+* Fixed a little bug in example app.
+
+* Listeners of notification callbacks are working.
+
+* Added Release offline AAR package.
+
+* More comments in plugin.
+
+## 0.0.1
+
+* Pushe basic commands.
+
+* Support for Android OS.
+
+* Notification content callback.
+
+**Note**: Callbacks will be passed when flutter is running. So when the app is closed, notifications will not call the callback methods (They actually will, but the flutter doesn't get it).
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..86c0662
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,13 @@
+Copyright 2019 Pusheco
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d9134e9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,30 @@
+# Pushe flutter
+
+**Pushe** notification service official plugin for Flutter. Pushe is a push notification service. Refer to [Pushe Homepage](https://pushe.co) for more information.
+It supports **Android** and **iOS** (it's also possible to use it on [Flutter Web](https://medium.com/@malv/add-pushe-web-push-to-a-flutter-website-a9b1ab736e57))
+
+## Installation
+
+Add the plugin to `pubspec.yaml`:
+
+version: [![pub package](https://img.shields.io/pub/v/pushe_flutter)](https://pub.dartlang.org/packages/pushe_flutter)
+
+```yaml
+dependencies:
+ pushe_flutter:
+```
+
+* If you want to use the latest version, not necessarily released and stable, you can directly use the source code on Github.
+
+```yaml
+pushe_flutter:
+ git:
+ url: https://github.com/pusheco/pushe-flutter.git
+```
+
+Visit the [**Documentation**](https://docs.pushe.co/docs/flutter/intro/) for more information about usage and API reference.
+
+## More Info
+
+* FAQ and issues in [Github repo](https://github.com/pusheco/pushe-flutter/issues?q=is%3Aissue+)
+* Sample project is in the library source code and in the [Sample repo on github](https://github.com/pusheco/pushe-flutter-sample)
diff --git a/android/.gitignore b/android/.gitignore
new file mode 100644
index 0000000..c6cbe56
--- /dev/null
+++ b/android/.gitignore
@@ -0,0 +1,8 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
diff --git a/android/build.gradle b/android/build.gradle
new file mode 100644
index 0000000..414708c
--- /dev/null
+++ b/android/build.gradle
@@ -0,0 +1,53 @@
+group 'co.pushe.plus.flutter'
+version '1.0-SNAPSHOT'
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+
+buildscript {
+ ext.kotlin_version = '1.4.31'
+ repositories {
+ google()
+ mavenCentral()
+ maven {url 'https://developer.huawei.com/repo/'}
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.1.3'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+rootProject.allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ maven {url 'https://developer.huawei.com/repo/'}
+ }
+}
+
+
+
+android {
+ compileSdkVersion 31
+
+ defaultConfig {
+ minSdkVersion 16
+ }
+ lintOptions {
+ disable 'InvalidPackage'
+ }
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+}
+
+dependencies {
+ def pushe_version = "2.5.1"
+ implementation ("co.pushe.plus:base:$pushe_version")
+ compileOnly ("co.pushe.plus:hms:$pushe_version")
+ compileOnly ("co.pushe.plus:inappmessaging:$pushe_version")
+ api "androidx.multidex:multidex:2.0.1"
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation "androidx.lifecycle:lifecycle-common-java8:2.3.1"
+}
diff --git a/android/gradle.properties b/android/gradle.properties
new file mode 100644
index 0000000..d9cf55d
--- /dev/null
+++ b/android/gradle.properties
@@ -0,0 +1,2 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/android/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..39cb497
--- /dev/null
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Feb 19 10:37:37 IRST 2020
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
diff --git a/android/gradlew b/android/gradlew
new file mode 100644
index 0000000..cccdd3d
--- /dev/null
+++ b/android/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/android/gradlew.bat b/android/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/android/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/android/settings.gradle b/android/settings.gradle
new file mode 100644
index 0000000..6f9fd69
--- /dev/null
+++ b/android/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'pushe'
diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..64255fa
--- /dev/null
+++ b/android/src/main/AndroidManifest.xml
@@ -0,0 +1,3 @@
+
+
diff --git a/android/src/main/kotlin/co/pushe/plus/flutter/Constants.kt b/android/src/main/kotlin/co/pushe/plus/flutter/Constants.kt
new file mode 100644
index 0000000..0307cc6
--- /dev/null
+++ b/android/src/main/kotlin/co/pushe/plus/flutter/Constants.kt
@@ -0,0 +1,11 @@
+package co.pushe.plus.flutter
+
+object Constants {
+
+ // Types
+ const val RECEIVE = "receive"
+ const val CLICK = "click"
+ const val DISMISS = "dismiss"
+ const val CUSTOM_CONTENT = "custom_content"
+ const val BUTTON_CLICK = "button_click"
+}
\ No newline at end of file
diff --git a/android/src/main/kotlin/co/pushe/plus/flutter/HandleStorage.kt b/android/src/main/kotlin/co/pushe/plus/flutter/HandleStorage.kt
new file mode 100644
index 0000000..95e75f0
--- /dev/null
+++ b/android/src/main/kotlin/co/pushe/plus/flutter/HandleStorage.kt
@@ -0,0 +1,55 @@
+package co.pushe.plus.flutter
+
+import android.content.Context
+
+/**
+ * This object is mainly used to save and retrieve callback handles of dart side callback methods.
+ * One is the setup which will be called when the plugin was initialized on app startup.
+ * The other one is the callback which developer defines it as a static method or top level function and passes it to Plugin.
+ *
+ * SetupHandle: Is a top level method which that handles waking the channel and initializing for telling the plugin that the isolate is running
+ * and plugin can call the background stuff and send them through channel to dart.
+ *
+ * MessageHandle: Is the top level or static method that the user defines and passes to the `Pushe.setNotificationListener`.
+ */
+internal object HandleStorage {
+ private const val SHARED_PREFERENCES_KEY = "pushe_storage"
+ private const val BACKGROUND_SETUP_CALLBACK_HANDLE_KEY = "pushe_background_setup_handle"
+ private const val BACKGROUND_MESSAGE_CALLBACK_HANDLE_KEY = "pushe_background_message_handle"
+
+ @JvmStatic
+ fun saveSetupHandle(context: Context, setupHandle: Long) {
+ val preferences = context.getSharedPreferences(SHARED_PREFERENCES_KEY, 0x0000)
+ preferences.edit().putLong(BACKGROUND_SETUP_CALLBACK_HANDLE_KEY, setupHandle).apply()
+ }
+
+ @JvmStatic
+ fun saveMessageHandle(context: Context, messageHandle: Long) {
+ val preferences = context.getSharedPreferences(SHARED_PREFERENCES_KEY, 0x0000)
+ preferences.edit().putLong(BACKGROUND_MESSAGE_CALLBACK_HANDLE_KEY, messageHandle).apply()
+ }
+
+ @JvmStatic
+ fun getSetupHandle(context: Context): Long {
+ val preferences = context.getSharedPreferences(SHARED_PREFERENCES_KEY, 0x0000)
+ return preferences.getLong(BACKGROUND_SETUP_CALLBACK_HANDLE_KEY, 0)
+ }
+
+ @JvmStatic
+ fun getMessageHandle(context: Context): Long {
+ val preferences = context.getSharedPreferences(SHARED_PREFERENCES_KEY, 0x0000)
+ return preferences.getLong(BACKGROUND_MESSAGE_CALLBACK_HANDLE_KEY, 0)
+ }
+
+ @JvmStatic
+ fun hasSetupHandle(context: Context): Boolean {
+ val preferences = context.getSharedPreferences(SHARED_PREFERENCES_KEY, 0x0000)
+ return preferences.contains(BACKGROUND_SETUP_CALLBACK_HANDLE_KEY)
+ }
+
+ @JvmStatic
+ fun hasMessageHandle(context: Context): Boolean {
+ val preferences = context.getSharedPreferences(SHARED_PREFERENCES_KEY, 0x0000)
+ return preferences.contains(BACKGROUND_MESSAGE_CALLBACK_HANDLE_KEY)
+ }
+}
\ No newline at end of file
diff --git a/android/src/main/kotlin/co/pushe/plus/flutter/LatchResult.kt b/android/src/main/kotlin/co/pushe/plus/flutter/LatchResult.kt
new file mode 100644
index 0000000..409c2d2
--- /dev/null
+++ b/android/src/main/kotlin/co/pushe/plus/flutter/LatchResult.kt
@@ -0,0 +1,31 @@
+package co.pushe.plus.flutter
+
+import co.pushe.plus.flutter.Utils.lg
+import io.flutter.plugin.common.MethodChannel
+import java.util.concurrent.CountDownLatch
+
+/**
+ * A concurrent handler of the Flutter background isolate.
+ */
+internal class LatchResult(latch: CountDownLatch) {
+ val result: MethodChannel.Result
+
+ init {
+ result = object : MethodChannel.Result {
+ override fun success(result: Any?) {
+ lg("MethodChannel result, success")
+ latch.countDown()
+ }
+
+ override fun error(errorCode: String, errorMessage: String?, errorDetails: Any?) {
+ lg("MethodChannel result, error")
+ latch.countDown()
+ }
+
+ override fun notImplemented() {
+ lg("MethodChannel result, notImplemented")
+ latch.countDown()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/src/main/kotlin/co/pushe/plus/flutter/PusheChandler.kt b/android/src/main/kotlin/co/pushe/plus/flutter/PusheChandler.kt
new file mode 100644
index 0000000..e878bca
--- /dev/null
+++ b/android/src/main/kotlin/co/pushe/plus/flutter/PusheChandler.kt
@@ -0,0 +1,775 @@
+package co.pushe.plus.flutter
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.Build
+import androidx.annotation.VisibleForTesting
+import co.pushe.plus.Pushe
+import co.pushe.plus.analytics.PusheAnalytics
+import co.pushe.plus.analytics.event.Ecommerce
+import co.pushe.plus.analytics.event.Event
+import co.pushe.plus.analytics.event.EventAction
+import co.pushe.plus.fcm.PusheFCM
+import co.pushe.plus.flutter.HandleStorage.saveMessageHandle
+import co.pushe.plus.flutter.HandleStorage.saveSetupHandle
+import co.pushe.plus.flutter.InAppUtils.getInAppMessageAndButtonFromIntent
+import co.pushe.plus.flutter.InAppUtils.getInAppMessageFromIntent
+import co.pushe.plus.flutter.Pack.getCustomContentFromIntent
+import co.pushe.plus.flutter.Pack.getNotificationJsonFromIntent
+import co.pushe.plus.flutter.Utils.lg
+import co.pushe.plus.notification.PusheNotification
+import co.pushe.plus.notification.UserNotification
+import io.flutter.FlutterInjector
+import io.flutter.plugin.common.BinaryMessenger
+import io.flutter.plugin.common.MethodCall
+import io.flutter.plugin.common.MethodChannel
+import io.flutter.plugin.common.MethodChannel.MethodCallHandler
+
+/**
+ * PusheChandler
+ *
+ * @author Mahdi Malvandi
+ */
+@Suppress("SpellCheckingInspection")
+internal class PusheChandler(private val context: Context,
+ private val messenger: BinaryMessenger) : BroadcastReceiver(), MethodCallHandler {
+
+ /**
+ * Register a receiver to get Pushe foreground callbacks
+ * See `onReceive` at the end of the file
+ */
+ init {
+ val i = IntentFilter()
+ val packageName = context.packageName
+ i.addAction("$packageName.nr") // Receive
+ i.addAction("$packageName.nc") // Click
+ i.addAction("$packageName.nbc") // Button click
+ i.addAction("$packageName.nd") // Dismiss
+ i.addAction("$packageName.nccr") // CustomContent receive
+
+ i.addAction("$packageName.ir") // InAppMessage received
+ i.addAction("$packageName.ic") // InAppMessage clicked
+ i.addAction("$packageName.it") // InAppMessage triggered
+ i.addAction("$packageName.id") // InAppMessage dismissed
+ i.addAction("$packageName.ibc") // InAppMessage button clicked
+ context.registerReceiver(this, i)
+ }
+
+ private val notificationTypes = listOf("IdType.DeviceId", "IdType.AdvertisingId", "IdType.CustomId")
+
+ override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
+ val methodName = call.method
+ val notificationModule = Pushe.getPusheService(PusheNotification::class.java)
+ val analyticsModule = Pushe.getPusheService(PusheAnalytics::class.java)
+ val fcmModule = Pushe.getPusheService(PusheFCM::class.java)
+
+ when (methodName) {
+ "Pushe.initialize" -> Pushe.initialize()
+ "Pushe.setUserConsentGiven" -> setUserConsentGiven(call, result)
+ "Pushe.getUserConsentStatus" -> result.success(Pushe.getUserConsentStatus())
+ "Pushe.getDeviceId" -> result.success(Pushe.getDeviceId())
+ "Pushe.getAndroidId" -> result.success(Pushe.getAndroidId())
+ "Pushe.getGoogleAdvertisingId" -> result.success(Pushe.getGoogleAdvertisingId())
+ "Pushe.getAdvertisingId" -> result.success(Pushe.getAdvertisingId())
+ "Pushe.getCustomId" -> result.success(Pushe.getCustomId())
+ "Pushe.setCustomId" -> setCustomId(call, result)
+ "Pushe.getUserEmail" -> result.success(Pushe.getUserEmail())
+ "Pushe.setUserEmail" -> setUserEmail(call, result)
+ "Pushe.getUserPhoneNumber" -> result.success(Pushe.getUserPhoneNumber())
+ "Pushe.setUserPhoneNumber" -> setUserPhoneNumber(call, result)
+ "Pushe.subscribe" -> subscribeToTopic(call, result)
+ "Pushe.unsubscribe" -> unsubscribeFromTopic(call, result)
+ "Pushe.enableNotifications" -> setNotificationEnabled(true, result, notificationModule)
+ "Pushe.disableNotifications" -> setNotificationEnabled(false, result, notificationModule)
+ "Pushe.enableCustomSound" -> setCustomSoundEnabled(true, result, notificationModule)
+ "Pushe.disableCustomSound" -> setCustomSoundEnabled(false, result, notificationModule)
+ "Pushe.isNotificationEnable" -> isNotificationEnabled(result, notificationModule)
+ "Pushe.isCustomSoundEnabled" -> isCustomSoundEnabled(result, notificationModule)
+ "Pushe.createNotificationChannel" -> createNotificationChannel(call, result, notificationModule)
+ "Pushe.removeNotificationChannel" -> removeNotificationChannel(call, result, notificationModule)
+ "Pushe.isInitialized" -> result.success(Pushe.isInitialized())
+ "Pushe.isRegistered" -> result.success(Pushe.isRegistered())
+ "Pushe.sendUserNotification" -> sendUserNotification(call, result, notificationModule)
+ "Pushe.sendAdvancedUserNotification" -> sendAdvancedNotification(call, result, notificationModule)
+ "Pushe.sendEvent" -> sendEvent(call, result, analyticsModule)
+ "Pushe.sendEcommerceData" -> sendEcommerceData(call, result, analyticsModule)
+ "Pushe.initNotificationListenerManually" -> initializeForegroundNotifications()
+ "Pushe.setRegistrationCompleteListener" -> Pushe.setRegistrationCompleteListener {
+ result.success(true)
+ }
+ "Pushe.setInitializationCompleteListener" -> Pushe.setInitializationCompleteListener {
+ result.success(true)
+ }
+ "Pushe.addTags" -> addTag(call, result)
+ "Pushe.removeTags" -> removeTags(call, result)
+ "Pushe.getSubscribedTags" -> result.success(Pushe.getSubscribedTags())
+ "Pushe.getSubscribedTopics" -> result.success(Pushe.getSubscribedTopics())
+ "Pushe.notificationListener" -> setNotificationListeners(call, result)
+ // Background init
+ "Pushe.platformInitialized" -> initializeListenerPlatform(result)
+ // InAppMessaging
+ "Pushe.triggerEvent" -> triggerEvent(call, result)
+ "Pushe.disableInAppMessaging" -> disableInAppMessaging(result)
+ "Pushe.enableInAppMessaging" -> enableInAppMessaging(result)
+ "Pushe.isInAppMessagingEnabled" -> isInAppMessagingEnabled(result)
+ "Pushe.initializeInAppListeners" -> initializeInAppMessagingListeners()
+ "Pushe.dismissShownInApp" -> dismissShownInApp(result)
+ "Pushe.testInAppMessage" -> testInAppMessage(call, result)
+ "Pushe.getActiveCourier" -> getActiveService(result)
+ "Pushe.getFcmToken" -> getFcmTokenOrEmpty(result, fcmModule)
+ "Pushe.getHmsToken" -> getHmsTokenOrEmpty(result)
+ "Pushe.enableForceForegroundAware" -> enableForceForegroundAware(true, result, notificationModule)
+ "Pushe.disableForceForegroundAware" -> enableForceForegroundAware(false, result, notificationModule)
+ "Pushe.isForceForegroundAware" -> result.success(notificationModule?.isForegroundAwareByForce())
+ else -> result.notImplemented()
+ }
+ }
+
+ ///// Do stuff when a method was called
+
+ private fun setUserConsentGiven(call: MethodCall, result: MethodChannel.Result) {
+ try {
+ Pushe.setUserConsentGiven(call.argument("enabled") ?: true)
+ result.success(true)
+ } catch (e: java.lang.Exception) {
+ result.error("022", "Error occorred when parsing `enabled` argument. Must be of type bool", e.message)
+ }
+ }
+
+ private fun setCustomId(call: MethodCall, result: MethodChannel.Result) {
+ if (!call.hasArgument("id")) {
+ Pushe.setCustomId(null)
+ result.success(true)
+ return
+ }
+ Pushe.setCustomId(call.argument("id"))
+ result.success(true)
+ }
+
+ private fun setUserEmail(call: MethodCall, result: MethodChannel.Result) {
+ if (!call.hasArgument("email")) {
+ result.success(Pushe.setUserEmail(null))
+ return
+ }
+ result.success(Pushe.setUserEmail(call.argument("email")))
+ }
+
+ private fun setUserPhoneNumber(call: MethodCall, result: MethodChannel.Result) {
+ if (!call.hasArgument("phone")) {
+ result.success(Pushe.setUserPhoneNumber(null))
+ return
+ }
+ result.success(Pushe.setUserPhoneNumber(call.argument("phone")))
+ }
+
+ private fun subscribeToTopic(call: MethodCall, result: MethodChannel.Result) {
+ if (!call.hasArgument("topic")) {
+ result.error("004", "Call must contain 'topic'", null)
+ return
+ }
+ try {
+ Pushe.subscribeToTopic(call.argument("topic")) {
+ result.success(true)
+ }
+ } catch (e: Exception) {
+ result.error("004", "Could not subscribe to topic ${e.message}", null)
+ }
+ }
+
+ private fun unsubscribeFromTopic(call: MethodCall, result: MethodChannel.Result) {
+ if (!call.hasArgument("topic")) {
+ result.error("005", "Call must contain 'topic'", null)
+ return
+ }
+ try {
+ Pushe.unsubscribeFromTopic(call.argument("topic")) {
+ result.success(true)
+ }
+ } catch (e: Exception) {
+ result.error("005", "Could not unsubscribe from topic ${e.message}", null)
+ }
+ }
+
+ private fun setNotificationEnabled(enabled: Boolean, result: MethodChannel.Result, notificationModule: PusheNotification?) {
+ if (notificationModule == null) {
+ result.error("013", "Notification module is not ready. Notifications will not ba handled.", null)
+ return
+ }
+ if (enabled) {
+ notificationModule.enableNotifications()
+ } else {
+ notificationModule.disableNotifications()
+ }
+ }
+
+ private fun isNotificationEnabled(result: MethodChannel.Result, notificationModule: PusheNotification?) {
+ if (notificationModule == null) {
+ result.error("013", "Notification module is not ready. Notifications will not ba handled.", null)
+ return
+ }
+ result.success(notificationModule.isNotificationEnable())
+ }
+
+ private fun sendUserNotification(call: MethodCall, result: MethodChannel.Result, notificationModule: PusheNotification?) {
+ if (notificationModule == null) {
+ result.error("006", "Notification module is not ready. Notification APIs will not ba handled.", null)
+ return
+ }
+
+ if (!call.hasAll("type", "id", "title", "content")) {
+ result.error("006", "Call must contain 'type', 'id', 'title' and 'content'", null)
+ return
+ }
+
+ val type = call.argument("type")
+ lg("Type: $type")
+ if (!notificationTypes.contains(type)) {
+ result.error("006", "Type must be either 'DeviceId', 'GoogleAdvertisingId' or 'CustomId'", null)
+ return
+ }
+
+ val id = call.argument("id")
+ if (id == null || id.isEmpty()) {
+ result.error("006", "Id must not be null or empty", null)
+ return
+ }
+
+ val notification = when (type) {
+ "IdType.DeviceId" -> UserNotification.withDeviceId(id)
+ "IdType.AdvertisingId" -> UserNotification.withAdvertisementId(id)
+ "IdType.CustomId" -> UserNotification.withCustomId(id)
+ else -> {
+ result.error("006", "Type must be either 'DeviceId', 'GoogleAdvertisingId' or 'CustomId'", null)
+ return
+ }
+ }
+
+ val title = call.argument("title")
+ val content = call.argument("content")
+ val bigTitle = call.argument("bigTitle")
+ val bigContent = call.argument("bigContent")
+ val imageUrl = call.argument("imageUrl")
+ val iconUrl = call.argument("iconUrl")
+ val notifIcon = call.argument("notifIcon")
+ val customContent = call.argument("customContent")
+ notification?.setTitle(title)
+ ?.setContent(content)
+ ?.setBigTitle(bigTitle)
+ ?.setBigContent(bigContent)
+ ?.setImageUrl(imageUrl)
+ ?.setIconUrl(iconUrl)
+ ?.setNotifIcon(notifIcon)
+ ?.setCustomContent(customContent)
+ if (notification != null) {
+ notificationModule.sendNotificationToUser(notification)
+ result.success(true)
+ } else {
+ result.error("006", "There was a problem building notification for sending. Make sure data is provided correctly", null)
+ }
+ }
+
+ private fun sendAdvancedNotification(call: MethodCall, result: MethodChannel.Result, notificationModule: PusheNotification?) {
+ if (notificationModule == null) {
+ result.error("020", "Notification module is not ready. Notification APIs will not ba handled.", null)
+ return
+ }
+ if (!call.hasAll("type", "id", "advancedJson")) {
+ result.error("020", "Call must contain 'type', 'id' and 'advancedJson' (Use jsonEncode for advancedJson)", null)
+ return
+ }
+
+ val type = call.argument("type")
+ if (!notificationTypes.contains(type)) {
+ result.error("020", "Type must be either 'DeviceId', 'GoogleAdvertisingId' or 'CustomId'", null)
+ return
+ }
+
+ val id = call.argument("id")
+ if (id == null || id.isEmpty()) {
+ result.error("020", "Id must not be null or empty", null)
+ return
+ }
+ val notification = when (type) {
+ "IdType.DeviceId" -> UserNotification.withDeviceId(id)
+ "IdType.AdvertisingId" -> UserNotification.withAdvertisementId(id)
+ "IdType.CustomId" -> UserNotification.withCustomId(id)
+ else -> {
+ result.error("006", "Type must be either 'DeviceId', 'GoogleAdvertisingId' or 'CustomId'", null)
+ return
+ }
+ }
+ val advancedJson = call.argument("advancedJson")
+ notification.setAdvancedNotification(advancedJson)
+ notificationModule.sendNotificationToUser(notification)
+
+ }
+
+ private fun sendEvent(call: MethodCall, result: MethodChannel.Result, analyticsModule: PusheAnalytics?) {
+ if (analyticsModule == null) {
+ result.error("016", "Analytics module is not ready. Analytics APIs will not ba handled.", null)
+ return
+ }
+ if (!call.hasArgument("name")) {
+ result.error("016", "Call must contain 'name', only data and action are optional", null)
+ return
+ }
+ val name = call.argument("name")
+ if (name == null || name.isEmpty()) {
+ result.error("016", "Call must contain 'name', only data and action are optional", null)
+ return
+ }
+ val action = call.argument("action")
+
+ val actualAction = when (action?.removePrefix("EventAction.")) {
+ "custom" -> EventAction.CUSTOM
+ "sign_up" -> EventAction.SIGN_UP
+ "login" -> EventAction.LOGIN
+ "purchase" -> EventAction.PURCHASE
+ "achievement" -> EventAction.ACHIEVEMENT
+ "level" -> EventAction.LEVEL
+ else -> EventAction.CUSTOM
+ }
+
+ val eventBuilder = Event.Builder(name)
+ eventBuilder.setAction(actualAction)
+ call.argument