├── .github ├── ISSUE_TEMPLATE │ ├── a-regression.md │ ├── b-bug-report.md │ ├── c-feature-request.md │ ├── d-enhancement-proposal.md │ └── e-question.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .metadata ├── AUTHORS ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── android ├── .gitignore ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── settings.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── ninjasolutions │ └── pusher │ └── PusherPlugin.java ├── example ├── .gitignore ├── .metadata ├── android │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── pusherwebsocket │ │ │ │ │ └── pusher_example │ │ │ │ │ └── MainActivity.java │ │ │ └── res │ │ │ │ ├── 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 │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── ios │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ ├── Flutter.podspec │ │ └── Release.xcconfig │ ├── Podfile │ ├── Podfile.lock │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── 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 ├── lib │ └── main.dart ├── pubspec.lock ├── pubspec.yaml └── test │ └── widget_test.dart ├── ios ├── .gitignore ├── Assets │ └── .gitkeep ├── Classes │ ├── PusherPlugin.h │ ├── PusherPlugin.m │ ├── SwiftPusherPlugin.swift │ └── UserAgent.h └── flutter_pusher.podspec ├── lib ├── pusher.dart └── pusher.g.dart ├── pubspec.lock ├── pubspec.yaml └── test └── pusher_test.dart /.github/ISSUE_TEMPLATE/a-regression.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | name: 🔙 Regression 4 | about: Report unexpected behavior that worked previously 5 | --- 6 | 7 | ## 🔙 Regression 8 | 9 | 10 | 11 | ### Old (and correct) behavior 12 | 13 | ### Current behavior 14 | 15 | ### Reproduction steps 16 | 17 | ### Configuration 18 | 19 | **Version:** 1.x 20 | 21 | **Platform:** 22 | - [ ] :iphone: iOS 23 | - [ ] :robot: Android -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/b-bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | name: 🐛 Bug Report 4 | about: Create a report to help us fix bugs and make improvements 5 | --- 6 | 7 | ## 🐛 Bug Report 8 | 9 | 10 | 11 | ### Expected behavior 12 | 13 | ### Reproduction steps 14 | 15 | ### Configuration 16 | 17 | **Version:** 1.x 18 | 19 | **Platform:** 20 | - [ ] :iphone: iOS 21 | - [ ] :robot: Android -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/c-feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | name: 🚀 Feature Request 4 | about: Want to see something new included in the Framework? Submit it! 5 | --- 6 | 7 | ## 🚀 Feature Requests 8 | 9 | 10 | 11 | ### Contextualize the feature 12 | 13 | 14 | ### Describe the feature 15 | 16 | 17 | ### Platforms affected (mark all that apply) 18 | - [ ] :iphone: iOS 19 | - [ ] :robot: Android -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/d-enhancement-proposal.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | name: 🏗 Enhancement Proposal 4 | about: Proposals for code cleanup, refactor and improvements in general 5 | --- 6 | 7 | ## 🏗 Enhancement Proposal 8 | 9 | 10 | 11 | ### Pitch 12 | 13 | 14 | 15 | ### Platforms affected (mark all that apply) 16 | - [ ] :iphone: iOS 17 | - [ ] :robot: Android -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/e-question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 💬 Questions and Help 3 | about: If you have questions, please use this for support 4 | --- 5 | 6 | ## 💬 Questions and Help 7 | 8 | For questions or help we recommend checking: 9 | 10 | - The [Flutter tag in Stack Overflow](https://stackoverflow.com/questions/tagged/flutter) 11 | - The [Pusher tag in Stack Overflow](https://stackoverflow.com/questions/tagged/pusher) 12 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### :sparkles: What kind of change does this PR introduce? (Bug fix, feature, docs update...) 2 | 3 | ### :arrow_heading_down: What is the current behavior? 4 | 5 | ### :new: What is the new behavior (if this is a feature change)? 6 | 7 | ### :boom: Does this PR introduce a breaking change? 8 | 9 | ### :bug: Recommendations for testing 10 | 11 | ### :memo: Links to relevant issues/docs 12 | 13 | ### :thinking: Checklist before submitting 14 | 15 | - [ ] All projects build 16 | - [ ] Follows style guide lines ([code style guide](https://github.com/ninjasolutions/flutter_pusher/blob/master/CONTRIBUTING.md)) 17 | - [ ] Relevant documentation was updated 18 | - [ ] Rebased onto current develop 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # Flutter 13 | flutter_export_environment.sh 14 | .flutter-plugins-dependencies 15 | 16 | # IntelliJ related 17 | *.iml 18 | *.ipr 19 | *.iws 20 | .idea/ 21 | res/values 22 | 23 | # Visual Studio Code related 24 | .vscode/ 25 | 26 | # Flutter/Dart/Pub related 27 | **/doc/api/ 28 | .dart_tool/ 29 | .flutter-plugins 30 | .packages 31 | .pub-cache/ 32 | .pub/ 33 | /build/ 34 | 35 | # Android related 36 | **/android/**/gradle-wrapper.jar 37 | **/android/.gradle 38 | **/android/captures/ 39 | **/android/gradlew 40 | **/android/gradlew.bat 41 | **/android/local.properties 42 | **/android/**/GeneratedPluginRegistrant.java 43 | 44 | # iOS/XCode related 45 | **/ios/**/*.mode1v3 46 | **/ios/**/*.mode2v3 47 | **/ios/**/*.moved-aside 48 | **/ios/**/*.pbxuser 49 | **/ios/**/*.perspectivev3 50 | **/ios/**/*sync/ 51 | **/ios/**/.sconsign.dblite 52 | **/ios/**/.tags* 53 | **/ios/**/.vagrant/ 54 | **/ios/**/DerivedData/ 55 | **/ios/**/Icon? 56 | **/ios/**/Pods/ 57 | **/ios/**/.symlinks/ 58 | **/ios/**/profile 59 | **/ios/**/xcuserdata 60 | **/ios/.generated/ 61 | **/ios/Flutter/App.framework 62 | **/ios/Flutter/Flutter.framework 63 | **/ios/Flutter/Generated.xcconfig 64 | **/ios/Flutter/app.flx 65 | **/ios/Flutter/app.zip 66 | **/ios/Flutter/flutter_assets/ 67 | **/ios/ServiceDefinitions.json 68 | **/ios/Runner/GeneratedPluginRegistrant.* 69 | 70 | # Exceptions to above rules. 71 | !**/ios/**/default.mode1v3 72 | !**/ios/**/default.mode2v3 73 | !**/ios/**/default.pbxuser 74 | !**/ios/**/default.perspectivev3 75 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 76 | 77 | # Generated 78 | /lib/generated -------------------------------------------------------------------------------- /.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: 0f0cbeb722dfbba9ff3e99519982391d4fd3976d 8 | channel: master 9 | 10 | project_type: plugin 11 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # Below is a list of people and organizations that have contributed 2 | # to the Flutter project. Names should be added to the list like so: 3 | # 4 | # Name/Organization 5 | 6 | HomeX Mobile Team 7 | Genert Org 8 | Tim Shedor 9 | Josh Burton 10 | Tim Shedor 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 2.0.0 2 | 3 | * Migrate to null safety 4 | 5 | ## 1.0.4 6 | 7 | - Fixes data being ignored when data is a list instead of a JSON object. (@josh-burton) 8 | 9 | ## 1.0.3 10 | 11 | - Update PusherSwift library from 7.2.0 to 8.0.0 12 | 13 | ## 1.0.2 14 | 15 | - Fixes Android build error with missing trigger method. By @athornz 16 | 17 | ## 1.0.1 18 | 19 | - Update PusherSwift library from 7.0.0 to 7.2.0 20 | 21 | ## 1.0.0 22 | 23 | - Added data sending option for iOS channel client trigger. 24 | 25 | ## 0.0.4 26 | 27 | - Major changes. 28 | 29 | ## 0.0.3 30 | 31 | - Add trigger support. 32 | 33 | ## 0.0.2 34 | 35 | - [FA-69]: Fix Android build. 36 | - Add async/await support. 37 | - Check for configuration params in iOs. 38 | 39 | ## 0.0.1 40 | 41 | - Initial Release. 42 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the plugin 2 | 3 | ## What you will need 4 | 5 | - A Linux, Mac OS X, or Windows machine (note: to run and compile iOS specific parts you'll need access to a Mac OS X machine); 6 | - git (used for source version control, installation instruction can be found [here](https://git-scm.com/)); 7 | - The Flutter SDK (installation instructions can be found [here](https://flutter.io/get-started/install/)); 8 | - A personal GitHub account (if you don't have one, you can sign-up for free [here](https://github.com/)) 9 | 10 | ## Setting up your development environment 11 | 12 | - Fork the repository into your own GitHub account. If you already have a fork and moving to a new computer, make sure you update you fork. 13 | - If you haven't configured your machine with an SSH key that's known to github, then 14 | follow [GitHub's directions](https://help.github.com/articles/generating-ssh-keys/) 15 | to generate an SSH key. 16 | - Add an upstream to the original repo, so that fetch from the master repository and not your clone: `git remote add upstream git@github.com:ninjasolutions/flutter_pusher.git` 17 | 18 | ## Contribute 19 | 20 | We really appreciate contributions via GitHub pull requests. To contribute take the following steps: 21 | 22 | - Make sure you are up to date with the latest code on the master: 23 | - `git fetch upstream` 24 | - `git checkout upstream/develop -b ` 25 | - Apply your changes 26 | - Verify your changes and fix potential warnings/ errors: 27 | - Check formatting: `flutter format .` 28 | - Run static analyses: `flutter analyzes` 29 | - Run unit-tests: `flutter test` 30 | - Commit your changes: `git commit -am ""` 31 | - Push changes to your fork: `git push origin ` 32 | 33 | Send us your pull request. 34 | 35 | Please make sure you solved all warnings and errors reported by the static code analyses and that you fill in the full pull request template. Failing to do so will result in us asking you to fix it. 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright © `2019 - 2020` `Indoor Solutions AS` 5 | 6 | Permission is hereby granted, free of charge, to any person 7 | obtaining a copy of this software and associated documentation 8 | files (the “Software”), to deal in the Software without 9 | restriction, including without limitation the rights to use, 10 | copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following 13 | conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | OTHER DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pusher Flutter Client 2 | 3 | [![pub package](https://img.shields.io/pub/v/flutter_pusher.svg)](https://pub.dartlang.org/packages/flutter_pusher) 4 | 5 | An unofficial Flutter plugin that wraps [pusher-websocket-java](https://github.com/pusher/pusher-websocket-java) on Android and [pusher-websocket-swift](https://github.com/pusher/pusher-websocket-swift) on iOS. 6 | 7 | *Note*: This plugin is still under development, and some APIs might not be available yet. [Feedback](https://github.com/ninjasolutions/flutter_pusher/issues) and [Pull Requests](https://github.com/ninjasolutions/flutter_pusher/pulls) are most welcome! 8 | 9 | # How to install 10 | * Add to your pubspec.yaml 11 | 12 | ```yaml 13 | dependencies: 14 | flutter_pusher: ^1.0.2 15 | ``` 16 | 17 | * In `/ios/Podfile`, set global platform to at least 9.0 18 | `platform :ios, '9.0'` 19 | 20 | ### For iOS Objective-C based Flutter apps 21 | It is currently a bit difficult to get some Swift based Flutter plugins working in an Objective-C based Flutter app. See [here for info](https://github.com/flutter/flutter/issues/25676) and [here for a way to fix](https://github.com/fayeed/flutter_freshchat/issues/9#issuecomment-514329934). 22 | 23 | This set of steps should work to fix this for your project. 24 | * Add `use_frameworks!` to the end of the Runner section in `/ios/Podfile` 25 | * Set Swift version in your iOS Runner project. 26 | * Open the project with Xcode. 27 | * In Runner, File -> New -> File -> Swift File. Name it anything. 28 | * Xcode will ask you if you wish to create Bridging Header, click yes. 29 | * Go to Runner `Build Settings` and set `SWIFT_VERSION` to either 4.2 or 5.0 30 | * Delete the Swift file created in step 2 31 | * Delete the Bridging Header created in step 3 32 | * `flutter clean` 33 | * In /ios `pod install --repo-update` 34 | 35 | # How to use 36 | ## Pusher.init( ... ) 37 | |Parameter |Type |Description | 38 | |---------------|---------------|--------------------| 39 | |*appKey* |`String` |*Required* - The application key is a string which is globally unique to your application. It can be found in the API Access section of your application within the Channels user dashboard.| 40 | |*options* |`PusherOptions`|*Required* - The options provided to pusher, more information in the *PusherOptions* section.| 41 | |*enableLogging*|`bool` |*Optional* - Enabling this will activate the logging of important events to the console.| 42 | 43 | 44 | ## Pusher.connect( ... ) 45 | |Parameter |Type |Description | 46 | |-------------------------|---------------------------------|-------------------| 47 | |*onConnectionStateChange*|`Function(ConnectionStateChange)`|*Optional* - Callback when the state of the connection changes (eg. `CONNECTING`, `CONNECTED`, `DISCONNECTED`, ... ).| 48 | |*onError* |`Function(ConnectionError)` |*Optional* - Callback when the connection fires an error (eg. `UnauthorizedException`).| 49 | 50 | ## Pusher.subscribe( ... ) 51 | |Parameter |Type |Description | 52 | |-------------|--------|-------------------| 53 | |*channelName*|`String`|*Required* - provide the channel name to subscribe to (eg. `mychannel`, `private-mychannel` or `presence-mychannel`).| 54 | 55 | ## PusherOptions 56 | |Parameter |Type |Description | 57 | |-----------------|-------------|-------------------| 58 | |*auth* |`PusherAuth` |*Optional* - A mechanism for authenticating a user's access to a channel at the point of subscription.| 59 | |*cluster* |`String` |*Optional* - The identifier of the cluster your application was created in. When not supplied, will connect to the `mt1`(`us-east-1`) cluster.| 60 | |*host* |`String` |*Optional* - Provide your own (websocket) host instead of the default `ws.pusherapp.com`| 61 | |*port* |`int` |*Optional* - Provide your own (websocket) port instead of the default `443` (when encryption is enabled) or port `80` (when encryption is disabled).| 62 | |*encrypted* |`bool` |*Optional* - Tell pusher to only connect over TLS connections to ensure connection traffic is encrypted. This means using `wss://` instead of `ws://`, encryption is enabled by default.| 63 | |*activityTimeout*|`int` |*Optional* - After this time (in milliseconds) without any messages received from the server, a ping message will be sent to check if the connection is still working. Default value is supplied by the server, low values will result in unnecessary traffic. The default is set to `30000`.| 64 | 65 | ## PusherAuth 66 | |Parameter |Type |Description | 67 | |-----------|--------------------|-------------------| 68 | |*endpoint* |`String` |*Required* - The endpoint pusher should query to make the post request (eg. https://api.example.com/broadcating/auth).| 69 | |*headers* |`Map`|*Optional* - The headers that should be sent with the POST request to the above endpoint. 2 Different *Content-Types* are supported: `application/x-www-form-urlencoded` & `application/json`. Supplying any of the above types will result into the request body being sent in `form-urlencoded` format or `JSON` format. Defaults to `{'Content-Type': 'application/x-www-form-urlencoded'}`| 70 | 71 | 72 | ## Development 73 | Generate the models and the factories: `flutter packages pub run build_runner build --delete-conflicting-outputs` 74 | -------------------------------------------------------------------------------- /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.ninjasolutions.pusher' 2 | version '1.0-SNAPSHOT' 3 | 4 | buildscript { 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.5.3' 12 | } 13 | } 14 | 15 | rootProject.allprojects { 16 | repositories { 17 | google() 18 | jcenter() 19 | } 20 | } 21 | 22 | apply plugin: 'com.android.library' 23 | 24 | android { 25 | compileSdkVersion 28 26 | 27 | defaultConfig { 28 | minSdkVersion 16 29 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 30 | } 31 | lintOptions { 32 | disable 'InvalidPackage' 33 | } 34 | dependencies { 35 | implementation 'com.pusher:pusher-java-client:2.0.2' 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Aug 21 15:23:05 CEST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 7 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'pusher' 2 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /android/src/main/java/com/ninjasolutions/pusher/PusherPlugin.java: -------------------------------------------------------------------------------- 1 | package com.ninjasolutions.pusher; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import android.os.Handler; 6 | import android.os.Looper; 7 | import android.util.Log; 8 | 9 | import com.google.gson.Gson; 10 | import com.google.gson.JsonObject; 11 | import com.google.gson.JsonPrimitive; 12 | import com.google.gson.reflect.TypeToken; 13 | import com.pusher.client.Pusher; 14 | import com.pusher.client.PusherOptions; 15 | import com.pusher.client.channel.Channel; 16 | import com.pusher.client.channel.ChannelEventListener; 17 | import com.pusher.client.channel.PresenceChannelEventListener; 18 | import com.pusher.client.channel.PrivateChannel; 19 | import com.pusher.client.channel.PrivateChannelEventListener; 20 | import com.pusher.client.channel.PusherEvent; 21 | import com.pusher.client.channel.User; 22 | import com.pusher.client.connection.ConnectionEventListener; 23 | import com.pusher.client.connection.ConnectionState; 24 | import com.pusher.client.connection.ConnectionStateChange; 25 | import com.pusher.client.util.ConnectionFactory; 26 | import com.pusher.client.util.HttpAuthorizer; 27 | import com.pusher.client.util.UrlEncodedConnectionFactory; 28 | 29 | import org.json.JSONObject; 30 | 31 | import java.lang.reflect.Type; 32 | import java.util.HashMap; 33 | import java.util.Map; 34 | import java.util.Set; 35 | 36 | import io.flutter.embedding.engine.plugins.FlutterPlugin; 37 | import io.flutter.plugin.common.EventChannel; 38 | import io.flutter.plugin.common.MethodCall; 39 | import io.flutter.plugin.common.MethodChannel; 40 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler; 41 | import io.flutter.plugin.common.MethodChannel.Result; 42 | import io.flutter.plugin.common.PluginRegistry.Registrar; 43 | 44 | import static com.ninjasolutions.pusher.PusherPlugin.TAG; 45 | 46 | /** 47 | * PusherPlugin 48 | */ 49 | public class PusherPlugin implements FlutterPlugin, MethodCallHandler { 50 | private static Pusher pusher; 51 | private static Map channels = new HashMap<>(); 52 | private static EventChannelListener eventListener; 53 | private static PrivateChannelChannelListener eventListenerPrivate; 54 | private static PresenceChannelEventListener eventListenerPresence; 55 | 56 | static String TAG = "PusherPlugin"; 57 | static EventChannel.EventSink eventSink; 58 | static boolean isLoggingEnabled = false; 59 | 60 | /** 61 | * Plugin registration. 62 | */ 63 | public static void registerWith(Registrar registrar) { 64 | final MethodChannel channel = new MethodChannel(registrar.messenger(), "plugins.indoor.solutions/pusher"); 65 | final EventChannel eventStream = new EventChannel(registrar.messenger(), "plugins.indoor.solutions/pusherStream"); 66 | channel.setMethodCallHandler(new PusherPlugin()); 67 | PusherPlugin.migratedPluginRegistration(channel, eventStream); 68 | } 69 | 70 | @Override 71 | public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { 72 | final MethodChannel channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "plugins.indoor.solutions/pusher"); 73 | final EventChannel eventStream = new EventChannel(flutterPluginBinding.getBinaryMessenger(), "plugins.indoor.solutions/pusherStream"); 74 | channel.setMethodCallHandler(this); 75 | PusherPlugin.migratedPluginRegistration(channel, eventStream); 76 | } 77 | 78 | public static void migratedPluginRegistration(MethodChannel channel, EventChannel eventStream) { 79 | eventListener = new EventChannelListener(); 80 | eventListenerPrivate = new PrivateChannelChannelListener(); 81 | eventListenerPresence = new PresenceChannelChannelListener(); 82 | 83 | eventStream.setStreamHandler(new EventChannel.StreamHandler() { 84 | @Override 85 | public void onListen(Object args, final EventChannel.EventSink eventSink) { 86 | PusherPlugin.eventSink = eventSink; 87 | } 88 | 89 | @Override 90 | public void onCancel(Object args) { 91 | Log.d(TAG, String.format("onCancel args: %s", args != null ? args.toString() : "null")); 92 | } 93 | }); 94 | } 95 | 96 | @Override 97 | public void onMethodCall(MethodCall call, Result result) { 98 | switch (call.method) { 99 | case "init": 100 | init(call, result); 101 | break; 102 | case "connect": 103 | connect(call, result); 104 | break; 105 | case "disconnect": 106 | disconnect(call, result); 107 | break; 108 | case "subscribe": 109 | subscribe(call, result); 110 | break; 111 | case "unsubscribe": 112 | unsubscribe(call, result); 113 | break; 114 | case "bind": 115 | bind(call, result); 116 | break; 117 | case "unbind": 118 | unbind(call, result); 119 | break; 120 | case "trigger": 121 | trigger(call, result); 122 | break; 123 | default: 124 | result.notImplemented(); 125 | break; 126 | } 127 | } 128 | 129 | private void init(MethodCall call, Result result) { 130 | if (pusher != null) { 131 | for (Map.Entry entry : channels.entrySet()) { 132 | String name = entry.getKey(); 133 | pusher.unsubscribe(name); 134 | } 135 | channels = new HashMap<>(); 136 | } 137 | 138 | try { 139 | final JSONObject json = new JSONObject(call.arguments.toString()); 140 | final JSONObject options = json.getJSONObject("options"); 141 | 142 | if (json.has("isLoggingEnabled")) { 143 | isLoggingEnabled = json.getBoolean("isLoggingEnabled"); 144 | } 145 | 146 | // setup options 147 | final PusherOptions pusherOptions = new PusherOptions(); 148 | 149 | if (options.has("auth")) { 150 | final JSONObject auth = options.getJSONObject("auth"); 151 | final String endpoint = auth.getString("endpoint"); 152 | final Type mapType = new TypeToken>() {}.getType(); 153 | final Map headers = new Gson().fromJson(auth.get("headers").toString(), mapType); 154 | 155 | pusherOptions.setAuthorizer(getAuthorizer(endpoint, headers)); 156 | } 157 | 158 | if (options.has("activityTimeout")) { 159 | pusherOptions.setActivityTimeout(options.getInt("activityTimeout")); 160 | } 161 | if (options.has("cluster")) { 162 | pusherOptions.setCluster(options.getString("cluster")); 163 | } 164 | if (options.has("host")) { 165 | pusherOptions.setHost(options.getString("host")); 166 | } 167 | 168 | // defaults to encrypted connection on port 443 169 | final int port = options.has("port") ? options.getInt("port") : 443; 170 | final boolean encrypted = !options.has("encrypted") || options.getBoolean("encrypted"); 171 | 172 | if (encrypted) { 173 | pusherOptions.setWssPort(port); 174 | } else { 175 | pusherOptions.setWsPort(port); 176 | } 177 | pusherOptions.setEncrypted(encrypted); 178 | 179 | 180 | // create client 181 | pusher = new Pusher(json.getString("appKey"), pusherOptions); 182 | 183 | if (isLoggingEnabled) { 184 | Log.d(TAG, "init"); 185 | } 186 | result.success(null); 187 | } catch (Exception e) { 188 | if (isLoggingEnabled) { 189 | Log.d(TAG, "init error: " + e.getMessage()); 190 | e.printStackTrace(); 191 | } 192 | } 193 | } 194 | 195 | private static HttpAuthorizer getAuthorizer(String endpoint, Map headers) { 196 | final ConnectionFactory connection = headers.containsValue("application/json") ? 197 | new JsonEncodedConnectionFactory() : 198 | new UrlEncodedConnectionFactory(); 199 | 200 | final HttpAuthorizer authorizer = new HttpAuthorizer(endpoint, connection); 201 | authorizer.setHeaders(headers); 202 | 203 | return authorizer; 204 | 205 | } 206 | 207 | private void connect(MethodCall call, Result result) { 208 | pusher.connect(new ConnectionEventListener() { 209 | @Override 210 | public void onConnectionStateChange(final ConnectionStateChange change) { 211 | new Handler(Looper.getMainLooper()).post(new Runnable() { 212 | @Override 213 | public void run() { 214 | try { 215 | final JSONObject eventStreamMessageJson = new JSONObject(); 216 | final JSONObject connectionStateChangeJson = new JSONObject(); 217 | connectionStateChangeJson.put("currentState", change.getCurrentState().toString()); 218 | connectionStateChangeJson.put("previousState", change.getPreviousState().toString()); 219 | eventStreamMessageJson.put("connectionStateChange", connectionStateChangeJson); 220 | eventSink.success(eventStreamMessageJson.toString()); 221 | } catch (Exception e) { 222 | if (isLoggingEnabled) { 223 | Log.d(TAG, "onConnectionStateChange error: " + e.getMessage()); 224 | e.printStackTrace(); 225 | } 226 | } 227 | } 228 | }); 229 | } 230 | 231 | @Override 232 | public void onError(final String message, final String code, final Exception ex) { 233 | new Handler(Looper.getMainLooper()).post(new Runnable() { 234 | @Override 235 | public void run() { 236 | try { 237 | final String exMessage = ex != null ? ex.getMessage() : null; 238 | final JSONObject eventStreamMessageJson = new JSONObject(); 239 | final JSONObject connectionErrorJson = new JSONObject(); 240 | 241 | connectionErrorJson.put("message", message); 242 | connectionErrorJson.put("code", code); 243 | connectionErrorJson.put("exception", exMessage); 244 | eventStreamMessageJson.put("connectionError", connectionErrorJson); 245 | 246 | eventSink.success(eventStreamMessageJson.toString()); 247 | 248 | } catch (Exception e) { 249 | if (isLoggingEnabled) { 250 | Log.d(TAG, "onError exception: " + e.getMessage()); 251 | e.printStackTrace(); 252 | } 253 | } 254 | } 255 | }); 256 | } 257 | 258 | }, ConnectionState.ALL); 259 | 260 | if (isLoggingEnabled) { 261 | Log.d(TAG, "connect"); 262 | } 263 | result.success(null); 264 | } 265 | 266 | private void disconnect(MethodCall call, Result result) { 267 | pusher.disconnect(); 268 | if (isLoggingEnabled) { 269 | Log.d(TAG, "disconnect"); 270 | } 271 | result.success(null); 272 | } 273 | 274 | private void subscribe(MethodCall call, Result result) { 275 | final String channelName = call.arguments.toString(); 276 | final String channelType = channelName.split("-")[0]; 277 | Channel channel = channels.get(channelName); 278 | 279 | if (channel != null && channel.isSubscribed()) { 280 | if (isLoggingEnabled) { 281 | Log.d(TAG, "Already subscribed, ignoring ..."); 282 | } 283 | result.success(null); 284 | return; 285 | } 286 | 287 | switch (channelType) { 288 | case "private": 289 | channel = pusher.subscribePrivate(channelName, eventListenerPrivate); 290 | if (isLoggingEnabled) { 291 | Log.d(TAG, "subscribe (private)"); 292 | } 293 | break; 294 | case "presence": 295 | channel = pusher.subscribePresence(channelName, eventListenerPresence); 296 | if (isLoggingEnabled) { 297 | Log.d(TAG, "subscribe (presence)"); 298 | } 299 | break; 300 | default: 301 | channel = pusher.subscribe(channelName, eventListener); 302 | 303 | if (isLoggingEnabled) { 304 | Log.d(TAG, "subscribe"); 305 | } 306 | break; 307 | } 308 | 309 | channels.put(channelName, channel); 310 | result.success(null); 311 | } 312 | 313 | private void unsubscribe(MethodCall call, Result result) { 314 | final String channelName = call.arguments.toString(); 315 | pusher.unsubscribe(call.arguments.toString()); 316 | channels.remove(channelName); 317 | 318 | if (isLoggingEnabled) { 319 | Log.d(TAG, String.format("unsubscribe (%s)", channelName)); 320 | } 321 | result.success(null); 322 | } 323 | 324 | private void bind(MethodCall call, Result result) { 325 | try { 326 | final JSONObject json = new JSONObject(call.arguments.toString()); 327 | final String channelName = json.getString("channelName"); 328 | final String channelType = channelName.split("-")[0]; 329 | final String eventName = json.getString("eventName"); 330 | 331 | Channel channel = channels.get(channelName); 332 | 333 | switch (channelType) { 334 | case "private": 335 | channel.bind(eventName, eventListenerPrivate); 336 | break; 337 | case "presence": 338 | channel.bind(eventName, eventListenerPresence); 339 | break; 340 | default: 341 | channel.bind(eventName, eventListener); 342 | break; 343 | } 344 | 345 | if (isLoggingEnabled) { 346 | Log.d(TAG, String.format("bind (%s)", eventName)); 347 | } 348 | result.success(null); 349 | } catch (Exception e) { 350 | if (isLoggingEnabled) { 351 | Log.d(TAG, String.format("bind exception: %s", e.getMessage())); 352 | e.printStackTrace(); 353 | } 354 | } 355 | } 356 | 357 | private void unbind(MethodCall call, Result result) { 358 | try { 359 | final JSONObject json = new JSONObject(call.arguments.toString()); 360 | final String channelName = json.getString("channelName"); 361 | final String channelType = channelName.split("-")[0]; 362 | final String eventName = json.getString("eventName"); 363 | 364 | Channel channel = channels.get(channelName); 365 | switch (channelType) { 366 | case "private": 367 | channel.unbind(eventName, eventListenerPrivate); 368 | break; 369 | case "presence": 370 | channel.unbind(eventName, eventListenerPresence); 371 | break; 372 | default: 373 | channel.unbind(eventName, eventListener); 374 | break; 375 | } 376 | 377 | if (isLoggingEnabled) { 378 | Log.d(TAG, String.format("unbind (%s)", eventName)); 379 | } 380 | result.success(null); 381 | } catch (Exception e) { 382 | if (isLoggingEnabled) { 383 | Log.d(TAG, String.format("unbind exception: %s", e.getMessage())); 384 | e.printStackTrace(); 385 | } 386 | } 387 | } 388 | 389 | private void trigger(MethodCall call, Result result) { 390 | try { 391 | final JSONObject json = new JSONObject(call.arguments.toString()); 392 | final String channelName = json.getString("channelName"); 393 | final String eventName = json.getString("eventName"); 394 | 395 | String data = "{}"; 396 | if (json.has("data")) { 397 | data = json.getString("data"); 398 | } 399 | 400 | Channel channel = channels.get(channelName); 401 | if (channel instanceof PrivateChannel) { 402 | if (isLoggingEnabled) { 403 | Log.d(TAG, String.format("Trigger event: %s with data: %s", eventName, data)); 404 | } 405 | ((PrivateChannel) channel).trigger(eventName, data); 406 | } 407 | } catch (Exception e) { 408 | if (isLoggingEnabled) { 409 | Log.d(TAG, String.format("unbind exception: %s", e.getMessage())); 410 | e.printStackTrace(); 411 | } 412 | } 413 | } 414 | 415 | @Override 416 | public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { 417 | // TODO implement 418 | } 419 | } 420 | 421 | 422 | class JsonEncodedConnectionFactory extends ConnectionFactory { 423 | 424 | JsonEncodedConnectionFactory() { 425 | } 426 | 427 | @Override 428 | public String getCharset() { 429 | return "UTF-8"; 430 | } 431 | 432 | @Override 433 | public String getContentType() { 434 | return "application/json"; 435 | } 436 | 437 | public String getBody() { 438 | JsonObject payload = new JsonObject(); 439 | payload.add("channel_name", new JsonPrimitive(getChannelName())); 440 | payload.add("socket_id", new JsonPrimitive(getSocketId())); 441 | 442 | return payload.toString(); 443 | } 444 | } 445 | 446 | class EventChannelListener implements ChannelEventListener { 447 | static final String SUBSCRIPTION_SUCCESS_EVENT = "pusher:subscription_succeeded"; 448 | static final String MEMBER_ADDED_EVENT = "pusher:member_added"; 449 | static final String MEMBER_REMOVED_EVENT = "pusher:member_removed"; 450 | 451 | static PusherEvent toPusherEvent(String channel, String event, String userId, String data) { 452 | final Map eventData = new HashMap<>(); 453 | 454 | eventData.put("channel", channel); 455 | eventData.put("event", event); 456 | eventData.put("data", data != null ? data : ""); 457 | if (userId != null) { 458 | eventData.put("user_id", userId); 459 | } 460 | 461 | return new PusherEvent(eventData); 462 | } 463 | 464 | @Override 465 | public void onEvent(final PusherEvent pusherEvent) { 466 | new Handler(Looper.getMainLooper()).post(new Runnable() { 467 | @Override 468 | public void run() { 469 | try { 470 | final JSONObject eventStreamMessageJson = new JSONObject(); 471 | final JSONObject eventJson = new JSONObject(); 472 | final String channel = pusherEvent.getChannelName(); 473 | final String event = pusherEvent.getEventName(); 474 | final String data = pusherEvent.getData(); 475 | 476 | eventJson.put("channel", channel); 477 | eventJson.put("event", event); 478 | eventJson.put("data", data); 479 | eventStreamMessageJson.put("event", eventJson); 480 | 481 | PusherPlugin.eventSink.success(eventStreamMessageJson.toString()); 482 | 483 | if (PusherPlugin.isLoggingEnabled) { 484 | Log.d(TAG, String.format("onEvent: \nCHANNEL: %s \nEVENT: %s \nDATA: %s", channel, event, data)); 485 | } 486 | } catch (Exception e) { 487 | onError(e); 488 | } 489 | } 490 | }); 491 | 492 | } 493 | 494 | void onError(final Exception e) { 495 | new Handler(Looper.getMainLooper()).post(new Runnable() { 496 | @Override 497 | public void run() { 498 | try { 499 | JSONObject eventStreamMessageJson = new JSONObject(); 500 | JSONObject connectionErrorJson = new JSONObject(); 501 | connectionErrorJson.put("message", e.getMessage()); 502 | connectionErrorJson.put("code", "Channel error"); 503 | connectionErrorJson.put("exception", e); 504 | eventStreamMessageJson.put("connectionError", connectionErrorJson); 505 | 506 | PusherPlugin.eventSink.success(eventStreamMessageJson.toString()); 507 | 508 | if (PusherPlugin.isLoggingEnabled) { 509 | Log.d(TAG, "onError : " + e.getMessage()); 510 | e.printStackTrace(); 511 | } 512 | } catch (Exception ex) { 513 | if (PusherPlugin.isLoggingEnabled) { 514 | Log.d(TAG, "onError exception: " + e.getMessage()); 515 | ex.printStackTrace(); 516 | } 517 | } 518 | } 519 | }); 520 | } 521 | 522 | @Override 523 | public void onSubscriptionSucceeded(String channelName) { 524 | this.onEvent(toPusherEvent(channelName, SUBSCRIPTION_SUCCESS_EVENT, null, null)); 525 | } 526 | } 527 | 528 | class PresenceChannelChannelListener extends EventChannelListener implements PresenceChannelEventListener { 529 | 530 | @Override 531 | public void onSubscriptionSucceeded(String channelName) { 532 | this.onEvent(toPusherEvent(channelName, SUBSCRIPTION_SUCCESS_EVENT, null, null)); 533 | } 534 | 535 | @Override 536 | public void onAuthenticationFailure(String message, Exception e) { 537 | onError(e); 538 | } 539 | 540 | @Override 541 | public void onUsersInformationReceived(String channelName, Set users) { 542 | this.onEvent(toPusherEvent(channelName, SUBSCRIPTION_SUCCESS_EVENT, null, users.toString())); 543 | } 544 | 545 | @Override 546 | public void userSubscribed(String channelName, User user) { 547 | this.onEvent(toPusherEvent(channelName, MEMBER_ADDED_EVENT, user.getId(), null)); 548 | } 549 | 550 | @Override 551 | public void userUnsubscribed(String channelName, User user) { 552 | this.onEvent(toPusherEvent(channelName, MEMBER_REMOVED_EVENT, user.getId(), null)); 553 | } 554 | } 555 | 556 | class PrivateChannelChannelListener extends EventChannelListener implements PrivateChannelEventListener { 557 | 558 | @Override 559 | public void onSubscriptionSucceeded(String channelName) { 560 | this.onEvent(toPusherEvent(channelName, SUBSCRIPTION_SUCCESS_EVENT, null, null)); 561 | } 562 | 563 | @Override 564 | public void onAuthenticationFailure(String message, Exception e) { 565 | onError(e); 566 | } 567 | 568 | } 569 | -------------------------------------------------------------------------------- /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 | # Visual Studio Code related 19 | .vscode/ 20 | 21 | # Flutter/Dart/Pub related 22 | **/doc/api/ 23 | .dart_tool/ 24 | .flutter-plugins 25 | .packages 26 | .pub-cache/ 27 | .pub/ 28 | /build/ 29 | 30 | # Android related 31 | **/android/**/gradle-wrapper.jar 32 | **/android/.gradle 33 | **/android/captures/ 34 | **/android/gradlew 35 | **/android/gradlew.bat 36 | **/android/local.properties 37 | **/android/**/GeneratedPluginRegistrant.java 38 | 39 | # iOS/XCode related 40 | **/ios/**/*.mode1v3 41 | **/ios/**/*.mode2v3 42 | **/ios/**/*.moved-aside 43 | **/ios/**/*.pbxuser 44 | **/ios/**/*.perspectivev3 45 | **/ios/**/*sync/ 46 | **/ios/**/.sconsign.dblite 47 | **/ios/**/.tags* 48 | **/ios/**/.vagrant/ 49 | **/ios/**/DerivedData/ 50 | **/ios/**/Icon? 51 | **/ios/**/Pods/ 52 | **/ios/**/.symlinks/ 53 | **/ios/**/profile 54 | **/ios/**/xcuserdata 55 | **/ios/.generated/ 56 | **/ios/Flutter/App.framework 57 | **/ios/Flutter/Flutter.framework 58 | **/ios/Flutter/Generated.xcconfig 59 | **/ios/Flutter/app.flx 60 | **/ios/Flutter/app.zip 61 | **/ios/Flutter/flutter_assets/ 62 | **/ios/ServiceDefinitions.json 63 | **/ios/Runner/GeneratedPluginRegistrant.* 64 | 65 | # Exceptions to above rules. 66 | !**/ios/**/default.mode1v3 67 | !**/ios/**/default.mode2v3 68 | !**/ios/**/default.pbxuser 69 | !**/ios/**/default.perspectivev3 70 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 71 | -------------------------------------------------------------------------------- /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: 7a4c33425ddd78c54aba07d86f3f9a4a0051769b 8 | channel: beta 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | android { 28 | compileSdkVersion 28 29 | 30 | lintOptions { 31 | disable 'InvalidPackage' 32 | } 33 | 34 | defaultConfig { 35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 36 | applicationId "com.ninjasolutions.pusher_example" 37 | minSdkVersion 16 38 | targetSdkVersion 28 39 | versionCode flutterVersionCode.toInteger() 40 | versionName flutterVersionName 41 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 42 | } 43 | 44 | buildTypes { 45 | release { 46 | // TODO: Add your own signing config for the release build. 47 | // Signing with the debug keys for now, so `flutter run --release` works. 48 | signingConfig signingConfigs.debug 49 | } 50 | } 51 | } 52 | 53 | flutter { 54 | source '../..' 55 | } 56 | 57 | dependencies { 58 | testImplementation 'junit:junit:4.12' 59 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 60 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 61 | } 62 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 9 | 13 | 20 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/pusherwebsocket/pusher_example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.ninjasolutions.pusher_example; 2 | 3 | import android.os.Bundle; 4 | import io.flutter.app.FlutterActivity; 5 | import io.flutter.plugins.GeneratedPluginRegistrant; 6 | 7 | public class MainActivity extends FlutterActivity { 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | GeneratedPluginRegistrant.registerWith(this); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.5.0' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Aug 21 15:44:34 CEST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 7 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /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 | 8.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/Flutter.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: This podspec is NOT to be published. It is only used as a local source! 3 | # 4 | 5 | Pod::Spec.new do |s| 6 | s.name = 'Flutter' 7 | s.version = '1.0.0' 8 | s.summary = 'High-performance, high-fidelity mobile apps.' 9 | s.description = <<-DESC 10 | Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS. 11 | DESC 12 | s.homepage = 'https://flutter.io' 13 | s.license = { :type => 'MIT' } 14 | s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } 15 | s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } 16 | s.ios.deployment_target = '8.0' 17 | s.vendored_frameworks = 'Flutter.framework' 18 | end 19 | -------------------------------------------------------------------------------- /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, '9.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 parse_KV_file(file, separator='=') 14 | file_abs_path = File.expand_path(file) 15 | if !File.exists? file_abs_path 16 | return []; 17 | end 18 | pods_ary = [] 19 | skip_line_start_symbols = ["#", "/"] 20 | File.foreach(file_abs_path) { |line| 21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } 22 | plugin = line.split(pattern=separator) 23 | if plugin.length == 2 24 | podname = plugin[0].strip() 25 | path = plugin[1].strip() 26 | podpath = File.expand_path("#{path}", file_abs_path) 27 | pods_ary.push({:name => podname, :path => podpath}); 28 | else 29 | puts "Invalid plugin specification: #{line}" 30 | end 31 | } 32 | return pods_ary 33 | end 34 | 35 | target 'Runner' do 36 | use_frameworks! 37 | 38 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock 39 | # referring to absolute paths on developers' machines. 40 | system('rm -rf .symlinks') 41 | system('mkdir -p .symlinks/plugins') 42 | 43 | # Flutter Pods 44 | generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') 45 | if generated_xcode_build_settings.empty? 46 | puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." 47 | end 48 | generated_xcode_build_settings.map { |p| 49 | if p[:name] == 'FLUTTER_FRAMEWORK_DIR' 50 | symlink = File.join('.symlinks', 'flutter') 51 | File.symlink(File.dirname(p[:path]), symlink) 52 | pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) 53 | end 54 | } 55 | 56 | # Plugin Pods 57 | plugin_pods = parse_KV_file('../.flutter-plugins') 58 | plugin_pods.map { |p| 59 | symlink = File.join('.symlinks', 'plugins', p[:name]) 60 | File.symlink(p[:path], symlink) 61 | pod p[:name], :path => File.join(symlink, 'ios') 62 | } 63 | end 64 | 65 | post_install do |installer| 66 | installer.pods_project.targets.each do |target| 67 | target.build_configurations.each do |config| 68 | config.build_settings['ENABLE_BITCODE'] = 'NO' 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - CryptoSwift (0.15.0) 3 | - Flutter (1.0.0) 4 | - flutter_pusher (1.0.1): 5 | - Flutter 6 | - PusherSwift (= 7.2.0) 7 | - PusherSwift (7.2.0): 8 | - CryptoSwift (~> 0.9) 9 | - ReachabilitySwift (= 4.3.0) 10 | - Starscream (~> 3.0.5) 11 | - ReachabilitySwift (4.3.0) 12 | - Starscream (3.0.6) 13 | 14 | DEPENDENCIES: 15 | - Flutter (from `.symlinks/flutter/ios`) 16 | - flutter_pusher (from `.symlinks/plugins/flutter_pusher/ios`) 17 | 18 | SPEC REPOS: 19 | trunk: 20 | - CryptoSwift 21 | - PusherSwift 22 | - ReachabilitySwift 23 | - Starscream 24 | 25 | EXTERNAL SOURCES: 26 | Flutter: 27 | :path: ".symlinks/flutter/ios" 28 | flutter_pusher: 29 | :path: ".symlinks/plugins/flutter_pusher/ios" 30 | 31 | SPEC CHECKSUMS: 32 | CryptoSwift: 769f58a9e89f64e8796c2e59ce5f002dc81a2438 33 | Flutter: 0e3d915762c693b495b44d77113d4970485de6ec 34 | flutter_pusher: b3b0050cb346fd0add6f9e1d2fae5125ea105232 35 | PusherSwift: a5369a01e8a9106b4897e9186265af1426726062 36 | ReachabilitySwift: 408477d1b6ed9779dba301953171e017c31241f3 37 | Starscream: ef3ece99d765eeccb67de105bfa143f929026cf5 38 | 39 | PODFILE CHECKSUM: d231b65d6bea6d24555f84ca7901720538b5791f 40 | 41 | COCOAPODS: 1.8.4 42 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3366FAD09E65DB669A37F740 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5B9DD4225C1AD83CD279BDE /* Pods_Runner.framework */; }; 12 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 13 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 14 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 15 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 16 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 17 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 18 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 19 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 20 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 21 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXCopyFilesBuildPhase section */ 25 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 26 | isa = PBXCopyFilesBuildPhase; 27 | buildActionMask = 2147483647; 28 | dstPath = ""; 29 | dstSubfolderSpec = 10; 30 | files = ( 31 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, 32 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, 33 | ); 34 | name = "Embed Frameworks"; 35 | runOnlyForDeploymentPostprocessing = 0; 36 | }; 37 | /* End PBXCopyFilesBuildPhase section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 41 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 42 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 43 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 44 | 5641B39FA099972098CB823D /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 45 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 46 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 47 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 48 | 8DFDFAB12027999F374C909A /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 49 | 8F6D3A6328D093D690C77A85 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 50 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 51 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 52 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 53 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 55 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 56 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 57 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58 | D5B9DD4225C1AD83CD279BDE /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 67 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 68 | 3366FAD09E65DB669A37F740 /* Pods_Runner.framework in Frameworks */, 69 | ); 70 | runOnlyForDeploymentPostprocessing = 0; 71 | }; 72 | /* End PBXFrameworksBuildPhase section */ 73 | 74 | /* Begin PBXGroup section */ 75 | 15C8B4427ACFB8F243BA7957 /* Pods */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 8F6D3A6328D093D690C77A85 /* Pods-Runner.debug.xcconfig */, 79 | 5641B39FA099972098CB823D /* Pods-Runner.release.xcconfig */, 80 | 8DFDFAB12027999F374C909A /* Pods-Runner.profile.xcconfig */, 81 | ); 82 | name = Pods; 83 | sourceTree = ""; 84 | }; 85 | 1EBBBBEAC5F17FE2F43C82B5 /* Frameworks */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | D5B9DD4225C1AD83CD279BDE /* Pods_Runner.framework */, 89 | ); 90 | name = Frameworks; 91 | sourceTree = ""; 92 | }; 93 | 9740EEB11CF90186004384FC /* Flutter */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | 3B80C3931E831B6300D905FE /* App.framework */, 97 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 98 | 9740EEBA1CF902C7004384FC /* Flutter.framework */, 99 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 100 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 101 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 102 | ); 103 | name = Flutter; 104 | sourceTree = ""; 105 | }; 106 | 97C146E51CF9000F007C117D = { 107 | isa = PBXGroup; 108 | children = ( 109 | 9740EEB11CF90186004384FC /* Flutter */, 110 | 97C146F01CF9000F007C117D /* Runner */, 111 | 97C146EF1CF9000F007C117D /* Products */, 112 | 15C8B4427ACFB8F243BA7957 /* Pods */, 113 | 1EBBBBEAC5F17FE2F43C82B5 /* Frameworks */, 114 | ); 115 | sourceTree = ""; 116 | }; 117 | 97C146EF1CF9000F007C117D /* Products */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 97C146EE1CF9000F007C117D /* Runner.app */, 121 | ); 122 | name = Products; 123 | sourceTree = ""; 124 | }; 125 | 97C146F01CF9000F007C117D /* Runner */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 129 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 130 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 131 | 97C147021CF9000F007C117D /* Info.plist */, 132 | 97C146F11CF9000F007C117D /* Supporting Files */, 133 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 134 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 135 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 136 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 137 | ); 138 | path = Runner; 139 | sourceTree = ""; 140 | }; 141 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | ); 145 | name = "Supporting Files"; 146 | sourceTree = ""; 147 | }; 148 | /* End PBXGroup section */ 149 | 150 | /* Begin PBXNativeTarget section */ 151 | 97C146ED1CF9000F007C117D /* Runner */ = { 152 | isa = PBXNativeTarget; 153 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 154 | buildPhases = ( 155 | C7958581711D3158986BB957 /* [CP] Check Pods Manifest.lock */, 156 | 9740EEB61CF901F6004384FC /* Run Script */, 157 | 97C146EA1CF9000F007C117D /* Sources */, 158 | 97C146EB1CF9000F007C117D /* Frameworks */, 159 | 97C146EC1CF9000F007C117D /* Resources */, 160 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 161 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 162 | 76AEC7D49F2111AF4A794555 /* [CP] Embed Pods Frameworks */, 163 | ); 164 | buildRules = ( 165 | ); 166 | dependencies = ( 167 | ); 168 | name = Runner; 169 | productName = Runner; 170 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 171 | productType = "com.apple.product-type.application"; 172 | }; 173 | /* End PBXNativeTarget section */ 174 | 175 | /* Begin PBXProject section */ 176 | 97C146E61CF9000F007C117D /* Project object */ = { 177 | isa = PBXProject; 178 | attributes = { 179 | LastUpgradeCheck = 0910; 180 | ORGANIZATIONNAME = "The Chromium Authors"; 181 | TargetAttributes = { 182 | 97C146ED1CF9000F007C117D = { 183 | CreatedOnToolsVersion = 7.3.1; 184 | DevelopmentTeam = TZ5634C3KW; 185 | LastSwiftMigration = 0910; 186 | }; 187 | }; 188 | }; 189 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 190 | compatibilityVersion = "Xcode 3.2"; 191 | developmentRegion = English; 192 | hasScannedForEncodings = 0; 193 | knownRegions = ( 194 | English, 195 | en, 196 | Base, 197 | ); 198 | mainGroup = 97C146E51CF9000F007C117D; 199 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 200 | projectDirPath = ""; 201 | projectRoot = ""; 202 | targets = ( 203 | 97C146ED1CF9000F007C117D /* Runner */, 204 | ); 205 | }; 206 | /* End PBXProject section */ 207 | 208 | /* Begin PBXResourcesBuildPhase section */ 209 | 97C146EC1CF9000F007C117D /* Resources */ = { 210 | isa = PBXResourcesBuildPhase; 211 | buildActionMask = 2147483647; 212 | files = ( 213 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 214 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 215 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 216 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 217 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 218 | ); 219 | runOnlyForDeploymentPostprocessing = 0; 220 | }; 221 | /* End PBXResourcesBuildPhase section */ 222 | 223 | /* Begin PBXShellScriptBuildPhase section */ 224 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 225 | isa = PBXShellScriptBuildPhase; 226 | buildActionMask = 2147483647; 227 | files = ( 228 | ); 229 | inputPaths = ( 230 | ); 231 | name = "Thin Binary"; 232 | outputPaths = ( 233 | ); 234 | runOnlyForDeploymentPostprocessing = 0; 235 | shellPath = /bin/sh; 236 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; 237 | }; 238 | 76AEC7D49F2111AF4A794555 /* [CP] Embed Pods Frameworks */ = { 239 | isa = PBXShellScriptBuildPhase; 240 | buildActionMask = 2147483647; 241 | files = ( 242 | ); 243 | inputPaths = ( 244 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", 245 | "${BUILT_PRODUCTS_DIR}/CryptoSwift/CryptoSwift.framework", 246 | "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", 247 | "${BUILT_PRODUCTS_DIR}/PusherSwift/PusherSwift.framework", 248 | "${BUILT_PRODUCTS_DIR}/ReachabilitySwift/Reachability.framework", 249 | "${BUILT_PRODUCTS_DIR}/Starscream/Starscream.framework", 250 | "${BUILT_PRODUCTS_DIR}/flutter_pusher/flutter_pusher.framework", 251 | ); 252 | name = "[CP] Embed Pods Frameworks"; 253 | outputPaths = ( 254 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CryptoSwift.framework", 255 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", 256 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PusherSwift.framework", 257 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reachability.framework", 258 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Starscream.framework", 259 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_pusher.framework", 260 | ); 261 | runOnlyForDeploymentPostprocessing = 0; 262 | shellPath = /bin/sh; 263 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; 264 | showEnvVarsInLog = 0; 265 | }; 266 | 9740EEB61CF901F6004384FC /* Run Script */ = { 267 | isa = PBXShellScriptBuildPhase; 268 | buildActionMask = 2147483647; 269 | files = ( 270 | ); 271 | inputPaths = ( 272 | ); 273 | name = "Run Script"; 274 | outputPaths = ( 275 | ); 276 | runOnlyForDeploymentPostprocessing = 0; 277 | shellPath = /bin/sh; 278 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 279 | }; 280 | C7958581711D3158986BB957 /* [CP] Check Pods Manifest.lock */ = { 281 | isa = PBXShellScriptBuildPhase; 282 | buildActionMask = 2147483647; 283 | files = ( 284 | ); 285 | inputPaths = ( 286 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 287 | "${PODS_ROOT}/Manifest.lock", 288 | ); 289 | name = "[CP] Check Pods Manifest.lock"; 290 | outputPaths = ( 291 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 292 | ); 293 | runOnlyForDeploymentPostprocessing = 0; 294 | shellPath = /bin/sh; 295 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 296 | showEnvVarsInLog = 0; 297 | }; 298 | /* End PBXShellScriptBuildPhase section */ 299 | 300 | /* Begin PBXSourcesBuildPhase section */ 301 | 97C146EA1CF9000F007C117D /* Sources */ = { 302 | isa = PBXSourcesBuildPhase; 303 | buildActionMask = 2147483647; 304 | files = ( 305 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 306 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 307 | ); 308 | runOnlyForDeploymentPostprocessing = 0; 309 | }; 310 | /* End PBXSourcesBuildPhase section */ 311 | 312 | /* Begin PBXVariantGroup section */ 313 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 314 | isa = PBXVariantGroup; 315 | children = ( 316 | 97C146FB1CF9000F007C117D /* Base */, 317 | ); 318 | name = Main.storyboard; 319 | sourceTree = ""; 320 | }; 321 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 322 | isa = PBXVariantGroup; 323 | children = ( 324 | 97C147001CF9000F007C117D /* Base */, 325 | ); 326 | name = LaunchScreen.storyboard; 327 | sourceTree = ""; 328 | }; 329 | /* End PBXVariantGroup section */ 330 | 331 | /* Begin XCBuildConfiguration section */ 332 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 333 | isa = XCBuildConfiguration; 334 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 335 | buildSettings = { 336 | ALWAYS_SEARCH_USER_PATHS = NO; 337 | CLANG_ANALYZER_NONNULL = YES; 338 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 339 | CLANG_CXX_LIBRARY = "libc++"; 340 | CLANG_ENABLE_MODULES = YES; 341 | CLANG_ENABLE_OBJC_ARC = YES; 342 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 343 | CLANG_WARN_BOOL_CONVERSION = YES; 344 | CLANG_WARN_COMMA = YES; 345 | CLANG_WARN_CONSTANT_CONVERSION = YES; 346 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 347 | CLANG_WARN_EMPTY_BODY = YES; 348 | CLANG_WARN_ENUM_CONVERSION = YES; 349 | CLANG_WARN_INFINITE_RECURSION = YES; 350 | CLANG_WARN_INT_CONVERSION = YES; 351 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 352 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 353 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 354 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 355 | CLANG_WARN_STRICT_PROTOTYPES = YES; 356 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 357 | CLANG_WARN_UNREACHABLE_CODE = YES; 358 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 359 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 360 | COPY_PHASE_STRIP = NO; 361 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 362 | ENABLE_NS_ASSERTIONS = NO; 363 | ENABLE_STRICT_OBJC_MSGSEND = YES; 364 | GCC_C_LANGUAGE_STANDARD = gnu99; 365 | GCC_NO_COMMON_BLOCKS = YES; 366 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 367 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 368 | GCC_WARN_UNDECLARED_SELECTOR = YES; 369 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 370 | GCC_WARN_UNUSED_FUNCTION = YES; 371 | GCC_WARN_UNUSED_VARIABLE = YES; 372 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 373 | MTL_ENABLE_DEBUG_INFO = NO; 374 | SDKROOT = iphoneos; 375 | TARGETED_DEVICE_FAMILY = "1,2"; 376 | VALIDATE_PRODUCT = YES; 377 | }; 378 | name = Profile; 379 | }; 380 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 381 | isa = XCBuildConfiguration; 382 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 383 | buildSettings = { 384 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 385 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 386 | DEVELOPMENT_TEAM = TZ5634C3KW; 387 | ENABLE_BITCODE = NO; 388 | FRAMEWORK_SEARCH_PATHS = ( 389 | "$(inherited)", 390 | "$(PROJECT_DIR)/Flutter", 391 | ); 392 | INFOPLIST_FILE = Runner/Info.plist; 393 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 394 | LIBRARY_SEARCH_PATHS = ( 395 | "$(inherited)", 396 | "$(PROJECT_DIR)/Flutter", 397 | ); 398 | PRODUCT_BUNDLE_IDENTIFIER = com.ninjasolutions.pusherExample; 399 | PRODUCT_NAME = "$(TARGET_NAME)"; 400 | SWIFT_VERSION = 4.0; 401 | VERSIONING_SYSTEM = "apple-generic"; 402 | }; 403 | name = Profile; 404 | }; 405 | 97C147031CF9000F007C117D /* Debug */ = { 406 | isa = XCBuildConfiguration; 407 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 408 | buildSettings = { 409 | ALWAYS_SEARCH_USER_PATHS = NO; 410 | CLANG_ANALYZER_NONNULL = YES; 411 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 412 | CLANG_CXX_LIBRARY = "libc++"; 413 | CLANG_ENABLE_MODULES = YES; 414 | CLANG_ENABLE_OBJC_ARC = YES; 415 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 416 | CLANG_WARN_BOOL_CONVERSION = YES; 417 | CLANG_WARN_COMMA = YES; 418 | CLANG_WARN_CONSTANT_CONVERSION = YES; 419 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 420 | CLANG_WARN_EMPTY_BODY = YES; 421 | CLANG_WARN_ENUM_CONVERSION = YES; 422 | CLANG_WARN_INFINITE_RECURSION = YES; 423 | CLANG_WARN_INT_CONVERSION = YES; 424 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 425 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 426 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 427 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 428 | CLANG_WARN_STRICT_PROTOTYPES = YES; 429 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 430 | CLANG_WARN_UNREACHABLE_CODE = YES; 431 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 432 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 433 | COPY_PHASE_STRIP = NO; 434 | DEBUG_INFORMATION_FORMAT = dwarf; 435 | ENABLE_STRICT_OBJC_MSGSEND = YES; 436 | ENABLE_TESTABILITY = YES; 437 | GCC_C_LANGUAGE_STANDARD = gnu99; 438 | GCC_DYNAMIC_NO_PIC = NO; 439 | GCC_NO_COMMON_BLOCKS = YES; 440 | GCC_OPTIMIZATION_LEVEL = 0; 441 | GCC_PREPROCESSOR_DEFINITIONS = ( 442 | "DEBUG=1", 443 | "$(inherited)", 444 | ); 445 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 446 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 447 | GCC_WARN_UNDECLARED_SELECTOR = YES; 448 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 449 | GCC_WARN_UNUSED_FUNCTION = YES; 450 | GCC_WARN_UNUSED_VARIABLE = YES; 451 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 452 | MTL_ENABLE_DEBUG_INFO = YES; 453 | ONLY_ACTIVE_ARCH = YES; 454 | SDKROOT = iphoneos; 455 | TARGETED_DEVICE_FAMILY = "1,2"; 456 | }; 457 | name = Debug; 458 | }; 459 | 97C147041CF9000F007C117D /* Release */ = { 460 | isa = XCBuildConfiguration; 461 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 462 | buildSettings = { 463 | ALWAYS_SEARCH_USER_PATHS = NO; 464 | CLANG_ANALYZER_NONNULL = YES; 465 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 466 | CLANG_CXX_LIBRARY = "libc++"; 467 | CLANG_ENABLE_MODULES = YES; 468 | CLANG_ENABLE_OBJC_ARC = YES; 469 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 470 | CLANG_WARN_BOOL_CONVERSION = YES; 471 | CLANG_WARN_COMMA = YES; 472 | CLANG_WARN_CONSTANT_CONVERSION = YES; 473 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 474 | CLANG_WARN_EMPTY_BODY = YES; 475 | CLANG_WARN_ENUM_CONVERSION = YES; 476 | CLANG_WARN_INFINITE_RECURSION = YES; 477 | CLANG_WARN_INT_CONVERSION = YES; 478 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 479 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 480 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 481 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 482 | CLANG_WARN_STRICT_PROTOTYPES = YES; 483 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 484 | CLANG_WARN_UNREACHABLE_CODE = YES; 485 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 486 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 487 | COPY_PHASE_STRIP = NO; 488 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 489 | ENABLE_NS_ASSERTIONS = NO; 490 | ENABLE_STRICT_OBJC_MSGSEND = YES; 491 | GCC_C_LANGUAGE_STANDARD = gnu99; 492 | GCC_NO_COMMON_BLOCKS = YES; 493 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 494 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 495 | GCC_WARN_UNDECLARED_SELECTOR = YES; 496 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 497 | GCC_WARN_UNUSED_FUNCTION = YES; 498 | GCC_WARN_UNUSED_VARIABLE = YES; 499 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 500 | MTL_ENABLE_DEBUG_INFO = NO; 501 | SDKROOT = iphoneos; 502 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 503 | TARGETED_DEVICE_FAMILY = "1,2"; 504 | VALIDATE_PRODUCT = YES; 505 | }; 506 | name = Release; 507 | }; 508 | 97C147061CF9000F007C117D /* Debug */ = { 509 | isa = XCBuildConfiguration; 510 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 511 | buildSettings = { 512 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 513 | CLANG_ENABLE_MODULES = YES; 514 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 515 | DEVELOPMENT_TEAM = TZ5634C3KW; 516 | ENABLE_BITCODE = NO; 517 | FRAMEWORK_SEARCH_PATHS = ( 518 | "$(inherited)", 519 | "$(PROJECT_DIR)/Flutter", 520 | ); 521 | INFOPLIST_FILE = Runner/Info.plist; 522 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 523 | LIBRARY_SEARCH_PATHS = ( 524 | "$(inherited)", 525 | "$(PROJECT_DIR)/Flutter", 526 | ); 527 | PRODUCT_BUNDLE_IDENTIFIER = com.ninjasolutions.pusherExample; 528 | PRODUCT_NAME = "$(TARGET_NAME)"; 529 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 530 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 531 | SWIFT_SWIFT3_OBJC_INFERENCE = On; 532 | SWIFT_VERSION = 4.0; 533 | VERSIONING_SYSTEM = "apple-generic"; 534 | }; 535 | name = Debug; 536 | }; 537 | 97C147071CF9000F007C117D /* Release */ = { 538 | isa = XCBuildConfiguration; 539 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 540 | buildSettings = { 541 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 542 | CLANG_ENABLE_MODULES = YES; 543 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 544 | DEVELOPMENT_TEAM = TZ5634C3KW; 545 | ENABLE_BITCODE = NO; 546 | FRAMEWORK_SEARCH_PATHS = ( 547 | "$(inherited)", 548 | "$(PROJECT_DIR)/Flutter", 549 | ); 550 | INFOPLIST_FILE = Runner/Info.plist; 551 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 552 | LIBRARY_SEARCH_PATHS = ( 553 | "$(inherited)", 554 | "$(PROJECT_DIR)/Flutter", 555 | ); 556 | PRODUCT_BUNDLE_IDENTIFIER = com.ninjasolutions.pusherExample; 557 | PRODUCT_NAME = "$(TARGET_NAME)"; 558 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 559 | SWIFT_SWIFT3_OBJC_INFERENCE = On; 560 | SWIFT_VERSION = 4.0; 561 | VERSIONING_SYSTEM = "apple-generic"; 562 | }; 563 | name = Release; 564 | }; 565 | /* End XCBuildConfiguration section */ 566 | 567 | /* Begin XCConfigurationList section */ 568 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 569 | isa = XCConfigurationList; 570 | buildConfigurations = ( 571 | 97C147031CF9000F007C117D /* Debug */, 572 | 97C147041CF9000F007C117D /* Release */, 573 | 249021D3217E4FDB00AE95B9 /* Profile */, 574 | ); 575 | defaultConfigurationIsVisible = 0; 576 | defaultConfigurationName = Release; 577 | }; 578 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 579 | isa = XCConfigurationList; 580 | buildConfigurations = ( 581 | 97C147061CF9000F007C117D /* Debug */, 582 | 97C147071CF9000F007C117D /* Release */, 583 | 249021D4217E4FDB00AE95B9 /* Profile */, 584 | ); 585 | defaultConfigurationIsVisible = 0; 586 | defaultConfigurationName = Release; 587 | }; 588 | /* End XCConfigurationList section */ 589 | }; 590 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 591 | } 592 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /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 | BuildSystemType 6 | Original 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: 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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/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 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | pusher_example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:flutter_pusher/pusher.dart'; 4 | 5 | void main() => runApp(MyApp()); 6 | 7 | class MyApp extends StatefulWidget { 8 | @override 9 | _MyAppState createState() => _MyAppState(); 10 | } 11 | 12 | class _MyAppState extends State { 13 | Event? lastEvent; 14 | String? lastConnectionState; 15 | Channel? channel; 16 | 17 | var channelController = TextEditingController(text: "my-channel"); 18 | var eventController = TextEditingController(text: "my-event"); 19 | var triggerController = TextEditingController(text: "client-trigger"); 20 | 21 | @override 22 | void initState() { 23 | super.initState(); 24 | initPusher(); 25 | } 26 | 27 | Future initPusher() async { 28 | try { 29 | await Pusher.init( 30 | "APP_KEY", 31 | PusherOptions( 32 | cluster: "eu", 33 | ), 34 | enableLogging: true); 35 | } on PlatformException catch (e) { 36 | print(e.message); 37 | } 38 | } 39 | 40 | @override 41 | Widget build(BuildContext context) { 42 | return MaterialApp( 43 | home: Scaffold( 44 | appBar: AppBar( 45 | title: Text('Plugin example app'), 46 | ), 47 | body: Padding( 48 | padding: const EdgeInsets.all(8.0), 49 | child: Column( 50 | crossAxisAlignment: CrossAxisAlignment.start, 51 | children: [ 52 | _buildInfo(), 53 | ElevatedButton( 54 | child: Text("Connect"), 55 | onPressed: () { 56 | Pusher.connect(onConnectionStateChange: (x) async { 57 | if (mounted) 58 | setState(() { 59 | lastConnectionState = x.currentState; 60 | }); 61 | }, onError: (x) { 62 | debugPrint("Error: ${x.message}"); 63 | }); 64 | }, 65 | ), 66 | ElevatedButton( 67 | child: Text("Disconnect"), 68 | onPressed: () { 69 | Pusher.disconnect(); 70 | }, 71 | ), 72 | Row( 73 | children: [ 74 | Container( 75 | width: 200, 76 | child: TextField( 77 | autocorrect: false, 78 | controller: channelController, 79 | decoration: InputDecoration(hintText: "Channel"), 80 | ), 81 | ), 82 | ElevatedButton( 83 | child: Text("Subscribe"), 84 | onPressed: () async { 85 | channel = 86 | await Pusher.subscribe(channelController.text); 87 | }, 88 | ) 89 | ], 90 | ), 91 | Row( 92 | children: [ 93 | Container( 94 | width: 200, 95 | child: TextField( 96 | controller: channelController, 97 | decoration: InputDecoration(hintText: "Channel"), 98 | ), 99 | ), 100 | ElevatedButton( 101 | child: Text("Unsubscribe"), 102 | onPressed: () async { 103 | await Pusher.unsubscribe(channelController.text); 104 | channel = null; 105 | }, 106 | ) 107 | ], 108 | ), 109 | Row( 110 | children: [ 111 | Container( 112 | width: 200, 113 | child: TextField( 114 | controller: eventController, 115 | decoration: InputDecoration(hintText: "Event"), 116 | ), 117 | ), 118 | ElevatedButton( 119 | child: Text("Bind"), 120 | onPressed: () async { 121 | await channel!.bind(eventController.text, (x) { 122 | if (mounted) 123 | setState(() { 124 | lastEvent = x; 125 | }); 126 | }); 127 | }, 128 | ) 129 | ], 130 | ), 131 | Row( 132 | children: [ 133 | Container( 134 | width: 200, 135 | child: TextField( 136 | controller: eventController, 137 | decoration: InputDecoration(hintText: "Event"), 138 | ), 139 | ), 140 | ElevatedButton( 141 | child: Text("Unbind"), 142 | onPressed: () async { 143 | await channel!.unbind(eventController.text); 144 | }, 145 | ) 146 | ], 147 | ), 148 | Row( 149 | children: [ 150 | Container( 151 | width: 200, 152 | child: TextField( 153 | controller: triggerController, 154 | decoration: InputDecoration(hintText: "Trigger"), 155 | ), 156 | ), 157 | ElevatedButton( 158 | child: Text("Trigger"), 159 | onPressed: () async { 160 | await channel!.trigger(triggerController.text, 161 | data: 162 | '{"testValue": 123, "anotherOne": false, "nested": {"w0t": "m8"}}'); 163 | }, 164 | ) 165 | ], 166 | ), 167 | ], 168 | ), 169 | )), 170 | ); 171 | } 172 | 173 | Widget _buildInfo() { 174 | return Column( 175 | crossAxisAlignment: CrossAxisAlignment.start, 176 | children: [ 177 | Row( 178 | crossAxisAlignment: CrossAxisAlignment.start, 179 | children: [ 180 | Text( 181 | "Connection State: ", 182 | style: TextStyle(fontWeight: FontWeight.bold), 183 | ), 184 | Text(lastConnectionState ?? "Unknown"), 185 | ], 186 | ), 187 | SizedBox(height: 8), 188 | Row( 189 | crossAxisAlignment: CrossAxisAlignment.start, 190 | children: [ 191 | Text( 192 | "Last Event Channel: ", 193 | style: TextStyle(fontWeight: FontWeight.bold), 194 | ), 195 | Text(lastEvent?.channel ?? ""), 196 | ], 197 | ), 198 | SizedBox(height: 8), 199 | Row( 200 | crossAxisAlignment: CrossAxisAlignment.start, 201 | children: [ 202 | Text( 203 | "Last Event Name: ", 204 | style: TextStyle(fontWeight: FontWeight.bold), 205 | ), 206 | Text(lastEvent?.event ?? ""), 207 | ], 208 | ), 209 | SizedBox(height: 8), 210 | Row( 211 | crossAxisAlignment: CrossAxisAlignment.start, 212 | children: [ 213 | Text( 214 | "Last Event Data: ", 215 | style: TextStyle(fontWeight: FontWeight.bold), 216 | ), 217 | Text(lastEvent?.data ?? ""), 218 | ], 219 | ), 220 | ], 221 | ); 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /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 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.5.0" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.1.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.2.0" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.0" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.15.0" 46 | cupertino_icons: 47 | dependency: "direct main" 48 | description: 49 | name: cupertino_icons 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "0.1.2" 53 | fake_async: 54 | dependency: transitive 55 | description: 56 | name: fake_async 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.2.0" 60 | flutter: 61 | dependency: "direct main" 62 | description: flutter 63 | source: sdk 64 | version: "0.0.0" 65 | flutter_pusher: 66 | dependency: "direct dev" 67 | description: 68 | path: ".." 69 | relative: true 70 | source: path 71 | version: "2.0.0-nullsafety.0" 72 | flutter_test: 73 | dependency: "direct dev" 74 | description: flutter 75 | source: sdk 76 | version: "0.0.0" 77 | json_annotation: 78 | dependency: transitive 79 | description: 80 | name: json_annotation 81 | url: "https://pub.dartlang.org" 82 | source: hosted 83 | version: "4.0.1" 84 | matcher: 85 | dependency: transitive 86 | description: 87 | name: matcher 88 | url: "https://pub.dartlang.org" 89 | source: hosted 90 | version: "0.12.10" 91 | meta: 92 | dependency: transitive 93 | description: 94 | name: meta 95 | url: "https://pub.dartlang.org" 96 | source: hosted 97 | version: "1.3.0" 98 | path: 99 | dependency: transitive 100 | description: 101 | name: path 102 | url: "https://pub.dartlang.org" 103 | source: hosted 104 | version: "1.8.0" 105 | sky_engine: 106 | dependency: transitive 107 | description: flutter 108 | source: sdk 109 | version: "0.0.99" 110 | source_span: 111 | dependency: transitive 112 | description: 113 | name: source_span 114 | url: "https://pub.dartlang.org" 115 | source: hosted 116 | version: "1.8.0" 117 | stack_trace: 118 | dependency: transitive 119 | description: 120 | name: stack_trace 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "1.10.0" 124 | stream_channel: 125 | dependency: transitive 126 | description: 127 | name: stream_channel 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "2.1.0" 131 | string_scanner: 132 | dependency: transitive 133 | description: 134 | name: string_scanner 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "1.1.0" 138 | term_glyph: 139 | dependency: transitive 140 | description: 141 | name: term_glyph 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "1.2.0" 145 | test_api: 146 | dependency: transitive 147 | description: 148 | name: test_api 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "0.2.19" 152 | typed_data: 153 | dependency: transitive 154 | description: 155 | name: typed_data 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "1.3.0" 159 | vector_math: 160 | dependency: transitive 161 | description: 162 | name: vector_math 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "2.1.0" 166 | sdks: 167 | dart: ">=2.12.0 <3.0.0" 168 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: pusher_example 2 | description: Demonstrates how to use the pusher plugin. 3 | publish_to: 'none' 4 | 5 | environment: 6 | sdk: ">=2.12.0 <3.0.0" 7 | 8 | dependencies: 9 | flutter: 10 | sdk: flutter 11 | 12 | # The following adds the Cupertino Icons font to your application. 13 | # Use with the CupertinoIcons class for iOS style icons. 14 | cupertino_icons: ^0.1.2 15 | 16 | dev_dependencies: 17 | flutter_test: 18 | sdk: flutter 19 | 20 | flutter_pusher: 21 | path: ../ 22 | 23 | # For information on the generic Dart part of this file, see the 24 | # following page: https://www.dartlang.org/tools/pub/pubspec 25 | 26 | # The following section is specific to Flutter. 27 | flutter: 28 | 29 | # The following line ensures that the Material Icons font is 30 | # included with your application, so that you can use the icons in 31 | # the material Icons class. 32 | uses-material-design: true 33 | 34 | # To add assets to your application, add an assets section, like this: 35 | # assets: 36 | # - images/a_dot_burr.jpeg 37 | # - images/a_dot_ham.jpeg 38 | 39 | # An image asset can refer to one or more resolution-specific "variants", see 40 | # https://flutter.dev/assets-and-images/#resolution-aware. 41 | 42 | # For details regarding adding assets from package dependencies, see 43 | # https://flutter.dev/assets-and-images/#from-packages 44 | 45 | # To add custom fonts to your application, add a fonts section here, 46 | # in this "flutter" section. Each entry in this list should have a 47 | # "family" key with the font family name, and a "fonts" key with a 48 | # list giving the asset and other descriptors for the font. For 49 | # example: 50 | # fonts: 51 | # - family: Schyler 52 | # fonts: 53 | # - asset: fonts/Schyler-Regular.ttf 54 | # - asset: fonts/Schyler-Italic.ttf 55 | # style: italic 56 | # - family: Trajan Pro 57 | # fonts: 58 | # - asset: fonts/TrajanPro.ttf 59 | # - asset: fonts/TrajanPro_Bold.ttf 60 | # weight: 700 61 | # 62 | # For details regarding fonts from package dependencies, 63 | # see https://flutter.dev/custom-fonts/#from-packages 64 | -------------------------------------------------------------------------------- /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 that Flutter provides. 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 | 11 | import '../lib/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Verify Platform version', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that platform version is retrieved. 19 | expect( 20 | find.byWidgetPredicate( 21 | (Widget widget) => 22 | widget is Text && (widget.data?.startsWith('Running on:') ?? false), 23 | ), 24 | findsOneWidget, 25 | ); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ios/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ninjasolutions/flutter_pusher/cac96c9e31148001dde043a31666c3e73ae2c960/ios/Assets/.gitkeep -------------------------------------------------------------------------------- /ios/Classes/PusherPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface PusherPlugin : NSObject 4 | @end 5 | -------------------------------------------------------------------------------- /ios/Classes/PusherPlugin.m: -------------------------------------------------------------------------------- 1 | #import "PusherPlugin.h" 2 | #import 3 | 4 | @implementation PusherPlugin 5 | + (void)registerWithRegistrar:(NSObject*)registrar { 6 | [SwiftPusherPlugin registerWithRegistrar:registrar]; 7 | } 8 | @end 9 | -------------------------------------------------------------------------------- /ios/Classes/SwiftPusherPlugin.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import PusherSwift 4 | 5 | public class SwiftPusherPlugin: NSObject, FlutterPlugin, PusherDelegate { 6 | 7 | public static var pusher: Pusher? 8 | public static var isLoggingEnabled: Bool = false; 9 | public static var bindedEvents = [String:String]() 10 | public static var channels = [String:PusherChannel]() 11 | public static var eventSink: FlutterEventSink? 12 | 13 | public static func register(with registrar: FlutterPluginRegistrar) { 14 | let channel = FlutterMethodChannel(name: "plugins.indoor.solutions/pusher", binaryMessenger: registrar.messenger()) 15 | let instance = SwiftPusherPlugin() 16 | let eventChannel = FlutterEventChannel(name: "plugins.indoor.solutions/pusherStream", binaryMessenger: registrar.messenger()) 17 | 18 | registrar.addMethodCallDelegate(instance, channel: channel) 19 | eventChannel.setStreamHandler(StreamHandler()) 20 | } 21 | 22 | public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { 23 | switch call.method { 24 | case "init": 25 | setup(call, result: result) 26 | case "connect": 27 | connect(call, result: result) 28 | case "disconnect": 29 | disconnect(call, result: result) 30 | case "subscribe": 31 | subscribe(call, result: result) 32 | case "unsubscribe": 33 | unsubscribe(call, result: result) 34 | case "bind": 35 | bind(call, result: result) 36 | case "unbind": 37 | unbind(call, result: result) 38 | case "trigger": 39 | trigger(call, result: result) 40 | default: 41 | result(FlutterMethodNotImplemented) 42 | } 43 | } 44 | 45 | public func setup(_ call: FlutterMethodCall, result: @escaping FlutterResult) { 46 | if let pusherObj = SwiftPusherPlugin.pusher { 47 | pusherObj.unbindAll(); 48 | pusherObj.unsubscribeAll() 49 | } 50 | 51 | for (_, pusherChannel) in SwiftPusherPlugin.channels { 52 | pusherChannel.unbindAll() 53 | } 54 | 55 | SwiftPusherPlugin.channels.removeAll(); 56 | SwiftPusherPlugin.bindedEvents.removeAll() 57 | 58 | do { 59 | let json = call.arguments as! String 60 | let jsonDecoder = JSONDecoder() 61 | let initArgs = try jsonDecoder.decode(InitArgs.self, from: json.data(using: .utf8)!) 62 | 63 | SwiftPusherPlugin.isLoggingEnabled = initArgs.isLoggingEnabled 64 | 65 | let options = PusherClientOptions( 66 | authMethod: initArgs.options.auth != nil ? AuthMethod.authRequestBuilder(authRequestBuilder: AuthRequestBuilder(endpoint: initArgs.options.auth!.endpoint, headers: initArgs.options.auth!.headers)): .noMethod, 67 | host: initArgs.options.host != nil ? .host(initArgs.options.host!) : (initArgs.options.cluster != nil ? .cluster(initArgs.options.cluster!) : .host("ws.pusherapp.com")), 68 | port: initArgs.options.port ?? (initArgs.options.encrypted ?? true ? 443 : 80), 69 | useTLS: initArgs.options.encrypted ?? true, 70 | activityTimeout: Double(initArgs.options.activityTimeout ?? 30000) / 1000 71 | ) 72 | 73 | SwiftPusherPlugin.pusher = Pusher( 74 | key: initArgs.appKey, 75 | options: options 76 | ) 77 | SwiftPusherPlugin.pusher!.connection.delegate = self 78 | 79 | if (SwiftPusherPlugin.isLoggingEnabled) { 80 | print("Pusher init") 81 | } 82 | } catch { 83 | if (SwiftPusherPlugin.isLoggingEnabled) { 84 | print("Pusher init error:" + error.localizedDescription) 85 | } 86 | } 87 | result(nil); 88 | } 89 | 90 | public func connect(_ call: FlutterMethodCall, result: @escaping FlutterResult) { 91 | if let pusherObj = SwiftPusherPlugin.pusher { 92 | pusherObj.connect(); 93 | if (SwiftPusherPlugin.isLoggingEnabled) { 94 | print("Pusher connect") 95 | } 96 | } 97 | result(nil); 98 | } 99 | 100 | public func disconnect(_ call: FlutterMethodCall, result: @escaping FlutterResult) { 101 | if let pusherObj = SwiftPusherPlugin.pusher { 102 | pusherObj.disconnect(); 103 | if (SwiftPusherPlugin.isLoggingEnabled) { 104 | print("Pusher disconnect") 105 | } 106 | } 107 | result(nil); 108 | } 109 | 110 | public func subscribe(_ call: FlutterMethodCall, result: @escaping FlutterResult) { 111 | if let pusherObj = SwiftPusherPlugin.pusher { 112 | let channelName = call.arguments as! String 113 | let channelType = channelName.components(separatedBy: "-")[0] 114 | var channel: PusherChannel 115 | 116 | switch channelType{ 117 | case "private": 118 | channel = pusherObj.subscribe(channelName) 119 | if (SwiftPusherPlugin.isLoggingEnabled) { 120 | print("Pusher subscribe (private)") 121 | } 122 | case "presence": 123 | channel = pusherObj.subscribeToPresenceChannel(channelName: channelName) 124 | if (SwiftPusherPlugin.isLoggingEnabled) { 125 | print("Pusher subscribe (presence)") 126 | } 127 | default: 128 | channel = pusherObj.subscribe(channelName) 129 | if (SwiftPusherPlugin.isLoggingEnabled) { 130 | print("Pusher subscribe") 131 | } 132 | } 133 | 134 | SwiftPusherPlugin.channels[channelName] = channel; 135 | } 136 | result(nil); 137 | } 138 | 139 | public func subscribeToPresence(_ call: FlutterMethodCall, result: @escaping FlutterResult) { 140 | if let pusherObj = SwiftPusherPlugin.pusher { 141 | let channelName = call.arguments as! String 142 | let channel = pusherObj.subscribeToPresenceChannel(channelName: channelName) 143 | SwiftPusherPlugin.channels[channelName] = channel; 144 | 145 | if (SwiftPusherPlugin.isLoggingEnabled) { 146 | print("Pusher subscribe to presence channel") 147 | } 148 | } 149 | result(nil); 150 | } 151 | 152 | public func unsubscribe(_ call: FlutterMethodCall, result: @escaping FlutterResult) { 153 | if let pusherObj = SwiftPusherPlugin.pusher { 154 | let channelName = call.arguments as! String 155 | pusherObj.unsubscribe(channelName) 156 | SwiftPusherPlugin.channels.removeValue(forKey: "channelName") 157 | 158 | if (SwiftPusherPlugin.isLoggingEnabled) { 159 | print("Pusher unsubscribe") 160 | } 161 | } 162 | result(nil); 163 | } 164 | 165 | public func bind(_ call: FlutterMethodCall, result: @escaping FlutterResult) { 166 | do { 167 | let json = call.arguments as! String 168 | let jsonDecoder = JSONDecoder() 169 | let bindArgs = try jsonDecoder.decode(BindArgs.self, from: json.data(using: .utf8)!) 170 | 171 | let channel = SwiftPusherPlugin.channels[bindArgs.channelName] 172 | if let channelObj = channel { 173 | unbindIfBound(channelName: bindArgs.channelName, eventName: bindArgs.eventName) 174 | SwiftPusherPlugin.bindedEvents[bindArgs.channelName + bindArgs.eventName] = channelObj.bind(eventName: bindArgs.eventName, callback: { data in 175 | do { 176 | if JSONSerialization.isValidJSONObject(data) { 177 | let pushJsonData = try! JSONSerialization.data(withJSONObject: data) 178 | let pushJsonString = NSString(data: pushJsonData, encoding: String.Encoding.utf8.rawValue) 179 | let event = Event(channel: bindArgs.channelName, event: bindArgs.eventName, data: pushJsonString! as String) 180 | let message = PusherEventStreamMessage(event: event, connectionStateChange: nil) 181 | let jsonEncoder = JSONEncoder() 182 | let jsonData = try jsonEncoder.encode(message) 183 | let jsonString = String(data: jsonData, encoding: .utf8) 184 | if let eventSinkObj = SwiftPusherPlugin.eventSink { 185 | eventSinkObj(jsonString) 186 | 187 | if (SwiftPusherPlugin.isLoggingEnabled) { 188 | print("Pusher event: CHANNEL:\(bindArgs.channelName) EVENT:\(bindArgs.eventName) DATA:\(jsonString ?? "no data")") 189 | } 190 | } 191 | } 192 | } catch { 193 | if (SwiftPusherPlugin.isLoggingEnabled) { 194 | print("Pusher bind error:" + error.localizedDescription) 195 | } 196 | } 197 | }) 198 | if (SwiftPusherPlugin.isLoggingEnabled) { 199 | print("Pusher bind (\(bindArgs.eventName))") 200 | } 201 | } 202 | } catch { 203 | if (SwiftPusherPlugin.isLoggingEnabled) { 204 | print("Pusher bind error:" + error.localizedDescription) 205 | } 206 | } 207 | result(nil); 208 | } 209 | 210 | public func unbind(_ call: FlutterMethodCall, result: @escaping FlutterResult) { 211 | do { 212 | let json = call.arguments as! String 213 | let jsonDecoder = JSONDecoder() 214 | let bindArgs = try jsonDecoder.decode(BindArgs.self, from: json.data(using: .utf8)!) 215 | unbindIfBound(channelName: bindArgs.channelName, eventName: bindArgs.eventName) 216 | } catch { 217 | if (SwiftPusherPlugin.isLoggingEnabled) { 218 | print("Pusher unbind error:" + error.localizedDescription) 219 | } 220 | } 221 | result(nil); 222 | } 223 | 224 | private func unbindIfBound(channelName: String, eventName: String) { 225 | let channel = SwiftPusherPlugin.channels[channelName] 226 | if let channelObj = channel { 227 | let callbackId = SwiftPusherPlugin.bindedEvents[channelName + eventName] 228 | if let callbackIdObj = callbackId { 229 | channelObj.unbind(eventName: eventName, callbackId: callbackIdObj) 230 | SwiftPusherPlugin.bindedEvents.removeValue(forKey: channelName + eventName) 231 | 232 | if (SwiftPusherPlugin.isLoggingEnabled) { 233 | print("Pusher unbind") 234 | } 235 | } 236 | } 237 | } 238 | 239 | public func changedConnectionState(from old: ConnectionState, to new: ConnectionState) { 240 | do { 241 | let stateChange = ConnectionStateChange(currentState: new.stringValue(), previousState: old.stringValue()) 242 | let message = PusherEventStreamMessage(event: nil, connectionStateChange: stateChange) 243 | let jsonEncoder = JSONEncoder() 244 | let jsonData = try jsonEncoder.encode(message) 245 | let jsonString = String(data: jsonData, encoding: .utf8) 246 | if let eventSinkObj = SwiftPusherPlugin.eventSink { 247 | eventSinkObj(jsonString) 248 | } 249 | } catch { 250 | if (SwiftPusherPlugin.isLoggingEnabled) { 251 | print("Pusher changedConnectionState error:" + error.localizedDescription) 252 | } 253 | } 254 | } 255 | 256 | public func trigger(_ call: FlutterMethodCall, result: @escaping FlutterResult) { 257 | if (SwiftPusherPlugin.isLoggingEnabled) { 258 | print("Pusher trigger") 259 | } 260 | 261 | do { 262 | let json = call.arguments as! String 263 | let jsonDecoder = JSONDecoder() 264 | let bindArgs = try jsonDecoder.decode(BindArgs.self, from: json.data(using: .utf8)!) 265 | var data: String = ""; 266 | 267 | if let triggerData = bindArgs.data { 268 | data = triggerData 269 | } 270 | 271 | let channel = SwiftPusherPlugin.channels[bindArgs.channelName] 272 | if let channelObj = channel { 273 | let eventName = bindArgs.eventName 274 | 275 | channelObj.trigger(eventName: eventName, data: data) 276 | } 277 | } catch { 278 | if (SwiftPusherPlugin.isLoggingEnabled) { 279 | print("Pusher trigger error:" + error.localizedDescription) 280 | } 281 | } 282 | } 283 | } 284 | 285 | class AuthRequestBuilder: AuthRequestBuilderProtocol { 286 | var endpoint: String 287 | var headers: [String: String] 288 | 289 | init(endpoint: String, headers: [String: String]) { 290 | self.endpoint = endpoint 291 | self.headers = headers 292 | } 293 | 294 | func requestFor(socketID: String, channelName: String) -> URLRequest? { 295 | do{ 296 | var request = URLRequest(url: URL(string: endpoint)!) 297 | request.httpMethod = "POST" 298 | 299 | if (headers.values.contains("application/json")){ 300 | let jsonEncoder = JSONEncoder() 301 | request.httpBody = try jsonEncoder.encode(["socket_id": socketID, "channel_name": channelName]) 302 | } else{ 303 | request.httpBody = "socket_id=\(socketID)&channel_name=\(channelName)".data(using: String.Encoding.utf8) 304 | } 305 | 306 | for (key, value) in headers { 307 | request.addValue(value, forHTTPHeaderField: key) 308 | } 309 | return request 310 | } catch { 311 | if (SwiftPusherPlugin.isLoggingEnabled) { 312 | print("Authentication error:" + error.localizedDescription) 313 | } 314 | return nil 315 | } 316 | 317 | } 318 | } 319 | 320 | class StreamHandler: NSObject, FlutterStreamHandler { 321 | public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { 322 | SwiftPusherPlugin.eventSink = events 323 | return nil; 324 | } 325 | 326 | public func onCancel(withArguments arguments: Any?) -> FlutterError? { 327 | return nil; 328 | } 329 | } 330 | 331 | struct InitArgs: Codable { 332 | var appKey: String 333 | var options: Options 334 | var isLoggingEnabled: Bool 335 | } 336 | 337 | struct Options: Codable { 338 | var cluster: String? 339 | var host: String? 340 | var port: Int? 341 | var encrypted: Bool? 342 | var auth: Auth? 343 | var activityTimeout: Int? 344 | } 345 | 346 | struct Auth: Codable{ 347 | var endpoint: String 348 | var headers: [String: String] 349 | } 350 | 351 | struct PusherEventStreamMessage: Codable { 352 | var event: Event? 353 | var connectionStateChange: ConnectionStateChange? 354 | } 355 | 356 | struct ConnectionStateChange: Codable { 357 | var currentState: String 358 | var previousState: String 359 | } 360 | 361 | struct Event: Codable { 362 | var channel: String 363 | var event: String 364 | var data: String 365 | } 366 | 367 | struct BindArgs: Codable { 368 | var channelName: String 369 | var eventName: String 370 | var data: String? 371 | } 372 | -------------------------------------------------------------------------------- /ios/Classes/UserAgent.h: -------------------------------------------------------------------------------- 1 | // Generated file, do not edit 2 | #define LIBRARY_VERSION @"1.0.3" 3 | #define LIBRARY_NAME @"flutter_pusher" 4 | #define PUSHER_LIBRARY_VERSION @"8.0.0" 5 | -------------------------------------------------------------------------------- /ios/flutter_pusher.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 3 | # 4 | require 'yaml' 5 | pubspec = YAML.load_file(File.join('..', 'pubspec.yaml')) 6 | libraryVersion = pubspec['version'].gsub('+', '-') 7 | pusherLibraryVersion = '8.0.0' 8 | 9 | Pod::Spec.new do |s| 10 | s.name = 'flutter_pusher' 11 | s.version = libraryVersion 12 | s.summary = 'A new flutter plugin project.' 13 | s.description = <<-DESC 14 | A new flutter plugin project. 15 | DESC 16 | s.homepage = 'http://example.com' 17 | s.license = { :file => '../LICENSE' } 18 | s.author = { 'Genert Org' => 'genert.org@indoor.solutions' } 19 | s.source = { :path => '.' } 20 | s.source_files = 'Classes/**/*' 21 | s.public_header_files = 'Classes/**/*.h' 22 | s.dependency 'Flutter' 23 | s.dependency 'PusherSwift', pusherLibraryVersion 24 | 25 | s.ios.deployment_target = '9.0' 26 | 27 | s.prepare_command = <<-CMD 28 | echo // Generated file, do not edit > Classes/UserAgent.h 29 | echo "#define LIBRARY_VERSION @\\"#{libraryVersion}\\"" >> Classes/UserAgent.h 30 | echo "#define LIBRARY_NAME @\\"flutter_pusher\\"" >> Classes/UserAgent.h 31 | echo "#define PUSHER_LIBRARY_VERSION @\\"#{pusherLibraryVersion}\\"" >> Classes/UserAgent.h 32 | CMD 33 | end 34 | 35 | -------------------------------------------------------------------------------- /lib/pusher.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | import 'package:json_annotation/json_annotation.dart'; 3 | import 'dart:convert'; 4 | 5 | part 'pusher.g.dart'; 6 | 7 | enum PusherConnectionState { 8 | connecting, 9 | connected, 10 | disconnecting, 11 | disconnected, 12 | reconnecting, 13 | reconnectingWhenNetworkBecomesReachable 14 | } 15 | 16 | /// Used to listen to events sent through pusher 17 | class Pusher { 18 | Pusher._(); 19 | 20 | static const _channel = 21 | const MethodChannel('plugins.indoor.solutions/pusher'); 22 | static const _eventChannel = 23 | const EventChannel('plugins.indoor.solutions/pusherStream'); 24 | 25 | static void Function(ConnectionStateChange)? _onConnectionStateChange; 26 | static void Function(ConnectionError)? _onError; 27 | 28 | static Map eventCallbacks = 29 | {}; 30 | 31 | /// Setup app key and options 32 | static Future init( 33 | String appKey, 34 | PusherOptions options, { 35 | bool enableLogging = false, 36 | }) async { 37 | _eventChannel.receiveBroadcastStream().listen(_handleEvent); 38 | 39 | final initArgs = jsonEncode(InitArgs( 40 | appKey, 41 | options, 42 | isLoggingEnabled: enableLogging, 43 | ).toJson()); 44 | 45 | await _channel.invokeMethod('init', initArgs); 46 | } 47 | 48 | /// Connect the client to pusher 49 | static Future connect({ 50 | void Function(ConnectionStateChange)? onConnectionStateChange, 51 | void Function(ConnectionError)? onError, 52 | }) async { 53 | _onConnectionStateChange = onConnectionStateChange; 54 | _onError = onError; 55 | await _channel.invokeMethod('connect'); 56 | } 57 | 58 | /// Disconnect the client from pusher 59 | static Future disconnect() async { 60 | await _channel.invokeMethod('disconnect'); 61 | } 62 | 63 | /// Subscribe to a channel 64 | /// Use the returned [Channel] to bind events 65 | static Future subscribe(String channelName) async { 66 | await _channel.invokeMethod('subscribe', channelName); 67 | return Channel(name: channelName); 68 | } 69 | 70 | /// Unsubscribe from a channel 71 | static Future unsubscribe(String channelName) async { 72 | await _channel.invokeMethod('unsubscribe', channelName); 73 | } 74 | 75 | static Future _trigger( 76 | String channelName, String eventName, String data) async { 77 | final bindArgs = jsonEncode(BindArgs( 78 | channelName: channelName, 79 | eventName: eventName, 80 | data: data, 81 | ).toJson()); 82 | 83 | await _channel.invokeMethod('trigger', bindArgs); 84 | } 85 | 86 | static Future _bind( 87 | String channelName, 88 | String eventName, { 89 | void Function(Event)? onEvent, 90 | }) async { 91 | final bindArgs = jsonEncode(BindArgs( 92 | channelName: channelName, 93 | eventName: eventName, 94 | ).toJson()); 95 | 96 | eventCallbacks[channelName + eventName] = onEvent; 97 | await _channel.invokeMethod('bind', bindArgs); 98 | } 99 | 100 | static Future _unbind(String channelName, String eventName) async { 101 | final bindArgs = jsonEncode(BindArgs( 102 | channelName: channelName, 103 | eventName: eventName, 104 | ).toJson()); 105 | 106 | eventCallbacks.remove(channelName + eventName); 107 | await _channel.invokeMethod('unbind', bindArgs); 108 | } 109 | 110 | static void _handleEvent([dynamic arguments]) { 111 | var message = PusherEventStreamMessage.fromJson(jsonDecode(arguments)); 112 | 113 | if (message.isEvent) { 114 | var callback = 115 | eventCallbacks[message.event!.channel + message.event!.event]; 116 | if (callback != null) { 117 | callback(message.event!); 118 | } 119 | } else if (message.isConnectionStateChange) { 120 | if (_onConnectionStateChange != null) { 121 | _onConnectionStateChange!(message.connectionStateChange!); 122 | } 123 | } else if (message.isConnectionError) { 124 | if (_onError != null) { 125 | _onError!(message.connectionError!); 126 | } 127 | } 128 | } 129 | } 130 | 131 | @JsonSerializable() 132 | class InitArgs { 133 | final String appKey; 134 | final PusherOptions options; 135 | final bool isLoggingEnabled; 136 | 137 | InitArgs(this.appKey, this.options, {this.isLoggingEnabled = false}); 138 | 139 | factory InitArgs.fromJson(Map json) => 140 | _$InitArgsFromJson(json); 141 | 142 | Map toJson() => _$InitArgsToJson(this); 143 | } 144 | 145 | @JsonSerializable() 146 | class BindArgs { 147 | final String channelName; 148 | final String eventName; 149 | final String? data; 150 | 151 | BindArgs({ 152 | required this.channelName, 153 | required this.eventName, 154 | this.data, 155 | }); 156 | 157 | factory BindArgs.fromJson(Map json) => 158 | _$BindArgsFromJson(json); 159 | 160 | Map toJson() => _$BindArgsToJson(this); 161 | } 162 | 163 | @JsonSerializable(includeIfNull: false) 164 | class PusherOptions { 165 | final PusherAuth? auth; 166 | final String? cluster; 167 | final String? host; 168 | final int port; 169 | final bool encrypted; 170 | final int activityTimeout; 171 | 172 | PusherOptions({ 173 | this.auth, 174 | this.cluster, 175 | this.host, 176 | this.port = 443, 177 | this.encrypted = true, 178 | this.activityTimeout = 30000, 179 | }); 180 | 181 | factory PusherOptions.fromJson(Map json) => 182 | _$PusherOptionsFromJson(json); 183 | 184 | Map toJson() => _$PusherOptionsToJson(this); 185 | } 186 | 187 | @JsonSerializable() 188 | class PusherAuth { 189 | final String endpoint; 190 | final Map? headers; 191 | 192 | PusherAuth( 193 | this.endpoint, { 194 | this.headers = const {'Content-Type': 'application/x-www-form-urlencoded'}, 195 | }); 196 | 197 | factory PusherAuth.fromJson(Map json) => 198 | _$PusherAuthFromJson(json); 199 | 200 | Map toJson() => _$PusherAuthToJson(this); 201 | } 202 | 203 | @JsonSerializable() 204 | class ConnectionStateChange { 205 | final String currentState; 206 | final String previousState; 207 | 208 | ConnectionStateChange({ 209 | required this.currentState, 210 | required this.previousState, 211 | }); 212 | 213 | factory ConnectionStateChange.fromJson(Map json) => 214 | _$ConnectionStateChangeFromJson(json); 215 | 216 | Map toJson() => _$ConnectionStateChangeToJson(this); 217 | } 218 | 219 | @JsonSerializable() 220 | class ConnectionError { 221 | final String message; 222 | final String code; 223 | final String exception; 224 | 225 | ConnectionError({ 226 | required this.message, 227 | required this.code, 228 | required this.exception, 229 | }); 230 | 231 | factory ConnectionError.fromJson(Map json) => 232 | _$ConnectionErrorFromJson(json); 233 | 234 | Map toJson() => _$ConnectionErrorToJson(this); 235 | } 236 | 237 | @JsonSerializable() 238 | class Event { 239 | final String channel; 240 | final String event; 241 | final String? data; 242 | 243 | Event({ 244 | required this.channel, 245 | required this.event, 246 | this.data, 247 | }); 248 | 249 | factory Event.fromJson(Map json) => _$EventFromJson(json); 250 | 251 | Map toJson() => _$EventToJson(this); 252 | } 253 | 254 | class Channel { 255 | final String name; 256 | 257 | Channel({required this.name}); 258 | 259 | /// Bind to listen for events sent on the given channel 260 | Future bind(String eventName, void Function(Event) onEvent) async { 261 | await Pusher._bind(name, eventName, onEvent: onEvent); 262 | } 263 | 264 | Future unbind(String eventName) async { 265 | await Pusher._unbind(name, eventName); 266 | } 267 | 268 | /// Trigger [eventName] (will be prefixed with "client-" in case you have not) for [Channel]. 269 | /// 270 | /// Client events can only be triggered on private and presence channels because they require authentication 271 | /// You can only trigger a client event once a subscription has been successfully registered with Channels. 272 | Future trigger(String eventName, {String? data}) async { 273 | if (!eventName.startsWith('client-')) { 274 | eventName = "client-$eventName"; 275 | } 276 | 277 | await Pusher._trigger(name, eventName, data ?? "{}"); 278 | } 279 | } 280 | 281 | @JsonSerializable() 282 | class PusherEventStreamMessage { 283 | final Event? event; 284 | final ConnectionStateChange? connectionStateChange; 285 | final ConnectionError? connectionError; 286 | 287 | bool get isEvent => event != null; 288 | 289 | bool get isConnectionStateChange => connectionStateChange != null; 290 | 291 | bool get isConnectionError => connectionError != null; 292 | 293 | PusherEventStreamMessage({ 294 | this.event, 295 | this.connectionStateChange, 296 | this.connectionError, 297 | }); 298 | 299 | factory PusherEventStreamMessage.fromJson(Map json) => 300 | _$PusherEventStreamMessageFromJson(json); 301 | 302 | Map toJson() => _$PusherEventStreamMessageToJson(this); 303 | } 304 | -------------------------------------------------------------------------------- /lib/pusher.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'pusher.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | InitArgs _$InitArgsFromJson(Map json) { 10 | return InitArgs( 11 | json['appKey'] as String, 12 | PusherOptions.fromJson(json['options'] as Map), 13 | isLoggingEnabled: json['isLoggingEnabled'] as bool, 14 | ); 15 | } 16 | 17 | Map _$InitArgsToJson(InitArgs instance) => { 18 | 'appKey': instance.appKey, 19 | 'options': instance.options, 20 | 'isLoggingEnabled': instance.isLoggingEnabled, 21 | }; 22 | 23 | BindArgs _$BindArgsFromJson(Map json) { 24 | return BindArgs( 25 | channelName: json['channelName'] as String, 26 | eventName: json['eventName'] as String, 27 | data: json['data'] as String, 28 | ); 29 | } 30 | 31 | Map _$BindArgsToJson(BindArgs instance) => { 32 | 'channelName': instance.channelName, 33 | 'eventName': instance.eventName, 34 | 'data': instance.data, 35 | }; 36 | 37 | PusherOptions _$PusherOptionsFromJson(Map json) { 38 | return PusherOptions( 39 | auth: json['auth'] == null 40 | ? null 41 | : PusherAuth.fromJson(json['auth'] as Map), 42 | cluster: json['cluster'] as String, 43 | host: json['host'] as String, 44 | port: json['port'] as int, 45 | encrypted: json['encrypted'] as bool, 46 | activityTimeout: json['activityTimeout'] as int, 47 | ); 48 | } 49 | 50 | Map _$PusherOptionsToJson(PusherOptions instance) { 51 | final val = {}; 52 | 53 | void writeNotNull(String key, dynamic value) { 54 | if (value != null) { 55 | val[key] = value; 56 | } 57 | } 58 | 59 | writeNotNull('auth', instance.auth); 60 | writeNotNull('cluster', instance.cluster); 61 | writeNotNull('host', instance.host); 62 | writeNotNull('port', instance.port); 63 | writeNotNull('encrypted', instance.encrypted); 64 | writeNotNull('activityTimeout', instance.activityTimeout); 65 | return val; 66 | } 67 | 68 | PusherAuth _$PusherAuthFromJson(Map json) { 69 | return PusherAuth( 70 | json['endpoint'] as String, 71 | headers: (json['headers'] as Map).map( 72 | (k, e) => MapEntry(k, e as String), 73 | ), 74 | ); 75 | } 76 | 77 | Map _$PusherAuthToJson(PusherAuth instance) => 78 | { 79 | 'endpoint': instance.endpoint, 80 | 'headers': instance.headers, 81 | }; 82 | 83 | ConnectionStateChange _$ConnectionStateChangeFromJson( 84 | Map json) { 85 | return ConnectionStateChange( 86 | currentState: json['currentState'] as String, 87 | previousState: json['previousState'] as String, 88 | ); 89 | } 90 | 91 | Map _$ConnectionStateChangeToJson( 92 | ConnectionStateChange instance) => 93 | { 94 | 'currentState': instance.currentState, 95 | 'previousState': instance.previousState, 96 | }; 97 | 98 | ConnectionError _$ConnectionErrorFromJson(Map json) { 99 | return ConnectionError( 100 | message: json['message'] as String, 101 | code: json['code'] as String, 102 | exception: json['exception'] as String, 103 | ); 104 | } 105 | 106 | Map _$ConnectionErrorToJson(ConnectionError instance) => 107 | { 108 | 'message': instance.message, 109 | 'code': instance.code, 110 | 'exception': instance.exception, 111 | }; 112 | 113 | Event _$EventFromJson(Map json) { 114 | return Event( 115 | channel: json['channel'] as String, 116 | event: json['event'] as String, 117 | data: json['data'] as String, 118 | ); 119 | } 120 | 121 | Map _$EventToJson(Event instance) => { 122 | 'channel': instance.channel, 123 | 'event': instance.event, 124 | 'data': instance.data, 125 | }; 126 | 127 | PusherEventStreamMessage _$PusherEventStreamMessageFromJson( 128 | Map json) { 129 | return PusherEventStreamMessage( 130 | event: json['event'] == null 131 | ? null 132 | : Event.fromJson(json['event'] as Map), 133 | connectionStateChange: json['connectionStateChange'] == null 134 | ? null 135 | : ConnectionStateChange.fromJson( 136 | json['connectionStateChange'] as Map), 137 | connectionError: json['connectionError'] == null 138 | ? null 139 | : ConnectionError.fromJson( 140 | json['connectionError'] as Map), 141 | ); 142 | } 143 | 144 | Map _$PusherEventStreamMessageToJson( 145 | PusherEventStreamMessage instance) => 146 | { 147 | 'event': instance.event, 148 | 'connectionStateChange': instance.connectionStateChange, 149 | 'connectionError': instance.connectionError, 150 | }; 151 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | _fe_analyzer_shared: 5 | dependency: transitive 6 | description: 7 | name: _fe_analyzer_shared 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "19.0.0" 11 | analyzer: 12 | dependency: transitive 13 | description: 14 | name: analyzer 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "1.3.0" 18 | args: 19 | dependency: transitive 20 | description: 21 | name: args 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.0.0" 25 | async: 26 | dependency: transitive 27 | description: 28 | name: async 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "2.5.0" 32 | boolean_selector: 33 | dependency: transitive 34 | description: 35 | name: boolean_selector 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "2.1.0" 39 | build: 40 | dependency: transitive 41 | description: 42 | name: build 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "2.0.0" 46 | build_config: 47 | dependency: transitive 48 | description: 49 | name: build_config 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "0.4.7" 53 | build_daemon: 54 | dependency: transitive 55 | description: 56 | name: build_daemon 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "2.1.10" 60 | build_resolvers: 61 | dependency: transitive 62 | description: 63 | name: build_resolvers 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "2.0.0" 67 | build_runner: 68 | dependency: "direct dev" 69 | description: 70 | name: build_runner 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "1.12.2" 74 | build_runner_core: 75 | dependency: transitive 76 | description: 77 | name: build_runner_core 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "6.1.12" 81 | built_collection: 82 | dependency: transitive 83 | description: 84 | name: built_collection 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "5.0.0" 88 | built_value: 89 | dependency: transitive 90 | description: 91 | name: built_value 92 | url: "https://pub.dartlang.org" 93 | source: hosted 94 | version: "8.0.4" 95 | characters: 96 | dependency: transitive 97 | description: 98 | name: characters 99 | url: "https://pub.dartlang.org" 100 | source: hosted 101 | version: "1.1.0" 102 | charcode: 103 | dependency: transitive 104 | description: 105 | name: charcode 106 | url: "https://pub.dartlang.org" 107 | source: hosted 108 | version: "1.2.0" 109 | checked_yaml: 110 | dependency: transitive 111 | description: 112 | name: checked_yaml 113 | url: "https://pub.dartlang.org" 114 | source: hosted 115 | version: "2.0.1" 116 | cli_util: 117 | dependency: transitive 118 | description: 119 | name: cli_util 120 | url: "https://pub.dartlang.org" 121 | source: hosted 122 | version: "0.3.0" 123 | clock: 124 | dependency: transitive 125 | description: 126 | name: clock 127 | url: "https://pub.dartlang.org" 128 | source: hosted 129 | version: "1.1.0" 130 | code_builder: 131 | dependency: transitive 132 | description: 133 | name: code_builder 134 | url: "https://pub.dartlang.org" 135 | source: hosted 136 | version: "3.7.0" 137 | collection: 138 | dependency: transitive 139 | description: 140 | name: collection 141 | url: "https://pub.dartlang.org" 142 | source: hosted 143 | version: "1.15.0" 144 | convert: 145 | dependency: transitive 146 | description: 147 | name: convert 148 | url: "https://pub.dartlang.org" 149 | source: hosted 150 | version: "3.0.0" 151 | crypto: 152 | dependency: transitive 153 | description: 154 | name: crypto 155 | url: "https://pub.dartlang.org" 156 | source: hosted 157 | version: "3.0.1" 158 | dart_style: 159 | dependency: transitive 160 | description: 161 | name: dart_style 162 | url: "https://pub.dartlang.org" 163 | source: hosted 164 | version: "2.0.0" 165 | fake_async: 166 | dependency: transitive 167 | description: 168 | name: fake_async 169 | url: "https://pub.dartlang.org" 170 | source: hosted 171 | version: "1.2.0" 172 | file: 173 | dependency: transitive 174 | description: 175 | name: file 176 | url: "https://pub.dartlang.org" 177 | source: hosted 178 | version: "6.1.0" 179 | fixnum: 180 | dependency: transitive 181 | description: 182 | name: fixnum 183 | url: "https://pub.dartlang.org" 184 | source: hosted 185 | version: "1.0.0" 186 | flutter: 187 | dependency: "direct main" 188 | description: flutter 189 | source: sdk 190 | version: "0.0.0" 191 | flutter_test: 192 | dependency: "direct dev" 193 | description: flutter 194 | source: sdk 195 | version: "0.0.0" 196 | glob: 197 | dependency: transitive 198 | description: 199 | name: glob 200 | url: "https://pub.dartlang.org" 201 | source: hosted 202 | version: "2.0.1" 203 | graphs: 204 | dependency: transitive 205 | description: 206 | name: graphs 207 | url: "https://pub.dartlang.org" 208 | source: hosted 209 | version: "1.0.0" 210 | http_multi_server: 211 | dependency: transitive 212 | description: 213 | name: http_multi_server 214 | url: "https://pub.dartlang.org" 215 | source: hosted 216 | version: "3.0.0" 217 | http_parser: 218 | dependency: transitive 219 | description: 220 | name: http_parser 221 | url: "https://pub.dartlang.org" 222 | source: hosted 223 | version: "4.0.0" 224 | io: 225 | dependency: transitive 226 | description: 227 | name: io 228 | url: "https://pub.dartlang.org" 229 | source: hosted 230 | version: "1.0.0" 231 | js: 232 | dependency: transitive 233 | description: 234 | name: js 235 | url: "https://pub.dartlang.org" 236 | source: hosted 237 | version: "0.6.3" 238 | json_annotation: 239 | dependency: "direct main" 240 | description: 241 | name: json_annotation 242 | url: "https://pub.dartlang.org" 243 | source: hosted 244 | version: "4.0.1" 245 | json_serializable: 246 | dependency: "direct dev" 247 | description: 248 | name: json_serializable 249 | url: "https://pub.dartlang.org" 250 | source: hosted 251 | version: "4.1.0" 252 | logging: 253 | dependency: transitive 254 | description: 255 | name: logging 256 | url: "https://pub.dartlang.org" 257 | source: hosted 258 | version: "1.0.1" 259 | matcher: 260 | dependency: transitive 261 | description: 262 | name: matcher 263 | url: "https://pub.dartlang.org" 264 | source: hosted 265 | version: "0.12.10" 266 | meta: 267 | dependency: transitive 268 | description: 269 | name: meta 270 | url: "https://pub.dartlang.org" 271 | source: hosted 272 | version: "1.3.0" 273 | mime: 274 | dependency: transitive 275 | description: 276 | name: mime 277 | url: "https://pub.dartlang.org" 278 | source: hosted 279 | version: "1.0.0" 280 | package_config: 281 | dependency: transitive 282 | description: 283 | name: package_config 284 | url: "https://pub.dartlang.org" 285 | source: hosted 286 | version: "2.0.0" 287 | path: 288 | dependency: transitive 289 | description: 290 | name: path 291 | url: "https://pub.dartlang.org" 292 | source: hosted 293 | version: "1.8.0" 294 | pedantic: 295 | dependency: transitive 296 | description: 297 | name: pedantic 298 | url: "https://pub.dartlang.org" 299 | source: hosted 300 | version: "1.11.0" 301 | pool: 302 | dependency: transitive 303 | description: 304 | name: pool 305 | url: "https://pub.dartlang.org" 306 | source: hosted 307 | version: "1.5.0" 308 | pub_semver: 309 | dependency: transitive 310 | description: 311 | name: pub_semver 312 | url: "https://pub.dartlang.org" 313 | source: hosted 314 | version: "2.0.0" 315 | pubspec_parse: 316 | dependency: transitive 317 | description: 318 | name: pubspec_parse 319 | url: "https://pub.dartlang.org" 320 | source: hosted 321 | version: "1.0.0" 322 | shelf: 323 | dependency: transitive 324 | description: 325 | name: shelf 326 | url: "https://pub.dartlang.org" 327 | source: hosted 328 | version: "1.1.0" 329 | shelf_web_socket: 330 | dependency: transitive 331 | description: 332 | name: shelf_web_socket 333 | url: "https://pub.dartlang.org" 334 | source: hosted 335 | version: "1.0.1" 336 | sky_engine: 337 | dependency: transitive 338 | description: flutter 339 | source: sdk 340 | version: "0.0.99" 341 | source_gen: 342 | dependency: transitive 343 | description: 344 | name: source_gen 345 | url: "https://pub.dartlang.org" 346 | source: hosted 347 | version: "1.0.0" 348 | source_span: 349 | dependency: transitive 350 | description: 351 | name: source_span 352 | url: "https://pub.dartlang.org" 353 | source: hosted 354 | version: "1.8.0" 355 | stack_trace: 356 | dependency: transitive 357 | description: 358 | name: stack_trace 359 | url: "https://pub.dartlang.org" 360 | source: hosted 361 | version: "1.10.0" 362 | stream_channel: 363 | dependency: transitive 364 | description: 365 | name: stream_channel 366 | url: "https://pub.dartlang.org" 367 | source: hosted 368 | version: "2.1.0" 369 | stream_transform: 370 | dependency: transitive 371 | description: 372 | name: stream_transform 373 | url: "https://pub.dartlang.org" 374 | source: hosted 375 | version: "2.0.0" 376 | string_scanner: 377 | dependency: transitive 378 | description: 379 | name: string_scanner 380 | url: "https://pub.dartlang.org" 381 | source: hosted 382 | version: "1.1.0" 383 | term_glyph: 384 | dependency: transitive 385 | description: 386 | name: term_glyph 387 | url: "https://pub.dartlang.org" 388 | source: hosted 389 | version: "1.2.0" 390 | test_api: 391 | dependency: transitive 392 | description: 393 | name: test_api 394 | url: "https://pub.dartlang.org" 395 | source: hosted 396 | version: "0.2.19" 397 | timing: 398 | dependency: transitive 399 | description: 400 | name: timing 401 | url: "https://pub.dartlang.org" 402 | source: hosted 403 | version: "1.0.0" 404 | typed_data: 405 | dependency: transitive 406 | description: 407 | name: typed_data 408 | url: "https://pub.dartlang.org" 409 | source: hosted 410 | version: "1.3.0" 411 | vector_math: 412 | dependency: transitive 413 | description: 414 | name: vector_math 415 | url: "https://pub.dartlang.org" 416 | source: hosted 417 | version: "2.1.0" 418 | watcher: 419 | dependency: transitive 420 | description: 421 | name: watcher 422 | url: "https://pub.dartlang.org" 423 | source: hosted 424 | version: "1.0.0" 425 | web_socket_channel: 426 | dependency: transitive 427 | description: 428 | name: web_socket_channel 429 | url: "https://pub.dartlang.org" 430 | source: hosted 431 | version: "2.0.0" 432 | yaml: 433 | dependency: transitive 434 | description: 435 | name: yaml 436 | url: "https://pub.dartlang.org" 437 | source: hosted 438 | version: "3.1.0" 439 | sdks: 440 | dart: ">=2.12.0 <3.0.0" 441 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_pusher 2 | description: A Flutter plugin to listen to events sent through pusher. Wraps the native Java and Swift libraries. 3 | version: 2.0.0-nullsafety.0 4 | author: Indoor Solutions 5 | homepage: https://github.com/ninjasolutions/flutter_pusher 6 | 7 | environment: 8 | sdk: ">=2.12.0 <3.0.0" 9 | 10 | dependencies: 11 | json_annotation: ^4.0.1 12 | flutter: 13 | sdk: flutter 14 | 15 | dev_dependencies: 16 | build_runner: ^1.5.2 17 | json_serializable: ^4.1.0 18 | flutter_test: 19 | sdk: flutter 20 | 21 | flutter: 22 | # This section identifies this Flutter project as a plugin project. 23 | # The androidPackage and pluginClass identifiers should not ordinarily 24 | # be modified. They are used by the tooling to maintain consistency when 25 | # adding or updating assets for this project. 26 | plugin: 27 | androidPackage: com.ninjasolutions.pusher 28 | pluginClass: PusherPlugin 29 | -------------------------------------------------------------------------------- /test/pusher_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | 4 | void main() { 5 | const MethodChannel channel = MethodChannel('pusher'); 6 | 7 | setUp(() { 8 | channel.setMockMethodCallHandler((MethodCall methodCall) async { 9 | return '42'; 10 | }); 11 | }); 12 | 13 | tearDown(() { 14 | channel.setMockMethodCallHandler(null); 15 | }); 16 | 17 | test('getPlatformVersion', () async { 18 | //expect(await Pusher.platformVersion, '42'); 19 | }); 20 | } 21 | --------------------------------------------------------------------------------