├── .github ├── ISSUE_TEMPLATE │ ├── ask-question.yml │ ├── bug-report.yml │ └── general-feedback.yml ├── os_probot_metadata.js ├── pull_request_template.md ├── release-drafter.yml ├── set_response_times.js └── workflows │ ├── Zapier.yml │ ├── ci.yml │ ├── project.yml │ ├── release-drafter.yml │ └── set_response_time.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── MIGRATION_GUIDE.md ├── README.md ├── android ├── .gitignore ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── onesignal │ └── flutter │ ├── FlutterMessengerResponder.java │ ├── OneSignalDebug.java │ ├── OneSignalInAppMessages.java │ ├── OneSignalLocation.java │ ├── OneSignalNotifications.java │ ├── OneSignalPlugin.java │ ├── OneSignalPushSubscription.java │ ├── OneSignalSerializer.java │ ├── OneSignalSession.java │ └── OneSignalUser.java ├── example ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── onesignal │ │ │ │ └── onesignalexample │ │ │ │ └── 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 │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── ios │ ├── .gitignore │ ├── ExampleWidget │ │ ├── Assets.xcassets │ │ │ ├── AccentColor.colorset │ │ │ │ └── Contents.json │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ ├── WidgetBackground.colorset │ │ │ │ └── Contents.json │ │ │ └── onesignaldemo.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── onesignal-logo.png │ │ ├── ExampleWidgetBundle.swift │ │ ├── ExampleWidgetLiveActivity.swift │ │ └── Info.plist │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ ├── Flutter.podspec │ │ └── Release.xcconfig │ ├── OneSignalNotificationServiceExtension │ │ ├── Info.plist │ │ ├── NotificationService.h │ │ ├── NotificationService.m │ │ └── OneSignalNotificationServiceExtension.entitlements │ ├── Podfile │ ├── Podfile.lock │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── Runner │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── 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.entitlements │ │ └── main.m ├── lib │ └── main.dart └── pubspec.yaml ├── ios ├── .gitignore ├── Assets │ └── .gitkeep ├── Classes │ ├── OSFlutterCategories.h │ ├── OSFlutterCategories.m │ ├── OSFlutterDebug.h │ ├── OSFlutterDebug.m │ ├── OSFlutterInAppMessages.h │ ├── OSFlutterInAppMessages.m │ ├── OSFlutterLiveActivities.h │ ├── OSFlutterLiveActivities.m │ ├── OSFlutterLocation.h │ ├── OSFlutterLocation.m │ ├── OSFlutterNotifications.h │ ├── OSFlutterNotifications.m │ ├── OSFlutterPushSubscription.h │ ├── OSFlutterPushSubscription.m │ ├── OSFlutterSession.h │ ├── OSFlutterSession.m │ ├── OSFlutterUser.h │ ├── OSFlutterUser.m │ ├── OneSignalPlugin.h │ └── OneSignalPlugin.m └── onesignal_flutter.podspec ├── lib ├── onesignal_flutter.dart └── src │ ├── debug.dart │ ├── defines.dart │ ├── inappmessage.dart │ ├── inappmessages.dart │ ├── liveactivities.dart │ ├── location.dart │ ├── notification.dart │ ├── notifications.dart │ ├── permission.dart │ ├── pushsubscription.dart │ ├── session.dart │ ├── subscription.dart │ ├── user.dart │ └── utils.dart ├── pubspec.yaml ├── test.json └── test ├── mock_channel.dart └── onesignalflutter_test.dart /.github/ISSUE_TEMPLATE/ask-question.yml: -------------------------------------------------------------------------------- 1 | name: 🙋‍♂️ Ask a question 2 | description: Tell us what's on your mind 3 | title: "[question]: " 4 | labels: ["Question"] 5 | 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: | 10 | Having issues integrating this SDK? 11 | - type: textarea 12 | id: question 13 | attributes: 14 | label: How can we help? 15 | description: Specific question regarding integrating this SDK. 16 | placeholder: How do I...? 17 | validations: 18 | required: true 19 | - type: checkboxes 20 | id: terms 21 | attributes: 22 | label: Code of Conduct 23 | description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/OneSignal/OneSignal-Flutter-SDK/blob/main/CONTRIBUTING.md) 24 | options: 25 | - label: I agree to follow this project's Code of Conduct 26 | required: true 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.yml: -------------------------------------------------------------------------------- 1 | name: 🪳 Bug report 2 | description: File a bug report 3 | title: "[Bug]: " 4 | labels: ["Bug"] 5 | 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: | 10 | Thanks for taking the time to fill out this bug report! 11 | - type: textarea 12 | id: what-happened 13 | attributes: 14 | label: What happened? 15 | description: Provide a thorough description of whats going on. 16 | placeholder: e.g. The latest version of the SDK causes my screen to go blank when I tap on the screen three times. 17 | validations: 18 | required: true 19 | - type: textarea 20 | id: reproduction-steps 21 | attributes: 22 | label: Steps to reproduce? 23 | description: Provide as much detail as posible to reproduce the issue. 24 | placeholder: | 25 | 1. Install vX.Y.Z of dependency 26 | 2. Launch the app on iOS device 27 | 3. Tap the screen three times 28 | 4. Note that the app crashes 29 | render: Markdown 30 | validations: 31 | required: true 32 | - type: textarea 33 | id: what-are-expectations 34 | attributes: 35 | label: What did you expect to happen? 36 | description: Also tell us, what did you expect to happen? 37 | placeholder: I expected the app to continue running no matter how many times I tap the screen. 38 | validations: 39 | required: true 40 | - type: input 41 | id: flutter-sdk-version 42 | attributes: 43 | label: OneSignal Flutter SDK version 44 | description: What version of the OneSignal Flutter SDK are you using? 45 | placeholder: Release 3.4.1 46 | validations: 47 | required: true 48 | - type: checkboxes 49 | id: platforms 50 | attributes: 51 | label: Which platform(s) are affected? 52 | description: Indicate which mobile platforms this issue is affecting 53 | options: 54 | - label: iOS 55 | required: false 56 | - label: Android 57 | required: false 58 | - type: textarea 59 | id: logs 60 | attributes: 61 | label: Relevant log output 62 | description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. 63 | render: Shell 64 | - type: checkboxes 65 | id: terms 66 | attributes: 67 | label: Code of Conduct 68 | description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/OneSignal/OneSignal-Flutter-SDK/blob/main/CONTRIBUTING.md) 69 | options: 70 | - label: I agree to follow this project's Code of Conduct 71 | required: true 72 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/general-feedback.yml: -------------------------------------------------------------------------------- 1 | name: 📣 General feedback 2 | description: Tell us what's on your mind 3 | title: "[Feedback]: " 4 | labels: ["Feedback"] 5 | 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: | 10 | Thanks for sharing your valuable feedback! 11 | - type: textarea 12 | id: feedback 13 | attributes: 14 | label: What's on your mind? 15 | description: Feedback regarding this SDK. 16 | placeholder: Share your feedback... 17 | validations: 18 | required: true 19 | - type: checkboxes 20 | id: terms 21 | attributes: 22 | label: Code of Conduct 23 | description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/OneSignal/OneSignal-Flutter-SDK/blob/main/CONTRIBUTING.md) 24 | options: 25 | - label: I agree to follow this project's Code of Conduct 26 | required: true 27 | -------------------------------------------------------------------------------- /.github/os_probot_metadata.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Based on probot-metadata - https://github.com/probot/metadata 3 | */ 4 | const regex = /\n\n/ 5 | 6 | const { Octokit } = require("@octokit/action") 7 | 8 | const octokit = new Octokit() 9 | 10 | module.exports = (context, issue = null) => { 11 | console.log(context) 12 | const prefix = "onesignal-probot" 13 | 14 | if (!issue) issue = context.payload.issue 15 | 16 | return { 17 | async get (key = null) { 18 | let body = issue.body 19 | 20 | if (!body) { 21 | body = (await octokit.issues.get(issue)).data.body || '' 22 | } 23 | 24 | const match = body.match(regex) 25 | 26 | if (match) { 27 | const data = JSON.parse(match[1])[prefix] 28 | return key ? data && data[key] : data 29 | } 30 | }, 31 | 32 | async set (key, value) { 33 | let body = issue.body 34 | let data = {} 35 | 36 | if (!body) body = (await octokit.issues.get(issue)).data.body || '' 37 | 38 | body = body.replace(regex, (_, json) => { 39 | data = JSON.parse(json) 40 | return '' 41 | }) 42 | 43 | if (!data[prefix]) data[prefix] = {} 44 | 45 | if (typeof key === 'object') { 46 | Object.assign(data[prefix], key) 47 | } else { 48 | data[prefix][key] = value 49 | } 50 | 51 | body = `${body}\n\n` 52 | 53 | const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/") 54 | const issue_number = context.payload.issue.number 55 | return octokit.issues.update({ owner, repo, issue_number, body }) 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 2 | # READ AND DELETE THIS SECTION BEFORE SUBMITTING PR 3 | * **Fill out each _REQUIRED_ section** 4 | * **Fill out _OPTIONAL_ sections, remove section if it doesn't apply to your PR** 5 | * **Read and fill out each of the checklists below** 6 | * **Remove this section after reading** 7 | 8 | 9 | # Description 10 | ## One Line Summary 11 | **REQUIRED** - Very short description that summaries the changes in this PR. 12 | 13 | ## Details 14 | 15 | ### Motivation 16 | **REQUIRED -** Why is this code change being made? Or what is the goal of this PR? Examples: Fixes a specific bug, provides additional logging to debug future issues, feature to allow X. 17 | 18 | ### Scope 19 | **RECOMMEND - OPTIONAL -** What is intended to be effected. What is known not to change. Example: Notifications are grouped when parameter X is set, not enabled by default. 20 | 21 | ### OPTIONAL - Other 22 | **OPTIONAL -** Feel free to add any other sections or sub-sections that can explain your PR better. 23 | 24 | # Testing 25 | ## Unit testing 26 | **OPTIONAL -** Explain unit tests added, if not clear in the code. 27 | 28 | ## Manual testing 29 | **RECOMMEND - OPTIONAL -** Explain what scenarios were tested and the environment. 30 | Example: Tested opening a notification while the app was foregrounded, app build with Android Studio 2020.3 with a fresh install of the OneSignal example app on a Pixel 6 with Android 12. 31 | 32 | # Affected code checklist 33 | - [ ] Notifications 34 | - [ ] Display 35 | - [ ] Open 36 | - [ ] Push Processing 37 | - [ ] Confirm Deliveries 38 | - [ ] Outcomes 39 | - [ ] Sessions 40 | - [ ] In-App Messaging 41 | - [ ] REST API requests 42 | - [ ] Public API changes 43 | 44 | # Checklist 45 | ## Overview 46 | - [ ] I have filled out all **REQUIRED** sections above 47 | - [ ] PR does one thing 48 | - If it is hard to explain how any codes changes are related to each other then it most likely needs to be more than one PR 49 | - [ ] Any Public API changes are explained in the PR details and conform to existing APIs 50 | 51 | ## Testing 52 | - [ ] I have included test coverage for these changes, or explained why they are not needed 53 | - [ ] All automated tests pass, or I explained why that is not possible 54 | - [ ] I have personally tested this on my device, or explained why that is not possible 55 | 56 | ## Final pass 57 | - [ ] Code is as readable as possible. 58 | - Simplify with less code, followed by splitting up code into well named functions and variables, followed by adding comments to the code. 59 | - [ ] I have reviewed this PR myself, ensuring it meets each checklist item 60 | - WIP (Work In Progress) is ok, but explain what is still in progress and what you would like feedback on. Start the PR title with "WIP" to indicate this. -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name-template: $RESOLVED_VERSION 2 | tag-template: $RESOLVED_VERSION 3 | categories: 4 | - title: 🚀 Features 5 | label: Enhancement / Feature 6 | - title: 🐛 Bug Fixes 7 | label: Bug 8 | - title: 🧰 Improvements 9 | label: Improvement 10 | - title: down arrow Dependency Updates 11 | label: Dependencies 12 | change-template: '- $TITLE (#$NUMBER)' 13 | version-resolver: 14 | major: 15 | labels: 16 | - 'major' 17 | minor: 18 | labels: 19 | - 'minor' 20 | patch: 21 | labels: 22 | - 'patch' 23 | default: patch 24 | template: | 25 | ## Other Changes 26 | 27 | $CHANGES 28 | -------------------------------------------------------------------------------- /.github/set_response_times.js: -------------------------------------------------------------------------------- 1 | function calcResponseTimeForIssueCreatedAt(createdAt) { 2 | const issueOpenedDate = new Date(createdAt); 3 | const issueTriagedDate = new Date(); 4 | const businessDaysResponseTime = calcBusinessDaysBetweenDates(issueOpenedDate, issueTriagedDate); 5 | return businessDaysResponseTime; 6 | } 7 | 8 | function calcBusinessDaysBetweenDates(openedDate, triagedDate) { 9 | let differenceInWeeks, responseTime; 10 | if (triagedDate < openedDate) 11 | return -1; // error code if dates transposed 12 | let openedDay = openedDate.getDay(); // day of week 13 | let triagedDay = triagedDate.getDay(); 14 | openedDay = (openedDay == 0) ? 7 : openedDay; // change Sunday from 0 to 7 15 | triagedDay = (triagedDay == 0) ? 7 : triagedDay; 16 | openedDay = (openedDay > 5) ? 5 : openedDay; // only count weekdays 17 | triagedDay = (triagedDay > 5) ? 5 : triagedDay; 18 | // calculate differnece in weeks (1000mS * 60sec * 60min * 24hrs * 7 days = 604800000) 19 | differenceInWeeks = Math.floor((triagedDate.getTime() - openedDate.getTime()) / 604800000); 20 | if (openedDay < triagedDay) { //Equal to makes it reduce 5 days 21 | responseTime = (differenceInWeeks * 5) + (triagedDay - openedDay); 22 | } 23 | else if (openedDay == triagedDay) { 24 | responseTime = differenceInWeeks * 5; 25 | } 26 | else { 27 | responseTime = ((differenceInWeeks + 1) * 5) - (openedDay - triagedDay); 28 | } 29 | return (responseTime); 30 | } 31 | 32 | module.exports = async(context, osmetadata) => { 33 | const foundResponseTime = await osmetadata(context).get('response_time_in_business_days'); 34 | if (foundResponseTime) { 35 | const foundString = "already found response time in business days: " + foundResponseTime 36 | console.log(foundString); 37 | return foundString; 38 | } 39 | if (context.payload.comment && context.payload.comment.author_association != "MEMBER" && context.payload.comment.author_association != "OWNER" && context.payload.comment.author_association != "CONTRIBUTOR") { 40 | return; 41 | } 42 | const businessDaysResponseTime = calcResponseTimeForIssueCreatedAt(context.payload.issue.created_at); 43 | console.log("response time in business days: " + businessDaysResponseTime); 44 | const result = osmetadata(context, context.payload.issue).set('response_time_in_business_days', businessDaysResponseTime) 45 | console.log("osmetadata update result: " + result); 46 | return "set response time in business days: " + businessDaysResponseTime; 47 | } 48 | -------------------------------------------------------------------------------- /.github/workflows/Zapier.yml: -------------------------------------------------------------------------------- 1 | # This is an action to close asana tasks that were generated by Github issues 2 | 3 | name: Zapier web hook 4 | 5 | # Controls when the workflow will run 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the "main" branch 8 | issues: 9 | types: [closed] 10 | 11 | permissions: 12 | issues: read 13 | 14 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 15 | jobs: 16 | # This workflow contains a single job called "build" 17 | build: 18 | # The type of runner that the job will run on 19 | runs-on: ubuntu-latest 20 | 21 | # Steps represent a sequence of tasks that will be executed as part of the job 22 | steps: 23 | # Runs a set of commands using the runners shell 24 | - name: Call Zapier web hook to close Asana task 25 | if: ${{ !github.event.issue.pull_request }} 26 | env: 27 | ISSUE_TITLE: ${{ github.event.issue.title }} 28 | run: | 29 | curl --location --request POST 'https://hooks.zapier.com/hooks/catch/12728683/b7009qc/' \ 30 | --header 'Content-Type: application/json' \ 31 | --header 'Accept: application/json' \ 32 | --data-raw '{ 33 | "task_name" : "$ISSUE_TITLE" 34 | }' 35 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | pull_request: 4 | branches: 5 | - '**' 6 | paths-ignore: 7 | - '.github/**' 8 | - '.vscode/**' 9 | - 'README.md' 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Setup Flutter 18 | uses: subosito/flutter-action@v2 19 | with: 20 | flutter-version: '3.3.2' 21 | channel: 'stable' 22 | 23 | - name: Checkout OneSignal-Flutter-SDK 24 | uses: actions/checkout@v3 25 | 26 | - name: Install Dependencies 🔗⛓📦 27 | run: flutter pub get 28 | 29 | - name: Static Analysis 30 | run: flutter analyze 31 | 32 | - name: Ensure the Dart code is formatted correctly 33 | run: flutter format --set-exit-if-changed --dry-run . 34 | 35 | - name: Run Flutter unit tests 36 | run: flutter test 37 | -------------------------------------------------------------------------------- /.github/workflows/project.yml: -------------------------------------------------------------------------------- 1 | name: Add issues to project 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | 8 | jobs: 9 | add-to-project: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Add issue to project 13 | uses: actions/add-to-project@v1.0.2 14 | with: 15 | # SDK Cross-Platform Project 16 | project-url: https://github.com/orgs/OneSignal/projects/10 17 | github-token: ${{ secrets.GH_PROJECTS_TOKEN }} 18 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Release Drafter 3 | 4 | on: 5 | push: 6 | # branches to consider in the event; optional, defaults to all 7 | branches: 8 | - main 9 | # pull_request event is required only for autolabeler 10 | pull_request: 11 | # Only following types are handled by the action, but one can default to all as well 12 | types: [opened, reopened, synchronize] 13 | # pull_request_target event is required for autolabeler to support PRs from forks 14 | # pull_request_target: 15 | # types: [opened, reopened, synchronize] 16 | 17 | permissions: 18 | contents: read 19 | 20 | jobs: 21 | update_release_draft: 22 | permissions: 23 | # write permission is required to create a github release 24 | contents: write 25 | # write permission is required for autolabeler 26 | # otherwise, read permission is required at least 27 | pull-requests: write 28 | runs-on: ubuntu-latest 29 | steps: 30 | # (Optional) GitHub Enterprise requires GHE_HOST variable set 31 | #- name: Set GHE_HOST 32 | # run: | 33 | # echo "GHE_HOST=${GITHUB_SERVER_URL##https:\/\/}" >> $GITHUB_ENV 34 | 35 | # Drafts your next Release notes as Pull Requests are merged into "master" 36 | - uses: release-drafter/release-drafter@v5 37 | # (Optional) specify config name to use, relative to .github/. Default: release-drafter.yml 38 | # with: 39 | # config-name: my-config.yml 40 | # disable-autolabeler: true 41 | env: 42 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 43 | -------------------------------------------------------------------------------- /.github/workflows/set_response_time.yml: -------------------------------------------------------------------------------- 1 | name: Set Response Time 2 | on: 3 | issue_comment: 4 | types: 5 | - created 6 | issues: 7 | types: 8 | - closed 9 | jobs: 10 | calculate: 11 | name: set reponse time for the issue 12 | if: github.event.issue.pull_request == null 13 | runs-on: ubuntu-latest 14 | permissions: 15 | issues: write 16 | steps: 17 | - uses: actions/checkout@v3 18 | with: 19 | token: ${{ secrets.GITHUB_TOKEN }} 20 | - run: npm install @octokit/action@6.0.6 21 | - uses: actions/github-script@v6 22 | id: set-time 23 | with: 24 | result-encoding: string 25 | script: | 26 | const os_probot_metadata = require('./.github/os_probot_metadata.js') 27 | const set_response_time = require('./.github/set_response_times.js') 28 | return await set_response_time(context, os_probot_metadata) 29 | env: 30 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 31 | - name: Get result 32 | run: echo "${{steps.set-time.outputs.result}}" >> $GITHUB_STEP_SUMMARY 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .packages 5 | .pub/ 6 | pubspec.lock 7 | 8 | build/ 9 | android/.idea 10 | .flutter-plugins-dependencies 11 | flutter_export_environment.sh 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | sudo: false 4 | dist: trusty 5 | addons: 6 | apt: 7 | # Flutter depends on /usr/lib/x86_64-linux-gnu/libstdc++.so.6 version GLIBCXX_3.4.18 8 | sources: 9 | - ubuntu-toolchain-r-test # if we don't specify this, the libstdc++6 we get is the wrong version 10 | packages: 11 | - libstdc++6 12 | - fonts-droid 13 | before_script: 14 | - git clone https://github.com/flutter/flutter.git 15 | - ./flutter/bin/flutter doctor 16 | script: 17 | - ./flutter/bin/flutter test 18 | cache: 19 | directories: 20 | - $HOME/.pub-cache 21 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Please see the release notes page for the full change log 2 | https://github.com/OneSignal/OneSignal-Flutter-SDK/releases -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the OneSignal Flutter SDK 2 | 3 | :+1::tada: First off, thanks for taking the time to contribute! :tada::+1: 4 | 5 | ### How to Contribute 6 | We love the open source community and enjoy the support and contributions of many of our users. We ask that any potential contributors to the SDK Follow the following guidelines: 7 | 8 | If your proposed contribution is a small bug fix, please feel free to create your own fork of the repository and create a pull request. 9 | 10 | If your contribution would _break_ or _change_ the functionality of the SDK, please reach out to us on (contact) before you put in a lot of effort into a change we may not be able to use. We try our best to make sure that the SDK remains stable so that developers do not have to continually change their code, however some breaking changes _are_ desirable, so please get in touch to discuss your idea before you put in a lot of effort. 11 | 12 | #### Before Submitting A Bug Report 13 | Before creating bug reports, please check this list of steps to follow. 14 | 15 | 1. Make sure that you are actually encountering an _issue_ and not a _question_. If you simply have a question about the SDK, we would be more than happy to assist you in our Support section on the web (https://www.onesignal.com - click the Message button at the bottom right) 16 | 2. Please make sure to [include as many details as possible](#how-do-i-submit-a-good-bug-report) 17 | 18 | > **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one. 19 | 20 | 21 | #### How Do I Submit a Good Bug Report 22 | * **Use a clear and descriptive title** for the issue to identify the problem. 23 | * **Include Reproducibility** It is nearly always a good idea to include steps to reproduct the issue. If you cannot reliably reproduce the issue yourself, that's ok, but reproducible steps help best. 24 | * **Describe your environment**, tell us what version of the Flutter SDK you are using, how you added it to your project, how your initialized the SDK, and so on. 25 | * **Include a Stack Trace** If your issue involves a crash/exception, ***PLEASE*** post the stack trace to help us identify the root issue. 26 | * **Include an Example Project** This isn't required, but if you want your issue fixed quickly, it's often a good idea to include an example project as a zip and include it with the issue. You can also download the Demo project (included in the `/example` folder of this repo) and set up an example project with this code as a starting point. 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Modified MIT License 2 | 3 | Copyright 2018 OneSignal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | 1. The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | 2. All copies of substantial portions of the Software may only be used in connection 16 | with services provided by OneSignal. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | ### OneSignal Flutter SDK [![Build Status](https://travis-ci.org/OneSignal/OneSignal-Flutter-SDK.svg?branch=master)](https://travis-ci.org/OneSignal/OneSignal-Flutter-SDK) 6 | 7 | --- 8 | 9 | #### ⚠️ Migration Advisory for current OneSignal customers 10 | 11 | Our new [user-centric APIs and v5.x.x SDKs](https://onesignal.com/blog/unify-your-users-across-channels-and-devices/) offer an improved user and data management experience. However, they may not be at 1:1 feature parity with our previous versions yet. 12 | 13 | If you are migrating an existing app, we suggest using iOS and Android’s Phased Rollout capabilities to ensure that there are no unexpected issues or edge cases. Here is the documentation for each: 14 | 15 | - [iOS Phased Rollout](https://developer.apple.com/help/app-store-connect/update-your-app/release-a-version-update-in-phases/) 16 | - [Google Play Staged Rollouts](https://support.google.com/googleplay/android-developer/answer/6346149?hl=en) 17 | 18 | If you run into any challenges or have concerns, please contact our support team at support@onesignal.com 19 | 20 | --- 21 | 22 | [OneSignal](https://onesignal.com/) is a free email, sms, push notification, and in-app message service for mobile apps. This SDK makes it easy to integrate your Flutter iOS and/or Android apps with OneSignal. 23 | 24 |

Flutter Notification

25 | 26 | #### Installation 27 | See the [Setup Guide](https://documentation.onesignal.com/docs/flutter-sdk-setup) for setup instructions. 28 | 29 | #### Change Log 30 | See this repository's [release tags](https://github.com/onesignal/onesignal-flutter-sdk/releases) for a complete change log of every released version. 31 | 32 | #### Support 33 | Please visit this repository's [Github issue tracker](https://github.com/onesignal/onesignal-flutter-sdk/issues) for feature requests and bug reports related specificly to the SDK. 34 | For account issues and support please contact OneSignal support from the [OneSignal.com](https://onesignal.com) dashboard. 35 | 36 | #### Demo Project 37 | To make things easier, we have published a demo project in the `/example` folder of this repository. 38 | 39 | #### Supports: 40 | * Tested from iOS 8 to iOS 15 41 | * Tested from Android 4.0.3 (API level 15) to Android 12.0 (31) 42 | -------------------------------------------------------------------------------- /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.onesignal.flutter' 2 | version '5.3.3' 3 | 4 | buildscript { 5 | repositories { 6 | google() 7 | mavenCentral() 8 | } 9 | 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:7.0.0' 12 | } 13 | } 14 | 15 | rootProject.allprojects { 16 | repositories { 17 | google() 18 | mavenCentral() 19 | } 20 | } 21 | 22 | apply plugin: 'com.android.library' 23 | 24 | android { 25 | compileSdkVersion 34 26 | // Condition for namespace compatibility in AGP <4.2 27 | if (project.android.hasProperty("namespace")) { 28 | namespace 'com.onesignal.flutter' 29 | } 30 | 31 | defaultConfig { 32 | minSdkVersion 16 33 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 34 | } 35 | lintOptions { 36 | disable 'InvalidPackage' 37 | } 38 | } 39 | 40 | dependencies { 41 | implementation 'com.onesignal:OneSignal:5.1.34' 42 | } 43 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Oct 17 14:56:12 PDT 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-7.3.3-all.zip -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'onesignal' 2 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /android/src/main/java/com/onesignal/flutter/FlutterMessengerResponder.java: -------------------------------------------------------------------------------- 1 | package com.onesignal.flutter; 2 | 3 | import android.content.Context; 4 | import android.os.Handler; 5 | import android.os.Looper; 6 | 7 | import java.util.HashMap; 8 | 9 | import io.flutter.plugin.common.BinaryMessenger; 10 | import io.flutter.plugin.common.MethodChannel; 11 | 12 | abstract class FlutterMessengerResponder { 13 | Context context; 14 | protected MethodChannel channel; 15 | BinaryMessenger messenger; 16 | 17 | /** 18 | * MethodChannel class is home to success() method used by Result class 19 | * It has the @UiThread annotation and must be run on UI thread, otherwise a RuntimeException will be thrown 20 | * This will communicate success back to Dart 21 | */ 22 | void replySuccess(final MethodChannel.Result reply, final Object response) { 23 | runOnMainThread(new Runnable() { 24 | @Override 25 | public void run() { 26 | reply.success(response); 27 | } 28 | }); 29 | } 30 | 31 | /** 32 | * MethodChannel class is home to error() method used by Result class 33 | * It has the @UiThread annotation and must be run on UI thread, otherwise a RuntimeException will be thrown 34 | * This will communicate error back to Dart 35 | */ 36 | void replyError(final MethodChannel.Result reply, final String tag, final String message, final Object response) { 37 | runOnMainThread(new Runnable() { 38 | @Override 39 | public void run() { 40 | reply.error(tag, message, response); 41 | } 42 | }); 43 | } 44 | 45 | /** 46 | * MethodChannel class is home to notImplemented() method used by Result class 47 | * It has the @UiThread annotation and must be run on UI thread, otherwise a RuntimeException will be thrown 48 | * This will communicate not implemented back to Dart 49 | */ 50 | void replyNotImplemented(final MethodChannel.Result reply) { 51 | runOnMainThread(new Runnable() { 52 | @Override 53 | public void run() { 54 | reply.notImplemented(); 55 | } 56 | }); 57 | } 58 | 59 | private void runOnMainThread(final Runnable runnable) { 60 | if (Looper.getMainLooper().getThread() == Thread.currentThread()) 61 | runnable.run(); 62 | else { 63 | Handler handler = new Handler(Looper.getMainLooper()); 64 | handler.post(runnable); 65 | } 66 | } 67 | 68 | void invokeMethodOnUiThread(final String methodName, final HashMap map) { 69 | //final MethodChannel channel = this.channel; 70 | runOnMainThread(new Runnable() { 71 | @Override 72 | public void run() { 73 | channel.invokeMethod(methodName, map); 74 | } 75 | }); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /android/src/main/java/com/onesignal/flutter/OneSignalDebug.java: -------------------------------------------------------------------------------- 1 | package com.onesignal.flutter; 2 | 3 | import com.onesignal.OneSignal; 4 | import com.onesignal.debug.LogLevel; 5 | 6 | import io.flutter.plugin.common.BinaryMessenger; 7 | import io.flutter.plugin.common.MethodCall; 8 | import io.flutter.plugin.common.MethodChannel; 9 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler; 10 | import io.flutter.plugin.common.MethodChannel.Result; 11 | 12 | public class OneSignalDebug extends FlutterMessengerResponder implements MethodCallHandler { 13 | 14 | static void registerWith(BinaryMessenger messenger) { 15 | OneSignalDebug controller = new OneSignalDebug(); 16 | controller.messenger = messenger; 17 | controller.channel = new MethodChannel(messenger, "OneSignal#debug"); 18 | controller.channel.setMethodCallHandler(controller); 19 | } 20 | 21 | @Override 22 | public void onMethodCall(MethodCall call, Result result) { 23 | if (call.method.contentEquals("OneSignal#setLogLevel")) 24 | this.setLogLevel(call, result); 25 | else if (call.method.contentEquals("OneSignal#setAlertLevel")) 26 | this.setAlertLevel(call, result); 27 | else 28 | replyNotImplemented(result); 29 | } 30 | 31 | private void setLogLevel(MethodCall call, Result reply) { 32 | try { 33 | int console = call.argument("logLevel"); 34 | LogLevel consoleLogLevel = LogLevel.fromInt(console); 35 | OneSignal.getDebug().setLogLevel(consoleLogLevel); 36 | replySuccess(reply, null); 37 | } 38 | catch(ClassCastException e) { 39 | replyError(reply, "OneSignal", "failed with error: " + e.getMessage() + "\n" + e.getStackTrace(), null); 40 | } 41 | } 42 | 43 | private void setAlertLevel(MethodCall call, Result reply) { 44 | try { 45 | int visual = call.argument("visualLevel"); 46 | LogLevel visualLogLevel = LogLevel.fromInt(visual); 47 | OneSignal.getDebug().setAlertLevel(visualLogLevel); 48 | replySuccess(reply, null); 49 | } 50 | catch(ClassCastException e) { 51 | replyError(reply, "OneSignal", "failed with error: " + e.getMessage() + "\n" + e.getStackTrace(), null); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /android/src/main/java/com/onesignal/flutter/OneSignalLocation.java: -------------------------------------------------------------------------------- 1 | package com.onesignal.flutter; 2 | 3 | import com.onesignal.OneSignal; 4 | import com.onesignal.Continue; 5 | 6 | import io.flutter.plugin.common.BinaryMessenger; 7 | import io.flutter.plugin.common.MethodCall; 8 | import io.flutter.plugin.common.MethodChannel; 9 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler; 10 | import io.flutter.plugin.common.MethodChannel.Result; 11 | 12 | public class OneSignalLocation extends FlutterMessengerResponder implements MethodCallHandler { 13 | 14 | static void registerWith(BinaryMessenger messenger) { 15 | OneSignalLocation controller = new OneSignalLocation(); 16 | controller.messenger = messenger; 17 | controller.channel = new MethodChannel(messenger, "OneSignal#location"); 18 | controller.channel.setMethodCallHandler(controller); 19 | } 20 | 21 | @Override 22 | public void onMethodCall(MethodCall call, Result result) { 23 | if (call.method.contentEquals("OneSignal#requestPermission")) 24 | this.requestPermission(result); 25 | else if (call.method.contentEquals("OneSignal#setShared")) 26 | this.setShared(call, result); 27 | else if (call.method.contentEquals("OneSignal#isShared")) 28 | replySuccess(result, OneSignal.getLocation().isShared()); 29 | else 30 | replyNotImplemented(result); 31 | } 32 | 33 | private void requestPermission(Result reply) { 34 | OneSignal.getLocation().requestPermission(Continue.none()); 35 | replySuccess(reply, null); 36 | } 37 | 38 | private void setShared(MethodCall call, Result result) { 39 | OneSignal.getLocation().setShared((boolean) call.arguments); 40 | replySuccess(result, null); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java: -------------------------------------------------------------------------------- 1 | package com.onesignal.flutter; 2 | 3 | import android.content.Context; 4 | 5 | import io.flutter.embedding.engine.plugins.activity.ActivityAware; 6 | import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; 7 | 8 | import com.onesignal.OneSignal; 9 | import com.onesignal.common.OneSignalWrapper; 10 | 11 | import androidx.annotation.NonNull; 12 | import io.flutter.embedding.engine.plugins.FlutterPlugin; 13 | import io.flutter.plugin.common.BinaryMessenger; 14 | import io.flutter.plugin.common.MethodCall; 15 | import io.flutter.plugin.common.MethodChannel; 16 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler; 17 | import io.flutter.plugin.common.MethodChannel.Result; 18 | 19 | /** OnesignalPlugin */ 20 | public class OneSignalPlugin extends FlutterMessengerResponder implements FlutterPlugin, MethodCallHandler, ActivityAware { 21 | 22 | public OneSignalPlugin() { 23 | } 24 | 25 | private void init(Context context, BinaryMessenger messenger) 26 | { 27 | this.context = context; 28 | this.messenger = messenger; 29 | OneSignalWrapper.setSdkType("flutter"); 30 | // For 5.0.0, hard code to reflect SDK version 31 | OneSignalWrapper.setSdkVersion("050303"); 32 | 33 | channel = new MethodChannel(messenger, "OneSignal"); 34 | channel.setMethodCallHandler(this); 35 | 36 | OneSignalDebug.registerWith(messenger); 37 | OneSignalLocation.registerWith(messenger); 38 | OneSignalSession.registerWith(messenger); 39 | OneSignalInAppMessages.registerWith(messenger); 40 | OneSignalUser.registerWith(messenger); 41 | OneSignalPushSubscription.registerWith(messenger); 42 | OneSignalNotifications.registerWith(messenger); 43 | } 44 | 45 | @Override 46 | public void onAttachedToEngine(@NonNull FlutterPlugin.FlutterPluginBinding flutterPluginBinding) { 47 | init( 48 | flutterPluginBinding.getApplicationContext(), 49 | flutterPluginBinding.getBinaryMessenger() 50 | ); 51 | } 52 | 53 | @Override 54 | public void onDetachedFromEngine(@NonNull FlutterPlugin.FlutterPluginBinding binding) { 55 | onDetachedFromEngine(); 56 | } 57 | 58 | private void onDetachedFromEngine() { 59 | } 60 | 61 | @Override 62 | public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { 63 | this.context = binding.getActivity(); 64 | } 65 | 66 | @Override 67 | public void onDetachedFromActivity() { 68 | } 69 | 70 | @Override 71 | public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { 72 | } 73 | 74 | @Override 75 | public void onDetachedFromActivityForConfigChanges() { 76 | } 77 | 78 | @Override 79 | public void onMethodCall(MethodCall call, Result result) { 80 | if (call.method.contentEquals("OneSignal#initialize")) 81 | this.initWithContext(call, result); 82 | else if (call.method.contentEquals("OneSignal#consentRequired")) 83 | this.setConsentRequired(call, result); 84 | else if (call.method.contentEquals("OneSignal#consentGiven")) 85 | this.setConsentGiven(call, result); 86 | else if (call.method.contentEquals("OneSignal#login")) 87 | this.login(call, result); 88 | else if (call.method.contentEquals("OneSignal#loginWithJWT")) 89 | this.loginWithJWT(call, result); 90 | else if (call.method.contentEquals("OneSignal#logout")) 91 | this.logout(call, result); 92 | else 93 | replyNotImplemented(result); 94 | } 95 | 96 | private void initWithContext(MethodCall call, Result reply) { 97 | String appId = call.argument("appId"); 98 | OneSignal.initWithContext(context, appId); 99 | replySuccess(reply, null); 100 | } 101 | 102 | private void setConsentRequired(MethodCall call, Result reply) { 103 | boolean required = call.argument("required"); 104 | OneSignal.setConsentRequired(required); 105 | replySuccess(reply, null); 106 | } 107 | 108 | private void setConsentGiven(MethodCall call, Result reply) { 109 | boolean granted = call.argument("granted"); 110 | OneSignal.setConsentGiven(granted); 111 | replySuccess(reply, null); 112 | } 113 | 114 | private void login(MethodCall call, Result result) { 115 | OneSignal.login((String) call.argument("externalId")); 116 | replySuccess(result, null); 117 | } 118 | 119 | private void loginWithJWT(MethodCall call, Result result) { 120 | OneSignal.login((String) call.argument("externalId"), (String) call.argument("jwt")); 121 | replySuccess(result, null); 122 | } 123 | 124 | private void logout(MethodCall call, Result result) { 125 | OneSignal.logout(); 126 | replySuccess(result, null); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /android/src/main/java/com/onesignal/flutter/OneSignalPushSubscription.java: -------------------------------------------------------------------------------- 1 | package com.onesignal.flutter; 2 | 3 | import com.onesignal.OneSignal; 4 | 5 | import com.onesignal.user.subscriptions.IPushSubscriptionObserver; 6 | import com.onesignal.user.subscriptions.PushSubscriptionChangedState; 7 | import com.onesignal.debug.internal.logging.Logging; 8 | 9 | import org.json.JSONException; 10 | 11 | import io.flutter.plugin.common.BinaryMessenger; 12 | import io.flutter.plugin.common.MethodCall; 13 | import io.flutter.plugin.common.MethodChannel; 14 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler; 15 | import io.flutter.plugin.common.MethodChannel.Result; 16 | 17 | public class OneSignalPushSubscription extends FlutterMessengerResponder implements MethodCallHandler, IPushSubscriptionObserver { 18 | 19 | static void registerWith(BinaryMessenger messenger) { 20 | OneSignalPushSubscription controller = new OneSignalPushSubscription(); 21 | controller.messenger = messenger; 22 | controller.channel = new MethodChannel(messenger, "OneSignal#pushsubscription"); 23 | controller.channel.setMethodCallHandler(controller); 24 | } 25 | 26 | @Override 27 | public void onMethodCall(MethodCall call, Result result) { 28 | if (call.method.contentEquals("OneSignal#optIn")) 29 | this.optIn(call, result); 30 | else if (call.method.contentEquals("OneSignal#optOut")) 31 | this.optOut(call, result); 32 | else if (call.method.contentEquals("OneSignal#pushSubscriptionId")) 33 | replySuccess(result, OneSignal.getUser().getPushSubscription().getId()); 34 | else if (call.method.contentEquals("OneSignal#pushSubscriptionToken")) 35 | replySuccess(result, OneSignal.getUser().getPushSubscription().getToken()); 36 | else if (call.method.contentEquals("OneSignal#pushSubscriptionOptedIn")) 37 | replySuccess(result, OneSignal.getUser().getPushSubscription().getOptedIn()); 38 | else if (call.method.contentEquals("OneSignal#lifecycleInit")) 39 | this.lifecycleInit(); 40 | else 41 | replyNotImplemented(result); 42 | } 43 | 44 | private void optIn(MethodCall call, Result reply) { 45 | OneSignal.getUser().getPushSubscription().optIn(); 46 | replySuccess(reply, null); 47 | } 48 | private void optOut(MethodCall call, Result reply) { 49 | OneSignal.getUser().getPushSubscription().optOut(); 50 | replySuccess(reply, null); 51 | } 52 | 53 | private void lifecycleInit() { 54 | OneSignal.getUser().getPushSubscription().addObserver(this); 55 | } 56 | 57 | @Override 58 | public void onPushSubscriptionChange(PushSubscriptionChangedState changeState) { 59 | try { 60 | invokeMethodOnUiThread("OneSignal#onPushSubscriptionChange", OneSignalSerializer.convertOnPushSubscriptionChange(changeState)); 61 | } catch (JSONException e) { 62 | e.getStackTrace(); 63 | Logging.error("Encountered an error attempting to convert PushSubscriptionChangedState object to hash map:" + e.toString(), null); 64 | } 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /android/src/main/java/com/onesignal/flutter/OneSignalSession.java: -------------------------------------------------------------------------------- 1 | package com.onesignal.flutter; 2 | 3 | import com.onesignal.OneSignal; 4 | 5 | import io.flutter.plugin.common.BinaryMessenger; 6 | import io.flutter.plugin.common.MethodCall; 7 | import io.flutter.plugin.common.MethodChannel; 8 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler; 9 | import io.flutter.plugin.common.MethodChannel.Result; 10 | 11 | public class OneSignalSession extends FlutterMessengerResponder implements MethodCallHandler { 12 | 13 | static void registerWith(BinaryMessenger messenger) { 14 | OneSignalSession controller = new OneSignalSession(); 15 | controller.messenger = messenger; 16 | controller.channel = new MethodChannel(messenger, "OneSignal#session"); 17 | controller.channel.setMethodCallHandler(controller); 18 | } 19 | 20 | @Override 21 | public void onMethodCall(MethodCall call, Result result) { 22 | if (call.method.contentEquals("OneSignal#addOutcome")) 23 | this.addOutcome(call, result); 24 | else if (call.method.contentEquals("OneSignal#addUniqueOutcome")) 25 | this.addUniqueOutcome(call, result); 26 | else if (call.method.contentEquals("OneSignal#addOutcomeWithValue")) 27 | this.addOutcomeWithValue(call, result); 28 | else 29 | replyNotImplemented(result); 30 | } 31 | 32 | private void addOutcome(MethodCall call, Result result) { 33 | String name = (String) call.arguments; 34 | 35 | if (name == null || name.isEmpty()) { 36 | replyError(result, "OneSignal", "addOutcome() name must not be null or empty", null); 37 | return; 38 | } 39 | 40 | OneSignal.getSession().addOutcome(name); 41 | replySuccess(result, null); 42 | } 43 | 44 | private void addUniqueOutcome(MethodCall call, Result result) { 45 | String name = (String) call.arguments; 46 | 47 | if (name == null || name.isEmpty()) { 48 | replyError(result, "OneSignal", "sendUniqueOutcome() name must not be null or empty", null); 49 | return; 50 | } 51 | 52 | OneSignal.getSession().addUniqueOutcome(name); 53 | replySuccess(result, null); 54 | } 55 | 56 | private void addOutcomeWithValue(MethodCall call, Result result) { 57 | String name = call.argument("outcome_name"); 58 | Double value = call.argument("outcome_value"); 59 | 60 | if (name == null || name.isEmpty()) { 61 | replyError(result, "OneSignal", "sendOutcomeWithValue() name must not be null or empty", null); 62 | return; 63 | } 64 | 65 | if (value == null) { 66 | replyError(result, "OneSignal", "sendOutcomeWithValue() value must not be null", null); 67 | return; 68 | } 69 | 70 | OneSignal.getSession().addOutcomeWithValue(name, value.floatValue()); 71 | replySuccess(result, null); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .packages 5 | .pub/ 6 | 7 | build/ 8 | 9 | .flutter-plugins 10 | .flutter-plugins-dependencies 11 | flutter_export_environment.sh -------------------------------------------------------------------------------- /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: c7ea3ca377e909469c68f2ab878a5bc53d3cf66b 8 | channel: beta 9 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # onesignal_example 2 | 3 | Demonstrates how to use the onesignal plugin. 4 | 5 | ## Getting Started 6 | 7 | For help getting started with Flutter, view our online 8 | [documentation](https://flutter.io/). 9 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.class 3 | .gradle 4 | /local.properties 5 | /.idea/workspace.xml 6 | /.idea/libraries 7 | .DS_Store 8 | /build 9 | /captures 10 | GeneratedPluginRegistrant.java 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 | apply plugin: 'com.android.application' 15 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 16 | 17 | android { 18 | compileSdkVersion 34 19 | 20 | lintOptions { 21 | disable 'InvalidPackage' 22 | } 23 | 24 | defaultConfig { 25 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 26 | applicationId "com.onesignal.onesignalexample" 27 | minSdkVersion 19 28 | targetSdkVersion 33 29 | versionCode 1 30 | versionName "1.0" 31 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 32 | } 33 | 34 | buildTypes { 35 | release { 36 | // TODO: Add your own signing config for the release build. 37 | // Signing with the debug keys for now, so `flutter run --release` works. 38 | signingConfig signingConfigs.debug 39 | } 40 | } 41 | } 42 | 43 | flutter { 44 | source '../..' 45 | } 46 | 47 | dependencies { 48 | testImplementation 'junit:junit:4.12' 49 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 50 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 51 | } 52 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 21 | 24 | 32 | 36 | 40 | 45 | 49 | 50 | 51 | 52 | 53 | 54 | 56 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/onesignal/onesignalexample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.onesignal.onesignalexample; 2 | 3 | import io.flutter.embedding.android.FlutterActivity; 4 | 5 | public class MainActivity extends FlutterActivity { 6 | } 7 | -------------------------------------------------------------------------------- /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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:7.0.0' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | mavenCentral() 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 | 3 | android.enableR8=true 4 | android.enableD8=true 5 | 6 | android.useAndroidX=true 7 | android.enableJetifier=true 8 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Oct 17 15:00:44 PDT 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-7.3.3-all.zip -------------------------------------------------------------------------------- /example/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /example/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /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/.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/app.flx 37 | /Flutter/app.zip 38 | /Flutter/flutter_assets/ 39 | /Flutter/App.framework 40 | /Flutter/Flutter.framework 41 | /Flutter/Generated.xcconfig 42 | /ServiceDefinitions.json 43 | 44 | Pods/ 45 | .symlinks/ 46 | -------------------------------------------------------------------------------- /example/ios/ExampleWidget/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /example/ios/ExampleWidget/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/ExampleWidget/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /example/ios/ExampleWidget/Assets.xcassets/WidgetBackground.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /example/ios/ExampleWidget/Assets.xcassets/onesignaldemo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "filename" : "onesignal-logo.png", 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/ios/ExampleWidget/Assets.xcassets/onesignaldemo.imageset/onesignal-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/example/ios/ExampleWidget/Assets.xcassets/onesignaldemo.imageset/onesignal-logo.png -------------------------------------------------------------------------------- /example/ios/ExampleWidget/ExampleWidgetBundle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleWidgetBundle.swift 3 | // ExampleWidget 4 | // 5 | // Created by Brian Smith on 4/30/24. 6 | // Copyright © 2024 The Chromium Authors. All rights reserved. 7 | // 8 | 9 | import WidgetKit 10 | import SwiftUI 11 | 12 | @main 13 | struct ExampleWidgetBundle: WidgetBundle { 14 | var body: some Widget { 15 | ExampleWidgetLiveActivity() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /example/ios/ExampleWidget/ExampleWidgetLiveActivity.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleWidgetLiveActivity.swift 3 | // ExampleWidget 4 | // 5 | // Created by Brian Smith on 4/30/24. 6 | // Copyright © 2024 The Chromium Authors. All rights reserved. 7 | // 8 | 9 | import ActivityKit 10 | import WidgetKit 11 | import SwiftUI 12 | import OneSignalLiveActivities 13 | 14 | struct ExampleWidgetLiveActivity: Widget { 15 | var body: some WidgetConfiguration { 16 | ActivityConfiguration(for: DefaultLiveActivityAttributes.self) { context in 17 | // Lock screen/banner UI goes here\VStack(alignment: .leading) { 18 | VStack { 19 | Spacer() 20 | Text("FLUTTER: " + (context.attributes.data["title"]?.asString() ?? "")).font(.headline) 21 | Spacer() 22 | HStack { 23 | Spacer() 24 | Label { 25 | Text(context.state.data["message"]?.asDict()?["en"]?.asString() ?? "") 26 | } icon: { 27 | Image("onesignaldemo") 28 | .resizable() 29 | .scaledToFit() 30 | .frame(width: 40.0, height: 40.0) 31 | } 32 | Spacer() 33 | } 34 | Text("INT: " + String(context.state.data["intValue"]?.asInt() ?? 0)) 35 | Text("DBL: " + String(context.state.data["doubleValue"]?.asDouble() ?? 0.0)) 36 | Text("BOL: " + String(context.state.data["boolValue"]?.asBool() ?? false)) 37 | Spacer() 38 | } 39 | .activitySystemActionForegroundColor(.black) 40 | .activityBackgroundTint(.white) 41 | } dynamicIsland: { _ in 42 | DynamicIsland { 43 | // Expanded UI goes here. Compose the expanded UI through 44 | // various regions, like leading/trailing/center/bottom 45 | DynamicIslandExpandedRegion(.leading) { 46 | Text("Leading") 47 | } 48 | DynamicIslandExpandedRegion(.trailing) { 49 | Text("Trailing") 50 | } 51 | DynamicIslandExpandedRegion(.bottom) { 52 | Text("Bottom") 53 | // more content 54 | } 55 | } compactLeading: { 56 | Text("L") 57 | } compactTrailing: { 58 | Text("T") 59 | } minimal: { 60 | Text("Min") 61 | } 62 | .widgetURL(URL(string: "http://www.apple.com")) 63 | .keylineTint(Color.red) 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /example/ios/ExampleWidget/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSExtension 6 | 7 | NSExtensionPointIdentifier 8 | com.apple.widgetkit-extension 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Flutter.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # This podspec is NOT to be published. It is only used as a local source! 3 | # This is a generated file; do not edit or check into version control. 4 | # 5 | 6 | Pod::Spec.new do |s| 7 | s.name = 'Flutter' 8 | s.version = '1.0.0' 9 | s.summary = 'A UI toolkit for beautiful and fast apps.' 10 | s.homepage = 'https://flutter.dev' 11 | s.license = { :type => 'BSD' } 12 | s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } 13 | s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } 14 | s.ios.deployment_target = '12.0' 15 | # Framework linking is handled by Flutter tooling, not CocoaPods. 16 | # Add a placeholder to satisfy `s.dependency 'Flutter'` plugin podspecs. 17 | s.vendored_frameworks = 'path/to/nothing' 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/OneSignalNotificationServiceExtension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | OneSignalNotificationServiceExtension 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | XPC! 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | NSAppTransportSecurity 24 | 25 | NSAllowsArbitraryLoads 26 | 27 | 28 | NSExtension 29 | 30 | NSExtensionPointIdentifier 31 | com.apple.usernotifications.service 32 | NSExtensionPrincipalClass 33 | NotificationService 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /example/ios/OneSignalNotificationServiceExtension/NotificationService.h: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationService.h 3 | // OneSignalNotificationServiceExtension 4 | // 5 | // Created by Brad Hesse on 7/13/18. 6 | // Copyright © 2018 The Chromium Authors. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NotificationService : UNNotificationServiceExtension 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /example/ios/OneSignalNotificationServiceExtension/NotificationService.m: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationService.m 3 | // OneSignalNotificationServiceExtension 4 | // 5 | // Created by Brad Hesse on 7/13/18. 6 | // Copyright © 2018 The Chromium Authors. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "NotificationService.h" 12 | 13 | @interface NotificationService () 14 | 15 | @property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver); 16 | @property (nonatomic, strong) UNNotificationRequest *receivedRequest; 17 | @property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent; 18 | 19 | @end 20 | 21 | @implementation NotificationService 22 | 23 | - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler { 24 | self.receivedRequest = request; 25 | self.contentHandler = contentHandler; 26 | self.bestAttemptContent = [request.content mutableCopy]; 27 | 28 | [OneSignal didReceiveNotificationExtensionRequest:self.receivedRequest withMutableNotificationContent:self.bestAttemptContent withContentHandler:self.contentHandler]; 29 | } 30 | 31 | - (void)serviceExtensionTimeWillExpire { 32 | // Called just before the extension will be terminated by the system. 33 | // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used. 34 | 35 | [OneSignal serviceExtensionTimeWillExpireRequest:self.receivedRequest withMutableNotificationContent:self.bestAttemptContent]; 36 | 37 | self.contentHandler(self.bestAttemptContent); 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /example/ios/OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.com.onesignal.example.onesignal 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | platform :ios, '12.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 32 | end 33 | 34 | target 'OneSignalNotificationServiceExtension' do 35 | pod 'OneSignalXCFramework', '>= 5.0.2', '< 6.0.0' 36 | end 37 | 38 | target 'ExampleWidgetExtension' do 39 | pod 'OneSignalXCFramework', '>= 5.0.2', '< 6.0.0' 40 | end 41 | 42 | post_install do |installer| 43 | installer.pods_project.targets.each do |target| 44 | flutter_additional_ios_build_settings(target) 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - onesignal_flutter (5.1.5): 4 | - Flutter 5 | - OneSignalXCFramework (= 5.2.0) 6 | - OneSignalXCFramework (5.2.0): 7 | - OneSignalXCFramework/OneSignalComplete (= 5.2.0) 8 | - OneSignalXCFramework/OneSignal (5.2.0): 9 | - OneSignalXCFramework/OneSignalCore 10 | - OneSignalXCFramework/OneSignalExtension 11 | - OneSignalXCFramework/OneSignalLiveActivities 12 | - OneSignalXCFramework/OneSignalNotifications 13 | - OneSignalXCFramework/OneSignalOSCore 14 | - OneSignalXCFramework/OneSignalOutcomes 15 | - OneSignalXCFramework/OneSignalUser 16 | - OneSignalXCFramework/OneSignalComplete (5.2.0): 17 | - OneSignalXCFramework/OneSignal 18 | - OneSignalXCFramework/OneSignalInAppMessages 19 | - OneSignalXCFramework/OneSignalLocation 20 | - OneSignalXCFramework/OneSignalCore (5.2.0) 21 | - OneSignalXCFramework/OneSignalExtension (5.2.0): 22 | - OneSignalXCFramework/OneSignalCore 23 | - OneSignalXCFramework/OneSignalOutcomes 24 | - OneSignalXCFramework/OneSignalInAppMessages (5.2.0): 25 | - OneSignalXCFramework/OneSignalCore 26 | - OneSignalXCFramework/OneSignalNotifications 27 | - OneSignalXCFramework/OneSignalOSCore 28 | - OneSignalXCFramework/OneSignalOutcomes 29 | - OneSignalXCFramework/OneSignalUser 30 | - OneSignalXCFramework/OneSignalLiveActivities (5.2.0): 31 | - OneSignalXCFramework/OneSignalCore 32 | - OneSignalXCFramework/OneSignalOSCore 33 | - OneSignalXCFramework/OneSignalUser 34 | - OneSignalXCFramework/OneSignalLocation (5.2.0): 35 | - OneSignalXCFramework/OneSignalCore 36 | - OneSignalXCFramework/OneSignalNotifications 37 | - OneSignalXCFramework/OneSignalOSCore 38 | - OneSignalXCFramework/OneSignalUser 39 | - OneSignalXCFramework/OneSignalNotifications (5.2.0): 40 | - OneSignalXCFramework/OneSignalCore 41 | - OneSignalXCFramework/OneSignalExtension 42 | - OneSignalXCFramework/OneSignalOutcomes 43 | - OneSignalXCFramework/OneSignalOSCore (5.2.0): 44 | - OneSignalXCFramework/OneSignalCore 45 | - OneSignalXCFramework/OneSignalOutcomes (5.2.0): 46 | - OneSignalXCFramework/OneSignalCore 47 | - OneSignalXCFramework/OneSignalUser (5.2.0): 48 | - OneSignalXCFramework/OneSignalCore 49 | - OneSignalXCFramework/OneSignalNotifications 50 | - OneSignalXCFramework/OneSignalOSCore 51 | - OneSignalXCFramework/OneSignalOutcomes 52 | 53 | DEPENDENCIES: 54 | - Flutter (from `Flutter`) 55 | - onesignal_flutter (from `.symlinks/plugins/onesignal_flutter/ios`) 56 | - OneSignalXCFramework (< 6.0.0, >= 5.0.2) 57 | 58 | SPEC REPOS: 59 | trunk: 60 | - OneSignalXCFramework 61 | 62 | EXTERNAL SOURCES: 63 | Flutter: 64 | :path: Flutter 65 | onesignal_flutter: 66 | :path: ".symlinks/plugins/onesignal_flutter/ios" 67 | 68 | SPEC CHECKSUMS: 69 | Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 70 | onesignal_flutter: 6e7b22bc9bbdb32cbaf79728e624a02264adec94 71 | OneSignalXCFramework: bdf74fdc06888f9466dc21e826fe1549ed143095 72 | 73 | PODFILE CHECKSUM: 4866dde54f21b323e83902730ef350ff4a561f44 74 | 75 | COCOAPODS: 1.15.2 76 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /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/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/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 | CADisableMinimumFrameDurationOnPhone 6 | 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleDisplayName 10 | OneSignalDemo 11 | CFBundleExecutable 12 | $(EXECUTABLE_NAME) 13 | CFBundleIdentifier 14 | $(PRODUCT_BUNDLE_IDENTIFIER) 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | onesignal_example 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1 27 | LSRequiresIPhoneOS 28 | 29 | NSAppTransportSecurity 30 | 31 | NSAllowsArbitraryLoads 32 | 33 | 34 | NSSupportsLiveActivities 35 | 36 | UIApplicationSupportsIndirectInputEvents 37 | 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIMainStoryboardFile 41 | Main 42 | UISupportedInterfaceOrientations 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | UISupportedInterfaceOrientations~ipad 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationPortraitUpsideDown 52 | UIInterfaceOrientationLandscapeLeft 53 | UIInterfaceOrientationLandscapeRight 54 | 55 | UIViewControllerBasedStatusBarAppearance 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | development 7 | com.apple.security.application-groups 8 | 9 | group.com.onesignal.example.onesignal 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: onesignal_example 2 | description: Demonstrates how to use the onesignal plugin. 3 | version: 1.0.0+1 4 | 5 | dependencies: 6 | flutter: 7 | sdk: flutter 8 | # The following adds the Cupertino Icons font to your application. 9 | # Use with the CupertinoIcons class for iOS style icons. 10 | cupertino_icons: ^1.0.0 11 | 12 | environment: 13 | sdk: ">=2.12.0 <3.0.0" 14 | 15 | dev_dependencies: 16 | flutter_test: 17 | sdk: flutter 18 | 19 | onesignal_flutter: 20 | path: ../ 21 | 22 | # For information on the generic Dart part of this file, see the 23 | # following page: https://www.dartlang.org/tools/pub/pubspec 24 | 25 | # The following section is specific to Flutter. 26 | flutter: 27 | 28 | # The following line ensures that the Material Icons font is 29 | # included with your application, so that you can use the icons in 30 | # the material Icons class. 31 | uses-material-design: true 32 | 33 | # To add assets to your application, add an assets section, like this: 34 | # assets: 35 | # - images/a_dot_burr.jpeg 36 | # - images/a_dot_ham.jpeg 37 | 38 | # An image asset can refer to one or more resolution-specific "variants", see 39 | # https://flutter.io/assets-and-images/#resolution-aware. 40 | 41 | # For details regarding adding assets from package dependencies, see 42 | # https://flutter.io/assets-and-images/#from-packages 43 | 44 | # To add custom fonts to your application, add a fonts section here, 45 | # in this "flutter" section. Each entry in this list should have a 46 | # "family" key with the font family name, and a "fonts" key with a 47 | # list giving the asset and other descriptors for the font. For 48 | # example: 49 | # fonts: 50 | # - family: Schyler 51 | # fonts: 52 | # - asset: fonts/Schyler-Regular.ttf 53 | # - asset: fonts/Schyler-Italic.ttf 54 | # style: italic 55 | # - family: Trajan Pro 56 | # fonts: 57 | # - asset: fonts/TrajanPro.ttf 58 | # - asset: fonts/TrajanPro_Bold.ttf 59 | # weight: 700 60 | # 61 | # For details regarding fonts from package dependencies, 62 | # see https://flutter.io/custom-fonts/#from-packages -------------------------------------------------------------------------------- /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/OneSignal/OneSignal-Flutter-SDK/4b0330cd008bbc07c84359f435263b7ad5cb1d16/ios/Assets/.gitkeep -------------------------------------------------------------------------------- /ios/Classes/OSFlutterCategories.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2017 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | #import 29 | #import 30 | 31 | #ifndef OneSignalCategories_h 32 | #define OneSignalCategories_h 33 | 34 | @interface OSNotification (Flutter) 35 | - (NSDictionary *)toJson; 36 | @end 37 | 38 | @interface OSNotificationWillDisplayEvent (Flutter) 39 | - (NSDictionary *)toJson; 40 | @end 41 | 42 | @interface OSNotificationClickEvent (Flutter) 43 | - (NSDictionary *)toJson; 44 | @end 45 | 46 | @interface OSNotificationClickResult (Flutter) 47 | - (NSDictionary *)toJson; 48 | @end 49 | 50 | @interface OSInAppMessage (Flutter) 51 | - (NSDictionary *)toJson; 52 | @end 53 | 54 | @interface NSError (Flutter) 55 | - (FlutterError *)flutterError; 56 | @end 57 | 58 | @interface OSInAppMessageWillDisplayEvent (Flutter) 59 | - (NSDictionary *)toJson; 60 | @end 61 | 62 | @interface OSInAppMessageDidDisplayEvent (Flutter) 63 | - (NSDictionary *)toJson; 64 | @end 65 | 66 | @interface OSInAppMessageWillDismissEvent (Flutter) 67 | - (NSDictionary *)toJson; 68 | @end 69 | 70 | @interface OSInAppMessageDidDismissEvent (Flutter) 71 | - (NSDictionary *)toJson; 72 | @end 73 | 74 | @interface OSInAppMessageClickEvent (Flutter) 75 | - (NSDictionary *)toJson; 76 | @end 77 | 78 | @interface OSInAppMessageClickResult (Flutter) 79 | - (NSDictionary *)toJson; 80 | @end 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /ios/Classes/OSFlutterCategories.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2017 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | #import "OSFlutterCategories.h" 29 | 30 | /* 31 | The OneSignal iOS SDK implements similar methods (`toDictionary`) 32 | However we decided to implement custom `toJson` methods for several 33 | of these objects to add more properties. 34 | 35 | TODO: Update the native iOS SDK to add these details 36 | (ie. `templateId` is missing from OSNotificationPayload's `toDictionary` 37 | method in the native SDK) and remove them from here. 38 | */ 39 | 40 | @implementation OSNotification (Flutter) 41 | - (NSDictionary *)toJson { 42 | NSMutableDictionary *json = [NSMutableDictionary new]; 43 | 44 | json[@"contentAvailable"] = @(self.contentAvailable); 45 | json[@"mutableContent"] = @(self.mutableContent); 46 | 47 | if (self.rawPayload) { 48 | NSError *jsonError; 49 | NSData *data = [NSJSONSerialization dataWithJSONObject:self.rawPayload options:NSJSONWritingPrettyPrinted error:&jsonError]; 50 | 51 | if (!jsonError) { 52 | NSString *rawPayloadString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 53 | json[@"rawPayload"] = rawPayloadString; 54 | } 55 | } 56 | 57 | if (self.notificationId) json[@"notificationId"] = self.notificationId; 58 | if (self.templateName) json[@"templateName"] = self.templateName; 59 | if (self.templateId) json[@"templateId"] = self.templateId; 60 | if (self.badge) json[@"badge"] = @(self.badge); 61 | if (self.badgeIncrement) json[@"badgeIncrement"] = @(self.badgeIncrement); 62 | if (self.sound) json[@"sound"] = self.sound; 63 | if (self.title) json[@"title"] = self.title; 64 | if (self.subtitle) json[@"subtitle"] = self.subtitle; 65 | if (self.body) json[@"body"] = self.body; 66 | if (self.launchURL) json[@"launchUrl"] = self.launchURL; 67 | if (self.additionalData) json[@"additionalData"] = self.additionalData; 68 | if (self.attachments) json[@"attachments"] = self.attachments; 69 | if (self.actionButtons) json[@"buttons"] = self.actionButtons; 70 | if (self.category) json[@"category"] = self.category; 71 | 72 | return json; 73 | } 74 | @end 75 | 76 | @implementation OSNotificationClickEvent (Flutter) 77 | - (NSDictionary *)toJson { 78 | NSMutableDictionary *json = [NSMutableDictionary new]; 79 | 80 | json[@"notification"] = self.notification.toJson; 81 | json[@"result"] = self.result.toJson; 82 | 83 | return json; 84 | } 85 | @end 86 | 87 | @implementation OSNotificationClickResult (Flutter) 88 | - (NSDictionary *)toJson { 89 | NSMutableDictionary *json = [NSMutableDictionary new]; 90 | 91 | json[@"action_id"] = self.actionId; 92 | json[@"url"] = self.url; 93 | 94 | return json; 95 | } 96 | @end 97 | 98 | @implementation OSNotificationWillDisplayEvent (Flutter) 99 | - (NSDictionary *)toJson { 100 | NSMutableDictionary *json = [NSMutableDictionary new]; 101 | 102 | json[@"notification"] = self.notification.toJson; 103 | 104 | return json; 105 | } 106 | @end 107 | 108 | @implementation OSInAppMessageWillDisplayEvent (Flutter) 109 | - (NSDictionary *)toJson { 110 | NSMutableDictionary *json = [NSMutableDictionary new]; 111 | 112 | json[@"message"] = self.message.toJson; 113 | 114 | return json; 115 | } 116 | @end 117 | 118 | @implementation OSInAppMessageDidDisplayEvent (Flutter) 119 | - (NSDictionary *)toJson { 120 | NSMutableDictionary *json = [NSMutableDictionary new]; 121 | 122 | json[@"message"] = self.message.toJson; 123 | 124 | return json; 125 | } 126 | @end 127 | 128 | @implementation OSInAppMessageWillDismissEvent (Flutter) 129 | - (NSDictionary *)toJson { 130 | NSMutableDictionary *json = [NSMutableDictionary new]; 131 | 132 | json[@"message"] = self.message.toJson; 133 | 134 | return json; 135 | } 136 | @end 137 | 138 | @implementation OSInAppMessageDidDismissEvent (Flutter) 139 | - (NSDictionary *)toJson { 140 | NSMutableDictionary *json = [NSMutableDictionary new]; 141 | 142 | json[@"message"] = self.message.toJson; 143 | 144 | return json; 145 | } 146 | @end 147 | 148 | @implementation OSInAppMessageClickEvent (Flutter) 149 | - (NSDictionary *)toJson { 150 | NSMutableDictionary *json = [NSMutableDictionary new]; 151 | 152 | json[@"message"] = self.message.toJson; 153 | json[@"result"] = self.result.toJson; 154 | 155 | return json; 156 | } 157 | @end 158 | 159 | @implementation OSInAppMessageClickResult (Flutter) 160 | - (NSDictionary *)toJson { 161 | NSMutableDictionary *json = [NSMutableDictionary new]; 162 | 163 | json[@"action_id"] = self.actionId; 164 | json[@"url"] = self.url; 165 | json[@"closing_message"] = @(self.closingMessage); 166 | 167 | return json; 168 | } 169 | @end 170 | 171 | @implementation OSInAppMessage (Flutter) 172 | - (NSDictionary *)toJson { 173 | NSMutableDictionary *json = [NSMutableDictionary new]; 174 | 175 | json[@"message_id"] = self.messageId; 176 | 177 | return json; 178 | } 179 | @end 180 | 181 | @implementation NSError (Flutter) 182 | - (FlutterError *)flutterError { 183 | return [FlutterError errorWithCode:[NSString stringWithFormat:@"%i", (int)self.code] message:self.localizedDescription details:nil]; 184 | } 185 | @end 186 | -------------------------------------------------------------------------------- /ios/Classes/OSFlutterDebug.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2017 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | 29 | #import 30 | #import 31 | 32 | @interface OSFlutterDebug : NSObject 33 | 34 | @property (strong, nonatomic) FlutterMethodChannel *channel; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /ios/Classes/OSFlutterDebug.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2023 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | #import "OSFlutterDebug.h" 29 | #import 30 | #import "OSFlutterCategories.h" 31 | 32 | @implementation OSFlutterDebug 33 | + (void)registerWithRegistrar:(NSObject*)registrar { 34 | OSFlutterDebug *instance = [OSFlutterDebug new]; 35 | 36 | instance.channel = [FlutterMethodChannel 37 | methodChannelWithName:@"OneSignal#debug" 38 | binaryMessenger:[registrar messenger]]; 39 | 40 | [registrar addMethodCallDelegate:instance channel:instance.channel]; 41 | } 42 | 43 | - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { 44 | if ([@"OneSignal#setLogLevel" isEqualToString:call.method]) 45 | [self setLogLevel:call withResult:result]; 46 | else if ([@"OneSignal#setAlertLevel" isEqualToString:call.method]) 47 | [self setAlertLevel:call withResult:result]; 48 | else 49 | result(FlutterMethodNotImplemented); 50 | } 51 | 52 | - (void)setLogLevel:(FlutterMethodCall *)call withResult:(FlutterResult)result{ 53 | ONE_S_LOG_LEVEL logLevel = (ONE_S_LOG_LEVEL)[call.arguments[@"logLevel"] intValue]; 54 | [OneSignal.Debug setLogLevel:logLevel]; 55 | result(nil); 56 | } 57 | 58 | - (void)setAlertLevel:(FlutterMethodCall *)call withResult:(FlutterResult)result{ 59 | ONE_S_LOG_LEVEL visualLogLevel = (ONE_S_LOG_LEVEL)[call.arguments[@"visualLevel"] intValue]; 60 | [OneSignal.Debug setAlertLevel:visualLogLevel]; 61 | result(nil); 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /ios/Classes/OSFlutterInAppMessages.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2017 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | 29 | #import 30 | #import 31 | #import 32 | 33 | @interface OSFlutterInAppMessages : NSObject 34 | 35 | @property (strong, nonatomic) FlutterMethodChannel *channel; 36 | + (instancetype)sharedInstance; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /ios/Classes/OSFlutterInAppMessages.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2023 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | #import "OSFlutterInAppMessages.h" 29 | #import 30 | #import "OSFlutterCategories.h" 31 | 32 | @implementation OSFlutterInAppMessages 33 | 34 | + (instancetype)sharedInstance { 35 | static OSFlutterInAppMessages *sharedInstance = nil; 36 | static dispatch_once_t onceToken; 37 | dispatch_once(&onceToken, ^{ 38 | sharedInstance = [OSFlutterInAppMessages new]; 39 | }); 40 | return sharedInstance; 41 | } 42 | 43 | + (void)registerWithRegistrar:(NSObject*)registrar { 44 | 45 | OSFlutterInAppMessages.sharedInstance.channel = [FlutterMethodChannel 46 | methodChannelWithName:@"OneSignal#inappmessages" 47 | binaryMessenger:[registrar messenger]]; 48 | 49 | [registrar addMethodCallDelegate:OSFlutterInAppMessages.sharedInstance channel:OSFlutterInAppMessages.sharedInstance.channel]; 50 | } 51 | 52 | - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { 53 | if ([@"OneSignal#addTrigger" isEqualToString:call.method]) 54 | [self addTriggers:call withResult:result]; 55 | else if ([@"OneSignal#addTriggers" isEqualToString:call.method]) 56 | [self addTriggers:call withResult:result]; 57 | else if ([@"OneSignal#removeTrigger" isEqualToString:call.method]) 58 | [self removeTrigger:call withResult:result]; 59 | else if ([@"OneSignal#removeTriggers" isEqualToString:call.method]) 60 | [self removeTriggers:call withResult:result]; 61 | else if ([@"OneSignal#clearTriggers" isEqualToString:call.method]) 62 | [self clearTriggers:call withResult:result]; 63 | else if ([@"OneSignal#paused" isEqualToString:call.method]) 64 | [self paused:call withResult:result]; 65 | else if ([@"OneSignal#arePaused" isEqualToString:call.method]) 66 | result(@([OneSignal.InAppMessages paused])); 67 | else if ([@"OneSignal#lifecycleInit" isEqualToString:call.method]) 68 | [self lifecycleInit:call withResult:result]; 69 | else 70 | result(FlutterMethodNotImplemented); 71 | 72 | } 73 | 74 | - (void)addTriggers:(FlutterMethodCall *)call withResult:(FlutterResult)result { 75 | NSDictionary *triggers = call.arguments; 76 | [OneSignal.InAppMessages addTriggers:triggers]; 77 | result(nil); 78 | } 79 | 80 | - (void)removeTrigger:(FlutterMethodCall *)call withResult:(FlutterResult)result { 81 | NSString *key = call.arguments; 82 | [OneSignal.InAppMessages removeTrigger:key]; 83 | result(nil); 84 | } 85 | 86 | - (void)removeTriggers:(FlutterMethodCall *)call withResult:(FlutterResult)result { 87 | NSArray *keys = call.arguments; 88 | [OneSignal.InAppMessages removeTriggers:keys]; 89 | result(nil); 90 | } 91 | 92 | - (void)clearTriggers:(FlutterMethodCall *)call withResult:(FlutterResult)result { 93 | [OneSignal.InAppMessages clearTriggers]; 94 | result(nil); 95 | } 96 | 97 | - (void)paused:(FlutterMethodCall *)call withResult:(FlutterResult)result { 98 | BOOL pause = [call.arguments boolValue]; 99 | [OneSignal.InAppMessages paused:pause]; 100 | result(nil); 101 | } 102 | 103 | - (void)lifecycleInit:(FlutterMethodCall *)call withResult:(FlutterResult)result { 104 | [OneSignal.InAppMessages addClickListener:OSFlutterInAppMessages.sharedInstance]; 105 | [OneSignal.InAppMessages addLifecycleListener:OSFlutterInAppMessages.sharedInstance]; 106 | } 107 | 108 | 109 | 110 | #pragma mark In App Message Click 111 | 112 | - (void)onClickInAppMessage:(OSInAppMessageClickEvent * _Nonnull)event { 113 | [self.channel invokeMethod:@"OneSignal#onClickInAppMessage" arguments:event.toJson]; 114 | } 115 | 116 | #pragma mark OSInAppMessageLifecycleListener 117 | - (void)onWillDisplayInAppMessage:(OSInAppMessageWillDisplayEvent *) event { 118 | [self.channel invokeMethod:@"OneSignal#onWillDisplayInAppMessage" arguments:event.toJson]; 119 | } 120 | 121 | - (void)onDidDisplayInAppMessage:(OSInAppMessageDidDisplayEvent *) event { 122 | [self.channel invokeMethod:@"OneSignal#onDidDisplayInAppMessage" arguments:event.toJson]; 123 | } 124 | 125 | - (void)onWillDismissInAppMessage:(OSInAppMessageWillDismissEvent *) event { 126 | [self.channel invokeMethod:@"OneSignal#onWillDismissInAppMessage" arguments:event.toJson]; 127 | } 128 | 129 | - (void)onDidDismissInAppMessage:(OSInAppMessageDidDismissEvent *) event { 130 | [self.channel invokeMethod:@"OneSignal#onDidDismissInAppMessage" arguments:event.toJson]; 131 | } 132 | 133 | @end 134 | -------------------------------------------------------------------------------- /ios/Classes/OSFlutterLiveActivities.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2023 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | #import 29 | #import 30 | 31 | @interface OSFlutterLiveActivities : NSObject 32 | 33 | @property (strong, nonatomic) FlutterMethodChannel *channel; 34 | 35 | @end -------------------------------------------------------------------------------- /ios/Classes/OSFlutterLiveActivities.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2023 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | #import "OSFlutterLiveActivities.h" 29 | #import 30 | #import "OneSignalLiveActivities/OneSignalLiveActivities-Swift.h" 31 | #import "OSFlutterCategories.h" 32 | 33 | @implementation OSFlutterLiveActivities 34 | + (void)registerWithRegistrar:(NSObject*)registrar { 35 | OSFlutterLiveActivities *instance = [OSFlutterLiveActivities new]; 36 | 37 | instance.channel = [FlutterMethodChannel 38 | methodChannelWithName:@"OneSignal#liveactivities" 39 | binaryMessenger:[registrar messenger]]; 40 | 41 | [registrar addMethodCallDelegate:instance channel:instance.channel]; 42 | } 43 | 44 | - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { 45 | if ([@"OneSignal#enterLiveActivity" isEqualToString:call.method]) 46 | [self enterLiveActivity:call withResult:result]; 47 | else if ([@"OneSignal#exitLiveActivity" isEqualToString:call.method]) 48 | [self exitLiveActivity:call withResult:result]; 49 | else if ([@"OneSignal#setPushToStartToken" isEqualToString:call.method]) 50 | [self setPushToStartToken:call withResult:result]; 51 | else if ([@"OneSignal#removePushToStartToken" isEqualToString:call.method]) 52 | [self removePushToStartToken:call withResult:result]; 53 | else if ([@"OneSignal#setupDefault" isEqualToString:call.method]) 54 | [self setupDefault:call withResult:result]; 55 | else if ([@"OneSignal#startDefault" isEqualToString:call.method]) 56 | [self startDefault:call withResult:result]; 57 | else 58 | result(FlutterMethodNotImplemented); 59 | } 60 | 61 | - (void)enterLiveActivity:(FlutterMethodCall *)call withResult:(FlutterResult)result { 62 | NSString *activityId = call.arguments[@"activityId"]; 63 | NSString *token = call.arguments[@"token"]; 64 | 65 | [OneSignal.LiveActivities enter:activityId withToken:token withSuccess:^(NSDictionary *results) { 66 | result(results); 67 | } withFailure:^(NSError *error) { 68 | result(error.flutterError); 69 | }]; 70 | } 71 | 72 | - (void)exitLiveActivity:(FlutterMethodCall *)call withResult:(FlutterResult)result { 73 | NSString *activityId = call.arguments[@"activityId"]; 74 | 75 | [OneSignal.LiveActivities exit:activityId withSuccess:^(NSDictionary *results) { 76 | result(results); 77 | } withFailure:^(NSError *error) { 78 | result(error.flutterError); 79 | }]; 80 | } 81 | 82 | - (void)setPushToStartToken:(FlutterMethodCall *)call withResult:(FlutterResult)result { 83 | NSString *activityType = call.arguments[@"activityType"]; 84 | NSString *token = call.arguments[@"token"]; 85 | NSError* err=nil; 86 | 87 | if (@available(iOS 17.2, *)) { 88 | [OneSignalLiveActivitiesManagerImpl setPushToStartToken:activityType withToken:token error:&err]; 89 | if (err) { 90 | [OneSignalLog onesignalLog:ONE_S_LL_ERROR message:[NSString stringWithFormat:@"activityType must be the name of your ActivityAttributes struct"]]; 91 | } 92 | } else { 93 | [OneSignalLog onesignalLog:ONE_S_LL_ERROR message:[NSString stringWithFormat:@"cannot setPushToStartToken on iOS < 17.2"]]; 94 | } 95 | 96 | result(nil); 97 | } 98 | 99 | - (void)removePushToStartToken:(FlutterMethodCall *)call withResult:(FlutterResult)result { 100 | NSString *activityType = call.arguments[@"activityType"]; 101 | NSError* err=nil; 102 | 103 | if (@available(iOS 17.2, *)) { 104 | [OneSignalLiveActivitiesManagerImpl removePushToStartToken:activityType error:&err]; 105 | if (err) { 106 | [OneSignalLog onesignalLog:ONE_S_LL_ERROR message:[NSString stringWithFormat:@"activityType must be the name of your ActivityAttributes struct"]]; 107 | } 108 | } else { 109 | [OneSignalLog onesignalLog:ONE_S_LL_ERROR message:[NSString stringWithFormat:@"cannot removePushToStartToken on iOS < 17.2"]]; 110 | } 111 | 112 | result(nil); 113 | } 114 | 115 | - (void)setupDefault:(FlutterMethodCall *)call withResult:(FlutterResult)result { 116 | NSDictionary *options = call.arguments[@"options"]; 117 | 118 | LiveActivitySetupOptions *laOptions = nil; 119 | 120 | if (options != [NSNull null]) { 121 | laOptions = [LiveActivitySetupOptions alloc]; 122 | [laOptions setEnablePushToStart:[options[@"enablePushToStart"] boolValue]]; 123 | [laOptions setEnablePushToUpdate:[options[@"enablePushToUpdate"] boolValue]]; 124 | } 125 | 126 | if (@available(iOS 16.1, *)) { 127 | [OneSignalLiveActivitiesManagerImpl setupDefaultWithOptions:laOptions]; 128 | } else { 129 | [OneSignalLog onesignalLog:ONE_S_LL_ERROR message:[NSString stringWithFormat:@"cannot setupDefault on iOS < 16.1"]]; 130 | } 131 | 132 | result(nil); 133 | } 134 | 135 | - (void)startDefault:(FlutterMethodCall *)call withResult:(FlutterResult)result { 136 | NSString *activityId = call.arguments[@"activityId"]; 137 | NSDictionary *attributes = call.arguments[@"attributes"]; 138 | NSDictionary *content = call.arguments[@"content"]; 139 | 140 | if (@available(iOS 16.1, *)) { 141 | [OneSignalLiveActivitiesManagerImpl startDefault:activityId attributes:attributes content:content]; 142 | } else { 143 | [OneSignalLog onesignalLog:ONE_S_LL_ERROR message:[NSString stringWithFormat:@"cannot startDefault on iOS < 16.1"]]; 144 | } 145 | 146 | result(nil); 147 | } 148 | 149 | @end 150 | -------------------------------------------------------------------------------- /ios/Classes/OSFlutterLocation.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2017 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | 29 | #import 30 | #import 31 | 32 | @interface OSFlutterLocation : NSObject 33 | 34 | @property (strong, nonatomic) FlutterMethodChannel *channel; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /ios/Classes/OSFlutterLocation.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2023 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | #import "OSFlutterLocation.h" 29 | #import 30 | #import "OSFlutterCategories.h" 31 | 32 | @implementation OSFlutterLocation 33 | + (void)registerWithRegistrar:(NSObject*)registrar { 34 | OSFlutterLocation *instance = [OSFlutterLocation new]; 35 | 36 | instance.channel = [FlutterMethodChannel 37 | methodChannelWithName:@"OneSignal#location" 38 | binaryMessenger:[registrar messenger]]; 39 | 40 | [registrar addMethodCallDelegate:instance channel:instance.channel]; 41 | } 42 | 43 | - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { 44 | if ([@"OneSignal#requestPermission" isEqualToString:call.method]) 45 | [self requestPermission:call withResult:result]; 46 | else if ([@"OneSignal#setShared" isEqualToString:call.method]) 47 | [self setLocationShared:call withResult:result]; 48 | else if ([@"OneSignal#isShared" isEqualToString:call.method]) 49 | result(@([OneSignal.Location isShared])); 50 | else 51 | result(FlutterMethodNotImplemented); 52 | } 53 | 54 | - (void)setLocationShared:(FlutterMethodCall *)call withResult:(FlutterResult)result { 55 | BOOL locationShared = [call.arguments boolValue]; 56 | [OneSignal.Location setShared:locationShared]; 57 | result(nil); 58 | } 59 | 60 | - (void)requestPermission:(FlutterMethodCall *)call withResult:(FlutterResult)result { 61 | [OneSignal.Location requestPermission]; 62 | result(nil); 63 | } 64 | 65 | 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /ios/Classes/OSFlutterNotifications.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2017 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | 29 | #import 30 | #import 31 | #import 32 | 33 | @interface OSFlutterNotifications : NSObject 34 | 35 | @property (strong, nonatomic) FlutterMethodChannel *channel; 36 | + (instancetype)sharedInstance; 37 | @property (strong, nonatomic) NSMutableDictionary* onWillDisplayEventCache; 38 | @property (strong, nonatomic) NSMutableDictionary* preventedDefaultCache; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /ios/Classes/OSFlutterPushSubscription.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2017 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | 29 | #import 30 | #import 31 | #import 32 | 33 | @interface OSFlutterPushSubscription : NSObject 34 | 35 | + (instancetype)sharedInstance; 36 | @property (strong, nonatomic) FlutterMethodChannel *channel; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /ios/Classes/OSFlutterPushSubscription.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2023 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | #import "OSFlutterPushSubscription.h" 29 | #import 30 | #import 31 | #import "OSFlutterCategories.h" 32 | 33 | @implementation OSFlutterPushSubscription 34 | 35 | + (void)registerWithRegistrar:(NSObject*)registrar { 36 | OSFlutterPushSubscription *instance = [OSFlutterPushSubscription new]; 37 | 38 | instance.channel = [FlutterMethodChannel 39 | methodChannelWithName:@"OneSignal#pushsubscription" 40 | binaryMessenger:[registrar messenger]]; 41 | 42 | [registrar addMethodCallDelegate:instance channel:instance.channel]; 43 | } 44 | 45 | - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { 46 | if ([@"OneSignal#pushSubscriptionId" isEqualToString:call.method]) 47 | result(OneSignal.User.pushSubscription.id); 48 | else if ([@"OneSignal#pushSubscriptionToken" isEqualToString:call.method]) 49 | result(OneSignal.User.pushSubscription.token); 50 | else if ([@"OneSignal#pushSubscriptionOptedIn" isEqualToString:call.method]) 51 | result(@(OneSignal.User.pushSubscription.optedIn)); 52 | else if ([@"OneSignal#optIn" isEqualToString:call.method]) 53 | [self optIn:call withResult:result]; 54 | else if ([@"OneSignal#optOut" isEqualToString:call.method]) 55 | [self optOut:call withResult:result]; 56 | else if ([@"OneSignal#lifecycleInit" isEqualToString:call.method]) 57 | [self lifecycleInit:call withResult:result]; 58 | else 59 | result(FlutterMethodNotImplemented); 60 | } 61 | 62 | - (void)optIn:(FlutterMethodCall *)call withResult:(FlutterResult)result { 63 | [OneSignal.User.pushSubscription optIn]; 64 | result(nil); 65 | } 66 | 67 | - (void)optOut:(FlutterMethodCall *)call withResult:(FlutterResult)result { 68 | [OneSignal.User.pushSubscription optOut]; 69 | result(nil); 70 | } 71 | 72 | - (void)lifecycleInit:(FlutterMethodCall *)call withResult:(FlutterResult)result { 73 | [OneSignal.User.pushSubscription addObserver:self]; 74 | result(nil); 75 | } 76 | 77 | - (void)onPushSubscriptionDidChangeWithState:(OSPushSubscriptionChangedState *)state { 78 | [self.channel invokeMethod:@"OneSignal#onPushSubscriptionChange" arguments:state.jsonRepresentation]; 79 | } 80 | 81 | @end 82 | 83 | -------------------------------------------------------------------------------- /ios/Classes/OSFlutterSession.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2017 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | 29 | #import 30 | #import 31 | 32 | @interface OSFlutterSession : NSObject 33 | 34 | @property (strong, nonatomic) FlutterMethodChannel *channel; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /ios/Classes/OSFlutterSession.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2023 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | #import "OSFlutterSession.h" 29 | #import 30 | #import "OSFlutterCategories.h" 31 | 32 | @implementation OSFlutterSession 33 | + (void)registerWithRegistrar:(NSObject*)registrar { 34 | OSFlutterSession *instance = [OSFlutterSession new]; 35 | 36 | instance.channel = [FlutterMethodChannel 37 | methodChannelWithName:@"OneSignal#session" 38 | binaryMessenger:[registrar messenger]]; 39 | 40 | [registrar addMethodCallDelegate:instance channel:instance.channel]; 41 | } 42 | 43 | - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { 44 | if ([@"OneSignal#addOutcome" isEqualToString:call.method]) { 45 | [self addOutcome:call withResult:result]; 46 | } else if ([@"OneSignal#addUniqueOutcome" isEqualToString:call.method]) { 47 | [self addUniqueOutcome:call withResult:result]; 48 | } else if ([@"OneSignal#addOutcomeWithValue" isEqualToString:call.method]) { 49 | [self addOutcomeWithValue:call withResult:result]; 50 | } else { 51 | result(FlutterMethodNotImplemented); 52 | } 53 | } 54 | 55 | - (void)addOutcome:(FlutterMethodCall *)call withResult:(FlutterResult)result { 56 | NSString *name = call.arguments; 57 | [OneSignal.Session addOutcome:name]; 58 | result(nil); 59 | } 60 | 61 | - (void)addUniqueOutcome:(FlutterMethodCall *)call withResult:(FlutterResult)result { 62 | NSString *name = call.arguments; 63 | [OneSignal.Session addUniqueOutcome:name]; 64 | result(nil); 65 | } 66 | 67 | - (void)addOutcomeWithValue:(FlutterMethodCall *)call withResult:(FlutterResult)result { 68 | NSString *name = call.arguments[@"outcome_name"]; 69 | NSNumber *value = call.arguments[@"outcome_value"]; 70 | [OneSignal.Session addOutcomeWithValue:name value:value]; 71 | result(nil); 72 | } 73 | 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /ios/Classes/OSFlutterUser.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2017 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | 29 | #import 30 | #import 31 | 32 | @interface OSFlutterUser : NSObject 33 | 34 | @property (strong, nonatomic) FlutterMethodChannel *channel; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /ios/Classes/OneSignalPlugin.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2017 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | #import 29 | #import 30 | 31 | @interface OneSignalPlugin : NSObject 32 | 33 | // Do NOT initialize instances of this class. 34 | // You must only reference the shared instance. 35 | + (instancetype)sharedInstance; 36 | @end 37 | -------------------------------------------------------------------------------- /ios/Classes/OneSignalPlugin.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Modified MIT License 3 | * 4 | * Copyright 2023 OneSignal 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * 1. The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * 2. All copies of substantial portions of the Software may only be used in connection 17 | * with services provided by OneSignal. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | #import "OneSignalPlugin.h" 29 | #import "OSFlutterCategories.h" 30 | #import "OSFlutterDebug.h" 31 | #import "OSFlutterUser.h" 32 | #import "OSFlutterNotifications.h" 33 | #import "OSFlutterSession.h" 34 | #import "OSFlutterLocation.h" 35 | #import "OSFlutterInAppMessages.h" 36 | #import "OSFlutterLiveActivities.h" 37 | 38 | 39 | @interface OneSignalPlugin () 40 | 41 | @property (strong, nonatomic) FlutterMethodChannel *channel; 42 | 43 | @end 44 | 45 | @implementation OneSignalPlugin 46 | 47 | + (instancetype)sharedInstance { 48 | static OneSignalPlugin *sharedInstance = nil; 49 | static dispatch_once_t onceToken; 50 | dispatch_once(&onceToken, ^{ 51 | sharedInstance = [OneSignalPlugin new]; 52 | }); 53 | return sharedInstance; 54 | } 55 | 56 | #pragma mark FlutterPlugin 57 | + (void)registerWithRegistrar:(NSObject*)registrar { 58 | 59 | OneSignalWrapper.sdkType = @"flutter"; 60 | OneSignalWrapper.sdkVersion = @"050303"; 61 | [OneSignal initialize:nil withLaunchOptions:nil]; 62 | 63 | OneSignalPlugin.sharedInstance.channel = [FlutterMethodChannel 64 | methodChannelWithName:@"OneSignal" 65 | binaryMessenger:[registrar messenger]]; 66 | 67 | [registrar addMethodCallDelegate:OneSignalPlugin.sharedInstance channel:OneSignalPlugin.sharedInstance.channel]; 68 | [OSFlutterDebug registerWithRegistrar:registrar]; 69 | [OSFlutterUser registerWithRegistrar:registrar]; 70 | [OSFlutterNotifications registerWithRegistrar:registrar]; 71 | [OSFlutterSession registerWithRegistrar:registrar]; 72 | [OSFlutterLocation registerWithRegistrar:registrar]; 73 | [OSFlutterInAppMessages registerWithRegistrar:registrar]; 74 | [OSFlutterLiveActivities registerWithRegistrar:registrar]; 75 | } 76 | 77 | - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { 78 | if ([@"OneSignal#initialize" isEqualToString:call.method]) 79 | [self initialize:call withResult:result]; 80 | else if ([@"OneSignal#login" isEqualToString:call.method]) 81 | [self login:call withResult:result]; 82 | else if ([@"OneSignal#logout" isEqualToString:call.method]) 83 | [self logout:call withResult:result]; 84 | else if ([@"OneSignal#consentRequired" isEqualToString:call.method]) 85 | [self setConsentRequired:call withResult:result]; 86 | else if ([@"OneSignal#consentGiven" isEqualToString:call.method]) 87 | [self setConsentGiven:call withResult:result]; 88 | else 89 | result(FlutterMethodNotImplemented); 90 | } 91 | 92 | #pragma mark Init 93 | 94 | - (void)initialize:(FlutterMethodCall *)call withResult:(FlutterResult)result{ 95 | [OneSignal initialize:call.arguments[@"appId"] withLaunchOptions:nil]; 96 | result(nil); 97 | } 98 | 99 | #pragma mark Login Logout 100 | 101 | - (void)login:(FlutterMethodCall *)call withResult:(FlutterResult)result{ 102 | [OneSignal login:call.arguments[@"externalId"]]; 103 | result(nil); 104 | } 105 | 106 | - (void)logout:(FlutterMethodCall *)call withResult:(FlutterResult)result{ 107 | [OneSignal logout]; 108 | result(nil); 109 | } 110 | 111 | #pragma mark Privacy Consent 112 | 113 | - (void)setConsentGiven:(FlutterMethodCall *)call withResult:(FlutterResult)result{ 114 | BOOL granted = [call.arguments[@"granted"] boolValue]; 115 | [OneSignal setConsentGiven:granted]; 116 | result(nil); 117 | } 118 | 119 | - (void)setConsentRequired:(FlutterMethodCall *)call withResult:(FlutterResult)result{ 120 | BOOL required = [call.arguments[@"required"] boolValue]; 121 | [OneSignal setConsentRequired:required]; 122 | result(nil); 123 | } 124 | 125 | @end 126 | -------------------------------------------------------------------------------- /ios/onesignal_flutter.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 3 | # 4 | Pod::Spec.new do |s| 5 | s.name = 'onesignal_flutter' 6 | s.version = '5.3.3' 7 | s.summary = 'The OneSignal Flutter SDK' 8 | s.description = 'Allows you to easily add OneSignal to your flutter projects, to make sending and handling push notifications easy' 9 | s.homepage = 'https://www.onesignal.com' 10 | s.license = { :file => '../LICENSE' } 11 | s.author = { 'Brad Hesse' => 'brad@onesignal.com', 'Josh Kasten' => 'josh@onesignal.com' } 12 | s.source = { :path => '.' } 13 | s.source_files = 'Classes/**/*' 14 | s.public_header_files = 'Classes/**/*.h' 15 | s.dependency 'Flutter' 16 | s.dependency 'OneSignalXCFramework', '5.2.13' 17 | s.ios.deployment_target = '11.0' 18 | s.static_framework = true 19 | end 20 | -------------------------------------------------------------------------------- /lib/onesignal_flutter.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io' show Platform; 3 | import 'package:flutter/services.dart'; 4 | import 'package:onesignal_flutter/src/debug.dart'; 5 | import 'package:onesignal_flutter/src/user.dart'; 6 | import 'package:onesignal_flutter/src/notifications.dart'; 7 | import 'package:onesignal_flutter/src/session.dart'; 8 | import 'package:onesignal_flutter/src/location.dart'; 9 | import 'package:onesignal_flutter/src/inappmessages.dart'; 10 | import 'package:onesignal_flutter/src/liveactivities.dart'; 11 | 12 | export 'src/defines.dart'; 13 | export 'src/pushsubscription.dart'; 14 | export 'src/subscription.dart'; 15 | export 'src/notification.dart'; 16 | export 'src/notifications.dart'; 17 | export 'src/inappmessage.dart'; 18 | export 'src/inappmessages.dart'; 19 | export 'src/liveactivities.dart'; 20 | 21 | class OneSignal { 22 | /// A singleton representing the OneSignal SDK. 23 | /// Note that the iOS and Android native libraries are static, 24 | /// so if you create multiple instances of OneSignal, they will 25 | /// mostly share the same state. 26 | // ignore: non_constant_identifier_names 27 | static OneSignalDebug Debug = new OneSignalDebug(); 28 | // ignore: non_constant_identifier_names 29 | static OneSignalUser User = new OneSignalUser(); 30 | // ignore: non_constant_identifier_names 31 | static OneSignalNotifications Notifications = new OneSignalNotifications(); 32 | // ignore: non_constant_identifier_names 33 | static OneSignalSession Session = new OneSignalSession(); 34 | // ignore: non_constant_identifier_names 35 | static OneSignalLocation Location = new OneSignalLocation(); 36 | // ignore: non_constant_identifier_names 37 | static OneSignalInAppMessages InAppMessages = new OneSignalInAppMessages(); 38 | // ignore: non_constant_identifier_names 39 | static OneSignalLiveActivities LiveActivities = new OneSignalLiveActivities(); 40 | 41 | // private channels used to bridge to ObjC/Java 42 | static MethodChannel _channel = const MethodChannel('OneSignal'); 43 | 44 | /// The initializer for OneSignal. 45 | /// 46 | /// The initializer accepts an [appId] which the developer can get 47 | /// from the OneSignal consoleas well as a dictonary of [launchOptions] 48 | static void initialize(String appId) { 49 | _channel.invokeMethod('OneSignal#initialize', {'appId': appId}); 50 | InAppMessages.lifecycleInit(); 51 | User.lifecycleInit(); 52 | User.pushSubscription.lifecycleInit(); 53 | Notifications.lifecycleInit(); 54 | } 55 | 56 | /// Login to OneSignal under the user identified by the [externalId] provided. 57 | /// 58 | /// The act of logging a user into the OneSignal SDK will switch the 59 | /// user context to that specific user. 60 | static Future login(String externalId) async { 61 | return await _channel 62 | .invokeMethod('OneSignal#login', {'externalId': externalId}); 63 | } 64 | 65 | /// Login to OneSignal under the user identified by the [externalId] provided. 66 | /// 67 | /// The act of logging a user into the OneSignal SDK will switch the 68 | /// user context to that specific user. 69 | @Deprecated( 70 | 'Do not use, this method is not implemented. See https://documentation.onesignal.com/docs/identity-verification for updates.') 71 | static Future loginWithJWT(String externalId, String jwt) async { 72 | if (Platform.isAndroid) { 73 | return await _channel.invokeMethod( 74 | 'OneSignal#loginWithJWT', {'externalId': externalId, 'jwt': jwt}); 75 | } 76 | } 77 | 78 | /// Logout the user previously logged in via [login]. The user property now 79 | /// 80 | /// references a new device-scoped user. A device-scoped user has no user identity 81 | /// that can later be retrieved, except through this device as long as the app 82 | /// remains installed and the app data is not cleared. 83 | static Future logout() async { 84 | return await _channel.invokeMethod('OneSignal#logout'); 85 | } 86 | 87 | /// Sets the whether or not privacy consent has been [granted] 88 | /// 89 | /// This field is only relevant when the application has 90 | /// opted into data privacy protections. See [consentRequired]. 91 | static Future consentGiven(bool granted) async { 92 | return await _channel 93 | .invokeMethod("OneSignal#consentGiven", {'granted': granted}); 94 | } 95 | 96 | /// Allows you to completely disable the SDK until your app calls the 97 | /// OneSignal.consentGiven(true) function. This is useful if you want 98 | /// to show a Terms and Conditions or privacy popup for GDPR. 99 | static Future consentRequired(bool require) async { 100 | return await _channel 101 | .invokeMethod("OneSignal#consentRequired", {'required': require}); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /lib/src/debug.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:onesignal_flutter/src/defines.dart'; 4 | 5 | class OneSignalDebug { 6 | // private channels used to bridge to ObjC/Java 7 | MethodChannel _channel = const MethodChannel('OneSignal#debug'); 8 | 9 | /// Sets the log level for the SDK. 10 | /// 11 | /// The parameter [logLevel] controls 12 | /// how verbose logs in the console/logcat are 13 | Future setLogLevel(OSLogLevel logLevel) async { 14 | return await _channel 15 | .invokeMethod("OneSignal#setLogLevel", {'logLevel': logLevel.index}); 16 | } 17 | 18 | /// Sets the log level for the SDK. 19 | /// 20 | /// The parameter [visualLevel] controls 21 | /// if the SDK will show alerts for each logged message 22 | Future setAlertLevel(OSLogLevel visualLevel) async { 23 | return await _channel.invokeMethod( 24 | "OneSignal#setAlertLevel", {'visualLevel': visualLevel.index}); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/src/defines.dart: -------------------------------------------------------------------------------- 1 | // Determines how notifications should be displayed 2 | enum OSNotificationDisplayType { none, alert, notification } 3 | 4 | /// Indicates whether a user tapped a notification (`opened`) 5 | /// or took a specific action by tapping a button (`actionTaken`) 6 | enum OSNotificationActionType { opened, actionTaken } 7 | 8 | enum OSNotificationPermission { 9 | notDetermined, 10 | denied, 11 | authorized, 12 | provisional, // only available in iOS 12 13 | ephemeral, // only available in iOS 14 14 | } 15 | 16 | /// An enum that declares different types of log levels you can 17 | /// use with the OneSignal SDK, going from the least verbose (none) 18 | /// to verbose (print all comments). 19 | enum OSLogLevel { none, fatal, error, warn, info, debug, verbose } 20 | 21 | /// Various iOS Settings that can be passed during initialization 22 | enum OSiOSSettings { 23 | autoPrompt, 24 | inAppAlerts, 25 | inAppLaunchUrl, 26 | promptBeforeOpeningPushUrl, 27 | inFocusDisplayOption 28 | } 29 | 30 | enum OSSession { DIRECT, INDIRECT, UNATTRIBUTED, DISABLED } 31 | 32 | /// Applies to iOS notifications only 33 | /// Determines if the badgeCount is used to increment 34 | /// the existing badge count, or sets the badge count directly 35 | enum OSCreateNotificationBadgeType { increase, setTo } 36 | 37 | /// control how the notification is delayed 38 | /// timezone: Deliver at a specific time of day in each user's timezone 39 | /// last-active: Deliver at the same time the user last used your app 40 | enum OSCreateNotificationDelayOption { timezone, lastActive } 41 | -------------------------------------------------------------------------------- /lib/src/inappmessage.dart: -------------------------------------------------------------------------------- 1 | import 'package:onesignal_flutter/src/utils.dart'; 2 | 3 | /// When a click action is defined on an In App Message form the dashboard, 4 | /// the handler returns an OSInAppMessageClickEvent object so the Dart code can act accordingly 5 | /// This event includes the message and the result of the click 6 | class OSInAppMessageClickEvent extends JSONStringRepresentable { 7 | late OSInAppMessage message; 8 | 9 | late OSInAppMessageClickResult result; 10 | 11 | OSInAppMessageClickEvent(Map json) { 12 | this.message = OSInAppMessage(json["message"].cast()); 13 | this.result = 14 | OSInAppMessageClickResult(json["result"].cast()); 15 | } 16 | 17 | String jsonRepresentation() { 18 | return convertToJsonString({ 19 | 'message': this.message, 20 | 'result': this.result, 21 | }); 22 | } 23 | } 24 | 25 | /// When a click action is defined on an In App Message form the dashboard, 26 | /// the handler returns an OSInAppMessageAction object so the Dart code can act accordingly 27 | /// This allows for custom action events within Dart 28 | class OSInAppMessageClickResult extends JSONStringRepresentable { 29 | // Name of the action event defined for the IAM element 30 | String? actionId; 31 | 32 | // URL given to the IAM element defined in the dashboard 33 | String? url; 34 | 35 | // Whether or not the click action should dismiss the IAM 36 | bool closingMessage = false; 37 | 38 | OSInAppMessageClickResult(Map json) { 39 | this.actionId = json["action_id"]; 40 | this.url = json["url"]; 41 | this.closingMessage = json["closing_message"] as bool; 42 | } 43 | 44 | String jsonRepresentation() { 45 | return convertToJsonString({ 46 | 'action_id': this.actionId, 47 | 'url': this.url, 48 | 'closing_message': this.closingMessage, 49 | }); 50 | } 51 | } 52 | 53 | class OSInAppMessage extends JSONStringRepresentable { 54 | String? messageId; 55 | 56 | OSInAppMessage(Map json) { 57 | this.messageId = json["message_id"]; 58 | } 59 | 60 | String jsonRepresentation() { 61 | return convertToJsonString({'message_id': this.messageId}); 62 | } 63 | } 64 | 65 | class OSInAppMessageWillDisplayEvent extends JSONStringRepresentable { 66 | late OSInAppMessage message; 67 | 68 | OSInAppMessageWillDisplayEvent(Map json) { 69 | this.message = OSInAppMessage(json["message"].cast()); 70 | } 71 | 72 | String jsonRepresentation() { 73 | return convertToJsonString({'message': this.message.jsonRepresentation()}); 74 | } 75 | } 76 | 77 | class OSInAppMessageDidDisplayEvent extends JSONStringRepresentable { 78 | late OSInAppMessage message; 79 | 80 | OSInAppMessageDidDisplayEvent(Map json) { 81 | this.message = OSInAppMessage(json["message"].cast()); 82 | } 83 | 84 | String jsonRepresentation() { 85 | return convertToJsonString({'message': this.message.jsonRepresentation()}); 86 | } 87 | } 88 | 89 | class OSInAppMessageWillDismissEvent extends JSONStringRepresentable { 90 | late OSInAppMessage message; 91 | 92 | OSInAppMessageWillDismissEvent(Map json) { 93 | this.message = OSInAppMessage(json["message"].cast()); 94 | } 95 | 96 | String jsonRepresentation() { 97 | return convertToJsonString({'message': this.message.jsonRepresentation()}); 98 | } 99 | } 100 | 101 | class OSInAppMessageDidDismissEvent extends JSONStringRepresentable { 102 | late OSInAppMessage message; 103 | 104 | OSInAppMessageDidDismissEvent(Map json) { 105 | this.message = OSInAppMessage(json["message"].cast()); 106 | } 107 | 108 | String jsonRepresentation() { 109 | return convertToJsonString({'message': this.message.jsonRepresentation()}); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /lib/src/inappmessages.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:onesignal_flutter/onesignal_flutter.dart'; 4 | import 'package:onesignal_flutter/src/inappmessage.dart'; 5 | 6 | typedef void OnClickInAppMessageListener(OSInAppMessageClickEvent event); 7 | 8 | typedef void OnWillDisplayInAppMessageListener( 9 | OSInAppMessageWillDisplayEvent event); 10 | typedef void OnDidDisplayInAppMessageListener( 11 | OSInAppMessageDidDisplayEvent event); 12 | typedef void OnWillDismissInAppMessageListener( 13 | OSInAppMessageWillDismissEvent event); 14 | typedef void OnDidDismissInAppMessageListener( 15 | OSInAppMessageDidDismissEvent event); 16 | 17 | class OneSignalInAppMessages { 18 | // private channels used to bridge to ObjC/Java 19 | MethodChannel _channel = const MethodChannel('OneSignal#inappmessages'); 20 | 21 | // constructor method 22 | OneSignalInAppMessages() { 23 | this._channel.setMethodCallHandler(_handleMethod); 24 | } 25 | 26 | List _clickListeners = 27 | []; 28 | List _willDisplayListeners = 29 | []; 30 | List _didDisplayListeners = 31 | []; 32 | List _willDismissListeners = 33 | []; 34 | List _didDismissListeners = 35 | []; 36 | 37 | /// Adds a single key, value trigger, which will trigger an in app message 38 | /// if one exists matching the specific trigger added 39 | Future addTrigger(String key, String value) async { 40 | return await _channel.invokeMethod("OneSignal#addTrigger", {key: value}); 41 | } 42 | 43 | /// Adds one or more key, value triggers, which will trigger in app messages 44 | /// (one at a time) if any exist matching the specific triggers added 45 | Future addTriggers(Map triggers) async { 46 | return await _channel.invokeMethod("OneSignal#addTriggers", triggers); 47 | } 48 | 49 | /// Remove a single key, value trigger to prevent an in app message from 50 | /// showing with that trigger 51 | Future removeTrigger(String key) async { 52 | return await _channel.invokeMethod("OneSignal#removeTrigger", key); 53 | } 54 | 55 | /// Remove one or more key, value triggers to prevent any in app messages 56 | /// from showing with those triggers 57 | Future removeTriggers(List keys) async { 58 | return await _channel.invokeMethod("OneSignal#removeTriggers", keys); 59 | } 60 | 61 | /// Get the trigger value associated with the key provided 62 | Future clearTriggers() async { 63 | return await _channel.invokeMethod("OneSignal#clearTriggers"); 64 | } 65 | 66 | /// Toggles the showing of all in app messages 67 | Future paused(bool pause) async { 68 | return await _channel.invokeMethod("OneSignal#paused", pause); 69 | } 70 | 71 | /// Gets whether of not in app messages are paused 72 | Future arePaused() async { 73 | return await _channel.invokeMethod("OneSignal#arePaused"); 74 | } 75 | 76 | Future lifecycleInit() async { 77 | return await _channel.invokeMethod("OneSignal#lifecycleInit"); 78 | } 79 | 80 | // Private function that gets called by ObjC/Java 81 | Future _handleMethod(MethodCall call) async { 82 | if (call.method == 'OneSignal#onClickInAppMessage') { 83 | for (var listener in _clickListeners) { 84 | listener( 85 | OSInAppMessageClickEvent(call.arguments.cast())); 86 | } 87 | } else if (call.method == 'OneSignal#onWillDisplayInAppMessage') { 88 | for (var listener in _willDisplayListeners) { 89 | listener(OSInAppMessageWillDisplayEvent( 90 | call.arguments.cast())); 91 | } 92 | } else if (call.method == 'OneSignal#onDidDisplayInAppMessage') { 93 | for (var listener in _didDisplayListeners) { 94 | listener(OSInAppMessageDidDisplayEvent( 95 | call.arguments.cast())); 96 | } 97 | } else if (call.method == 'OneSignal#onWillDismissInAppMessage') { 98 | for (var listener in _willDismissListeners) { 99 | listener(OSInAppMessageWillDismissEvent( 100 | call.arguments.cast())); 101 | } 102 | } else if (call.method == 'OneSignal#onDidDismissInAppMessage') { 103 | for (var listener in _didDismissListeners) { 104 | listener(OSInAppMessageDidDismissEvent( 105 | call.arguments.cast())); 106 | } 107 | } 108 | return null; 109 | } 110 | 111 | /// The in app message clicked handler is called whenever the user clicks a 112 | /// OneSignal IAM button or image with an action event attacthed to it 113 | void addClickListener(OnClickInAppMessageListener listener) { 114 | _clickListeners.add(listener); 115 | } 116 | 117 | void removeClickListener(OnClickInAppMessageListener listener) { 118 | _clickListeners.remove(listener); 119 | } 120 | 121 | void addWillDisplayListener(OnWillDisplayInAppMessageListener listener) { 122 | _willDisplayListeners.add(listener); 123 | } 124 | 125 | void removeWillDisplayListener(OnWillDisplayInAppMessageListener listener) { 126 | _willDisplayListeners.remove(listener); 127 | } 128 | 129 | void addDidDisplayListener(OnDidDisplayInAppMessageListener listener) { 130 | _didDisplayListeners.add(listener); 131 | } 132 | 133 | void removeDidDisplayListener(OnDidDisplayInAppMessageListener listener) { 134 | _didDisplayListeners.remove(listener); 135 | } 136 | 137 | void addWillDismissListener(OnWillDismissInAppMessageListener listener) { 138 | _willDismissListeners.add(listener); 139 | } 140 | 141 | void removeWillDismissListener(OnWillDismissInAppMessageListener listener) { 142 | _willDismissListeners.remove(listener); 143 | } 144 | 145 | void addDidDismissListener(OnDidDismissInAppMessageListener listener) { 146 | _didDismissListeners.add(listener); 147 | } 148 | 149 | void removeDidDismissListener(OnDidDismissInAppMessageListener listener) { 150 | _didDismissListeners.remove(listener); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /lib/src/liveactivities.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io'; 3 | import 'package:flutter/services.dart'; 4 | 5 | class OneSignalLiveActivities { 6 | // private channels used to bridge to ObjC/Java 7 | MethodChannel _channel = const MethodChannel('OneSignal#liveactivities'); 8 | 9 | /// Indicate this device has exited a live activity, identified within OneSignal by the [activityId]. The 10 | /// [token] is the ActivityKit's update token that will be used to update the live activity. 11 | /// 12 | /// Only applies to iOS. 13 | Future enterLiveActivity(String activityId, String token) async { 14 | if (Platform.isIOS) { 15 | return await _channel.invokeMethod("OneSignal#enterLiveActivity", 16 | {'activityId': activityId, 'token': token}); 17 | } 18 | } 19 | 20 | /// Indicate this device has exited a live activity, identified within OneSignal by the [activityId]. 21 | /// 22 | /// Only applies to iOS. 23 | Future exitLiveActivity(String activityId) async { 24 | if (Platform.isIOS) { 25 | return await _channel.invokeMethod( 26 | "OneSignal#exitLiveActivity", {'activityId': activityId}); 27 | } 28 | } 29 | 30 | /// Enable the OneSignalSDK to setup the default`DefaultLiveActivityAttributes` structure, 31 | /// which conforms to the `OneSignalLiveActivityAttributes`. When using this function, the 32 | /// widget attributes are owned by the OneSignal SDK, which will allow the SDK to handle the 33 | /// entire lifecycle of the live activity. All that is needed from an app-perspective is to 34 | /// create a Live Activity widget in a widget extension, with a `ActivityConfiguration` for 35 | /// `DefaultLiveActivityAttributes`. This is most useful for users that (1) only have one Live 36 | /// Activity widget and (2) are using a cross-platform framework and do not want to create the 37 | /// cross-platform <-> iOS native bindings to manage ActivityKit. An optional [options] 38 | /// parameter can be provided for more granular setup options. 39 | /// 40 | /// Only applies to iOS. 41 | Future setupDefault({LiveActivitySetupOptions? options}) async { 42 | if (Platform.isIOS) { 43 | dynamic optionsMap; 44 | 45 | if (options != null) { 46 | optionsMap = { 47 | 'enablePushToStart': options.enablePushToStart, 48 | 'enablePushToUpdate': options.enablePushToUpdate, 49 | }; 50 | } 51 | 52 | return await _channel 53 | .invokeMethod("OneSignal#setupDefault", {'options': optionsMap}); 54 | } 55 | } 56 | 57 | /// Start a new LiveActivity that is modelled by the default`DefaultLiveActivityAttributes` 58 | /// structure. The `DefaultLiveActivityAttributes` is initialized with the dynamic [attributes] 59 | /// and [content] passed in. The live activity started can be updated with the [activityId] 60 | /// provided. 61 | /// 62 | /// Only applies to iOS. 63 | Future startDefault( 64 | String activityId, dynamic attributes, dynamic content) async { 65 | if (Platform.isIOS) { 66 | return await _channel.invokeMethod("OneSignal#startDefault", { 67 | 'activityId': activityId, 68 | 'attributes': attributes, 69 | 'content': content 70 | }); 71 | } 72 | } 73 | 74 | /// Indicate this device is capable of receiving pushToStart live activities for the 75 | /// [activityType]. The [activityType] **must** be the name of the struct conforming 76 | /// to `ActivityAttributes` that will be used to start the live activity. The [token] 77 | /// is ActivityKit's pushToStart token that will be used to start the live activity. 78 | /// 79 | /// Only applies to iOS. 80 | Future setPushToStartToken(String activityType, String token) async { 81 | if (Platform.isIOS) { 82 | return await _channel.invokeMethod("OneSignal#setPushToStartToken", 83 | {'activityType': activityType, 'token': token}); 84 | } 85 | } 86 | 87 | /// Indicate this device is no longer capable of receiving pushToStart live activities 88 | /// for the [activityType]. The [activityType] **must** be the name of the struct conforming 89 | /// to `ActivityAttributes` that will be used to start the live activity. 90 | /// 91 | /// Only applies to iOS. 92 | Future removePushToStartToken(String activityType) async { 93 | if (Platform.isIOS) { 94 | return await _channel.invokeMethod( 95 | "OneSignal#removePushToStartToken", {'activityType': activityType}); 96 | } 97 | } 98 | } 99 | 100 | /// The setup options for [OneSignal.LiveActivities.setupDefault]. 101 | class LiveActivitySetupOptions { 102 | bool _enablePushToStart = true; 103 | bool _enablePushToUpdate = true; 104 | 105 | LiveActivitySetupOptions( 106 | {bool enablePushToStart = true, bool enablePushToUpdate = true}) { 107 | this._enablePushToStart = enablePushToStart; 108 | this._enablePushToUpdate = enablePushToUpdate; 109 | } 110 | 111 | /// When true, OneSignal will listen for pushToStart tokens. 112 | bool get enablePushToStart { 113 | return this._enablePushToStart; 114 | } 115 | 116 | /// When true, OneSignal will listen for pushToUpdate tokens for each started live activity. 117 | bool get enablePushToUpdate { 118 | return this._enablePushToUpdate; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /lib/src/location.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/services.dart'; 3 | 4 | class OneSignalLocation { 5 | // private channels used to bridge to ObjC/Java 6 | MethodChannel _channel = const MethodChannel('OneSignal#location'); 7 | 8 | /// Allows you to prompt the user for permission to use location services 9 | Future requestPermission() async { 10 | return await _channel.invokeMethod("OneSignal#requestPermission"); 11 | } 12 | 13 | /// Set whether location is currently shared with OneSignal. 14 | Future setShared(bool shared) async { 15 | return await _channel.invokeMethod("OneSignal#setShared", shared); 16 | } 17 | 18 | /// Allows you to determine if the user's location data is shared with OneSignal. 19 | /// This allows you to do things like geofenced notifications, etc. 20 | Future isShared() async { 21 | return await _channel.invokeMethod("OneSignal#isShared"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lib/src/permission.dart: -------------------------------------------------------------------------------- 1 | import 'package:onesignal_flutter/src/utils.dart'; 2 | 3 | class OSPermissionState extends JSONStringRepresentable { 4 | bool permission = false; 5 | OSPermissionState(Map json) { 6 | if (json.containsKey('permission')) { 7 | permission = json['permission'] as bool; 8 | } 9 | } 10 | 11 | String jsonRepresentation() { 12 | return convertToJsonString({'permission': this.permission}); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/pushsubscription.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:onesignal_flutter/src/subscription.dart'; 4 | 5 | typedef void OnPushSubscriptionChangeObserver( 6 | OSPushSubscriptionChangedState stateChanges); 7 | 8 | class OneSignalPushSubscription { 9 | MethodChannel _channel = const MethodChannel('OneSignal#pushsubscription'); 10 | 11 | String? _id; 12 | String? _token; 13 | bool? _optedIn; 14 | 15 | List _observers = 16 | []; 17 | // constructor method 18 | OneSignalPushSubscription() { 19 | this._channel.setMethodCallHandler(_handleMethod); 20 | } 21 | 22 | String? get id { 23 | return this._id; 24 | } 25 | 26 | /// The readonly push token. 27 | String? get token { 28 | return this._token; 29 | } 30 | 31 | /// Gets a boolean value indicating whether the current user is opted in to receive push notifications. 32 | /// If the device does not have push permission, optedIn is false. 33 | /// If the device has push permission, but no push token or subscription ID yet, optedIn is true. 34 | /// If the device has push permission and optOut() was not called, optedIn is true. 35 | /// If the device has push permission and optOut() was called, optedIn is false. 36 | bool? get optedIn { 37 | return _optedIn; 38 | } 39 | 40 | /// Call this method to receive push notifications on the device or to resume receiving of 41 | /// push notifications after calling optOut. If needed, this method will prompt the user for 42 | /// push notifications permission. 43 | Future optIn() async { 44 | await _channel.invokeMethod("OneSignal#optIn"); 45 | } 46 | 47 | /// If at any point you want the user to stop receiving push notifications on the current 48 | /// device (regardless of system-level permission status), you can call this method to opt out. 49 | Future optOut() async { 50 | await _channel.invokeMethod("OneSignal#optOut"); 51 | } 52 | 53 | /// The OSPushSubscriptionObserver.onOSPushSubscriptionChanged method will be fired on the passed-in 54 | // object when the push subscription changes. This method returns the current OSPushSubscriptionState 55 | // at the time of adding this observer. 56 | void addObserver(OnPushSubscriptionChangeObserver observer) { 57 | _observers.add(observer); 58 | } 59 | 60 | // Remove a push subscription observer that has been previously added. 61 | void removeObserver(OnPushSubscriptionChangeObserver observer) { 62 | _observers.remove(observer); 63 | } 64 | 65 | Future lifecycleInit() async { 66 | _token = await _channel.invokeMethod("OneSignal#pushSubscriptionToken"); 67 | _id = await _channel.invokeMethod("OneSignal#pushSubscriptionId"); 68 | _optedIn = await _channel.invokeMethod("OneSignal#pushSubscriptionOptedIn"); 69 | return await _channel.invokeMethod("OneSignal#lifecycleInit"); 70 | } 71 | 72 | // Private function that gets called by ObjC/Java 73 | Future _handleMethod(MethodCall call) async { 74 | if (call.method == 'OneSignal#onPushSubscriptionChange') { 75 | this._onPushSubscriptionChange(OSPushSubscriptionChangedState( 76 | call.arguments.cast())); 77 | } 78 | return null; 79 | } 80 | 81 | void _onPushSubscriptionChange( 82 | OSPushSubscriptionChangedState stateChanges) async { 83 | this._id = stateChanges.current.id; 84 | this._token = stateChanges.current.token; 85 | this._optedIn = stateChanges.current.optedIn; 86 | 87 | for (var observer in _observers) { 88 | observer(stateChanges); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /lib/src/session.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/services.dart'; 3 | 4 | class OneSignalSession { 5 | // private channels used to bridge to ObjC/Java 6 | MethodChannel _channel = const MethodChannel('OneSignal#session'); 7 | 8 | /// Send a normal outcome event for the current session and notifications with the attribution window 9 | /// Counted each time sent successfully, failed ones will be cached and reattempted in future 10 | Future addOutcome(String name) async { 11 | return await _channel.invokeMethod("OneSignal#addOutcome", name); 12 | } 13 | 14 | /// Send a unique outcome event for the current session and notifications with the attribution window 15 | /// Counted once per notification when sent successfully, failed ones will be cached and reattempted in future 16 | Future addUniqueOutcome(String name) async { 17 | return await _channel.invokeMethod("OneSignal#addUniqueOutcome", name); 18 | } 19 | 20 | /// Send an outcome event with a value for the current session and notifications with the attribution window 21 | /// Counted each time sent successfully, failed ones will be cached and reattempted in future 22 | Future addOutcomeWithValue(String name, double value) async { 23 | return await _channel.invokeMethod("OneSignal#addOutcomeWithValue", 24 | {"outcome_name": name, "outcome_value": value}); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/src/subscription.dart: -------------------------------------------------------------------------------- 1 | import 'package:onesignal_flutter/src/utils.dart'; 2 | 3 | /// Represents the current user's subscription state with OneSignal 4 | class OSPushSubscriptionState extends JSONStringRepresentable { 5 | String? id; 6 | 7 | /// The APNS (iOS), GCM/FCM (Android) push token 8 | String? token; 9 | 10 | bool optedIn = false; 11 | 12 | OSPushSubscriptionState(Map json) { 13 | if (json.containsKey('id')) this.id = json['id'] as String?; 14 | if (json.containsKey('token')) this.token = json['token'] as String?; 15 | this.optedIn = json['optedIn'] as bool; 16 | } 17 | 18 | String jsonRepresentation() { 19 | return convertToJsonString( 20 | {'id': this.id, 'token': this.token, 'optedIn': this.optedIn}); 21 | } 22 | } 23 | 24 | /// An instance of this class describes a change in the user's OneSignal 25 | /// push notification subscription state, ie. the user subscribed to 26 | /// push notifications with your app. 27 | class OSPushSubscriptionChangedState extends JSONStringRepresentable { 28 | late OSPushSubscriptionState current; 29 | late OSPushSubscriptionState previous; 30 | 31 | OSPushSubscriptionChangedState(Map json) { 32 | if (json.containsKey('current')) 33 | this.current = 34 | OSPushSubscriptionState(json['current'].cast()); 35 | if (json.containsKey('previous')) 36 | this.previous = 37 | OSPushSubscriptionState(json['previous'].cast()); 38 | } 39 | 40 | String jsonRepresentation() { 41 | return convertToJsonString({ 42 | 'current': current.jsonRepresentation(), 43 | 'previous': previous.jsonRepresentation() 44 | }); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/src/utils.dart: -------------------------------------------------------------------------------- 1 | import 'package:onesignal_flutter/src/defines.dart'; 2 | import 'dart:convert'; 3 | 4 | // produces a string like this: 2018-07-23T17:56:30.951030 UTC-7:00 5 | String dateToStringWithOffset(DateTime date) { 6 | var offsetHours = date.timeZoneOffset.inHours; 7 | var offsetMinutes = date.timeZoneOffset.inMinutes % 60; 8 | var dateString = "${date.toIso8601String()} "; 9 | 10 | dateString += "UTC" + 11 | ((offsetHours > 10 || offsetHours < 0) 12 | ? "$offsetHours" 13 | : "0$offsetHours"); 14 | dateString += ":" + 15 | ((offsetMinutes.abs() > 10) ? "$offsetMinutes" : "0$offsetMinutes:00"); 16 | 17 | return dateString; 18 | } 19 | 20 | // in some places, we want to send an enum value to 21 | // ObjC. Before we can do this, we must convert it 22 | // to a string/int/etc. 23 | // However, in some places such as iOS init settings, 24 | // there could be multiple different types of enum, 25 | // so we've combined it into this one function. 26 | dynamic convertEnumCaseToValue(dynamic key) { 27 | switch (key) { 28 | case OSiOSSettings.autoPrompt: 29 | return "kOSSettingsKeyAutoPrompt"; 30 | case OSiOSSettings.inAppAlerts: 31 | return "kOSSettingsKeyInAppAlerts"; 32 | case OSiOSSettings.inAppLaunchUrl: 33 | return "kOSSettingsKeyInAppLaunchURL"; 34 | case OSiOSSettings.inFocusDisplayOption: 35 | return "kOSSettingsKeyInFocusDisplayOption"; 36 | case OSiOSSettings.promptBeforeOpeningPushUrl: 37 | return "kOSSSettingsKeyPromptBeforeOpeningPushURL"; 38 | } 39 | 40 | switch (key) { 41 | case OSCreateNotificationBadgeType.increase: 42 | return "Increase"; 43 | case OSCreateNotificationBadgeType.setTo: 44 | return "SetTo"; 45 | } 46 | 47 | switch (key) { 48 | case OSCreateNotificationDelayOption.lastActive: 49 | return "last_active"; 50 | case OSCreateNotificationDelayOption.timezone: 51 | return "timezone"; 52 | } 53 | 54 | switch (key) { 55 | case OSNotificationDisplayType.none: 56 | return 0; 57 | case OSNotificationDisplayType.alert: 58 | return 1; 59 | case OSNotificationDisplayType.notification: 60 | return 2; 61 | } 62 | 63 | switch (key) { 64 | case OSSession.DIRECT: 65 | return "DIRECT"; 66 | case OSSession.INDIRECT: 67 | return "INDIRECT"; 68 | case OSSession.UNATTRIBUTED: 69 | return "UNATTRIBUTED"; 70 | case OSSession.DISABLED: 71 | return "DISABLED"; 72 | } 73 | 74 | return key; 75 | } 76 | 77 | /// An abstract class to provide JSON decoding 78 | abstract class JSONStringRepresentable { 79 | String jsonRepresentation(); 80 | 81 | String convertToJsonString(Map? object) => 82 | JsonEncoder.withIndent(' ') 83 | .convert(object) 84 | .replaceAll("\\n", "\n") 85 | .replaceAll("\\", ""); 86 | } 87 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: onesignal_flutter 2 | description: OneSignal is a free push notification service for mobile apps. This plugin makes it easy to integrate your flutter app with OneSignal 3 | version: 5.3.3 4 | homepage: https://github.com/OneSignal/OneSignal-Flutter-SDK 5 | 6 | flutter: 7 | plugin: 8 | platforms: 9 | android: 10 | package: com.onesignal.flutter 11 | pluginClass: OneSignalPlugin 12 | ios: 13 | pluginClass: OneSignalPlugin 14 | 15 | dependencies: 16 | flutter: 17 | sdk: flutter 18 | 19 | dev_dependencies: 20 | test: ^1.5.1 21 | flutter_test: 22 | sdk: flutter 23 | 24 | environment: 25 | sdk: '>=2.12.0 <3.0.0' 26 | flutter: '>=1.10.0' 27 | -------------------------------------------------------------------------------- /test.json: -------------------------------------------------------------------------------- 1 | { 2 | "subscription_changed_test" : { 3 | "from": { 4 | "isSubscribed": false, 5 | "isPushDisabled": true, 6 | "pushToken": "07afbb0b4cb6e7ae5e81efc7fd5d35267ea9a4f12120045aebe29945e52ea30e", 7 | "userId": null 8 | }, 9 | "to": { 10 | "isSubscribed": true, 11 | "isPushDisabled": true, 12 | "pushToken": "07afbb0b4cb6e7ae5e81efc7fd5d35267ea9a4f12120045aebe29945e52ea30e", 13 | "userId": "c1b395fc-3b17-4c18-aaa6-195cd3461311" 14 | } 15 | }, 16 | "email_changed_test" : { 17 | "from" : { 18 | "subscribed" : false, 19 | "emailUserId" : null, 20 | "emailAddress" : null 21 | }, 22 | "to" : { 23 | "subscribed" : true, 24 | "emailUserId" : "c1b395fc-3b17-4c18-aaa6-195cd3461311", 25 | "emailAddress" : "brad@hesse.io" 26 | } 27 | }, 28 | "notification_parsing_test" : { 29 | "shown" : true, 30 | "rawPayload" : "{ \"test\" : \"raw payload\" }", 31 | "additionalData" : { 32 | "additional" : "data" 33 | }, 34 | "notificationId" : "8e0eeec2-aa42-4ff7-a74b-bce9ca9e588b", 35 | "buttons" : [ 36 | { 37 | "id" : "test1", 38 | "text" : "BTN1" 39 | } 40 | ], 41 | "contentAvailable" : true, 42 | "sound" : "default", 43 | "attachments" : { 44 | "id" : "https://www.onesignal.com" 45 | }, 46 | "body" : "Welcome to OneSignal!", 47 | "mutableContent" : true, 48 | "displayType" : 1, 49 | "appInFocus" : true, 50 | "silent" : true 51 | }, 52 | "permission_parsing_test" : { 53 | "from" : { 54 | "hasPrompted" : false, 55 | "provisional" : false, 56 | "status" : 0 57 | }, 58 | "to" : { 59 | "hasPrompted" : true, 60 | "provisional" : true, 61 | "status" : 2 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /test/mock_channel.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | import 'package:onesignal_flutter/onesignal_flutter.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | 5 | /* 6 | This class mocks an iOS or Android host device 7 | It has a OneSignalState object that reflects changes to 8 | state that the various requests make. 9 | */ 10 | 11 | class OneSignalMockChannelController { 12 | MethodChannel _channel = const MethodChannel('OneSignal'); 13 | MethodChannel _debugChannel = const MethodChannel('OneSignal#debug'); 14 | MethodChannel _tagsChannel = const MethodChannel('OneSignal#tags'); 15 | 16 | late OneSignalState state; 17 | 18 | OneSignalMockChannelController() { 19 | this._channel.setMockMethodCallHandler(_handleMethod); 20 | this._tagsChannel.setMockMethodCallHandler(_handleMethod); 21 | this._debugChannel.setMockMethodCallHandler(_handleMethod); 22 | } 23 | 24 | void resetState() { 25 | state = OneSignalState(); 26 | } 27 | 28 | Future _handleMethod(MethodCall call) async { 29 | print("Mock method called: ${call.method}"); 30 | switch (call.method) { 31 | case "OneSignal#setAppId": 32 | this.state.setAppId(call.arguments); 33 | break; 34 | case "OneSignal#setLogLevel": 35 | this.state.setLogLevel(call.arguments); 36 | break; 37 | case "OneSignal#consentGiven": 38 | this.state.consentGiven = 39 | (call.arguments as Map)['given'] as bool?; 40 | break; 41 | case "OneSignal#promptPermission": 42 | this.state.calledPromptPermission = true; 43 | break; 44 | case "OneSignal#log": 45 | this.state.log(call.arguments); 46 | break; 47 | case "OneSignal#disablePush": 48 | this.state.disablePush = call.arguments as bool?; 49 | break; 50 | case "OneSignal#postNotification": 51 | this.state.postNotificationJson = 52 | call.arguments as Map?; 53 | return {"success": true}; 54 | case "OneSignal#setLocationShared": 55 | this.state.locationShared = call.arguments as bool?; 56 | break; 57 | case "OneSignal#setEmail": 58 | this.state.setEmail(call.arguments); 59 | break; 60 | case "OneSignal#sendTags": 61 | this.state.tags = call.arguments; 62 | return {"success": true}; 63 | case "OneSignal#deleteTags": 64 | this.state.deleteTags = call.arguments; 65 | return {"success": true}; 66 | case "OneSignal#setExternalUserId": 67 | this.state.externalId = (call.arguments 68 | as Map)['externalUserId'] as String?; 69 | return {"success": true}; 70 | case "OneSignal#removeExternalUserId": 71 | this.state.externalId = null; 72 | return {"success": true}; 73 | case "OneSignal#setLanguage": 74 | this.state.language = 75 | (call.arguments as Map)['language'] as String?; 76 | return {"success": true}; 77 | } 78 | } 79 | } 80 | 81 | class OneSignalState { 82 | //initialization 83 | String? appId; 84 | 85 | //email 86 | String? email; 87 | String? emailAuthHashToken; 88 | 89 | // logging 90 | String? latestLogStatement; 91 | OSLogLevel? latestLogLevel; 92 | 93 | // miscellaneous params 94 | bool? requiresPrivacyConsent = false; 95 | late OSLogLevel logLevel; 96 | late OSLogLevel visualLevel; 97 | bool? consentGiven = false; 98 | bool? calledPromptPermission; 99 | bool? locationShared; 100 | OSNotificationDisplayType? inFocusDisplayType; 101 | bool? disablePush; 102 | String? externalId; 103 | String? language; 104 | 105 | // tags 106 | Map? tags; 107 | List? deleteTags; 108 | 109 | // notifications 110 | Map? postNotificationJson; 111 | 112 | /* 113 | All of the following functions parse the MethodCall 114 | parameters, and sets properties on the object itself 115 | */ 116 | 117 | void setAppId(Map params) { 118 | this.appId = params['appId']; 119 | } 120 | 121 | void setLogLevel(Map params) { 122 | int? level = params['logLevel'] as int?; 123 | int? visual = params['visual'] as int?; 124 | 125 | if (level != null) this.logLevel = OSLogLevel.values[level]; 126 | if (visual != null) this.visualLevel = OSLogLevel.values[visual]; 127 | } 128 | 129 | void consentRequired(Map params) { 130 | this.requiresPrivacyConsent = params['required'] as bool?; 131 | } 132 | 133 | void log(Map params) { 134 | var level = params['logLevel'] as int?; 135 | 136 | if (level != null) this.latestLogLevel = OSLogLevel.values[level]; 137 | this.latestLogStatement = params['message']; 138 | } 139 | 140 | void setDisplayType(Map params) { 141 | var type = params['displayType'] as int?; 142 | if (type != null) 143 | this.inFocusDisplayType = OSNotificationDisplayType.values[type]; 144 | } 145 | 146 | void setEmail(Map params) { 147 | this.email = params['email'] as String?; 148 | this.emailAuthHashToken = params['emailAuthHashToken'] as String?; 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /test/onesignalflutter_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | import 'package:onesignal_flutter/onesignal_flutter.dart'; 3 | import 'mock_channel.dart'; 4 | 5 | void main() { 6 | TestWidgetsFlutterBinding.ensureInitialized(); 7 | 8 | OneSignalMockChannelController channelController = 9 | OneSignalMockChannelController(); 10 | 11 | setUp(() { 12 | channelController.resetState(); 13 | }); 14 | 15 | test('set log level', () { 16 | OneSignal.Debug.setLogLevel( 17 | OSLogLevel.info, 18 | ).then(expectAsync1((v) { 19 | expect(channelController.state.logLevel.index, OSLogLevel.info.index); 20 | })); 21 | }); 22 | } 23 | --------------------------------------------------------------------------------