From 7f4cb661b1757fd3571e5076a515e52a2bbb32a7 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Thu, 28 May 2026 13:24:50 -0700 Subject: [PATCH 01/20] chore: add demo_fm example reproducing #1138 firebase_messaging coexistence demo_fm is a copy of the demo app with firebase_core + firebase_messaging added and FCM listeners registered before OneSignal, matching the affected users' setup in issue #1138. Initializing Firebase registers a FirebaseMessagingService in the manifest, which is what triggers the FCM hijack + click-listener routing problems the fix addresses. Also gitignores google-services.json / GoogleService-Info.plist so per-dev Firebase config is not committed. Co-authored-by: Cursor --- .gitignore | 6 + examples/demo_fm/.env.example | 6 + examples/demo_fm/.gitignore | 48 + examples/demo_fm/.metadata | 45 + examples/demo_fm/ISSUE_1138_REPRO.md | 183 +++ examples/demo_fm/README.md | 16 + examples/demo_fm/UPSTREAM_ISSUE_DRAFT.md | 129 ++ examples/demo_fm/analysis_options.yaml | 28 + examples/demo_fm/android/.gitignore | 14 + examples/demo_fm/android/app/build.gradle.kts | 46 + .../android/app/src/debug/AndroidManifest.xml | 7 + .../android/app/src/main/AndroidManifest.xml | 47 + .../com/onesignal/example/MainActivity.kt | 5 + .../drawable-hdpi/ic_launcher_foreground.png | Bin 0 -> 8752 bytes .../drawable-mdpi/ic_launcher_foreground.png | Bin 0 -> 5085 bytes .../res/drawable-v21/launch_background.xml | 12 + .../drawable-xhdpi/ic_launcher_foreground.png | Bin 0 -> 11025 bytes .../ic_launcher_foreground.png | Bin 0 -> 17788 bytes .../ic_launcher_foreground.png | Bin 0 -> 25554 bytes .../main/res/drawable/launch_background.xml | 12 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 9 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3492 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2130 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4548 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 7316 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9755 bytes .../app/src/main/res/values-night/styles.xml | 18 + .../app/src/main/res/values/colors.xml | 4 + .../app/src/main/res/values/styles.xml | 18 + .../app/src/profile/AndroidManifest.xml | 7 + examples/demo_fm/android/build.gradle.kts | 24 + examples/demo_fm/android/gradle.properties | 2 + .../gradle/wrapper/gradle-wrapper.properties | 5 + examples/demo_fm/android/settings.gradle.kts | 28 + examples/demo_fm/assets/onesignal_logo.svg | 20 + .../assets/onesignal_logo_icon_padded.png | Bin 0 -> 81225 bytes examples/demo_fm/ios/.gitignore | 34 + examples/demo_fm/ios/ExportOptions.plist | 23 + .../ios/Flutter/AppFrameworkInfo.plist | 26 + examples/demo_fm/ios/Flutter/Debug.xcconfig | 1 + examples/demo_fm/ios/Flutter/Release.xcconfig | 6 + .../Info.plist | 13 + .../NotificationService.swift | 32 + ...lNotificationServiceExtension.entitlements | 10 + .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 35 + .../Assets.xcassets/Contents.json | 6 + .../WidgetBackground.colorset/Contents.json | 11 + .../demo_fm/ios/OneSignalWidget/Info.plist | 11 + .../OneSignalWidgetBundle.swift | 16 + .../OneSignalWidgetLiveActivity.swift | 142 +++ .../ios/Runner.xcodeproj/project.pbxproj | 1112 +++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 119 ++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + examples/demo_fm/ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 1 + .../Icon-App-1024x1024@1x.png | Bin 0 -> 70226 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 607 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1486 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 2284 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 996 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 2155 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 3427 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1486 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 3166 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 4841 bytes .../AppIcon.appiconset/Icon-App-50x50@1x.png | Bin 0 -> 1936 bytes .../AppIcon.appiconset/Icon-App-50x50@2x.png | Bin 0 -> 4107 bytes .../AppIcon.appiconset/Icon-App-57x57@1x.png | Bin 0 -> 2171 bytes .../AppIcon.appiconset/Icon-App-57x57@2x.png | Bin 0 -> 4663 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 4841 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 7623 bytes .../AppIcon.appiconset/Icon-App-72x72@1x.png | Bin 0 -> 2953 bytes .../AppIcon.appiconset/Icon-App-72x72@2x.png | Bin 0 -> 6127 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 3107 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 6710 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 7352 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 + .../ios/Runner/Base.lproj/Main.storyboard | 26 + examples/demo_fm/ios/Runner/Info.plist | 59 + .../ios/Runner/Runner-Bridging-Header.h | 1 + .../demo_fm/ios/Runner/Runner.entitlements | 12 + .../demo_fm/ios/RunnerTests/RunnerTests.swift | 12 + examples/demo_fm/lib/main.dart | 156 +++ .../lib/models/in_app_message_type.dart | 11 + .../demo_fm/lib/models/notification_type.dart | 38 + examples/demo_fm/lib/models/user_data.dart | 56 + examples/demo_fm/lib/screens/home_screen.dart | 145 +++ .../demo_fm/lib/screens/secondary_screen.dart | 21 + .../lib/services/onesignal_api_service.dart | 218 ++++ .../lib/services/preferences_service.dart | 42 + .../demo_fm/lib/services/tooltip_helper.dart | 74 ++ examples/demo_fm/lib/theme.dart | 125 ++ .../demo_fm/lib/viewmodels/app_viewmodel.dart | 564 +++++++++ .../demo_fm/lib/widgets/action_button.dart | 78 ++ .../demo_fm/lib/widgets/app_text_field.dart | 18 + examples/demo_fm/lib/widgets/dialogs.dart | 782 ++++++++++++ .../demo_fm/lib/widgets/list_widgets.dart | 272 ++++ .../demo_fm/lib/widgets/section_card.dart | 77 ++ .../lib/widgets/sections/aliases_section.dart | 82 ++ .../lib/widgets/sections/app_section.dart | 119 ++ .../sections/custom_events_section.dart | 45 + .../lib/widgets/sections/emails_section.dart | 63 + .../lib/widgets/sections/in_app_section.dart | 37 + .../sections/live_activities_section.dart | 144 +++ .../widgets/sections/location_section.dart | 59 + .../widgets/sections/outcomes_section.dart | 55 + .../lib/widgets/sections/push_section.dart | 77 ++ .../widgets/sections/send_iam_section.dart | 35 + .../widgets/sections/send_push_section.dart | 67 + .../lib/widgets/sections/sms_section.dart | 63 + .../lib/widgets/sections/tags_section.dart | 98 ++ .../widgets/sections/triggers_section.dart | 101 ++ .../lib/widgets/sections/user_section.dart | 108 ++ examples/demo_fm/lib/widgets/toggle_row.dart | 49 + examples/demo_fm/pubspec.yaml | 46 + 126 files changed, 6507 insertions(+) create mode 100644 examples/demo_fm/.env.example create mode 100644 examples/demo_fm/.gitignore create mode 100644 examples/demo_fm/.metadata create mode 100644 examples/demo_fm/ISSUE_1138_REPRO.md create mode 100644 examples/demo_fm/README.md create mode 100644 examples/demo_fm/UPSTREAM_ISSUE_DRAFT.md create mode 100644 examples/demo_fm/analysis_options.yaml create mode 100644 examples/demo_fm/android/.gitignore create mode 100644 examples/demo_fm/android/app/build.gradle.kts create mode 100644 examples/demo_fm/android/app/src/debug/AndroidManifest.xml create mode 100644 examples/demo_fm/android/app/src/main/AndroidManifest.xml create mode 100644 examples/demo_fm/android/app/src/main/kotlin/com/onesignal/example/MainActivity.kt create mode 100644 examples/demo_fm/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png create mode 100644 examples/demo_fm/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png create mode 100644 examples/demo_fm/android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 examples/demo_fm/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png create mode 100644 examples/demo_fm/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png create mode 100644 examples/demo_fm/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png create mode 100644 examples/demo_fm/android/app/src/main/res/drawable/launch_background.xml create mode 100644 examples/demo_fm/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 examples/demo_fm/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 examples/demo_fm/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 examples/demo_fm/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 examples/demo_fm/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 examples/demo_fm/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 examples/demo_fm/android/app/src/main/res/values-night/styles.xml create mode 100644 examples/demo_fm/android/app/src/main/res/values/colors.xml create mode 100644 examples/demo_fm/android/app/src/main/res/values/styles.xml create mode 100644 examples/demo_fm/android/app/src/profile/AndroidManifest.xml create mode 100644 examples/demo_fm/android/build.gradle.kts create mode 100644 examples/demo_fm/android/gradle.properties create mode 100644 examples/demo_fm/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 examples/demo_fm/android/settings.gradle.kts create mode 100644 examples/demo_fm/assets/onesignal_logo.svg create mode 100644 examples/demo_fm/assets/onesignal_logo_icon_padded.png create mode 100644 examples/demo_fm/ios/.gitignore create mode 100644 examples/demo_fm/ios/ExportOptions.plist create mode 100644 examples/demo_fm/ios/Flutter/AppFrameworkInfo.plist create mode 100644 examples/demo_fm/ios/Flutter/Debug.xcconfig create mode 100644 examples/demo_fm/ios/Flutter/Release.xcconfig create mode 100644 examples/demo_fm/ios/OneSignalNotificationServiceExtension/Info.plist create mode 100644 examples/demo_fm/ios/OneSignalNotificationServiceExtension/NotificationService.swift create mode 100644 examples/demo_fm/ios/OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements create mode 100644 examples/demo_fm/ios/OneSignalWidget/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 examples/demo_fm/ios/OneSignalWidget/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 examples/demo_fm/ios/OneSignalWidget/Assets.xcassets/Contents.json create mode 100644 examples/demo_fm/ios/OneSignalWidget/Assets.xcassets/WidgetBackground.colorset/Contents.json create mode 100644 examples/demo_fm/ios/OneSignalWidget/Info.plist create mode 100644 examples/demo_fm/ios/OneSignalWidget/OneSignalWidgetBundle.swift create mode 100644 examples/demo_fm/ios/OneSignalWidget/OneSignalWidgetLiveActivity.swift create mode 100644 examples/demo_fm/ios/Runner.xcodeproj/project.pbxproj create mode 100644 examples/demo_fm/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 examples/demo_fm/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 examples/demo_fm/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 examples/demo_fm/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 examples/demo_fm/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 examples/demo_fm/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 examples/demo_fm/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 examples/demo_fm/ios/Runner/AppDelegate.swift create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 examples/demo_fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 examples/demo_fm/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 examples/demo_fm/ios/Runner/Base.lproj/Main.storyboard create mode 100644 examples/demo_fm/ios/Runner/Info.plist create mode 100644 examples/demo_fm/ios/Runner/Runner-Bridging-Header.h create mode 100644 examples/demo_fm/ios/Runner/Runner.entitlements create mode 100644 examples/demo_fm/ios/RunnerTests/RunnerTests.swift create mode 100644 examples/demo_fm/lib/main.dart create mode 100644 examples/demo_fm/lib/models/in_app_message_type.dart create mode 100644 examples/demo_fm/lib/models/notification_type.dart create mode 100644 examples/demo_fm/lib/models/user_data.dart create mode 100644 examples/demo_fm/lib/screens/home_screen.dart create mode 100644 examples/demo_fm/lib/screens/secondary_screen.dart create mode 100644 examples/demo_fm/lib/services/onesignal_api_service.dart create mode 100644 examples/demo_fm/lib/services/preferences_service.dart create mode 100644 examples/demo_fm/lib/services/tooltip_helper.dart create mode 100644 examples/demo_fm/lib/theme.dart create mode 100644 examples/demo_fm/lib/viewmodels/app_viewmodel.dart create mode 100644 examples/demo_fm/lib/widgets/action_button.dart create mode 100644 examples/demo_fm/lib/widgets/app_text_field.dart create mode 100644 examples/demo_fm/lib/widgets/dialogs.dart create mode 100644 examples/demo_fm/lib/widgets/list_widgets.dart create mode 100644 examples/demo_fm/lib/widgets/section_card.dart create mode 100644 examples/demo_fm/lib/widgets/sections/aliases_section.dart create mode 100644 examples/demo_fm/lib/widgets/sections/app_section.dart create mode 100644 examples/demo_fm/lib/widgets/sections/custom_events_section.dart create mode 100644 examples/demo_fm/lib/widgets/sections/emails_section.dart create mode 100644 examples/demo_fm/lib/widgets/sections/in_app_section.dart create mode 100644 examples/demo_fm/lib/widgets/sections/live_activities_section.dart create mode 100644 examples/demo_fm/lib/widgets/sections/location_section.dart create mode 100644 examples/demo_fm/lib/widgets/sections/outcomes_section.dart create mode 100644 examples/demo_fm/lib/widgets/sections/push_section.dart create mode 100644 examples/demo_fm/lib/widgets/sections/send_iam_section.dart create mode 100644 examples/demo_fm/lib/widgets/sections/send_push_section.dart create mode 100644 examples/demo_fm/lib/widgets/sections/sms_section.dart create mode 100644 examples/demo_fm/lib/widgets/sections/tags_section.dart create mode 100644 examples/demo_fm/lib/widgets/sections/triggers_section.dart create mode 100644 examples/demo_fm/lib/widgets/sections/user_section.dart create mode 100644 examples/demo_fm/lib/widgets/toggle_row.dart create mode 100644 examples/demo_fm/pubspec.yaml diff --git a/.gitignore b/.gitignore index f624417f..66b98420 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,9 @@ dlcov.log **/Package.resolved **/.lock **/workspace-state.json + +# Per-developer Firebase config for issue #1138 repro scaffolding +# (only needed because firebase_messaging is wired into examples/demo; +# OneSignal itself does NOT need this file). +**/google-services.json +**/GoogleService-Info.plist diff --git a/examples/demo_fm/.env.example b/examples/demo_fm/.env.example new file mode 100644 index 00000000..d789fef7 --- /dev/null +++ b/examples/demo_fm/.env.example @@ -0,0 +1,6 @@ +ONESIGNAL_APP_ID=your-onesignal-app-id +ONESIGNAL_API_KEY=your-onesignal-api-key + +# Optional: Android Notification Channel ID for the WITH SOUND test notification. +# Create one in your OneSignal dashboard under Settings > Android Notification Categories. +ONESIGNAL_ANDROID_CHANNEL_ID= diff --git a/examples/demo_fm/.gitignore b/examples/demo_fm/.gitignore new file mode 100644 index 00000000..b841075b --- /dev/null +++ b/examples/demo_fm/.gitignore @@ -0,0 +1,48 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ +/coverage/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release + +# Environment +.env diff --git a/examples/demo_fm/.metadata b/examples/demo_fm/.metadata new file mode 100644 index 00000000..83b34ebb --- /dev/null +++ b/examples/demo_fm/.metadata @@ -0,0 +1,45 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "f6ff1529fd6d8af5f706051d9251ac9231c83407" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: f6ff1529fd6d8af5f706051d9251ac9231c83407 + base_revision: f6ff1529fd6d8af5f706051d9251ac9231c83407 + - platform: android + create_revision: f6ff1529fd6d8af5f706051d9251ac9231c83407 + base_revision: f6ff1529fd6d8af5f706051d9251ac9231c83407 + - platform: ios + create_revision: f6ff1529fd6d8af5f706051d9251ac9231c83407 + base_revision: f6ff1529fd6d8af5f706051d9251ac9231c83407 + - platform: linux + create_revision: f6ff1529fd6d8af5f706051d9251ac9231c83407 + base_revision: f6ff1529fd6d8af5f706051d9251ac9231c83407 + - platform: macos + create_revision: f6ff1529fd6d8af5f706051d9251ac9231c83407 + base_revision: f6ff1529fd6d8af5f706051d9251ac9231c83407 + - platform: web + create_revision: f6ff1529fd6d8af5f706051d9251ac9231c83407 + base_revision: f6ff1529fd6d8af5f706051d9251ac9231c83407 + - platform: windows + create_revision: f6ff1529fd6d8af5f706051d9251ac9231c83407 + base_revision: f6ff1529fd6d8af5f706051d9251ac9231c83407 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/examples/demo_fm/ISSUE_1138_REPRO.md b/examples/demo_fm/ISSUE_1138_REPRO.md new file mode 100644 index 00000000..6fa12581 --- /dev/null +++ b/examples/demo_fm/ISSUE_1138_REPRO.md @@ -0,0 +1,183 @@ +# Issue #1138 reproduction — Branch B-2 (manifest-override-only variant) + +Branch: `fadi/issue-1138-manifest-override-only` + +This branch keeps the demo app on the **in-tree OneSignal SDK** (currently +`5.5.5` via `path: ../..`) and adds `firebase_core` + `firebase_messaging` +to mimic the affected users' setup in +[issue #1138](https://github.com/OneSignal/OneSignal-Flutter-SDK/issues/1138). + +Use this branch as the **suspected-broken case**. According to the users +in the issue, with this combo (OneSignal >= 5.4 + FCM in the same app) +`addClickListener` does not fire on Android when the app is in the +background, even though it fires correctly when the app is killed and +when the app is in the foreground. + +Companion control branch: `fadi/issue-1138-repro-5.3.4-with-firebase`, +which is the same demo with OneSignal pinned to 5.3.4. Diffing the two +branches isolates the change set introduced between 5.3.4 and 5.5.x. + +## Setup + +1. Add your own Firebase project's `google-services.json` to + `examples/demo_fm/android/app/google-services.json`. + + The `com.google.gms.google-services` Gradle plugin is wired in + (`android/settings.gradle.kts` and `android/app/build.gradle.kts`) so the + Android build will FAIL without this file. We do not commit one because it + is per-developer. + +2. Make sure the Firebase project's package name matches the Android + `applicationId` (`com.onesignal.example` by default in this demo). + +3. Configure your OneSignal app for FCM as usual (Server Key / V1 in + OneSignal dashboard) and put the OneSignal app id in + `examples/demo_fm/.env`: + + ``` + ONESIGNAL_APP_ID= + ONESIGNAL_API_KEY= + ``` + +4. Run on a real Android device: + + ``` + cd examples/demo_fm + flutter pub get + flutter run -d + ``` + +## Reproduction steps + +The click listener is registered **before `runApp`**, mirroring the snippet +in the issue: + +```dart +WidgetsFlutterBinding.ensureInitialized(); +await OneSignal.initialize(appId); +OneSignal.Notifications.addClickListener((event) { + debugPrint('[ISSUE-1138] addClickListener fired ...'); +}); +``` + +For each app state, send a push from the OneSignal dashboard and tap it: + +| State | Expected (per the bug report) | +| ------------------------------ | ------------------------------------- | +| Foreground | `[ISSUE-1138] addClickListener fired` | +| **Background (home button)** | **NO log line — bug reproduces** | +| Killed (swiped away) | `[ISSUE-1138] addClickListener fired` (some users see this fail too) | + +Watch `flutter logs` (or `adb logcat | grep ISSUE-1138`) to confirm whether +the callback runs. + +## Differences from `main` + +- `examples/demo_fm/pubspec.yaml`: added `firebase_core` + `firebase_messaging`. +- `examples/demo_fm/lib/main.dart`: Firebase initialization + FCM handlers, + early `addClickListener` registration tagged `[ISSUE-1138]`. +- `examples/demo_fm/android/{settings,app/build}.gradle.kts`: apply + `com.google.gms.google-services` plugin. + +## Experimental fixes to the SDK (also on this branch) + +### Fix 1 — click-listener lifecycle + +The change extends the defensive unsubscribe added in PR #1140 (5.5.4) to +also cover the case where the host activity is destroyed but the Flutter +engine survives. + +Files changed: + +- `android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java` + - Tracks whether Dart has requested a click listener. + - Adds `onAttachedToActivity()` / `onDetachedFromActivity()` that + add/remove the native-SDK click listener so clicks delivered while + the JNI is detached get queued by the native SDK instead of being + dispatched into a dead channel. +- `android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java` + - Wires the `ActivityAware` lifecycle (previously no-ops) into the + `OneSignalNotifications` hooks above, including the + config-change variants. +- Adds verbose lifecycle logging tagged `[ISSUE-1138]` to make the + attach/detach + dispatch ordering visible in `adb logcat`. + +### Fix 2 — `firebase_messaging` coexistence (manifest-override, no bridge service) + +This branch takes a different approach than its sibling +`fadi/issue-1138-repro-current-with-firebase`. Instead of adding a +competing `FirebaseMessagingService` that wins service dispatch and +fans the message out manually, we **address the root cause** by +removing the offending `` filter from OneSignal Android SDK's +`FCMBroadcastReceiver` directly, via the Android manifest merger. + +Background: OneSignal's `FCMBroadcastReceiver` is registered with an +intent filter that requires a `` matching the app package +name (e.g. ``). That +category was set on the GCM-era ordered broadcast but **modern FCM no +longer sets it**, so OneSignal's receiver never matches the broadcast +when a competing `FirebaseMessagingService` (e.g. FlutterFire's) takes +over the modern dispatch path. The result: OneSignal pushes silently +disappear. + +Files changed: + +- `android/src/main/AndroidManifest.xml` + - Re-declares the `com.onesignal.notifications.receivers.FCMBroadcastReceiver` + with `tools:node="replace"`, providing an intent-filter that has + only `` + — no ``. The manifest merger replaces the AAR-bundled + receiver definition with ours because the Flutter plugin's manifest + has higher merge priority than the OneSignal Android SDK AAR's. + +Trade-offs vs. the bridge-service approach on the sibling branch: + +| | Bridge service (sibling branch) | Manifest override (this branch) | +| --- | --- | --- | +| Code surface | ~80 LOC of Java + new manifest service | ~10 LOC of manifest only | +| Failure mode if OneSignal SDK changes the receiver layout | Bridge still calls `FCMBroadcastReceiver.onReceive` — generally stable | `tools:node="replace"` may diverge from upstream if they add other attributes (e.g. a new intent-filter) | +| Failure mode if modern FCM stops sending the legacy broadcast | Bridge still works (we win the service path) | Receiver stops being called — needs a real upstream fix | +| Coexistence with other FCM SDKs in the same app | Generic — bridge sees all messages | Only fixes OneSignal — other SDKs still need their own fix if they have the same category-filter bug | +| Noise in logs | NPE on `goAsync().finish()` after each push (harmless) | None | + +The bridge wins on forward-compatibility (it doesn't rely on the legacy +broadcast continuing to exist). The manifest override wins on +simplicity and on producing a clean log surface. Either is a viable +band-aid until OneSignal Android SDK fixes the upstream manifest — see +`examples/demo_fm/UPSTREAM_ISSUE_DRAFT.md` for the proposed upstream +report. + +## Verifying the fixes + +After running on Android, filter logs by `[ISSUE-1138]`: + +``` +adb logcat | rg 'ISSUE-1138|FlutterJNI was detached|NotificationWorkManager|FLTFireMsgReceiver' +``` + +A healthy **foreground** push (with `firebase_messaging` present) should +now look like: + +``` +... OneSignal: NotificationWorkManager enqueueing notification work ... +... OneSignal: Fire notificationWillShowInForegroundHandler ... +... I flutter : [FCM fg] received: ... (FlutterFire's onMessage fires) +... I flutter : Notification foreground will display: (OneSignal foreground listener fires) +``` + +A healthy **background-tap** flow should look like: + +``` +[ISSUE-1138] OneSignalFcmServiceBridge.onMessageReceived ... +[ISSUE-1138] OneSignalPlugin.onDetachedFromActivity() +[ISSUE-1138] OneSignalNotifications.onDetachedFromActivity() — removing native click listener +... (user taps notification) ... +[ISSUE-1138] OneSignalPlugin.onAttachedToActivity() +[ISSUE-1138] OneSignalNotifications.onAttachedToActivity() — re-adding native click listener (queued events should drain) +[ISSUE-1138] OneSignalNotifications.onClick() — native SDK dispatched click; forwarding to MethodChannel +[ISSUE-1138 late] addClickListener fired: ... (from main.dart) +``` + +If you still see `W/FlutterJNI ... Channel: OneSignal#notifications` AND +no `[ISSUE-1138 late] addClickListener fired`, the fix didn't help in your +scenario — capture the surrounding 50 lines of logs and we'll iterate. diff --git a/examples/demo_fm/README.md b/examples/demo_fm/README.md new file mode 100644 index 00000000..dbd403a0 --- /dev/null +++ b/examples/demo_fm/README.md @@ -0,0 +1,16 @@ +# demo + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/examples/demo_fm/UPSTREAM_ISSUE_DRAFT.md b/examples/demo_fm/UPSTREAM_ISSUE_DRAFT.md new file mode 100644 index 00000000..134bed13 --- /dev/null +++ b/examples/demo_fm/UPSTREAM_ISSUE_DRAFT.md @@ -0,0 +1,129 @@ +# Draft issue for `OneSignal/OneSignal-Android-SDK` + +Suggested title: + +> Notifications silently dropped on Android when app coexists with another `FirebaseMessagingService` (e.g. `firebase_messaging` / FlutterFire) + +--- + +## Summary + +`com.onesignal.notifications.receivers.FCMBroadcastReceiver` registers an +intent filter that requires both: + +```xml +<intent-filter android:priority="999"> + <action android:name="com.google.android.c2dm.intent.RECEIVE" /> + <category android:name="<APP_PACKAGE_NAME>" /> +</intent-filter> +``` + +The `<category>` requirement is a vestige from GCM, where each broadcast +carried the target app's package name as a category. **Modern FCM +(`firebase-messaging` 22.x+) no longer sets that category on its +broadcasts**, so the filter never matches and OneSignal's receiver is +silently skipped on apps that also have another `FirebaseMessagingService` +registered. + +The reason this is invisible in OneSignal-only apps is that GMS's own +`com.google.firebase.iid.FirebaseInstanceIdReceiver` (which has no +category filter) handles the broadcast and the modern service-dispatch +path routes the payload to OneSignal indirectly. As soon as a customer +adds an FCM-based plugin that registers its own +`FirebaseMessagingService` (FlutterFire's `firebase_messaging` being the +common case, but also `aws_amplify_push_notifications`, OEM SDKs, custom +services), that other service wins service-dispatch and OneSignal's +broadcast path stops being exercised. Net result: pushes "vanish" — no +foreground listener, no notification displayed, no click event. + +## Repro (Flutter, but architecture-level — same applies to any Android app) + +1. Empty Flutter app, add `onesignal_flutter: ^5.5.5` and + `firebase_messaging: ^15.2.10`. +2. Configure Firebase (`google-services.json`) and OneSignal as normal. +3. `await OneSignal.initialize(...)`. +4. Register both + ```dart + FirebaseMessaging.onMessage.listen((m) => print('[FCM] $m')); + OneSignal.Notifications.addForegroundWillDisplayListener((e) { + print('[OS fg] ${e.notification.title}'); + e.notification.display(); + }); + ``` +5. Send a push from the OneSignal dashboard with app in foreground. + +Observed: only `[FCM]` fires. No OneSignal log, no banner. +Expected: both fire; OneSignal shows the banner. + +Full Flutter-side reproduction (with `adb logcat` evidence) lives in +[OneSignal-Flutter-SDK#1138](https://github.com/OneSignal/OneSignal-Flutter-SDK/issues/1138) +and the `fadi/issue-1138-repro-current-with-firebase` branch there. + +## Why the existing manifest filter was OK in 2016 and isn't now + +| Era | How FCM/GCM routed to apps | What OneSignal's filter saw | +|---|---|---| +| GCM (≤2018) | Ordered broadcast with `<category>` matching app package | Matched, processed, optionally aborted | +| Early FCM | Same ordered broadcast, category still set | Matched | +| Modern FCM (firebase-messaging 22+) | Either service-only dispatch, OR an ordered broadcast WITHOUT the package category | Never matches | + +`firebase-messaging` source confirms it: `FirebaseInstanceIdReceiver` +has no category filter and is the de-facto sink for the broadcast. + +## Suggested fixes (any one of these unblocks customers) + +**(a) One-line manifest fix — preferred, fully backward-compatible** + +Drop the `<category>` element from `FCMBroadcastReceiver`'s intent +filter. The remaining `android:permission="com.google.android.c2dm.permission.SEND"` +plus the app-package-scoped delivery semantics of `c2dm.intent.RECEIVE` +already prevent cross-app spoofing. No customer code changes required. + +**(b) Modern entry point — service base class** + +Ship a public `OneSignalFirebaseMessagingService extends FirebaseMessagingService` +that customers can register at higher priority than competing services, +or extend in their own service: + +```java +public class MyService extends OneSignalFirebaseMessagingService { + @Override public void onMessageReceived(RemoteMessage m) { + super.onMessageReceived(m); // OneSignal handles its payloads + if (isMine(m)) handleMine(m); + } +} +``` + +**(c) Public ingestion API — most flexible for SDK-on-SDK coexistence** + +```java +OneSignal.getNotifications().handleRemoteMessage(remoteMessage); +``` + +Callable from any `FirebaseMessagingService.onMessageReceived`. This is +what the OneSignal Flutter SDK is currently re-implementing in +[OneSignalFcmServiceBridge](https://github.com/OneSignal/OneSignal-Flutter-SDK/blob/fadi/issue-1138-repro-current-with-firebase/android/src/main/java/com/onesignal/flutter/OneSignalFcmServiceBridge.java) +by synthesizing a `c2dm.intent.RECEIVE` `Intent` and feeding it back +into `FCMBroadcastReceiver.onReceive` — which works but produces a noisy +`NullPointerException` on the receiver's `goAsync().finish()` tail +because that call is meaningless outside of a real ordered broadcast. + +## Reference workaround (Flutter plugin, until upstream lands) + +See `android/src/main/AndroidManifest.xml` and +`android/src/main/java/com/onesignal/flutter/OneSignalFcmServiceBridge.java` +on the +[`fadi/issue-1138-repro-current-with-firebase`](https://github.com/OneSignal/OneSignal-Flutter-SDK/tree/fadi/issue-1138-repro-current-with-firebase) +branch. The plugin registers its own `FirebaseMessagingService` at +`android:priority="100"`, wins the modern service dispatch race, and +synthesizes the legacy intent to feed the OneSignal SDK. This is a +band-aid we'd happily delete the moment any of (a)/(b)/(c) lands. + +## Severity + +This affects every OneSignal Android customer who also uses any other +FCM plugin or service — most Flutter + push deployments fall in this +bucket. The failure mode is silent (no exception, no log line, no +notification), so it's high-cost to diagnose and easy to misattribute +to OneSignal's foreground-listener bridge (which is the symptom, not +the cause). diff --git a/examples/demo_fm/analysis_options.yaml b/examples/demo_fm/analysis_options.yaml new file mode 100644 index 00000000..0d290213 --- /dev/null +++ b/examples/demo_fm/analysis_options.yaml @@ -0,0 +1,28 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/examples/demo_fm/android/.gitignore b/examples/demo_fm/android/.gitignore new file mode 100644 index 00000000..be3943c9 --- /dev/null +++ b/examples/demo_fm/android/.gitignore @@ -0,0 +1,14 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java +.cxx/ + +# Remember to never publicly share your keystore. +# See https://flutter.dev/to/reference-keystore +key.properties +**/*.keystore +**/*.jks diff --git a/examples/demo_fm/android/app/build.gradle.kts b/examples/demo_fm/android/app/build.gradle.kts new file mode 100644 index 00000000..ffefdd35 --- /dev/null +++ b/examples/demo_fm/android/app/build.gradle.kts @@ -0,0 +1,46 @@ +plugins { + id("com.android.application") + id("kotlin-android") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") + // Issue #1138 reproduction: required by firebase_messaging. + id("com.google.gms.google-services") +} + +android { + namespace = "com.onesignal.example" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.onesignal.example" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} diff --git a/examples/demo_fm/android/app/src/debug/AndroidManifest.xml b/examples/demo_fm/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..399f6981 --- /dev/null +++ b/examples/demo_fm/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- The INTERNET permission is required for development. Specifically, + the Flutter tool needs it to communicate with the running application + to allow setting breakpoints, to provide hot reload, etc. + --> + <uses-permission android:name="android.permission.INTERNET"/> +</manifest> diff --git a/examples/demo_fm/android/app/src/main/AndroidManifest.xml b/examples/demo_fm/android/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..dca75d49 --- /dev/null +++ b/examples/demo_fm/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,47 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android"> + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> + <application + android:label="OneSignal Demo" + android:name="${applicationName}" + android:icon="@mipmap/ic_launcher"> + <activity + android:name=".MainActivity" + android:exported="true" + android:launchMode="singleTop" + android:taskAffinity="" + android:theme="@style/LaunchTheme" + android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" + android:hardwareAccelerated="true" + android:windowSoftInputMode="adjustResize"> + <!-- Specifies an Android theme to apply to this Activity as soon as + the Android process has started. This theme is visible to the user + while the Flutter UI initializes. After that, this theme continues + to determine the Window background behind the Flutter UI. --> + <meta-data + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" + /> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.LAUNCHER"/> + </intent-filter> + </activity> + <!-- Don't delete the meta-data below. + This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> + <meta-data + android:name="flutterEmbedding" + android:value="2" /> + </application> + <!-- Required to query activities that can process text, see: + https://developer.android.com/training/package-visibility and + https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT. + + In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. --> + <queries> + <intent> + <action android:name="android.intent.action.PROCESS_TEXT"/> + <data android:mimeType="text/plain"/> + </intent> + </queries> +</manifest> diff --git a/examples/demo_fm/android/app/src/main/kotlin/com/onesignal/example/MainActivity.kt b/examples/demo_fm/android/app/src/main/kotlin/com/onesignal/example/MainActivity.kt new file mode 100644 index 00000000..df66b4f0 --- /dev/null +++ b/examples/demo_fm/android/app/src/main/kotlin/com/onesignal/example/MainActivity.kt @@ -0,0 +1,5 @@ +package com.onesignal.example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity : FlutterActivity() diff --git a/examples/demo_fm/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png b/examples/demo_fm/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..95de5cbfbfe878fc8ff2a8dd54c4fdbfe1e4b9b1 GIT binary patch literal 8752 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 YsgMdPYkFgTOoBkk%cw}#0ZoGc2b@~;N&o-= literal 0 HcmV?d00001 diff --git a/examples/demo_fm/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png b/examples/demo_fm/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..639bc1f7e8b1735232957950cc1bb4256958822d GIT binary patch literal 5085 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 X!oKu;_uToX?eH{Ibd+nAkP-g@5zmHg literal 0 HcmV?d00001 diff --git a/examples/demo_fm/android/app/src/main/res/drawable-v21/launch_background.xml b/examples/demo_fm/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 00000000..f74085f3 --- /dev/null +++ b/examples/demo_fm/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Modify this file to customize your launch splash screen --> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:drawable="?android:colorBackground" /> + + <!-- You can insert your own image assets here --> + <!-- <item> + <bitmap + android:gravity="center" + android:src="@mipmap/launch_image" /> + </item> --> +</layer-list> diff --git a/examples/demo_fm/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png b/examples/demo_fm/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..db57e20526b30e8f576418e0585f54ef0e810130 GIT binary patch literal 11025 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 TrsM6`QdfYYtcpy96a@BvY(e1e literal 0 HcmV?d00001 diff --git a/examples/demo_fm/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png b/examples/demo_fm/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..0f9c289765a0b1f396b67c45ee634adf6ee9014e GIT binary patch literal 17788 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 DA4!-; literal 0 HcmV?d00001 diff --git a/examples/demo_fm/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png b/examples/demo_fm/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..f278b3881bd03c4aabc9fe4c7aa93d9696e6f0e4 GIT binary patch literal 25554 zcmeEt^LM1r6K=4vlZmxSHrZrj+qP}nb~d(c+qP}n+}PHg&-eZn_niB~oHJ+Mce<W> zy1Kf$sya+gMic=S2Nnbb1VLO(NC5-{wD!LbG$insQ5m{FARvZm;zImNZkZQbP;ThT z>rgk}X=xj_@fq333ed<NDcj1G<SZ9mHCs)3J57~W)z#JQ$urs$>q9!r{uMuAp~aN> zIDS9}J{&%Inod7wW(*F6ie)%nOK<Pox1Q%`xW-RzerGaXXBPZL7JwEP(C9?+1AbW} z1n31K3&f*BU=anz77BriKok9<koQ9Yz9aGfAN@bTh8V8Y#}F3$^!KwVyq$VgxS}%p z&~CV}a+Xa7HRs0BD8*BuOB1+E%u@P90VMKVAITeyZd`ym6Q6P~6FS12oip@}t?ixl z`tsq{9zqc1z+CBy-Y)0>UFTkCx21Iuz1?&lKlB<p1lDP-8kNTS2ex6Qsfq}{Ye++B z@7{&CnaT1`N>i1TB?Yxzm&a!_jq2h75H?E~bQ8O2m)H2I@1b=s{jUfKEq&x~QJVhv zzxLXoma_#>=se$d!*Xr`hy-8FWj<3e&W~`Ek^i1ZIV)I1oCUwvRLwu{pl(kD#OiZF zNbtiaEb0<DGGEPIJoUdD8*Pkfo@cG5;xkShj$Q3r#{s=2%77HI`Jr8^@wT};U*kwY z6p~7_jq~6p>58qFqn?4t<&Ur+TqvjBskD-g1!hQ@6|>tIkwQ~)i?DuYJB;}#kX}Lb zz1d@F>Fp?#X%fk^^KLcV2iuL!)rSF(o*H7TFcFGLF;RX{k#+nc<2PAlEQd-KPj!<w zzrC_-5=81hc-zu-@YAzY>h1dEL<4kyVWr{J`6tVNkhY&1Jujvvs3d%lrM#TU$#WUf z@>;|J9jjT`+85LO`?5$A<2>Sq;Red+1uUr56@R;r6R0=3HBO&tvN{SJM4Z_c0jN7t z6HLE|E@2?B#4V~8{D>R1(oJyV6POJQJeEhPI;x!P(o1YrLoBgQv``B0w?AN}1%pxG zNR{OmcdBDs)$X75P<E6?>6A+HO*r#Rv{e*1M5Lt4y;J2;;H$MyZ8h54>dYTo5FR5= zR8(iG5g^Ys1>=aLelfz*#XGrpyD&4+mKa%?EYl}A-W5OD7eyX?l$i69iO9aq;Lsb~ zyLr;@q-45$ehoIXk)K#ZPc1WUSX}D6F+AR9h-R!}z<#jx6d&_0v{-xJZltFx|21R6 zxi<W5<SXYFS4hN@#;mOWiWqW|N<(Uzm5|{p!W!bqw&HxNB_Y)`B%)%VLAO1UE+$l4 z=7)jn;}ESCQ8jYwp4Bc(P2So32e5u8GPInsQ@#4OA3R(f^<}o0D~~OX0nq!U-xS@r z$x^{V#Ch^>z|rw{r1%V1<?7WxOy*W%4-n@8vrj)V&$6SoY*c#qLUWBV<00*<_WZ(! z=rg-kFLlAK%os{a-n6!cyM}PS-1PNlapD3HlCUt)5p)a!4;}llHIfF$X%zt!=@YJH zClvGr|2mmR7fxJqX-n`3tgd2BD$)bSh6pmFqs+V~T)!e|1V*0C=EtU$iHV(Z*r1PF z9u<N0d=L_tJmzo)ZJGBVZHXG*rqX|f#KO1$48ck{At_(_bR4D~*}o=O|1O;fd1@<H z^jBOdJ^uyZqt|dX*bfx&vM|{&lxD>Jf`+9-bsZ|BcpY*5lgdCtX}Q1K_#l{-X>4y- z?O1Dc4UjVVW0>w{xjvm(xxj(0<LTgYBDwO`x$|M_IRrEvD^Kf)nU;ZE3K3LMAayn# zriGYWOts(AqU~HM{H%+|E8d0^3VxSM8+}5-$yXv~k?fvriqZepsxE3Z$31u&8_RAF zLYAw$zZ=5C-EVnB=IMc(NZFm@Cbl9RoGdQ`=kwv;tHn4vcuM%{Mjx^G!4ZvY!6%ot z7$5yvB2m>x#A<h2(V>iMn~kUS`Sx}~b0HC<JP?v%v@xah<aBT4=X&$sC&xK8SX|P| ziN}tzaqY7Z?4cSt;wBpxT{M5r97cwQv~6@0c5ZGJahJJoPopn&&zQQzq(nePq>NkC zn>OAa+V=MQ_j&6|Q8YnPC=xX;qs*pG{H*0P)?sE4us!-G&$4Phze0{wZSUXC_PwnN zKY_CYr9BZ!dEHM_q?)55=T-+tg*La!NHZ&?|GsqhFFq`8Wi_&ru^ZpD6uSO7XRUVc z8qUHJBM4z&HG)=fR0n7<P*GSa&bNi=+dO)`guhEnG70CL$zwaPXvE?3@pZwqLQIb` z?VV({%`3pWuWfX@Ki+D}U8Xm-SXcrtkYMQ?<kXm=vNoC?CO6t2Um_AncrCE@yQpz& zobB@2MJvbDEF9szy;nnRi&d>&Cw5e8+>Hu$RMD>uNycKpBJpCGI;LFg%}>!!l3d=k zqyJVL93aX`5}6k~LY$VpW|d^6>e>x$Y&3I!&q(7EXs^xIQf!Zi#A8BWt=WzwCr5sJ z)^yjj_TBZR^}9Bp&=Yl_@|%E4a#rQuGncqrdA%CqE^po4oGrzOAOsYnkMRH%ey3VE zwcF;*{l5Hde6*E+Zcsw)F)jQgeIFXRQB8aKbyL^&`g^DCF67+gdb2H6Ao2nZmacw< zOQqs6o`AdhRa<_H+9jIF#!fhIOrSnzP^&@hpuS>(`K(DWc;>y-;r%|QTKoM3J&LJH z><JM9>s7kEd^d4^e(d@2;<Hfm1j0aDJDu_ul;i~5+!;_-N@k+2-R(nomF#w{)#)R@ z_6pFpo&v!lFXVeJD(gKxpI;|Nm1Yu?PX)qh3}9~=oKhWq41D^O1LnC5bJTjSWNWM` zd^JxRKe*Spfk-teSSl`O27*7`%YUD*msUFt>@I4GNv*6yDP7nhzF78v+TvxUeBYr< zVrtJLM+Y8wTm8BPdb%8x9D-Asko%;#0v<dw$LJM=0C@+LHH~R@7c-Y>^@d?-uEVn; zNt#qe?Iyoq10z*{-r?_k#)JL(tCP*mhUd@f(CxAUSIlM~weTFc6=%LlBMSIB)hz&I zak-ui6d(m{@-+IhNR5e45u|A<Mn<aV404dnbn`lB@819YlP>*ZH;%kjpU>+^4S}Y+ z8FfR8tl7ngtNV2@?^wf{y95dMc1lu{h4*1LeF;e^L_iu~^aG$*sGPl#bT|1=o)%#N zFQHAXrIrM-eemp*m~N0$96q#|4b&Aj)4i=0;U830Ei}~<M9vZ-Gc)?tBwi_oq~!eN zi0B_fI(Yo<b)1(oi&%mvKTq#an;IdvSB4)g7kq_z7%aLVq5tZ(u~BmIFI^YzP#Ya& z^lux-UbAG<o(AqBc*{#u@vjevZ$&{x?8IbLdR9VW-WKz4+wlG&bN;+vhIq}F$4ZA? zN`M`yC8~A0hSgPJnU9dvZ^iT50<AEM-!KN{wWQ)*{T30qDEVGBH5f2=HDTFIQ=iiP z%L;`{Mi^6y)e7-BD?qfEoHC%&gkNd!8*FEi-|St+%s`1;B?C~<ggATh(|@u+y`6{E z?B8U^1+UhdFYYq$##fJJ{cnICzFPUzF<VdNJH!fxbK6GVy%gE;&^jq3R=XP^NZce7 zo1{dpCzqYmDVXODPiXsAt&tJ`LZg}+o2G~ouQywBw42YDF4XnEbi(J4j|fJ{D92Jn z%+!G(D_O{1$RYo6@257i%4&Z~fRNjzhMQ{5UyU}jygLVSgebnBi#E^dXj$R%c0Q^# z+uy9eNDNm=ELC`0>+9^bJ7XdSp&-<tl;f{XnG6sArP+{gsd;+WNM3B`F{pVs2^!7v z84<9cXxN+_n@U$<>6yPzwczUy!EH>@*RCogh)s+|eacojqGX~WS$>A>?tzq>PWsgu z(Z3+^f=PED(^-lxL{DXfOL4RO{*Fhx<Ir|kswY+4URC(g2g)851zqkd4fjWjfQ@+< zyzY+a$OAN$APUYw_if3rg~0pEuVP1MbN7Wy>dlN=Wv31Nm3}5IWa;5CX(F+_yX~zT z0o_CPI$t5`bm2}6uY#sh`=O-VlCg~!cO*Z3o5J&{LvV4+<$YbA<a;Ah(C0>o85aUp z8PMkWZ+C-c`pikz(`^~uGa7wKKh%^@J0i~g_*CxgDP#z^Nba>8+VF*!vzwyV2cK<R zd$&pm-LAXqcpbF>{u*ugOW!^yYER&;W{4<RiMKq*;6{o|iw$rQwigNMEW44f_hhWX z1#@nMXmJ5Rfwg9TzU)S0H)zHuJ5pG$xziR0%_eRNe;#Zy?p@D;r;%=@e`mUQe+4b) zge+NrQ&RD7<GT{gE<zh$S}cCNlh!`s4n=BpBHjCini>jnohI-QaNAt1!S!(aH0<<{ zY>x;{0+|GT7@H*bwCc?@_2kqdiJROTLddm*xd?z1IA6ew{tKR`QCWN7t7s0;?y*_X zYbh!8M<58#1P$=ZN-BLnqpT%VC27Ba`iUyNY-%E*nqoP6aT`+IZu1)7u)WoMdEiEf zOpghn#!1HG?_pe+(#h-afGIN#8-I7t{bW;vc<#qjo8?TV<^A?q)8#K<+0zu9R;=zP zlNIOumR5&2Vz(sYw&MYwC)@33VR!TE+yqedq%zDU3y<}o&+0m^j8y$~TLvVI9tkMJ zMaX{dr34DmeGOxd^RhaRdM?aV>nyK8AD<iYibyc8jJm|qAsP`?gK8ElfciIPGiCMP z=hZQ@HxHIY*>AXlZVGJQ<BK;N<L}Xi4acjOz4v!8kBcJq`Dr=7Cc*uJ<MqFvv{}n- zhvEcFNk(T(fV`r^lYRy#XgpCoP*3@>?=Ss3FWj+;Bh!mNG*O@ET*quT!aI3i_uu|C zTOiEoc<i(7$@^(p5m!zX8e>rtDLTu5sCob1OL!pohY(P3o7T?UmzjO;RU<67uwgi1 zDb*vlSch9-yGR1c<&<2LNH&YlHBN>GKXK81`xg{wo2|(9k#A7rrS{`o$>=5C#e=)M z8Qkn_`j^@o)2MQo5bs-_pAI)b^dyK8#hbitHvy(bN7|-LHR&lgY^=GFSg_6)SZ*Rw z(agqv9585-6B7$h{isfF=Yr5w>Vd^+4SJKW7+e6Emz^Z6DB}$)Z(V$r{jP}=s&>1C znHExt{FDze*jkr<>y|QFnarDQF%$0K--2$~kcs=#cDlX@cw3&sU*vPV(46hdJ2Bp~ z$ZU`Z{Qven+;ZF@=hAk5c{PNXHC$(;v)u9)3{P{Nbi9^Ol~-s2gLq=7Xs}9rJ5B2K z5W^84h2hE&vNr~}I`!WXV3(1KaXjv@OeGQ7)}(1U+mw=zKQG(Q<r!V5fWcA!s#e@A zD-o<=`G^69x8uv`jEv^Z<sO`+WlzjAeH^$TX!4-~6~=i(fk@Zpz&=|dse@Zsm4t#; zEulMGrebk#a`xKC3Czb|(I=_Eq;mCGPOo3Y0gxmwOHwb}pCGFWDA$7T$_5;B)urmP z@OU3@M-iA=orT?3qUkbHIsiTKNy8?M?F_cP2!<sVjyz5T>|A_i6l_dg$f4uhSqo7O zS<Z+l#EHU!-E1cS&WTsh?tv^Tt#XpzV3dw&N5M*o;c!)}*=>Ivp|a9s5wfHVa7c;B z&TUSo{SxCz24ejINv}VxR<$}_p!2`+*FL};{0aWBLu=@;Na1r6NXQU)eY@eQ^^g+z zp6sWG;XwL&?8d79h71V6Twea-BTDun?~RY0u#o>|b~uzY4tEyl4^CMvKCHDD>(~`2 zHO~(8VG%&2x$TfS-3Gtv;f;Pn+79|oV$FRCfN@1^lxk}zfkbpazqmdoY$~s_SL}=l zyTFC5{dG{QvG_a^{a)WP#ZE>v5aEcGbsy_;&cqfWiFPFzAvQnnah>LXdJ#ehx>G?* z^tNZp=a1kxn90|@rStTfdP^Deaa_SqiG!;;@}4@nT>v6UjG=5yD~0uKA-hD+F^9uq zP|@p%XuU`z*0v|2W{n6-JOA;OI)Sh;lv2RM2$y%FD-$^-;7Vlk1N)@eoZDl|{;U7> z1PizT>Q{g&2e$5hGuiFtjF?9&qE;(sJJ#mQ*k$_QY!(dj%`w5!-k~kuSy6o!mO&%o z!(KnIqNFkZ-VS+W+~=+nXKyp@=J6^#svp|P(!~s$9ZnVZ1EUh(Tr7FMo}N1QDo`Wj z+8()M3<kyX#$uppqgoCV=@WLTARV*{BCXxFLrX`*hQA(=^}`k+jv7v!OH(iL;WF`B zF+7<h(8Wc3Kk()=nj!B+&1`L@J>Pim+`)A9q?+rG@KlI%=wr8w<^@PyTuAN-`$$U0 z7De*HC-2kT@Vo*Zk}Oe+73C|vv@h)7eR5@cLTa?yU+&BtDxX*N<^4$M?8RfoXE+b1 z_p876!=5_EX9S);p9Lqz#Z!?8<GBW>q6-QE%kS5sp9wJ}Z?6}Dr`O0cDJ4#ST7{ru zwAzerm%<#h4pUIi1>-)XRAn{3?gbIugKmY^h0_8M{smNS*oK__3!UJ*)#f-|{dQT{ ze3bcIxmtJqRB!s?{yydPdA)9QrKWT@(z^FtbUu$B?a={=`8Di9ZNNQO1`(7}Wo4o9 zGT7cks}M>G^ddi&xT&jN2ILJ*+7VPT>F`6~Yja##6lAzy%JZ9dkT#M*_Njeq9Kl6; zk(dF&I+{`cmaT8DS78Wl`f$QP_MlsNp$qB|Md+Xd1$O74-PCMt?CLZ?ltCNTdhrm+ zuawAXF!h#@o7MDI@$HO_`!tk5NJ*eJkNoso2Ff*jy3d_FKipfSC`|Ai@w_0i<{nx? z{;m%PzUYu-YF_=DJ8v83%e}3#*4!yTmgEBH!H8*f#3155DE&zcgrQ~r4c?4fEh=&C zb9tqXiTRh*KbU?{qcp%L5QA1=$#ti%$q-6lqav4;g%2(m`5n{6ecQDbL-H>C067CP zqSk3uk4?+&(1=(qHe|8;a}S3HkBXaQ*^fp?HMFZac9*jE8f|zNj}CgBmmuW&)fDB; z%Vl$haoG#4fM>Sldtrx_h3dVo%-m25Df9yjLd_qAP<-X--1Ak>_3T&lk2DS`#{tLh z9KEqA*-*{{@MV)gba;q7D{9f*30nCUC-%%GX1Y#LHFOA+;=!k4l)OH`)Z$L4Ss<tq zISRPMVuV=&=K6ZnjW;`#&p9v3*pz=&EmqkGet?}kiUL;}Z<Jno51+%gjgVd#`c)ET z4S!)fhSwMp%q=&&GV}W>e@G{j`}9Saj&{u8yW8luoF6H&J*e(Z%ghq1)74#UUmMOf zryM<l{CNA%&*lw1@jDZQ?KiFQ*||o2?nV3!l++&NxTf=7%d=iEP&#tE+T@gaLw*08 zZ1=H`X>1qwXfiMfyol*MWu?B-Qh}|`*V!tSAKd1%5fQO0UgQte+J+OXx66Ez^E*jw zC)E3GtCz01r%kFTKG(ccH5P-<sfi3No`)MGqP||^Esim^;UZ{`N&ASQU{rtc;&OPO ziu31t?0ZqK4N(YRniZo1PB!6kf1Te~FPE`^NaL;$-CTl|-uDPQJwoz%$x7UZc;7?$ z7{I$c7e2D~0?;*-LgcmKRJ0?4g(dr(@bl)0nOx4pF9d)0FS+trh0{|ENCl=2ggwB~ z2xzxM?fG_LJzxKAvI=!qt>JOq{`kDxaO;1Na<KxM9Px&YY*&wLk14`5^(}#W7?R85 zgW?|h!Q?S^gB#%tj~Tu>b}*v%fybiH6FZe=^UuzGQMxTYB`((a^%Zl%_sh~h`57&J zZRV7nIWq#ajy!J9)neGZ1eLCYt6EpbzN}$BDf?;*vTWFY7Xgc(=MbgRx85~sKrANu zb5Xi0O5V5p!b6z$+*qg!-PMP`jvCF@BVo`?j{hWA+kgA%`<(|{?h>%lm+@R^h-&5q zbGYfcL%j6|(YY*xm6NrPrSl$cC@u`tn5zq^)|CF((FuD?+wo(!f=+Q3J|4pCSJy~Z zDyUz5HwYmBHJl|fYkk8hMc8&DjCoq@CCX8T3=lk7S*8g)??Z;I6{2fueR<FtV)%K5 z9|9S2w1^h}r!$=s`fqFvOy0K-<h7-(z%8@w7E$rK&tq04qTg-uETXX9=a(qchYwDF zNL0vWVwv3`CX=fU8GmWSP7x(H_{Z}~pX*GH!3_9;3)K|3&QX3mjp}qwRTrBLlz;(w z?|!AJhDM5J$D`ZNE4T*@rPb-o@J2LQ@sFD~^YmH1&rWu^6q*3rWvf~~F{%4sU$-M+ z`Hq1+8DX=S4SVNH;Aj8h#Iop6(m9J>b;WjbGG4OUp$Ne)zdYw2{u$CWD-U0~4edWB z+;e2PDz5}zXKVFbnQL_M_y8r751BM|GFc72mxXKe9<sE5W)}CmtXSW`V`aX$9@do! zAntsyn*nf1t7&7pepQCbN$w);1`_#*w1a+zDART82A#3)_`7`2kFvSIrgGP{^oB|Q ze!7C281NOmjA9*FZRgG&$=_OPc;;n!|HS3p)VWpPL@W#_0Es}mrN3S23m~MbUH2Gb z?qm!3tW=C+u@e*Ub!*}|fVHI-T|kQ=Y4>6VpfvB3Rv~gpyZvl^ab95|e%rJx{d(xB z)pkHp2#J!qFg1$gcP#pOR8Bc-H-R5|QiQgb`PpXM<LjlZz0|{lnz#JMmJ1S*pco!r zoEe+uiO#0_ysyg|(x02f1wrvUJF|6f300==(Q@u(*hvVJHV8G`DKZ#d9RO)4$_)1W zjh;78W0&nfoJlhB;Ux2GvyF&l>|z0F82mZ+mev=%!Zvb3Ka_iLzN&e?!}HnurrlVw zI)8)w707RIdAXIw_4c#FZM{P$qJZ*l`x9*IZ@lE%h2VUC5(U+$U?g5Xr?>Yyr1?Rv zc^82bx@8-_g&cywmTM?GEjyk~<F4HD+m4Yp=6x-@Cw!2DKHh@cVsp9kjD1HuKL>{r ze>mMOg|8R?_4FlxfrGrCxQR0Q(`KzcEjsx!k3A>!bY8X(>?RtLY-fih6JZVtZ2oN( zD~i`U_fI_O$pfnr16C%=m44p?Yv>pp$eAEazKQchJH?2);pk48+2XCh;f`x?q~HSw zJXpggUqS|};l)?Sn78gcePu1g{D6Fr1Tn3*mFH8(sXgqqk|E11LHhDK8E%5?g=w)) zIWza^rJJ!3=q?U?5pBbJda`wU7v#F<v14kXrA`RC;V7Y!iW=!w5hQ!6r|wUEE<0Kr z+ja!1Kfat8b4jWB=2<!TTn|aN4W<OBv(6S$iGg5J`O`M4PtHTyUlv%Q6N`D!P*s(H zY{r?Wri|Z-$<~tT!0@&2^qQ6SKGAGsl|KxkEV1S|uecfU)O8zX=~Sk4NBV-hu9_Q} z!vnRS&<iJ}8}XK_a`yDX*GlK>u%+4hlkW?~NeZABAKLq3Si|#dpJhp<qw1TEYu>U6 zwqy|{`MQO=5Htr3rt2FtyiyE~o}?$S@5L66VZikC8B^MQgUTkG1G{qjd$64kjcgPU zym&t?Dy@zGa$%d%p?IWdd%gDF_kC5FDNh*o<G>yS9|0ou$G!qib{6w)YUjtj{!ObC z{+~2+vG05E+QY-)f{&WrP)P97?-9e$>C6p0t+2blVm{&@HeR4F->+a^_a`Jr<CMEs zTA6e`j8i6}%LuIcC0`(`o7ejeTJA2MEu0>Y-S5Lk6UE}R+n_-E&{I@?lIsDLwciSz z5$H1T9@wxABCS#E_gW2&Q*Eurh<e`IsORwV$HRQJHaKiDK<HfAf<B6I?Ilv_mJPfQ zr!P$p?$opynBMtB>@+atiWXomDLouEWwm+fQI?j*-3RIf1JubBfSIFi;fM$kF>=8b z@_Dhacd^Y#)Gx^t7uw_R*c1GGw34o>DCT!S{4Um+gBhN?*WJ_W`|zt!HVc*%B|B>9 zNp@lPYwO6Y^TelCOzDm2U+`Z|kB9dAk82DqKI_Nhd=SPow<l-8XM$(Hv2XQ}r+%D8 zq_Pq+k&!&;YBTcCbzd$>@8is42-gE|xkEp?9KyMlZPCX~_ffB1P&4c_7<<8eJT|P> zQyix4XTAIUY1A;`w%<p`S>9qE!#kMEOEd`@odJ0ujB(I4nx2o{e-xL(59D<(69Xb~ zZKXm}e1+XkJpkLk2}0;CZT6k{<H3oG&&!Lq{4Yca{EuZKJVV3Ip7sopGwX?$)5t#| zqaBa(e89i#A2QbtJ{MJNabW4t9;KfXwKe9C2na%ca|QoK$9~>Kpk6|IMnXf;*;b}R z_IgzoO8JaMF5oxt$5$?GJHt_v<%Y;Ehz^rJ8j4bD5|-a>yD?ZywhijG3Oc-#I*p5G z*e|ZnUbxa}+6OHg;zWj}ODKgMU<^QX9|Aj$+hUnP0H-*~hLN=K5eQTr=(I&{|K<<1 zCZ*_Hr@hTMVn%@Gex+T!Dis<In%XcPI(H?|^pI-!c~n0k=lkefr~G2P@8=?HzVfcK zq42eiW4k~G6auW}BxGu9Ie5fP@yNY#>ShYEo1kVIL=CWo1ffI`(;cAw$o6ID`K0{C zgC%&_6(gsu8nZY-6R?zpx`Nz*iP7i%E^XHSO>|1>{4evM-Db<S)8W)W<6;Gv&Lz{U z1EKuNT4faTxRr4i>v=&X$B1~C?_hwB9!A<0-d#)CCn)@d$d>EN3?=PD$Y9$8jvNKJ z<v<#gz!wxHW;6Mb-*7BOGnGh@1xwR)GLqDC1r2%7uy4mH0_qYQCi!raxf%DlRaOwi zw&}n=oeEnqMX*vPNFQ|i{)GEO$1SbDf&@*w<Q}tNuWTgN;WSB(dfDwNAO79Er0@BW z%Wh0D3^sRbr(|aUlUl<KCaNEi2DUbUYQe<uv&{Ef)G0tRoBL2M1W9DPHOwA?mIP1a zpn{g<<>_6|sR?x$`NIf<c%vfDWvi*y<Y@5n!^xQjtmjL@jnG5tEU~#2p6uu_+sB~9 z|MXhP>Rn4?577_o;%7&`W=jTa)l;6Hl*V&=E8jyWmC+Uxf&|yI%|0X!&;#Z@f1&jl z{tOeXENHcYz#(u0N%Qr@f{mGJrmDMC9VUeAc82??=_avORI>kF0apF~_TYKdb%`DX zdHK_4R?ZJ!XpJS~y?<ZfwpQipsEmBH{Zpk>MRW7YMz|$U)(O|=!CdPsVGvWh0mV7y z8y{O$J7RUY@D`f>)@N0`gy?56YK!uC#RQgQi^hG-_*BNtSoCEBc|Rf|keYuF{rQfS zk?yI72>4V7B7G|J)HX92gBEwr*IiMglD1;D%4B1LnOSi&CV9>6kQA&tU=fsvlCt!W z5d)wbi3ccNci5wyN(j?y=2>tv=%8d(W}Kp+F34G`S`MV(h0}W!h`0*VytF>jXPG2) z2Z}=3p2F*i@ZtvfLq4}irQR3xhnpUnTGN^+>1Cq$QKPC2xixB(Rn@DE7qgk0jIemo zxXqAY&hxM>h5$V%{z~ia!oyY>7f+-#=b^?dm$BDc6O$2R4w1#0oO@=0nI54%;U}0J zM#89>Z?v)#9c0fnHI^WXn@uJJ<`r$E#fftpRnT+Y_owe3#~w{Pjl_k4T5w??UN&aw zwB>>olHIx~%cEVt$Ix4`949BOVnoB4P8F}18(l&SN0RyTghR6FwOviZzs4s&o$nG~ zq)1In`n)fd&E5`j3Lmw?p8KOmr#SO$H8j@d-`<uK!khnt-8V$4T|GTdRit$s=uwWA z4M!6`0g$RZr^f;2TvYogI!C`0us&#eAXi#%?KK+~*p0CKy*-KA1$2@F;RUfX(zxTm zE_&tt@PDQhtJ6?kdNlR5HDdM*4hCG-3g#6K>Mz;Wm3#HZ1pod9^?sG`kWa(IvPEuM zDDHC~K(KSBOz`AsvN|#3{$dmA(IvIU(bAXVuBiPNZpu>aOJ;<%_~-;e-izqR_8K#D z?Nlh*0H6=M_U1Pf<32ikk;3;cI13x;Gnp#5A%>F56c}EXSlscZ#hc+mSUOGC${{j7 zBoBN`=GSeL(b%G~QLSNwi-`8tzb{5IM>PBff(EhQkD8h0kvX1`ms(?=W`nWNXs?X# z0G!-Rry)$H<31~2iNEJBG3Q?`sm8g_k=nZv6!&`137d7kx|mN$2_sZz>TVuA(<a+~ z$(86te*!%Ph{NU6Vu9oROl+G8U}DDqeo(QH_dVQNY)uX6`@XT8h#u51)aM1}V<5PH z%{F(@QEJg4@loKwuX{HlMY63~NYZ;|anXKYo)L1oqDuWwo>7Moa8w!UKO95F<TC2d zvIcL{?)Oo(tN0G0e3>Ns_xV@RoPCrPhfAdR5jMHE(;a!-cbIA&Vm<_ry^N25MW2>J z_aiSD;$VHQMcdw;5wFLiA2<P*gs`=riTUQu6%y^+#-rz3Ah-<3Wm}&9;yx$g=kiQE zPp(+F<K_>-QbSJB?VMNq$GikVq$H9C`jAbcv}&SAf^Ju?3e%2rlXF8yINZb}2_pLM zVPICg(&JN{WJ?AV@l6;A2YAV0Xob9<;nq=iN4_Xo4YB<ZqjUd)o|9B#eU6qCbYoYj zFj{F^k@svdnR$0v($pNLK@tn@?_~2pHh2Mg?|H^EH6+64ox~N+Je2rXc>|;&&@m8d z2j>ezTls_Sg#~cl?6_Zs(ZLOk9i160!+KK_A=aDZfkVS74kG&Fda`eHkQ8ZaS8{%r zP!;*L@@Z)W0P~t_@M*Z2fT7bw1)5+-tl;Q&%r6KPbwTYAp=vR}_6R}9k?gZzLhHYp z*1}8EoS<2MVZFbxiRpq|*>j%@^AahnOjfzb8>~Qld#y5A(Gx9e?_!?db&fn*hQGzG zxvV~BLP9$~3F(rS*?-+(pHJ+4-*^{h`y@A}6O(7TL)=6Yz<fs37$`oQFoL`{ZH@c* z&gBQGrs-5>0o4{I7Aii(%*>ax+Ma!TLaDeC!-o+5<O$UA2G6}Awm<wfg2els2_LaV zV+|l9o|x+)^kOv0f9+>XNgZSV!+IUg6mb;%CMGmpTa%Rw91ff-`zqw*Fq^8%d7ExG zn@jx|a;EN7aL4ny&+Ja|05Ys5-Giy?hH9R+Bi|iTp#K#MHz*1VMt540&$;XL@rSbf z%k67cakpCct1$({1`KSi_fMLviFT*1)!ofM748ELFKVk15=M#PD6~`|l+C^0#~T2h zUsr?dSYKw4I1v$h>>l-v?d1buiEz_`2f7512{$@wi*zs7?JgaMOVmfSqUOfYT_T{( zNP|O*I|tamEtlMHzmmK^gs_Wzik}K%dWkuhZDIp|R&#zow8S!;ij`tiG`2s*73@yA zA!_ye=<jFM5?m#sWZ_RwO8e+Wo&H~xbgKv0n^Q*wCU!P&UIa1R?`II2JzsS_DNU2! zc2hBWgi}C1VT8-dL!R%k#W>&8*iXm|<)~C{27ZItcGDJ_$gMPyI6BIH^+e%j(|4(H z@`E;~44!h*bDH|wU^x^o!-GFHO#2CM+K+p<QM;)5JTg;csRmx4K?ZKSBh3jS1z033 z%o4F^j&WSVD|x@Mr?TpKaNkNt0lT8Y!K|+3{VoGY9PXnNnXwewlX|y&V<Q#li8}>0 zSimP##VW){yXl&*g%%=X_R_ra8|70?Tzfr6k%dgW4Sm@C5S|K=7O@QFWnAMt1Hi0k zLnTQ^Od1}=#qmjsTy?BmdCX>IeQ5*K$XoYleIX)*iWW(Xa_EC+dvyGLcad9RBZ{<f z*H`I7z34T^DM`~<EcZ$$E4y`7RlQ|lo;JvPpZwY4!nLcf%JWwduvtag5tpkn7Rv^T z)ph-BH*q#_!(xR<pU%U*K2RbhYhoKZu?=fe00Si;4AqgLeQWAL!Y4l3+Rh1q4&pID zblNLT7cN_LQiOhCZcOvQ!@EOaBZ~_OD*x`%>25ffNQ?KczhRcdH+!bF_?~zdSrLU= zB+HpztHUt@hZVNczJ9$R#!@Oz=7`E&Q#I!(juoW5u(e&gb!rzRjEpgf3R0}G9(OQ$ z<(axsSl-N&uaK)MFl72mpaO`AZe_e2o-C_rrW0kqw?{I)sEF$ze5SmAOKlRFYF0t~ zcKO5hnnZn6lc7<Gp9}Jiuz!f3k;Kg<yr4jwnehfg3(4CKd6OqNMRgB1erK$ZJV|t@ zck9E5S<N_;%uw~a@aZBzET%fNa?8kr`WE1!CNdnW+LG8KgGTHr0{VnI2;(FpfBVWm zuv<R1fL?cm*x~ZGL(!C?D%#)yy>vaSx6-zd79chHS5LD!?`Z;il<NWdz61q3pw(5G zED}n^md-ndA;8hl$z<8>Hd404WRN=_h!RoRn1qp`<PWNkiow=E;#fjnXpv=M=Ly(L z_Xi#oAP)sgoMwOEGvM1#mJ3fRa$vH%4M6=U82q#JYvbW$&_FpFwZu}dZXvC!@1%mE zMZ=*0I4A_7Xq>V<UU1-Z4}1#vG`(R_Whaq{Zuj_QXy+>d0G2l1imi9W+TV6tt5r0L z{(IjDo&rJ``tgsT(-DrNBq)^;*4e+wN^xATZdGaO<U^np<r+Um4Ghugh_oa)%K4hH zWMn?MPv`YKlBv;2O^C!D{#q9EdPOgc#54AA9FirS81GfBV)kyr0q!cS%+_=uu(jO( zP0E(`l?@(UYTycAVs#O*>fxd4FZi7c_QriKaSN{lj2G6*kOoUv3e0HFSrB0QnkP4% zFja7V0jeSS<i_Zkyw^vtW^r*Fp6=5MeWs^!YoahJSm1owFYL4XmsV(Cs>lMePJJVL z?<83|yF`b-CKKJjAqrM6EPgaYL_WFxKy34?XFbq02RKD6&GS-Q`$rxX7?6e^cBWEf z`?~j}ith=pLwpT9_fjYpE!Mj;^m3kn9dSz4B-u0_JxNPX=ql*8M2YBkh=MjlovKuf zlv&VV<4&r3xCD?ePCRhX@4v3BH#u0K7}WRHqt~)7_Gc&SzaiwloGt5gp-}JWdmMyf z1r@1NWwF;z9V&=NfLS4tnV9C}O0K@cL5e#4L%vysL?lDgEUwf5wOY4uAr&Y@hLgi> zFacAPNmiI~{4iRad;z0#)dm-W56D_A+Z{|(<~+&JAP)ojApW=o^*_eX#^|G1%o6Jp zgKwSgb+d&nDdHWySQb0q$k7L~Acn_2g+nS6V^gAwr-8?et}%4OsSW}q{+89c%?}t^ z8tg9rVTvA`;LUWTQMqAu2ACWg@h3EL|2To{cRZQ*oG9EvE~!^hkB~Da#e0P~UPi50 z(7d#Jyo{Rt5H4Our3yEYZPD0V+N)i8Fc1#~yHIs<?Qn#}pY~}Fv=3izlN;wr%Xc5> zaUe~+TvAx~Lrd@LO9M5ztLJ+cV#)}^WchW$xkOW?j&SJA@F^0@7;Gj^|C6X!iEf*c zwCQ?<d1)tIhYCjC?-Mqpyx2TEA1hejqki?y;jlAih@JQ-!(b}}-(A4}oP+8&VMrsI zjDI=lC~2?zg>v|~x-Osl6}m^87h#xVyZtT0>WFmg?Jw-*O|KunIvcT%Ag`})AF>n` zKdB$*zZLwoy26Ar<F~Y~vh@e(K2_K-e!XV>JVG!T)}zwit{aeSbU8Zdcie`MW0vga zhMeTJ|6|dk89DmQJNzyeAE8EVdN7;}H@;~};nJWUyTfI`;!Y+QId*UL)EVtHbp->l zY7?4JBq|}1Ha!IUKxV4O1Pg4vIbL23vR#U)6{|>g8{BHMXyR9H3e*Y`!iytLMk9Hj zT&;!qy4=`3TU>k4i2jg)7ITZGB1`04!{3skO)Lbi58<4}M*TmEli#mu%x3Co$1&Y( zqN^J}Bn1=NoT0-o0|r`5(6u0fic{*{xa1-@1$XMZ+@A)2!5T`KhLB_>C$4kD*6Qxb zF_)|{55kNoD(bUsnxup?+x_s>f+1K!tFZqY8xTY<l>7<8qaUBh-TzRppywEL`l;%o zEM0P<3tSmbl<lpV+Edj;Dvd7iS8x?e7A|GS5f>Zoi+FtNw8MJZEzL*Evmee3Zt|FP z2b2pr0q7if;CSKVV8Jp0wJiVX5WJLZ>w-Z4r~V07&m~PQOO7pa7(y~v-Y?EYYDWX6 zpdHmhCA%#O4}`(<kuS=?XQp7nKwP{@E%R^e6=R#yJaC00WaOK{qk7=8A&-v-o&t+7 z-tomEW>E+*E6$>${OGU+9(@9bc#fHECme>rmMj=jYKYFcO)V7G+z{gvy!W%^yVGI} z2?2nfb?q_YpbW<F<P16_TZD8@S){jY+;s|=ewL0N*=0t4f46%=A}({W1+-CNpN)eb z3<U=D$OAFZ^sQJ2IrY->u{chSebzlUYYS6%dWn?09}%noI)z<^d~Ub(tCD*R&2aTD ze}1qir)mgtz5H?F;7rr_B`)vR)R*BZfS>1B2NvS~Y@Z)Jvlm!her)?l)&9rz3dETq zF8ZfN9okp=pH_!Epo3a(!rErvNq_5%a-0@5GI~-;*R>++0EUfGK4sa{kRf?=_w~Y! zuf^y9J~Ud1j7_z?b9pSzbLlF6vHe{==_tQIkO(&gX<gwEaIP(bsXUB9-FzU6L1{ax zea_&~-Np*XXW-0BvjO~dbftk7frDwI3Be*1MFQs7#oeQk$LjK=6DF5wwyv#|{-7F3 zK9~T#j=g0ABq?c~d5w@F&1<!gxHVesbudu!cC+1FT~_mNfH1$HFvLZGRChC*sL2Vj zQpQ^?FvuEEP>!ISv5_qTd1rqUvK*);2ev^ZrxWOfgC+0NH3`9=(Ba^i;p5Efhh|M# zgZ8|_88JdKlOTjIfD*uGsFnov|I{A}I1~U~7AYUfKU%*CGPzc*WQ4343U^|R$Yt-% z&tMH89d9NIOqJG`>++!}O5H+8jt3*Cq;HA_ovxG;XKWHf&6jOrQ5seP?iwfw&!A}3 z-QgS5#&Ah|#?FrT2`6VT;_!GPOEMJaM8nPY_MCtJB!EW>jx}lwo$*abQ70Oa_pZxf zEwlzAdDLMhQBFPFs#+b>U06p}b%;^p6$<Y1HP%Z^6L=c13|Y{7KMH3#s_Z)?rK=GG zueCJkD+5Xbllbxq+4Sb9igoq&D>w`Ee@Iseh#A1FFb@`=D#O6NzX8x`6e$P6B3+%^ z;G}30oPZMTD#{gy^@7+*nd};OiS7yM(Bj4N^Yku0MeFR##;E;kSBtbJw2G`_eg1+~ zBD9!@pP*_yB_=8@ST^o|#WrdL{sJSx1B(&q9h%-CTd8N)u21(mrQpK_E`mahM)(F! zWQgN<Oub;$Y00d>U$9W%m1I3RLCHdO>-e$u5n`v0lK;I~nl36bl5Nm1zNQsVfAf<Y zlmtIw)t#$3w<b^{TzP$j+*s|u5eJKrjT<v6?xuxd>E`#aw48XvD2A+#ZSloiV!$e+ zlp;t4$Frg*tE7qL-J77re*_a<cZpUsf)t?q@9$~=VF}5&$h85i>AoS3(84sew8C=O zz9mY%>p9aJT^IBy?nrq|wR+@*kUII)AH_X%TN<JgN&lGzidcJW0t8&poZWra&GRW@ zsVBAs&F^`eu8LRxIG1PsC(HuHZoyoTbLgih!FG~8yg0(;i$`y2S?2&rH;QDuU*Ulm zLa44l9bO9NAhDfWE9FrP>w>&agCACAWs9{@3yjoBjKvinoQl6tA=GgB1)p0oDamXT zsO%l>qzwk3iNg3QHS$Jb=;rEaVg4^0Ou_}s`+1e8RS&_1AZWJ6oEIR4@Kiu6Gg#Le zo|nuQ|AR%}gSbWwTg!q&9Cw!d!0`AK1?3;FGI6XY!|ErIaE=_$<|O>L4@(NTrRPd& zSSBt&Utj`_!Yo|mY*5_xsnBmPiIq6~l2b$s3KdN7hXJ#P<F%0C26_+}naWR3ATPnR z<*cKrmMk9*E|Cyb06vbNQx-uMaksa_C{OSDNpfM?e?R}zCu%M<MqCYU&g?<Lay(k2 zY7s<+1CTL+AU!wfJEmrpjSb&x@bx$ZHb>5FWeMy)j0)`oXW;pV;0wKH2dz>uwHP7w zLv_?5;15wEj5t8Ug#!RHlRBg-3m&pImQO#t%*1TX&?W_R;+6pcq8U2}tnNQBqIy+T z;Vfmc%P`Yk#;YITDK@x~<B<ntCfnQ<Oz_<<Ocp<e>XnBht^0aS7T`#+fjl`)M?tfu zuKngcz+0{jRNiL~q2|RU5*(&64g3W%ooC`^1hDv$&3Tmu*10-a@V3o8@_q>dorWS4 z>J~P<&2;^mL~2+?3&VgPGk}3t5dc}GNaV%@OLmmULS#SuH+Bkg!P9n#E2;-3xMu7^ zV&BpKe3$1x*+8d7l8f8Pf~u2Z+<=~;F}h1<ao*RF&P`{)SFU;XWf(Y!ej>+EUr0rY zUR@442*@|MvS96WcL`;A0`g_W+Bs)dbV^+j?mwE2UW<gQZ-Gtp&rV=P$qZGshWM8b z8|&`$6nzhP9KBMCt^e>;)c`wdxj^3AqmFG<Sx`JOFtV^iT)1``975M>U}u@qfAY@f z<OT-~5ggazCbA#F0(0qjy*3Fundm0_ckFuRXv@@|7q<S-_b*U(GV7u(L3*~$m4d>4 zR)h7%F1?f5;6p%|Yeaayz|2%&y?%u`GqgBBN_ls5EJ<NPMH{MT3^yy>`Edf=$0BbB z0m!^iq?f8L>$5^pMXDo9Q}o7lP_d|V4lm|neDyA{Tf55;J~>-kUs^m#q1xt>V^u1r z%*aaL`V!V7;y#7E*Tt}_#aw%lPAW%`6$kugWw}2o!`1?y$a-IG(ff-uRYJ2O_9+4z zFD`qlsETW#eDc}~b4OH~P018EfkHqtX1i5oW>ywrL(;%@Ow*?7bZ$5W#pp<tlt5|H z%oT?Bz>jRy+;>LtRJVl*Vv7`mZcgW*fCDTC4={Px13gm*%8}MdX2y4KB51P)d&NAX zD=a{kLrz;z(m&oMqKGYSzNaP;oh=`Cx$g$5H?^$+$AHYt#d*nBnmYb}5tuStXH&y~ z{@MA*{vbTH7RX2;$&~hE0KFPBLRkV?@B5wRyh}N$P_vjlXd)mc(Y4owMh6zol&&p; zplMIeSo@a%E&Vkl#A?mz?!C>w3%dvA21rx*ZDYz^Xb8O)&M7L==B6KnY{+g$(i$n* zjk1{}#y3QIs4fN=s&W!TDlh2DTI$8i>ln}<$jMCsp7D7g@96T=MOF>t{`_=xtf^z5 zWUJv4dn-(QB@urc1v3R{DH4^&`HVh~kN;+mDc*6M_@InAEdhNOFhq59P&ORshf!bq zO&*!{#E9y=Xa}%5k@?BJu&I1H#FRe)k)45{B5$sNFR(v+#Ang-cWMJNjVlOiwGC}f zS`#Fp!vkSD>QU#~#lx!06QI|#|2{md{0EEieGmoif`wW=e3GC`s(P`$X?&Oe#`Zh% z36kV8oGruM97f4CJn=+#wT<Kny7$8brCK#e5SRb`^%CPhTnk1GGcD`+e?(U4q;!iE z%c_$d=7wnQ2#kB7a^y&$%vA^1tj^aIC8%kZ(>FSYKAJEL-~A}Y&x(r?06PDRQvV3{ z;e&GHD5U1oCv*^W;<EG(w4GuGzPwQcKoaT6pR!|_tG3$o(mS+fLLwrXC2=ArBkRHT zcH5e%3EVdQr;33m-KrW2bR}?(5E(t4j4WgCX;O0wiv(#WL)y(V8q)()qs-wYbbgyZ z5}&h*m60SjZ0z1AOHw2U0#DSt_gP80+G+|Mn-?6z(>Om?zMwsyvlWU-tqMem+i#`W zXJDb})vYW#H8Ir`7A9**i;=)}URJ6@hCVdBM9CY;a?cew@)J-XRtc<bp;(%@IGEiB z2zz;bb*Orc><Bqv9&3687eWiY>6{9)ToC~<tVVUydv{Z_1{rGUJlbQt>pHg#+C@Fl zzyn`*b=jMm{^Tq>YfGFUlTxJ`$;qR^oJ>v@xQ-G?vwcKlcwlPyh83NJL=pAw#?33H zLUxlnAZVt1{Wa(`C?4xS3~)c1-3#J0LduOZG{mURI=mo0IRETU($X~nG}76%3Pk#4 zK}F&-p{X}Y_r$~{Qy55X?7-)YC5wI-FYeBT^XX*;x)vn>CzpUpgm~^67v~sZYLsjG zLS}GPTtf#j6lxB&9fg`i1mxQXefA&V=NRQO%4$nYqsLyk#LYNP>Ng~o943tI=iG*p zHP91?<mh<*JkDP6=(0o<pP@@#la!%^1<PRRXLo8%6hXA~0nMk7Dea?^^3}{hZouM5 ztY=_v8pQac*}{)<j+)*HLk;z^?B~lE)%_F+WN2{gUeIvhIXqGbCD{i_id%bJfh~M0 zxN$-D@AF!UF;^tnAmA<5$Ih7|sTrAXVbguL4#G>idWbzoUHOqTXeAqXK>y3;ZlbFE zshU~c9{8TSd&V641H6_kQ{i|uX&?r~^W8f)&c)*A*oYqAvM{Eg{+&(lBC};tWT@JG zG#0M}dD7y4`43^b+N}!F^ULt~X(@s*^FBJS9AC(p+u!NxWMs>uacBGw{*K6QhvGOv zafJhr&jCfPLK4)sUn#a*7D6mmEZ*U|k=<;_FXiPH!DT_~ps=+&$V~9vt=(5yDA?F1 z<$5ZL5frcjIa46foc!yFp_UJ7|1}+?y43{58s*UyW_!ChG6p4L`ylRQvMZQ~z}t0g zUgs!c!?K8zrvL#y^_Orq&)}sbd3V$3^Gh3UAO@DZ_9kc18e0o3?FD+TA_tmG(Klfb zK`A!=M4GlS)?+9}8saF*6x3|SLlK920X9i#n|S28_yMzxo!WJeTN@rvK9kkt*e0?h z^`)TSP=x(1b44b}ue#iHt1(=tdFnf}GE=|UvGB?iqf_R`x67Y4*h4F~e;Su-E2YY} z9VlAtzE}hFJo9+)V5mx~KCfFVD;1?_hp|2wyZuf!@B1oQ7AC?xnt48Rovy(Qw@lU@ zLw|7z8rs3*l37#BZqfDfzKBV<g^lQDfd56$QNDVae=xWNfmqc+COn<7S-*K0ytpU} z4#Z4vDhBbA#2DbV3QTnE7eY8HCDG@4128+r4i2+tDn|b$bD>N5rJx-)`&?1z#Octh zrlc!cP}3y@%tm7@txUoF^GJ|Zp3=S3P)1hk!~)hxiZ+eIK_)Vt0OdXJh;wZ_;xN(z zPaz6QASdFAMbZS}KE1QyNpioG0Ttuibv~B~3gJ!QKuybN@DP*UKO@?U3i19N;a8zk z_8D9sWPB?)!W-Ubc_Ub0=)wmQAFq%Y5!wp^d$1Vw;u^2?D@HGBik2$iLRhQJtTu&6 zYP$sgOOwMqemz+eZtY&t^NXA-8VR!FV0c9|?iEbZpp%GbYe?Ww8H$qJ?WikQpw_nx zK9)RPBCLeQ-StN}{!>m0rO_oS!RtL)R`M0yYXau)p88amlpAbl&S9|M??W$fz-GEZ zM*R4JHL&^YAa)rZn7B0Euqr+28qv{hgH1ojvoSekX$`-y(}6Qp9Y_IvcE#7sds#}? zPGGd=5(s8RNL5jzTTg<em1ErCtZdZjS8vVPf4<VcUea?~q`}UC+2_0JCd8W|&dHK6 z7?%a}?#Hh%K#2-VTyICuL{_4|Q(Zn+^!VsVnrOiaM8_ZK=%vv1S#%#Rab@MMJ)jj1 zyYm3NDYyg`K4>kgFvA7+2$#}ZY8k7N5W9tP53-q0eEGb>-=tQ!T%GZSLxrHjUa@ai z?W>~xD&yX(Yv@t;KaimdF9VkwJKeRwi@W3}n-|>uKMeO6ey~&qRaB;|6&V<K1{s?O zW_SVmX}gGu$cTC*8mDyK5Hr2sB`>3wx}thTbHs6P&0!6JEdlO=!xp^2Th^;Q$R*30 z>1Rnh%ZpwPVjgd|3dcjr2z%-cdl$=s<1EK!+W($Q4UxSLtjYIE6Vn4PREnXl3Zj!Z zvZfHg^C0f~hTd}Pb&`+u2(MRf;}Q)np&?d%+-&ZLe}@<w;f)kkb`7Fv)gpiNN2Fi# zk!s5=FEXvxbi((E=KNq}qh=63Jix1Nm<cRbFO2RMsw%cU_LuZ{8Up#ObGEd-6De?N zX^jCgiV`DDqB7aqV0vwwg%{1wU{Qa`IrlOqDwe?|tPvX;!REccXI5SlbiJl(SmBFC zoUq-4sX&HL#M~)#FQRu3c@q>-RMmvV9NBBBIsPr(L3_;!EO+YJMZY#N-xoXm!TMQ* z8%O^`Cj)UMwXW8U;ZVAS9KQNMR>15E>|e#oM45Of+atrm|7q_lAENw%wn0)t5s<E> zI|Nx8l<r=TmhP7B?v|1elrHI7K%^z5mR`D+ZdhQS{k`ws@O*o|-)GJ>r{+F0*UU)` zdb-vkJ$k!g6(MaKaK%@FYdBe1n_K_ywCXG97d6sh^m>!~;26ot7OMDuxifu|O%aGa zk&ipdmu{t-5a<(gK)EMNT5PvO-899M8t$<$DM3AdWK=QPEmKk&c^Rq;>lM&dQqA`W zbXL7)LGD9oWK7X6$oP0A=CeR$LP<{70FD87?eHT;NI!}L_t^T;99A=tT<^sW)skCe zcG8~ZZ}D^90|$3G20%ms0!YUO?mzw>SwEccSIK^DK^-Y=gfvkO(c*QD-+HxwjfeF! z@4RSW^q-K8pq5;6I$VQN>ZBy=#{?}(VNc8rKEv*M$aD$6mP;qod>}`wpuE|Q<Jn(( z-#y^o!=A2aS>2_t_b}VSGcugY;&yvweqRa+Hl5#kiL3n+J-e+sKwScVD5a==r{t$< z9WQ2;C`L}}N*r|-;+4S>J<Im`CcE@uzW48fbkZzcGce*_=8zw#tGPhU5!9w>(CdYC z`=ZQ7F$A5fEo4_85m|y~skHZG_eUo`3-9`{?F7-2z~?v>L}4mEv=5z4-qQ+Ly~5Qj zG+5uZ_e^Z<)@=2=(e+zD7^sGOJi((L)JLD5+3jSP0XV<Vu6F0S5ESWO-;<lU&$ny7 z6?le0rylS_x_;@O3~-yc(g0~v@nHmhw+!U*7wJh-0$A54uO`WD26hHnmu6$mW+p=v zk2DG4L90D}bK-dvd#{nJ9@Veae3|9;=D;wu_!Ev*(`<a3`5WqPZ)oIGE^LhZcJ!e# zZuXMrqXlcs)R5`aZq{~4J$K}A_nrx>VCU5mGX9fyiGOu*taXZ^Cn(7Ih_tP!1CY=n z6j3R2)&5%!_BDytwr#(hFVeUqy=T5fZ7c4Ei32*tm45;^nATxHhK8uM*9`FFvbOb( zEic}jNl!zE_}lI_RA|CvNhZlmG_4c#StJq?`U6E2o5rZ|;kEqkE_J>|<F#4Z?p(%$ z+^pC$*}I@%G@UBd2c2SDdN-3Gatg$mJeg|Hp)w;}?XxT5M61o?a_e0h>03&uFRp&) z2ZKF;iwU~enc|L@eZC|%lA95>q_6;w{wis7eYGxat-$e@thjNnsQU=bGEYF)FC^wQ zmH+L#@??pGC5~Fuu+Jm%QfWE*yb!moFRsbdv{`3_Kk7QJ9S9z8t27u*#1r_Q#|E#1 z4Pn>Lsh}q6|Dg9zYn{5(-CckRU99Ry=hQ*Q=VI(4Pt*}nuhOAY|2nRfyl5P=OcJKj zCsCS6*cNfk569f*D-<Xt`J5*;5=-S|5I5MwBbPq!kyS9tfYrf9&T}{MNOqK;1uWCX znG<#%^C!EhkmD9Z1M#OP)ql^}EoYF3R;r+nrPo1o-T#a)WC=D>Kt?s+H%NCp*0@Dt zVtxg=d-msTam+H%<D|TX{{8FijUL`)xAWm6lCaaIUH|1_T-;CMx3Kq!zDea<(<b7g zW5ds*Fg%iI-7Q&Iqr;z#n1=vt@h9-r1EX+^ohVF`D8*}F&duMNJqbX8M|Zcwc`)?- z9rL_KU`{UZ6%CROWs6Liyd1fP(X=%<w8AY5eyRYce4vFXUbn0NF~W8xKnb1G$-*?v zsuJj?zS4&t7-@GhuD|LTQg1q|isGz_H~Ah2jiZa`C};xF9c>a<RNn~$LBRLph1%L( zG6w(tA7RYjay7T70Hp7u7B#RWy~{er3QdZFBO<D!X=24G(`&67$FF84WdbX4dszy9 zc=szb>igi!PpAT=V~5%o{m4)#)&i*i)sZT!Le)HJD5Taat>V>x{Dbr&iA*W6vO%YC zw;iYC8``T(fbX24#W*uMDOZTce$3s<MvDZIs5Q=EKv0B90nPGwj;G__yEkV>zW5nJ zlC=0v%VERIw1XBNpy!R7xZqkx#}y^LzW*<l=qi!RaINcm`6%RRdU|k#Dl&HJ;u+?v z?{^c$#Pq%vkSTGE=Ocb#>-WgU%k2@Xlg29381d9^vC)3lunP?a=L!nBIIs9@vYnN4 zcXb0PR{4(MRx_;NR}x6RBDlfok|<aWCTVapxlmp%Gh>nb+XF_eVd<h+kNd{FR#85b zl;lq^L|lrFxYYu15v$0*bAg*G=&STmg$dGij&rrc@sl=Q|I1d%#dtC@z4og3=S$Y# zDs(4Jr7o)%6T-4g9`K)~NDGTYq|M|(+Izc!<*F{sS4&HSW1(=oh;`UR`R}Y>Tf=L9 z8f1Q)Cv@9Bj&sXIO1CroW9u14@`DFj92o;XPr7pWAO^3*j|TSWcONiO1m=Xl7-Rg< zH^uYmarNaT3r&mh-U>T^zl>ogl2L0$D~g$!aMY%{DnN@Du6<;BqpvQo5=>h>8kC@1 zC7BvtRz`pMy0ve<Sw3J=Q~;P95sr#p5U2)@VCn*wvi^&P)V9~GoI;tqe6T*CS{IK8 znXdK#UHs1SiZ=}bc92~VCxP6!_$~cqH{8r^=+u|Ypp<AJD!ZWbIcBNnnLJ>lp^X}s z@AYXO*5qn%1eY46*7KuTF6p7u-5%ltPhHIDzJsFlDzMIlD>z=xboW1Yt&kg{&3-_f zsG(8);K=hjrR9LhV4m5ymHf+Vv5*8&1j_hE3drwvXa<bpx~n>~9=xaO1HH#q5+Z~m zvpFO6^XEmZ(WklF(GC2pAN!Q6{XXy8=01xgOj-|GQLIuXf=ufzNA6LLv!L&%Lp4Hj zIKRVESp=(lV4=v2Y}E9o11k<>6wfqrkknM_fhlV!_)yJpVAB(@Q+;VByvZuC;!Aqh z^0!Tr1puFPU0UzB6#RKjJ@tt7k^p&N?7**x(EA;z+=OWUwVglT#O(p^z&q3N-n>Za zD$$Q$>fT4$ZibU4hT1wcGG5Zr1P@mp=t<x3Y=ZV8?m}W~ERnbBprK=1FzofZr~^^4 zcH$8lCYd1a3eY5(_>D>I1$>Jt)ePnNRx)8(m?=nr$8qTnPn9}1`Grc@UyWZIkCC`) z|5elAsjkdr@9bXaZ9lmM_O<OWw_)Nb#rz^zF8%Mf_u)$Wtm_=}xu;7sG^tqW7Ufy@ zOIc%G1PUtg8v=qXZ2DI?+}}fRaSr#jX}KA~8R!#WAqjs`;?7n=P%X8k++;Kf@RVK* zlh6SG9E(IR6j=@!yGm{=J5F`HH+kc5Uj3|0L!2&P0jMsRR@)KXt<Hgv<^zsD2Zt0z z5ba^(R_(KXI4h$F=xrT~q%c_Ji)DdiVR;8ARbwY6qCIkmmgm>9>$C%<R7i8Gv}z(b z6asOgf;2B{2T)S``HC1frgH`tN<Ub|voUIl^YaC|vdW5!#9s9wq-u9Y6<JwzWu07^ z6Ykn<ar_T_<Jyd58@VOrOul`ku<lX<|NE)$^oiv1+3KxT;d+<;GP095_ZZ?mXLpj$ zhk34gZ6?qfRiJ0nlrple2kDz{;@>`Qid5|8HzG>+)&kiqpADbk5UOv2L^ckfMU=(* zmwwcd$z6#bY5h{d7=GwpuMFS%DTXCi$4k<65B?nPin^$kPOaaS9guC@zC<l@qC*CM zB4;$knfSN5)uUf6bFf`?kt%ak+$Tat&gNfCM@DjJ{>gEpItarf_C1xsq4dUDoUZ{u zTk`v-lr=Tog^+x;1p2bc@4vWLbuLTyJQK)1W%4lbaY>Kd*iG+hvq-L3RZ5mCpi&bf zz3U~phcn$Z{I!%bCCghsHB51es^c6fff{2(>AFBVjLf&vtS1#c8e2?VBdzXSseLt- z-jCFg{Y2!<E2?hk1$6D-N|sDGW(j}IXXI}yuazu(u5@p_H%Jx@Hu-lBJoBn@0{kXE zJF2f{8|h=H1q+Co|03)p+)+PROH;vrlS=FjMf<t+<q#(((_m9B5%77z)qbrjUd%K= zcGec8mw%ip_98l3W4~>g&GATon#uFJ6<wRU{R7V%Vg6U?-s3}Y1?VRP=rdh*SkC;u zVqODr``?j%Hd_*O=%3AEh$Ps07*smNsUoo}V}#(bXXPrH;I~O{z%tIup=xs1ds^rm zOm~^Jbw6ED8;40UsHHrjk>$x#-Df#SJNM-Lq4CYYt3Pa)^JBhfgyvmvz3*xL_)la< z*;IK{87i{jInM@?!HPoB9&Rz%y2109xmDz=|KXFQedKFqN4~AHs`#cg33PfSX9B{* z|1s=;$`Uk1_pYZo=BoKx2J9Zq(88jU5o1oz>iM^j)vuo`jwa9@v`rHo>AS7pptX2L zZw~6!YwkYmkB)o$uNOIx^rt$0`@=>4Y0=4dMczJl8cdmlXhQZT4S9_J<WqkPVPc}c zePvPuE%?=q#_G8fy)FDnws!p6NP36f96!eU^g3D${6qDk*OD@TCoDo*OAW+r8s7!+ zPP)~}3t5V*=T5vqqhi~D{j(xb$}W>K^GHuuY+j5-jNZ%j)FwVQ;93SXHL+)^c_cQy zFw|7-qpz^6<oig^hn8cXFWlRxnKK7$O?ocx#DL+4N~1AVm6{!#s+-c`Y=;A+!vuxj zJ=tuc`RvtHnTOJJ<ET`8MMC-Z(4uDsEe*La;z*|d)6nbhPQzm(_-a*;oANA)@HXlx zW^bhPTD0MMUy+YpIO42z->0D1rRS?7hr|sn0Bui70$_GFXSqN7=|E}XmBseo(bC=5 z5*b-M#N3hfE)I#5$p&NXaU?IWdEe_BeyTT@DVqSkKAk;K)B3JFl<X<uUS}eIt!f?T zzyBHM9T_plj^nvoeJCpa{TJtLJZ#NVmCmmSW-CSdy;SLKpWs-EKgyMEoysJ{Z@Y_Z z0qfBy+Nhm$ZO_21vxrp&=ZSV!PRH+Q&8}ezjx&&Lf<WTyh4lVW-^$QMvL<yE!jTqd zu6CdkKn>%Y7g_4<b03yGNQipjOF0tW*OW>8+^>cF_dfuTz)7M=_SOo9-%mS&gj}FF zzfHyIs*2AXo_GnV`)=v?h02Nwi&b%FX*_}B;wEP*C1@KZB>#yZmD4(ey&fB$$o(a7 zkn18N_qX=cmFnK>xGahxhZuenfOD{j%g<*^bkR_>Y!8612s2XiFlaqcbxP@OmTH%+ z8G<xh<PMb9p#)~^jqRlmotiI=^;TAEmS_6i;(Cs^bMq~OFP%2m^3;3(@nQ3|{n~y- zc@dg%+M}%Xxt-m_<)SokdUv;v|I)*T-5B?g1wH$3Ov1m$p(Hijd1Fd`k)ly)FwRGn z>dK;0yBW5N-dJK0KNYiYT{xH|wl>>N7dZ#pcRpx}R$nXiTQd8qel7-WKlj;L?7R|D zf}kN@qLzL%8C-x~xR;vxZw-I0k6KrLyK15yDkyD~9(kk;N-G;ws8^Se71Q=@#hfBW zRC8EiEkX@R+92u}bzCI2`pgr5C;gYU&lfUkv4UQqmTJkhcDiXjq+&_X-bCm3iqTf} z1F|KVpbk55d(oUR>$q=%`Bzb9x_AQLjmMxfX`0#>z-_}8x%YJ}!eCFT`)89B#6sv` z6sPB!4pP}TEB&!g>F-`88y5&zdQ|sL8K38nVOSeGPJXcGtSc^Oq5Uz{3#sh!rYTQf zA*rlP;~do^*x4REP06U;mk(oXw;|aUZ$FXQk&DRkLlT#qgQcY(#=v<a9GIq^k$j~| zqUt-pL_Vpuw7aC<#>%rEPMr4>osfn%vP^=F+H)+QhF)wM(db5I^=G$LHUvBmVe`yM zhg9S}qFp7{GYj)co*sO9!UETA`Ce1~;EdTe=+2C&rot(FB#!h{?RUfr$`1(6T2`EI zb{J`7kUgKEC`$)A^3rdlR}vv^L7E!@*E*Oz=%}Trgm1X&SPiM2un!-N3WF{cWE0c3 zVdfwGNER=wQ?5f_&K{ijvkns^5QG<|s+;|yT~RLhQkddd33?CdG;pJ0;o{->cAva; zA5UPi6oN8?eUEjxnzq?0&*VuhPWR6JCq)aS5J@DHa*zc08;cJ}@P8FL(ux3am9YSW zJHHw!>tRl~X)iiRpSZP+>L7R`vRdeV3-mK6PIuYChsHY}<06SVZ+#3#!g(hZPHYSF zK7P5!AQs#8iUSAY9fV8k0QEmmrc$2Ay%0{OVjgN8>2J84^~GjmU|Tj<3<R*ig^?1= z9Z({mjD-L}aZv{Y>`AQEe_ZEm&Ex$qD8&-CKi$8Hl~2;xzMQOj_VE)!JQ{Cz(KOT= zd?+|(s}w(xGf&uAc9cwz^j!C<`&o?Z?g}C>qhK^8@@JB~jqI&=1A5}VBp<F=r>W<E zlY~5gFNkpp_!5f|t_*@cp6Hw@sB7t8XYUT7u?|g@!eGYOVI&HeVnmi8;I}~K2<*#> zn;CR?5e;)9XQ69|Sng+S4q5XG|L#qyL$4?!zNFN{8wOVQVU5izKlD%jGw%7Lnkn)H z;aDTB7A$Twg}F9sTB)nuh#ZTYWZKqc_6%;!AX@b7s5!qC)tQFIQq1$bjfvXWV66x2 zOw&J#31IlE)Z6IrZK_<EbDl1ljw#o%;U$b+gnF8cy-{P_&++BhgBSeV%@U0lV;m6c zRq^Nb=YKR~U;%v8QaATY=w3sz_}16#t+oD>86kwT+1JuAa7IQ@0tJnK+RqPJ+AFlD zWhp^VY`;Eh<}>x>j6mA9ZN?1sl#}WN)Aw9OQY&H=$|iO`+AofbzEM2bEp^gPwvvcE zo0dS=7hNZmh0a>!@N2<fX;~(L;~;t*P)DgLBi7d$)qn@hcV)CpebhhLt_os_=Sw)O zEersyAq|45-jm$!wTQgoE&Rv!!$L{s+By-w)2}Oe5XKVa(90L7^GN~5+E0N!F~d2N z*T--Y`8<&&wI@Onee;XJ#`J*Bn^fL=J{(#%-185ZoLrT}4vXJ69sysgl{1O<uFAc_ z2h|l5UK-llgSs=mUFJ?V|Gp1Lagg8Mu+migCrVNXc{J~Nj{oD?p+CpX(vnu?(J^v9 zAvtonnAIO;EYG(!sHM?*68gFd{ODC@<q>81KK;J)G`6H9RbT4^_z`T&2qwFn1h3_J zhy@q?Cp;3x!DidRoP+%@q`*~V6lmmc9H*D&S^2s?GgHUBCUzg@G}~lF>4x^8)t@1$ ztzV~%pf*25yjx1nTqhh)wEWbV8G&XeW5Rb9B`rOPCeIk40ea{0L386HCuNHy_Af7c zdE?{P>HPeIob3;}b>tQs2H5qqBb3WHO2Z;gvJIyEG3G35@(-bUchGAGs}ZHDZL5z6 z)!|Z+N`xocx!r+`n)-V9k}t+R<)wT7%lJ{{=Z^9=Ted${fgeMfEllTh%1D-u731sF z3`FVJ{o2?kh(xi#U`0-btTA%oe(v^|Fqih6kLhWwSDVU@v{^RT1#wE_oK_WymiCN_ zNWam}y*KeZB$Wjiz2bk9mi<i~OlNQ3GN*Ln;4{6$nWyLTxL7loYm77_q_2<_ebTY+ zULebgeq0LGG>nF}Rhjy1^KQ=0j65H?_3P#_o>qR@E=nFw6^L0lgDIxCWISzBZu%VK zH~h8O76(Z+JLsi$yO`ok2+K`m1op=!#6V8cYN$-O6)V9AjU^{tZky)m>)(-)C@_@j zu=RHM`m>?+HSO8q57O%g%8Gi2p~W+GfG=UvTLN!^ET7FFupP-nKA37WFkdCDDc{J? z*vzkX1BiAZZW2AFDq3b^BW|$co{KbE++yhZSf8)&#dvmh$GGc(dXF{12w4D_+n`3A zcoK8Qjz3&i{uSqYuNX<JP?&K)sIWX6xaZRgyQsidf}lI0A#0XZS8|%Bn^!K^BeC2J zk>hpwa5<fz+`aVeN!BJ-)oy&pa#CKmTIVS~)k0uKoe*GL{b!^6KOHDdsd-(Wsf|0u zIr#=1?6c@SeK=h?+cWG0%ep}+w*gTDc~zdOQ#Z&~I><ZBQ`wJ$^eFGR;JulmKCgq= z+29#|snImRq}y~S)4*hxu~8c_KE5b7QX^)>I<2kaaDnUoZ&k`@6NFQ?TGp_`T?biH zush2=T|t>mLz3EpPN03&^mRxBQhpwlIk~mR3BJD;miTJtWP&_ThmU=^8fo+*S$QIz z;)IU&Q)#4Zq{roPi&hB?bqDbKciqHReRq%;;`;Q^zO|Mj;JC*;Jj~C*H;cZBmOdSQ za2W3BHGjwTevVE5T?7c5_wKcwYGRHz)dDa;c6uFOPfi}Hgw3as5&*KcYqU5$dR)o6 zeJ^OqYW%t!_XS>1>GVN)kEj!3fvt-t@TNYVCuik7<95UEQl1dOzLjEqgo)ibxWuX? z9wW+^^pWZX-o!A2;wHR==@e-U;bzY}dYpHK@!SOfzQNDwSVjt*zeY8LR%Y9r+^q-u z@J;Hp4|1it2+Yo^wrepb_pE!ejr2NqQVU4M-8?>K!NY~r3|EgoTtBV~2qjTF*)P@C z%-<~@{=L9|(bt3<M2+lD$v$v3=$;Sx4<<jFj_HCuf6!qeh`ATupFRBMewUO)tgEg1 zilNqu8S~7Lz|0k7fR%9ygWV)8biyn5;3k5wWTZ25H0BEX-JQ5Whh2<6g-T(!o)(yH zbtOX`n@0!>n^(xD%!vCkA<u%Rx=y72WFRQ3E5IUPFP2J^APjFpPMHN?#JTa<P)F<P zp|yE%6}cdnB2dDiTr=hqzQ~JBbX{ChPNV%<N}{-QUv0*Vr*XGHydXJeFh^OIVVZrZ zm5oHps;$a^BknULa(?Qp47p?(f)@ghiMqIR1iI9rzC|K|HU(QvfpS=RdTER=2~$rm z57U)NN#2fET(%u!^W3=rey@XF<BHpUR(p;Qrt6xjb+kbkfZl3kKq2NE!TSJHPA)H% z8s*3VFL+V7YGTFc=xC;{2=#j<2*xoMauloN>L3r!is#ebN^x09N(yb~PgQ9kuXpIT zz0>AH|2lN`zcS7og@NrTE7bzj7V=O@QIM@V=R?^`x`Uu!I<<Ld$)UcpPpkf7e%gBx zZkYMpxzc*cUWx^7iV4EX)Z^q;92^oW)&kCgaIkX;EbIms6_Zq_kuGN0ArU%~tcEGQ zpBEawtGd5t(Sc~d7V)<&pfc!B?I#*Kb#T0Mw>CL3{Yy2@Jl67^i|+ULaRJ}1+KQof zhzElYYe%H;>)?&<6Y*!l;+X-D&=wkflUV|iVQyyLd2s7mlbiGB-jz*jINKjBKobC+ ztSM(cw5AvK1)P_4Ip|+95Py1@>2q3>-<i+}=$>&B8;ZuPh5u0fN^xH(Imk$x?g*!# z(BkLXeHv*Vbip~kc^5&#ii(OE$Jeo{N(;)U%cSl4^T+&D_2_)PNg{AB3g*ezE#)Fc zou=YTZxI%{=bOyv2P~*IKnB?z-6Cf`Yjtp=pp%vVd095|=xlf1kgTQ?6kyZp><vv{ z2z-pWo4EC5iX9@fSa$eC&xke|ud60MIK;xP=fY3X3Tn^0R)Szo;h<txPIaJL-T3Ci zs?-9QCAslmBVc#^C$CN3ycPGfHCjpWkv?O(XxC^{eE5?>mVPBB52~BgH*2)AS>_}+ z)zu5mbZI1cm?Edq!A8o`-E}2{vato}JqL>qxdHo!OrQ2lveYPZQqIZ?VlLk?pUa3C z@xucjm)Bxt(1tD($g-@Oj}|n(n9u!}fY2tRDP<nI1o$mQwB1+~#GBJ_ldY0$N=Wkj zx8|j>Gi716&`DhR{_>xz2eLxOdk;M2#Ga&P6))j?y`%spFZcwHTE0>y(2~mDehhF# zkB<K#B-Fa;RrOmn`PIt57uQuBqY!y43=I63gbqJf$D<U=%`JIj^0yvV0j{n*!o%RS z*^N{FOCDVJJTc_Nb*(+HXEmO6E-h^be0$H*XTAnmKW`(@|E`P8JH_d{-h3C(-Bdd0 zd0&s*FFD{@Ay)PdWu27ny*_b&RSHNmj7TI2_n#ZpC7<GU%+@mOy}-Shf}FeAh;mpz z|6l-|l2XvAx^l^NdS{H|*K&fhCh;5nDHG(nG)~Q;XspRJkkjdGEdm%1xoQ6h5Bn3{ zKZsAgR-vusm{R236BAQ_X+k<DDi)v+qeiO6^_jKVQAcR2R=!<1jqwex%Kja$+hSsK zz$-Rh$m8Oe=7nhk{k@!U_jMy~!aX~666d$|DvqXQb|;A<ks*8Gg3o-kwQlVyA7PM) zk`K1g1ZGnwc@i4&2_w`}R8Yv=iCRV7GS|H*EylB2x!MqZJj~M=iJ^)xOu8fSXhoO} zAoSDaHYG*ET`D%=+$8p1bVg*$qDoAcg*sJJ)7Zk?yjUGh?7njToTNnM-9p~mydCH1 z*AA+hb8cOB_(nc7<Tk7B%t_XNnOCsIc%Q4Axa`yf4=6#NqvShDyF}w*8a?CsjRVZs zNQ8`#z*78hY#!TWB+SnWTxk9<vlBwumSvq_g`nY{LOrr<1N?+ICG6cV|HP%G;l`v8 zJKJovGQ&2OFN$+%C4<@7+217sANmik{iHQCG|C?pR8)?vc**b}ron;JE^~Cz%5rjY zwWB-kl!=2%br9HvU)L+ew1AS55>=A;0n(xwa+8x~#C;51V1H`qVBWiEhDi>^-7PP} z{4%STXJw)NYVccB5gc?fDclMxa=sz^8iwKyPyV+qwH0e#571OJW(J0>GT`Nd_i4?i z#@+Z!&1ls$a3hX8RE!ouBIO^2f`)>k`Y{9*C4?F98wEuwoxltQ<+~y_FAB;OBRUxh xiY?&_JQNgxm#D}$ByuDE@ALnyk$I+NH-DU~)0E~xzSV)ED61w@`_U}ye*iq8aNPg^ literal 0 HcmV?d00001 diff --git a/examples/demo_fm/android/app/src/main/res/drawable/launch_background.xml b/examples/demo_fm/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 00000000..304732f8 --- /dev/null +++ b/examples/demo_fm/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Modify this file to customize your launch splash screen --> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:drawable="@android:color/white" /> + + <!-- You can insert your own image assets here --> + <!-- <item> + <bitmap + android:gravity="center" + android:src="@mipmap/launch_image" /> + </item> --> +</layer-list> diff --git a/examples/demo_fm/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/examples/demo_fm/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 00000000..c79c58a3 --- /dev/null +++ b/examples/demo_fm/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@color/ic_launcher_background"/> + <foreground> + <inset + android:drawable="@drawable/ic_launcher_foreground" + android:inset="16%" /> + </foreground> +</adaptive-icon> diff --git a/examples/demo_fm/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/examples/demo_fm/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..88a040ba567177d631cd29073bbfb82ff719d4cf GIT binary patch literal 3492 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 SsxX-V0000<MNUMnLSTZkyrJ*_ literal 0 HcmV?d00001 diff --git a/examples/demo_fm/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/examples/demo_fm/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d2c144f1272de819c82601a6df553d94ba8b9e9c GIT binary patch literal 2130 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 IM6N<$f|n30MF0Q* literal 0 HcmV?d00001 diff --git a/examples/demo_fm/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/examples/demo_fm/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..680b2f0b332eded7ca197e017f92179f69854c8f GIT binary patch literal 4548 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 MMhmO?R^1N&KP#<%DF6Tf literal 0 HcmV?d00001 diff --git a/examples/demo_fm/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/examples/demo_fm/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d241773d9bf8b23d9ec3084830b333266cc010cd GIT binary patch literal 7316 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 literal 0 HcmV?d00001 diff --git a/examples/demo_fm/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/examples/demo_fm/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..6062e2827cfb8a12e8c93ce7ce9fdc832aa3e5f3 GIT binary patch literal 9755 zcmc&)^LHIg6TY!+8;zSZ){Si&ZEPEj)7Z9c=LU_{IBD$0&W-Wq{VTp7cK4h)XXni9 znVp^InT=FdltMuyL<9f;C^FLGs-J7$e*+%&b5>oqg#!R+c4fpx)IGD$bKqRnHQq;h z9lVvy6XPMN3&IuQX{5FI=o_Q3As8VMyLQQ5C?Oewg34`*I)CMx>WGM_Br|}*Hs^gZ z#_pcq4;2I5cxyMgImYB~HV?CT;hZ=9F1Z~p9+tM=-l);hx4$Mj5|NXmD?&rSUlED` zAiE{e0|9jy(ByqK{}0guB}0Y!rg(+CtVU(xp2j#f3YBVw8GEn@MO+#r;?e}9aesuk z<JWpEK4KcKv^C3nFJ?1$Df`+1!*rXb1KkaKi}qeQF$r`aJURz5VU@Z<Cn53%M`0ny zs&$Kju1zz^_u@wJuLBVvrU~}I2owCUfBsAmSCIr^*NxR}bLR}5<}HQ-8g_iH3qJ&$ z8!JzKv@Uut%GF}RBZ>eZ^3kKrHc-Os4T`{^P9kIwM<G}cjA>OEXXa!>L#LrGu660~ zdtqJN7gSBJNvlMgci}yd4;Pt^4=dT$_1Io<GSk4YS1_P~(}kw4PVD;Zd!Zb#92QFs zki|A__~B@}8_|V{If5J!)1}6YN#w7$vXc2r@6>(W)4W+dlZUN!*7AmeBy8%CleDt> z_31XKTgjiE;rY+;t(VP4I&2_$pm0Hv5TBj?d@|e!Ev-T%rW~ea_*XZC1{vnmBe-Es zLVj|ti@N*R&0h)<p+w6E``rQS+HQR7_Y&+u0Dm};er;Em)1K2_ChgX;PSNRk-FM)i z#_Lvaga}RQprUQ!>)()J1&eGht;>(v@~bMPTW4Vg7e2-TJELL>_-*b%dhF+w8eL(* z5~~||0(=GP)_Z+pe8~kByv43ymdXb#W<A!w+VO2CIgDv(2P?LrJFU#B=+MC7dG-u< z&C?|pQrk>+y|D;aFlcuRQH>*fR?#Z+W)P&1NT!#S^fr7WhlfkFVeiszhs52D3ryB8 z^`dWCi4IrG5;lpK#yXu~qf?Hkr$H|Aq;6Sp!OG&wX{BKGpgG1E_Y(NFTLZX|k?A;0 zX+7Usj2LV{sTum<7=2ijEpC|4<P5mjq#c{b%@*c=Y3g1_F-#30Lh8l>Cd#JNx4Wbr z1fw+U&GzZN3I{_BSeDHFEg|8r$@=^4X=jBlP6=e&ppVjK;D+D;4RqHiYqjOwt4OWE zs}SEUuUGd^1z+MVoW=HELhg(lLY-DMj5?_2ct|5BVbqX4`d#`<ZT2`Hm!xRbbq}N| za2mqrSLkj$=F}39xi3qiRG#lBD!^D!%vqCL=OQ{4NyZP3h^;mw2v~DsH#DG2Nd>FW ze^80w8t1rsRz=rqsROMW`f~EnJgf+OhiI-0K(Ki$s;5MDgpuMO`lroids*K=A3H_i zmmS7jMwN?jk^mG#fZyKUOZCO-Ib)6Vdihc%8Uf!3A^F4+qK+;h_W4{NHMIy+>b7^* zM_Ec*f-J?{5xHIF*+=h<w?qFUKRj9YL5ZVzPT1kD1W#-p;Fqj*Nf|kcI8saLEjP&f z@@*}0FR3*x)fVkZj4}e25fCX&{j7J&_3<Eno60IfAc--Tm4vHT6H@KRKkDNiUj3a; z8Vk#Y;fXmV5y7>1=(Vg^nkkH42xG24vM*o6-=sY%YI~dyX89V+F>eymrWN`F<S*8& zzI0S%FW6c;G38~k)4?&l)@>*yO@>bKO&a3pfPG{2La_I!B8rswgd(op&W1i5CA8AP zD5AKrldR4NFO2Ey*hhan#Z{+%{pAbJpPa58K6hgIh$UxnWGWCVubI0~PVL100Gw17 z;dYNmFjk-;#j^h@)oqvJYPnE>?lK)%X0sPf{rg2&x5NaWlXp>=33=*70f8s~0u=1; z6hD+yg{+;;2BIt2OEf9M_-M<wKnI7@CYzg`V2^`U+b4<!eo;$h$fNS*Hoc78hOZJ8 z)_95Ib&EhDPxJ+<FcI85^sq$&dvufWEY9%P>ye$#4<Vjb+fchxG~=o%5fCzEkS3ws zGaBfH#Q*B3pbJ$~lN7aJ#iXPkKHoy$whd*2BS7UVrQHm7k}Nry5OincgJ|)rxMq|R z)Bv!Q8^~vc`R)5iq4zv3PtPNwBeX}oJZln-@0_5^nx7OZ>Xwm;6Wfpbumo6&z*IiF zlgzt|te~3LA5`kA6@so!=AxMk?e7||dgS*Uh%kjCF~L<vM(Vu}5CS8L(2Ge4C38xh z;MePdqHw8m2G%t!)!+dj2oD(d_piN8m-`wvRSGSP3mI(>MspG^a3vrxV6j9*#5-h= zdXPyUFmnC9+^_}K)=;FcO-+WnGp-Z-xYPfiDtg8Z3{}0;bZ_QB_t{xHZrADcTHMG& z$R30VQ7%jJLNXs@$_|0zdkMl~DP{MmKwmGPbfH)DKg`0=zN{VE)z9RDdr=K=_hA0d zY)_;rb{g-^2*}YdHB8C9_F_xPOOYw?->0w)M}3LYgG575Fqw@esQ0*py`4KSW?l-s zC`yw3&UH7s&h@&yA$W6sUl>oM3%4K#AwKqF6}-X0&8b$w5ABWS6lEUa|19&N-OHur z;eTp;?8eup%Vd1!{y1q~|0h%C3sut3*%Lqtq;ds?N~L{jMU5AHM;${EQSn6D?{-&$ zZafw^*F5cx?lG+lkVo`pZ(BgafC{Fwm`#Q^9bk8%m7!?uxwf+$0)p8sG1A`L<0vm1 zYSw{4ceMTD_x2a&pSKHEJkvSB+`RyL=Fqz8-BNOVwvTfp*8#Jj<{782#*t_$s*wBV zYhs%fSc6V6)`fB*s_4j2Uowc8bfQl<ZH%|NIm!EJs?_Z^Pv^izpC^WL8~Ue{uV53w zSaKq@>G|lpBuwLg97CS-WKM+l(asF2mo~0p9b9db#m-+4+@GS6zSNYDTB5<r%&FJ5 ziIBQ(O!~Tzmou;S*2|EL2wFbGU%49;m&<rJt#%ZNV`5AE5!9;U3R$S-oQ}SoU&#~9 z2u;HT7WvLsXz-?4Q6p8{#6g(A>GX6`r54*J9_0tvMJTm=B7UxKIN{BAOh_-+-yP52 zaAL)z07b{<2MB-Rj&SWerLrn_Uau{9+U($pG(|F3pl&un1>>UtG0mEwSH=AtafM81 z6?N?DDq-jWC%lYT+PF4b@Hl4{cy;)-dpelC6t#jIQd*gTsOEfW&!$6q&}&`vcVh)v z7V3HZPQRA_+-jG8{o5l|br#o0o0hr384(+@b{0vkk$XS*mL(l!Ryl?MWvX1oKW@&r zhwMug2`A#*unZfh8Q#&SJr$4nc*aU0b<A_Od&QT+SnMR;n*wl?)U!h4S7P|vuO=_L zdXb|{jQ`u?`1G@H{lyB(n$+nwBXgIKJHnnhftPCvMl0t>kl(y{`2_(Ic%}edrsU^V zB2!AKN2tS65nJyy*WqOudekD)nw#hM_5L?1D6T@(3Ova4#MQHR|L62B9wl!b+!Huj zID@A#<q@YVz~t%DKw6FuNL74><?AsHL#6SXF^;WXtEkH*bh-Bff^V*vW`un&lwlW1 zD~^rzAAZMt2l=xrtEo&SJ+JeV@jm2oeo8}t6Jp2v6PHz;3&}%Lp1jusz2(Rzmgj+m zPCFx`iT{Tm4;pc2k297C&W8s%fA_y3ITM97=r=VbQNnzzya1kW&dEmqme4d^SOmCh zHnMs(lP`tT4E%C$2TtQ7@cLfeNpMdG6SZp(_655rPIf9FwEP3A0`A}|>m0B{tyT5t z*pPkkSc;tQi7m}PP%3jXAV6@ck{r(1>v*gK;0Z-Vvl7aL8*prnR`j!*(ucGmVT>gN zvXVS87cGSq!}8Kr?--|rVxJhG(Zo!rm$cQP2WGFTH$gPQaf+2StSG?fh|C9@vL*9Y z@U=>eqqKmX8*g)B9a7RYa_J#w=9|}CSob<On@nFyyc&>f+VBcS&CyCsfnhm_@DaOH zb0JrSX&pOYVGX|?db;|zzgWigf#!6%8hmqRdxSR`{w>wT0<l3h=E%!M<>?X2xJrKE zU^MXhc*&~HS0nzTWBzcjwOIW>-KE9FLdNm3S&j_iv>-LIkm9dxrrcNR$ptrLtbxqs zY4*$k5v+7*DK5F93$J+ON_N9u($up=`7gaIY=89N!v>1m6ZCThKsr$w4n`e!ngH`< zK8!Db5^bie+3KNr{cxd1epu+%rRhdT!*0M{m0Vvc_d5MgTL~KZX@R)%j%ktE2CTBN zuU=)pSdNvWiD3^twp_l9Oj^%6lODq$65sCv6zVuBRRQx^ZRsiGY216NVUclScatNK zgb)0z*;0!xtbmI!GNfO&g#>ur$Zv(A@okEGOhM%@7h)^@V#X5;<r7vVssk=oR!9~( zJVMOCCYzWDtUyUh6$P86R~h>nVWg=+1oW{EDdFqnwEo8vo9^;gZl_LTUnhz}ToAIv zEpGNNc3GNl^QFIE$1xQTB<VPFZ{|9hrqg(G4v1@NG$<7T9GPwD1k4Gvj$f#(woog7 zLh%Yu7-;?)@3?&xgX-zmwPl;iLYv*yqOcJawz%n1vA7R9y?=LnZ;a~9PRAG{Q?wIu znGJP8g8bH@89@(GK4|*XY(AB@v+yiOJ@e+L86$=d*Nw^_eT&C6ionWT-9T7MQ`cW_ z`(==wz>W9j_NY`zY~`m|;FO{ktT8Q@LT=~XT&R{lMl&V03M76?x@(&x(^tnYMfgI+ z|CEvNv~m9_Exn}iJ;grgqRKOB0fk*~%Z8v5WKj-Acj^PKIo&ewGper*B4vttnMOYt zfG%Q+;t0mJNu^1=E$@V!3s|&{dSD8cNh#EU1}`~dNiLwiux)sYmy2asTz)Qgl1FWi z3-*~_0HB&{m3{KgocW)xLHvhC@foUAG$6BTam)|->p({`g-8`OA4%C^`^1DY$hJe6 zx}z_kzFHqj=LI#sq*ytP!Uw97U#jnZC2hfs@2HTyiwIfpzaj;3W+5K)D<po>f~T*- zf-m2wX0$nV8)v}omfG7p+&e;kAG2pSTb&-<fbhG>hhpUEoq@-bfn<5G{a52s>M|kf zPtYMv5SEdh&6hKACAC?{O?{n>8@0_-PgWZ&b>i1owffs_o6Q#PUMy!N%A1~g_9UP9 zEAo9Ew~DZZr|)mi6z$jcsZ$gdbp!Yac!;~`$m5)R<!^_oVbGNaOV2OLZ`X992Om(Q zSq;ARn7{5^BV-`aGTDFVxK3`=`!!{(Iw^m_mD-r4_rGeB2;G9Qa-I<n0Sr@fl1?0i zMDo<&>@({*d55`;#O4<kT*G|yXDVdnlW^yDHpEMwQk>2a*kigUK+erSL`IT)`r@6Q z)E|R6JY%TzTAw@+=Hv~_yYl1hF$p-iN7KssfwDML5HEguj2K_O;P;}86gVTyVz0c7 z8x~uSl&_|)UdGc={lyKU1#?`;?<ky|3F)-e4rO(Wd7<7N&UP)}UTP*^VucZF=|Kn} z=M^s`QDUD~y4cD`_D|r42_8_%Pu?MQU{rsVD@F}jiR?7^oah-L6F8;4@ILQu`SGlE zVkB9-1YGE0?xs^zF;LRnXGi%8@?;IXJ35kQnO8Nd%gv^3j2(~y>~_%0`}6kWV*k!? z!~FHfpuF}$DGcsT3LL4Xp2W+JhQC1Xf7k2WD2%%LmmIzdFd8*JbLul=cp0~~)j;(I zrHxzb_YyKrhK^kQ`P|G_aDZQu9!_Ao-&l^_D{3!Euzb3bO~ma}QPygIXv3h>r4eP) zYt&dx<3*Z&e{Ep0y7pSHClgpVj^$e7ybzPxZpoxrnmKPxDoWb@H?>_Pz+a6W<yK+s zHZO-Orx;%fE3XYRBZ8N5@%`8WFc<A=Kaf|=#Aa?I9(q-wR8Puk+w}nC4-y(q>Gpv= zONP8^V49ymcNw9HGP6TBhn4u;Ja2p?vIa^t6kV-lcJnwxvuU(&$kFsSEh_%*Q_k)K z>qd6iaqD=#fydqj8QRTv_%qm_jyE$bT%YQE0pT9S6~cW?AU~X<bY!H1_Z1tcS5u4R z*36w6O355E|CS>ayJWSelv_d|L_F^A7u*?F{oP0XYy}TPFzw+^$CCtAI@y(fAaNf% z(HK9Uc)3-%Y7N@L#4$tzV5Mt7w`xOBLs%Fhe&W-Gbn}xTi46i3bLlvUjvFqK%QYr0 z+4FFi8}gT2MXi!%g)UqElH4dl7C?F;uUxr!&XCo91=19?tS6gJ2{A<&n+<vWkQFHM z1#mNbP*LHiibyU=>ww9aL^Q7dr~XVmOaUMxYgVmJojA{6L`bF-;L`Z&wPQ*hO-=~i z6BI;9hMfr;3Vjk2Q_#cx^!9zf(Q^|azeRFwe58@72I(6Xo|K<Mz^_96o%ZkLj%F@; zCD=qqN-d2{6SRyPG1FO7hmdT{mcMBO=_^8dB$MnpJHCWdpqx&R(V!Cwm>s-JhOQb6 z83Q&{o-&IGWn^jEf=MW-Z6PhGwFcE#Pm(BNBvDq&g$<)%s>hfnAw)w)ZE06T0Acp1 zwEx(kMW=q2>yBzlOZ|l=Hxp-HrBM#34uE=-17{vVwIjar4)QO2|0XK?MC6H$=y=SI z%<fgR&4ip?j{y9FYhzhQbE#5YcBeqcj2o#z)%;E|q+wTx3vi0uE(ByqW4C(ax58D? zBwC(C4N<ZYJ3l|${xlQ9d)$&1yept8LF@>i>k%RrMzKHxl1+y|cOPIrj~pXTmZNVs zr3Y}A;p#={Y}t^Qwq=Q}s#k>Apb@v?VR1o3;5$Z{jUJPPvQ|ZT4Owdo_tGe^Oi-S* z(8Rm^9gF2@ryk#<zjNe5GQkR*KW$PrlGh}+<Tf2eN(q@A7&r~B`~A2TKqb=7Lz^2* z|7z$@yvi7tHcuRg@;wTtHPaOA9gUr~xNQc}hLn#S@Ta`}@Hgfom9}Rw=1kZ$m@nJ7 z-Ih2cp&p@c_gcA5BM~8G*|Hcdq(sH(<SX<$bZV${O-awXRg0tdgHUZ`gqZYS=<Vx< z1rCiH1`-X88D+#k8o^J(YK9_7^p6RF?uGln_|Aq_hrR}cF7CHai^tBn8k&26$WUKb zVv5CaNl+wfZXCAZq0y@5Au+#z!J7=vv&{V$U}r{j(a)HWZL5la@kKt;4DJpk#?*-z zyc!w`8k<7<E&7uv;`?`Al*1h2*LrCx?F;8nW=pld(8|Vbcu_n|(Ot5?D#AJU5v@!i z1%d#gLDWBk8Tq_E7VkiuPl8D2_o5e?p<(q1+rJi_7e^WmG0Z4!jS%226~lg3+Yzo) zW4fYqAuf>1D3s(WCBQ`8u%GxOb*1u<(EQZHBmQ(_<J65{<3cr9UNU8CG%aUfj7Dp= z0;~GBI1jb-T61Yn>Z|01&C0^Eo*?P>f(_Ev@*xvJtZbVm!xEgpvSMsQ7f$L<`bwWD zwX7#CRv<x@>UIDyD8XrzZ~!xp0u|)eFyO?T-QoS4ArMP)uZLyUyAmA{8NdBcZfFR# zLq3o?WhvxL$oHEzhZo9xCGVihoqtqpHgP?*9<tfA&#b8sQHYlamLWuX^oV7e=orj? zc3q_ft=%L6{WBN?8l8H46T~aAd!NHUZS~iyxbjANdkIEK8^&?&hrrN~*j!G^kQFJp z+~uxENtl*&1Rgw-_GqWao}=J4`7F=Tbq*UL8my^a`Dc!=)vdv+CRHlYr7YmH+5vgO zkS5LMC4|7rB$FooA=%*_K9<60k1e(%-2bwWVAI#R;g~mCXrJF*J)Q6g&q?clQjk|e zIzIUp!|<&0bEUEzAWi)CyJsqH1DAHL3nO=)b7@0EK!^BVkz}VPoa@j*G`=XVRONjd zpd*l5Pdkp};~%&;Tq(8yN!}Gbq9nR<%5~!O1tZXFh=J|5H9DPk3T7q*6wi>U+qrNb z#UF@?cU_fhmw0nng}*S4gW4@=Fca*_4y$fw_;ga-4Vp+p`D;6`?<2+v2ROgh;DQq7 z_<&GCZAi6HcNGC+(`{AVcV&PnBmxt>zMfw<ek^s<w0Kb!*^eu`s(+QtM209_BF%T9 zc>-QL{K;f1<nUpwV`WAS=#+k2RF;ymXRKe$LE+$-D5a9PL!=9mp2{RSIiQJ6Dpx`x zLygpKD7&A?=V<{Q0!;^%d3rVoi(6iSt5tBt3P-oNiKH3Dg}dxVf3;Mun^?0gwCb?j zA<%n9r?+Md9PmYnXlFZIxVw|+L_~=gBkmygMxG`b%%79eyTvO4@84fO%R<s{s9M2Z zRU@V05B>?+HaJTY=}348Up4jm>qS(Ott2+&4IRleqSTr#D(gAw6S7}t<_s5vFl*1# z&~P2Xz^COd3WY)?F^T%i_5KPI6Nu^7#Kb9xbUbHDQ2=h-$hC{kahup47VV7w<+Og| zfzRVb2b}46a>aW`-%*$GhdWZ=kU^Rho72~9)uP{Ib%DhN2byVd1XcH+*9r$B9sfT) zA#u))TSTk${sQM~bj-1Shl-YA$OVQNm|rwzrZQqqU|7{G*!PisENgMUVMOp$zs8p+ zow5oCPqFUrzW3Em_1sSb&yhJXr~(blN_=k4?vWHU7)}JF@29pz1wGl^q9kh7J~^XX z)}o!)n=Io=J4gBpd;raL(=Ol?+}F9oq1YpArYLohx?325|4yC=4eWO7VP;r=)Q(EM zwVd#DxiNlmWBshsRD{DL$gOX%lSz1Cx%j!2U5K#dO(9)5NDqiRVt>TnrKGA&SB&mI zB(1Nfu;j6tE)`Kp0z$xEykv?Fo4Yz+2b3QMQqhFNC_#*ageTfv=rYtZ!n|-PN`h)l zZqwiKYhc5kSb_2x(3h}6ad53MMvl75j*q^naV||-PF#(+k@OJyExJts3}4<K>O%&v zo6Y{tv8M~aVXLT>Ia~Mt`0^#f`<)>DU+<uegUZxdugGdULYpWP(ggQbU)uCJ{pHf` z@9AG8sL!{FZa{H_z^kPLxu`H2>exL@t?25ra;ezBZ;>aCIw*rGwQ_s{92R}g(+`x! za;5eZMp}Yql<I=*hu`kilLwx8+m`YKZuYXX7qiJUC&aS>is{ihdcP2t<K*Qt<@Lg@ z8`x^JL(`vFoljt1<%)vC135E|UyiUgv&m>vj5rSrEk|PZ1THN64Aq(SP{a0Su8qxx z?gundOg#MBQzEbcCZE8|C487JIweB9Stnte*PD1LuT_M@lfLYiJVW4pu1{a1(BCD$ z@hAoMgMEY<809B~CA+n4LANk90<sBjL*9V<73s4dRH^{2nx*W^Ur|C`{1w+w`r|s9 ze(+vpf8w2y#S|HW?AJZn2vKaws{i34c9V)Mou^<8Q(C`<1TqNoM*n#76g+fZll>*k zudm@2?b6RjP6-3_+}jOJlcJ$kOpXwD)dN9yK@F!FicHQezh)WgUqu-YO834rKh<~y zveB-T<0K;<y$fMg3i&}*z8a<>4Qr(Vi2W+g3?0Bx7D~bsPe0wn2NAau7oE+9S{S3q zY&M-qYm$g-FHzDpYenz2KK{Igo8y;1-v?9Ez?4cv?J(0@<BL%SlZL_El2a9!LYBW4 zAF_d7SOm&CU>wO$->Yg3yr@{CodVvYBX9sa=M!m0WJwD@oD)@7g5-D)m3sR!H-~yf zhBct~y`53H%%6zZSPT#!3cQImg3Kr`Qc>Tqlz^BDWUKp2KH45<fi^Fwe|9N^KC0>@ zV%G*PF=ipl@7rsXe&l!>i^WYE4I+z?<)&wIXur1x;1{1QG3T=wRjc;1d9ZwflpwPW z*m`0r(r}U%#7wx$aPOm;K$oP1)Ge<ICZ@}}ZT%;mRB(^u{oN#c8i(yq2dfB62z2+f zwDUIsR*#{<{p5^huTX@2WJhq}5IVCr!mrkINN+AGOcB8!^vQ2<eeKpX*}}GQuM`-O zQG9o(M;BdWm^EDGB?iljRcwhdqOo$hKaOrMe+RV~;qC|ETn(H?MBo8T#)fW@F68Aq zwHQ+fd2n2PjCC8a6V2*GFtLcPZY7*~?>H>_XM2UKPr3VCPHgwj3F4Vpm@`GV?HKmY z`Jr<X=G0V?_o9#hi7pvb2P|6sw-$<12;+f#g`fSNg=3~Xx81*koCF)(F1k3B;KFXm z6eZ!PPtu1%K@p+d^ifcT-#ut|G1f7g2X+3YEpU7kA2)K>wBYSUo}SMGmTEWM_txVo z8MnxK)As|GLQ8t^(n85%imhV<ygMTSLI>=O%q5Z;b$RY|9Ih2J@99SQ(U_I{p6G~! zx&h-$c0r8;tRXDNjt}Q3Yo*L08;t7o&v!xWAe)(o>u|2Iv9RMIm@5s(X<hL!A+m!X zy&Wy>^z4SnFyPNr<x#7z>+e$}Iq-=F#dz>qS5!b(W)Vh)@H&X$o(~^LPFKu!qwuqi zlWtF#(X5kjHVv@q@9Hg9TmQu}7UuVp2yYrdqwq@`)(GieU%foPNJJXH$sVGEn8kA6 z8v@HRLFC143NW{ePq~TCU(_=xaMlNOb!(t~f=!b_w(rrlCHI76be%8?SQZfC+Xb>5 z-wCGbIbJ-}iV+vh>%4+RrJHmBA!)gD6_yF@8XfO&2-V>&+AQ~B3_AWfzg@A&<?(jN zm>|G7^zBf-ga-0_vWpk9dr}uqT5Y*{9mKgE2m^f`R!9s{a_F2s?lTjiV4S>x*vjR! zXEhlZh?mKVBs8*$%E~nUFt92h<h-Orcv{fqWLDywzt)ugHu?<@d2j2W#?zJdTbyEW zr3cw2a^&cb<(>dCrYhl(wq~Yn5DM!=XP#gV_^Ry5D=+NtAYaiYV&GL>_E`&Gr22!t z?izPHasCr?bp_#KRNC*A4}j}DX@yMxf^sMjQ=8|Et>=YQpWnl1x(n-Z!?4To{aDG_ zWhr!Su(Q+<De&q(Mb1H1BKn776<3{;Q|1fv`x!^qec|q-j3sFfszzSeGSRvvc#2Uo zxTYMr8Px92QGe>(v_*X>l*|<t?9B@J-6)5bmWWeG7mN<^vxaM+d*AJEn?Ks3(J*j@ z8R}<rEhR#)@bn5tef0-+Zc<s$#m4APY6%{zz{|gbs0mT?ANW@2kmTJ?$GfUU69!Mt zFQ|<8VF<fEU$3(HpwyPEwE0_u?N7wwTP!s$y`fdFH_})OywAfOEpjRvgdZ>adK~}V z71_AdO02JJ0<G8}$*ZS2T3Z*6>Ako?r;-`cljq`-%<+hOf_|teO?g4ZYH*epIRFWG zUt4P;=jM60cj8GS-*YAO(Ry2H+xth~KTn5$CiSyi>=dMtW6%kc0q|Qmcy<*+zLtMq zjtPiR*mXqfAE-1&vfKzulRg4FycqWVUVxiTaO+-A1z&lf+mWKSC#Qo?uP}JrFM<wl zGy+P{Qq-eJV$XEwVmDuGB!=G6H`q-r9U*}+NZ?!%A9r`dq}jI#7L{4QpbWhA5R>h$ zR4D!@acyXXhxdW<)qtZ?g@Tik2#0Bns)L0=F*wP8E9VJCkLYvcFhF`|9$Bf&HJ=yZ zE>{CVzKUzVerBI_QD_Z+VPw%~aP5FS3&X3U;!>oJW?fpBlB-}rKVsmvxz6<WkvO6H zu5R0x^=9`vDY=qsienT)9?iIs=I!;2k>!JbzS#D9)>*L30DZL1E(+F%Bs-d+El^%= zL+vMzKN^uY7KVUp{E(97;3shUxB%G&;#t36fcfkfbC)}IL}Q^|^txz9X*OB3S%W@V zFq;88HR>HRokJVEKf<@ujA@(J=_(2SWSj7SWgn<UpC>ny_u<3UW&<|bit7PiGR%aS z8ii08vR<#Jxhg#7e-k^cWwkpg0Q-1{HoQLqPG<?6E6bY(GqrDx_TB@1tLYMwJZD}m z;D)kBMIq-wZ8w4S;SeN4#BJD-XbrlH^|puDYlY0%fF6alAtyu$#I#W?Fh*mu&Y7dW z-}&wnUJw1~$K(Xp3{QOWl`eq$Q9$_ewhrm0x1Hmw)nstRl)1V1DcrZ_0*r~qo;}IE zTof<fs{c6C_2b))|6C)7-{!MV1^XFjU*SBhn@1db1<0O6t3=8q;R98ThJd<0rqB0t ziL9F)zE&&!@W@J}_RtWos4onRsEJA^p)R+jTsH4V>BYln_{EJO&yBva3_U}8Up|<G z9l$3xT3b^sYm{7E7VQ|&S8zYpY`t8jv;F-yGv+^z$d=1L;w7&=?qg!QK%tWJ88uGq zQSc(`mdCfYtx>(nDgM1R#Yb77g9D$_H3+aHIeZ`_S>MHHe^f?j|HH0jH5F=aHykxO ziYUP<;+PI2a=}Df!c<Tw@4S7?(^1dqdihhwtLGov9`zBf1)onC)yLcP#QxOn0lw+7 zZqUvot+~u7Shl#2jXYnIEs~K_rq|o)RC)&+2E8VITcFHT43^i{sUOTs>X_~1;55w8 zV$q(oh*j4lT{Y5aI8ARjiJv;fp=}Z&hbNb=Hmvh;ka#k@@jAUJDcN`Mu24^_RxN8? zveZ2`Yvf7MF6?3d{=70ctbmLeDPAytTv$|8<ZvPWvUiy!Z=N)!ehl_D2whphv08TK z(-R<->zL4S9W(9GxAfST@-9Ajjvx=z%^yFntz{=@Qp}9j;r{S^qAc_Ag?m*-Dn(ci xA_qViQo#cQm*FANw>g6V(4H~>AJOec;J91dA-e7I=cg}#jD(_it*CL({{Zjho}&N& literal 0 HcmV?d00001 diff --git a/examples/demo_fm/android/app/src/main/res/values-night/styles.xml b/examples/demo_fm/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 00000000..06952be7 --- /dev/null +++ b/examples/demo_fm/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on --> + <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar"> + <!-- Show a splash screen on the activity. Automatically removed when + the Flutter engine draws its first frame --> + <item name="android:windowBackground">@drawable/launch_background</item> + </style> + <!-- Theme applied to the Android Window as soon as the process has started. + This theme determines the color of the Android Window while your + Flutter UI initializes, as well as behind your Flutter UI while its + running. + + This Theme is only used starting with V2 of Flutter's Android embedding. --> + <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar"> + <item name="android:windowBackground">?android:colorBackground</item> + </style> +</resources> diff --git a/examples/demo_fm/android/app/src/main/res/values/colors.xml b/examples/demo_fm/android/app/src/main/res/values/colors.xml new file mode 100644 index 00000000..f42ada65 --- /dev/null +++ b/examples/demo_fm/android/app/src/main/res/values/colors.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <color name="ic_launcher_background">#FFFFFF</color> +</resources> diff --git a/examples/demo_fm/android/app/src/main/res/values/styles.xml b/examples/demo_fm/android/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..cb1ef880 --- /dev/null +++ b/examples/demo_fm/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off --> + <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar"> + <!-- Show a splash screen on the activity. Automatically removed when + the Flutter engine draws its first frame --> + <item name="android:windowBackground">@drawable/launch_background</item> + </style> + <!-- Theme applied to the Android Window as soon as the process has started. + This theme determines the color of the Android Window while your + Flutter UI initializes, as well as behind your Flutter UI while its + running. + + This Theme is only used starting with V2 of Flutter's Android embedding. --> + <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar"> + <item name="android:windowBackground">?android:colorBackground</item> + </style> +</resources> diff --git a/examples/demo_fm/android/app/src/profile/AndroidManifest.xml b/examples/demo_fm/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 00000000..399f6981 --- /dev/null +++ b/examples/demo_fm/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- The INTERNET permission is required for development. Specifically, + the Flutter tool needs it to communicate with the running application + to allow setting breakpoints, to provide hot reload, etc. + --> + <uses-permission android:name="android.permission.INTERNET"/> +</manifest> diff --git a/examples/demo_fm/android/build.gradle.kts b/examples/demo_fm/android/build.gradle.kts new file mode 100644 index 00000000..dbee657b --- /dev/null +++ b/examples/demo_fm/android/build.gradle.kts @@ -0,0 +1,24 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = + rootProject.layout.buildDirectory + .dir("../../build") + .get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register<Delete>("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/examples/demo_fm/android/gradle.properties b/examples/demo_fm/android/gradle.properties new file mode 100644 index 00000000..fbee1d8c --- /dev/null +++ b/examples/demo_fm/android/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError +android.useAndroidX=true diff --git a/examples/demo_fm/android/gradle/wrapper/gradle-wrapper.properties b/examples/demo_fm/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..e4ef43fb --- /dev/null +++ b/examples/demo_fm/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip diff --git a/examples/demo_fm/android/settings.gradle.kts b/examples/demo_fm/android/settings.gradle.kts new file mode 100644 index 00000000..c6ae567e --- /dev/null +++ b/examples/demo_fm/android/settings.gradle.kts @@ -0,0 +1,28 @@ +pluginManagement { + val flutterSdkPath = + run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "8.11.1" apply false + id("org.jetbrains.kotlin.android") version "2.2.20" apply false + // Issue #1138 reproduction: required by firebase_messaging. + id("com.google.gms.google-services") version "4.4.2" apply false +} + +include(":app") diff --git a/examples/demo_fm/assets/onesignal_logo.svg b/examples/demo_fm/assets/onesignal_logo.svg new file mode 100644 index 00000000..8bb8d138 --- /dev/null +++ b/examples/demo_fm/assets/onesignal_logo.svg @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg xmlns="http://www.w3.org/2000/svg" width="316" height="70" viewBox="0 0 316 70" fill="none"> +<g clip-path="url(#clip0_2277_11161)"> +<path d="M34.8106 0.345025C15.5675 0.383111 -0.107685 16.1805 0.000557241 35.4237C0.0499825 44.0258 3.27658 52.3062 9.06036 58.6738C14.8441 65.0414 22.7771 69.0471 31.3348 69.921C31.3907 69.9266 31.4472 69.9204 31.5006 69.9028C31.5539 69.8852 31.603 69.8565 31.6446 69.8187C31.6861 69.7809 31.7193 69.7348 31.7419 69.6834C31.7645 69.6319 31.7761 69.5763 31.7758 69.5201V35.2232H29.0657C28.9594 35.2232 28.8574 35.181 28.7822 35.1058C28.707 35.0306 28.6648 34.9286 28.6648 34.8223V29.4102C28.6648 29.3039 28.707 29.2019 28.7822 29.1267C28.8574 29.0515 28.9594 29.0093 29.0657 29.0093H37.5728C37.6791 29.0093 37.7811 29.0515 37.8563 29.1267C37.9314 29.2019 37.9737 29.3039 37.9737 29.4102V69.5201C37.9734 69.5763 37.9849 69.6319 38.0075 69.6834C38.0301 69.7348 38.0633 69.7809 38.1049 69.8187C38.1465 69.8565 38.1955 69.8852 38.2489 69.9028C38.3023 69.9204 38.3588 69.9266 38.4147 69.921C47.317 69.0121 55.5294 64.7164 61.3533 57.9223C67.1771 51.1281 70.1668 42.3555 69.7038 33.4189C69.2409 24.4823 65.3608 16.0654 58.8662 9.90943C52.3715 3.75341 43.7592 0.32918 34.8106 0.345025V0.345025ZM44.7228 62.1516C44.6622 62.1731 44.5974 62.1798 44.5337 62.171C44.47 62.1622 44.4094 62.1382 44.3569 62.1011C44.3044 62.0639 44.2616 62.0147 44.2322 61.9575C44.2027 61.9004 44.1874 61.837 44.1876 61.7727V56.0479C44.1877 55.934 44.2202 55.8225 44.2812 55.7263C44.3423 55.6301 44.4294 55.5533 44.5324 55.5047C49.1635 53.3017 52.9013 49.5803 55.1247 44.959C57.3481 40.3377 57.9233 35.0947 56.7545 30.1013C55.5858 25.1079 52.7436 20.6648 48.7002 17.5102C44.6568 14.3557 39.6557 12.6797 34.528 12.7609C22.5972 12.9433 12.8073 22.5648 12.4284 34.4916C12.2897 38.8588 13.4263 43.1719 15.6992 46.9037C17.9722 50.6354 21.283 53.6242 25.2271 55.5047C25.3301 55.5533 25.4172 55.6301 25.4782 55.7263C25.5393 55.8225 25.5718 55.934 25.5719 56.0479V61.7727C25.5721 61.837 25.5568 61.9004 25.5273 61.9575C25.4979 62.0147 25.4551 62.0639 25.4026 62.1011C25.3501 62.1382 25.2895 62.1622 25.2258 62.171C25.1621 62.1798 25.0973 62.1731 25.0367 62.1516C19.4788 60.1122 14.6871 56.4048 11.3177 51.5369C7.94824 46.669 6.16583 40.8787 6.21449 34.9586C6.35079 19.3877 19.0753 6.67321 34.6522 6.55895C50.5659 6.43067 63.543 19.3396 63.543 35.2232C63.543 47.5749 55.6974 58.1265 44.7228 62.1516Z" fill="white"/> +<path d="M117.641 47.5308C114.242 50.917 110.104 52.6088 105.23 52.6061C100.355 52.6035 96.2267 50.9117 92.8458 47.5308C89.4649 44.1498 87.7744 40.0046 87.7744 35.0949C87.7744 30.1852 89.4662 26.0426 92.8498 22.667C96.2307 19.2781 100.359 17.5836 105.234 17.5836C110.108 17.5836 114.244 19.2754 117.641 22.659C121.041 26.0453 122.741 30.1879 122.741 35.0869C122.741 39.9858 121.041 44.1338 117.641 47.5308ZM97.4882 43.0086C99.5729 45.0773 102.155 46.1116 105.234 46.1116C108.312 46.1116 110.894 45.0773 112.979 43.0086C115.064 40.94 116.106 38.3021 116.106 35.0949C116.106 31.8877 115.064 29.2418 112.979 27.1571C110.894 25.0751 108.312 24.0328 105.234 24.0301C102.155 24.0274 99.5729 25.0697 97.4882 27.1571C95.4035 29.2444 94.3612 31.8904 94.3612 35.0949C94.3612 38.2994 95.4035 40.9373 97.4882 43.0086Z" fill="white"/> +<path d="M140.493 27.2052C143.122 27.2052 145.295 28.0872 147.011 29.8511C148.727 31.6151 149.585 34.0525 149.585 37.1635V51.5317C149.585 51.5844 149.575 51.6365 149.554 51.6851C149.534 51.7338 149.505 51.778 149.468 51.8152C149.43 51.8524 149.386 51.882 149.337 51.9021C149.289 51.9223 149.237 51.9326 149.184 51.9326H143.772C143.666 51.9326 143.564 51.8904 143.488 51.8152C143.413 51.74 143.371 51.6381 143.371 51.5317V37.9332C143.371 36.3297 142.938 35.1029 142.072 34.253C141.206 33.4031 140.052 32.9781 138.608 32.9781C137.005 32.9781 135.722 33.4753 134.76 34.4695C133.798 35.4637 133.317 36.9551 133.317 38.9435V51.5317C133.317 51.6381 133.274 51.74 133.199 51.8152C133.124 51.8904 133.022 51.9326 132.916 51.9326H127.503C127.397 51.9326 127.295 51.8904 127.22 51.8152C127.145 51.74 127.103 51.6381 127.103 51.5317V28.2796C127.103 28.1733 127.145 28.0713 127.22 27.9961C127.295 27.9209 127.397 27.8787 127.503 27.8787H132.916C133.022 27.8787 133.124 27.9209 133.199 27.9961C133.274 28.0713 133.317 28.1733 133.317 28.2796V30.5727C134.832 28.3277 137.224 27.2052 140.493 27.2052Z" fill="white"/> +<path d="M160.125 42.4554C160.958 45.4701 163.22 46.9775 166.908 46.9775C169.152 46.9775 170.879 46.2606 172.091 44.8267C172.153 44.7573 172.236 44.7111 172.327 44.6961C172.419 44.6812 172.512 44.6983 172.593 44.7445L176.916 47.2381C176.965 47.2662 177.007 47.3041 177.04 47.3494C177.073 47.3947 177.096 47.4464 177.107 47.5012C177.119 47.556 177.119 47.6126 177.108 47.6674C177.096 47.7222 177.073 47.774 177.041 47.8194C174.675 51.0106 171.268 52.6061 166.818 52.6061C162.841 52.6061 159.65 51.4034 157.244 48.9981C154.839 46.5927 153.636 43.5619 153.636 39.9057C153.636 36.2829 154.823 33.2601 157.196 30.8373C159.569 28.4146 162.614 27.2039 166.331 27.2052C169.858 27.2052 172.769 28.4239 175.062 30.8614C177.355 33.2989 178.502 36.3136 178.502 39.9057C178.498 40.6443 178.436 41.3815 178.317 42.1106C178.302 42.2051 178.252 42.2908 178.179 42.3522C178.105 42.4136 178.012 42.4467 177.916 42.4454L160.125 42.4554ZM160.028 37.6446H172.296C171.942 36.0089 171.212 34.7902 170.107 33.9884C169.011 33.1909 167.686 32.769 166.331 32.7857C164.663 32.7857 163.284 33.2107 162.193 34.0606C161.103 34.9105 160.381 36.1051 160.028 37.6446Z" fill="white"/> +<path d="M193.656 52.6061C190.315 52.6061 187.509 51.8605 185.237 50.3691C183.099 48.9959 181.455 46.9753 180.546 44.6022C180.513 44.5135 180.511 44.4156 180.543 44.326C180.574 44.2364 180.637 44.161 180.719 44.1131L185.704 41.1986C185.753 41.1701 185.807 41.1523 185.863 41.1464C185.92 41.1404 185.977 41.1464 186.03 41.164C186.084 41.1816 186.134 41.2104 186.175 41.2485C186.217 41.2866 186.251 41.3331 186.273 41.385C187.634 44.5361 190.159 46.1116 193.848 46.1116C195.708 46.1116 197.071 45.7775 197.937 45.1093C198.343 44.8199 198.672 44.4371 198.898 43.9933C199.125 43.5494 199.24 43.0577 199.236 42.5596C199.236 41.3743 198.707 40.4522 197.649 39.7934C196.59 39.1346 194.698 38.421 191.972 37.6526C190.672 37.2795 189.395 36.8297 188.147 36.3056C187.041 35.822 185.993 35.217 185.02 34.5016C183.994 33.7679 183.174 32.782 182.639 31.6391C182.07 30.3695 181.79 28.9891 181.821 27.5981C181.821 24.5539 182.904 22.1245 185.069 20.3097C187.233 18.495 189.839 17.589 192.886 17.5916C195.612 17.5916 198.01 18.2598 200.078 19.5961C202.069 20.8877 203.679 22.6868 204.743 24.8078C204.789 24.8995 204.799 25.0056 204.769 25.104C204.74 25.2025 204.673 25.2859 204.584 25.337L199.703 28.1573C199.656 28.1843 199.605 28.2014 199.551 28.2078C199.497 28.2142 199.443 28.2097 199.391 28.1945C199.339 28.1793 199.291 28.1538 199.249 28.1196C199.207 28.0853 199.173 28.0429 199.148 27.995C197.793 25.3597 195.706 24.0414 192.886 24.0401C191.507 24.0401 190.425 24.3528 189.639 24.9782C189.264 25.2607 188.962 25.6281 188.757 26.0501C188.552 26.472 188.451 26.9366 188.46 27.4056C188.451 27.9105 188.568 28.4096 188.798 28.8586C189.029 29.3077 189.368 29.6927 189.783 29.9794C190.665 30.6396 192.357 31.3532 194.858 32.1202C195.885 32.4436 196.662 32.6922 197.192 32.8659C197.721 33.0396 198.442 33.3122 199.357 33.6837C200.091 33.9656 200.799 34.3117 201.473 34.718C202.069 35.1153 202.639 35.5491 203.181 36.017C203.761 36.492 204.257 37.0612 204.648 37.7007C205.462 39.1555 205.885 40.7965 205.875 42.4634C205.875 45.5757 204.745 48.0479 202.484 49.88C200.222 51.7121 197.28 52.6208 193.656 52.6061Z" fill="white"/> +<path d="M212.995 25.0003C211.989 24.9868 211.028 24.5812 210.317 23.8698C209.606 23.1585 209.2 22.1976 209.187 21.1917C209.184 20.6897 209.283 20.1922 209.477 19.7293C209.671 19.2663 209.957 18.8474 210.317 18.4977C210.658 18.1305 211.071 17.8382 211.531 17.6394C211.99 17.4406 212.486 17.3397 212.987 17.3431C213.495 17.3368 214 17.4362 214.467 17.6349C214.935 17.8337 215.357 18.1275 215.705 18.4977C216.066 18.8473 216.353 19.266 216.549 19.7289C216.744 20.1917 216.845 20.6892 216.844 21.1917C216.848 21.6904 216.749 22.1845 216.555 22.6437C216.36 23.1029 216.074 23.5174 215.713 23.8617C215.362 24.2274 214.94 24.5172 214.472 24.7131C214.005 24.9089 213.502 25.0067 212.995 25.0003ZM209.916 51.5397V28.2876C209.916 28.1813 209.958 28.0793 210.034 28.0041C210.109 27.929 210.211 27.8867 210.317 27.8867H215.729C215.836 27.8867 215.938 27.929 216.013 28.0041C216.088 28.0793 216.13 28.1813 216.13 28.2876V51.5397C216.13 51.6461 216.088 51.748 216.013 51.8232C215.938 51.8984 215.836 51.9406 215.729 51.9406H210.317C210.264 51.9407 210.211 51.93 210.162 51.9094C210.113 51.8887 210.068 51.8585 210.031 51.8204C209.993 51.7823 209.964 51.7372 209.944 51.6876C209.925 51.638 209.915 51.585 209.916 51.5317V51.5397Z" fill="white"/> +<path d="M240.625 27.8787H245.885C245.991 27.8787 246.093 27.9209 246.168 27.9961C246.244 28.0713 246.286 28.1733 246.286 28.2796V50.778C246.286 54.4984 245.058 57.3367 242.603 59.2931C240.149 61.2495 237.19 62.2277 233.728 62.2277C231.13 62.2277 228.845 61.7306 226.874 60.7364C225.065 59.8438 223.554 58.4438 222.526 56.7073C222.5 56.6617 222.483 56.6113 222.477 56.5591C222.47 56.5068 222.474 56.4538 222.487 56.403C222.501 56.3522 222.525 56.3046 222.557 56.2629C222.589 56.2212 222.629 56.1863 222.675 56.1601L227.273 53.5262C227.363 53.4752 227.469 53.4607 227.569 53.4857C227.669 53.5107 227.755 53.5733 227.81 53.6605C229.053 55.6824 231.09 56.694 233.92 56.6953C235.876 56.6953 237.413 56.1822 238.53 55.1559C239.648 54.1296 240.209 52.6703 240.216 50.778V48.1722C238.387 50.611 235.82 51.8297 232.517 51.8284C229.117 51.8284 226.272 50.6337 223.98 48.2444C221.688 45.855 220.541 42.9445 220.538 39.5128C220.538 36.1158 221.693 33.2133 224.004 30.8053C226.314 28.3972 229.152 27.1945 232.517 27.1972C235.82 27.1972 238.387 28.4159 240.216 30.8534V28.2796C240.216 28.2263 240.227 28.1735 240.247 28.1243C240.268 28.0751 240.298 28.0306 240.336 27.9933C240.374 27.9559 240.42 27.9266 240.469 27.9069C240.519 27.8872 240.572 27.8776 240.625 27.8787ZM228.654 44.2594C229.92 45.4955 231.531 46.1129 233.489 46.1116C235.447 46.1102 237.058 45.4929 238.322 44.2594C239.589 43.0273 240.223 41.4478 240.224 39.5208C240.224 37.6299 239.59 36.0664 238.322 34.8303C237.054 33.5942 235.443 32.9768 233.489 32.9781C231.531 32.9781 229.92 33.5955 228.654 34.8303C227.389 36.0651 226.755 37.6286 226.752 39.5208C226.752 41.4451 227.386 43.0247 228.654 44.2594Z" fill="white"/> +<path d="M265.286 27.2052C267.916 27.2052 270.089 28.0872 271.805 29.8511C273.521 31.6151 274.379 34.0525 274.379 37.1635V51.5317C274.379 51.5844 274.368 51.6365 274.348 51.6851C274.328 51.7338 274.299 51.778 274.261 51.8152C274.224 51.8524 274.18 51.882 274.131 51.9021C274.083 51.9223 274.03 51.9326 273.978 51.9326H268.566C268.459 51.9326 268.357 51.8904 268.282 51.8152C268.207 51.74 268.165 51.6381 268.165 51.5317V37.9332C268.165 36.3297 267.732 35.1029 266.866 34.253C266 33.4031 264.845 32.9781 263.402 32.9781C261.799 32.9781 260.516 33.4753 259.553 34.4695C258.591 35.4637 258.11 36.9551 258.11 38.9435V51.5317C258.11 51.6381 258.068 51.74 257.993 51.8152C257.918 51.8904 257.816 51.9326 257.709 51.9326H252.297C252.191 51.9326 252.089 51.8904 252.014 51.8152C251.939 51.74 251.896 51.6381 251.896 51.5317V28.2796C251.896 28.1733 251.939 28.0713 252.014 27.9961C252.089 27.9209 252.191 27.8787 252.297 27.8787H257.709C257.816 27.8787 257.918 27.9209 257.993 27.9961C258.068 28.0713 258.11 28.1733 258.11 28.2796V30.5727C259.623 28.3277 262.015 27.2052 265.286 27.2052Z" fill="white"/> +<path d="M298.352 27.8787H303.765C303.871 27.8787 303.973 27.9209 304.048 27.9961C304.123 28.0713 304.166 28.1733 304.166 28.2796V51.5317C304.166 51.6381 304.123 51.74 304.048 51.8152C303.973 51.8904 303.871 51.9326 303.765 51.9326H298.352C298.246 51.9326 298.144 51.8904 298.069 51.8152C297.994 51.74 297.952 51.6381 297.952 51.5317V49.0943C296.091 51.4382 293.478 52.6088 290.11 52.6061C286.903 52.6061 284.153 51.3794 281.859 48.9259C279.566 46.4724 278.42 43.4656 278.42 39.9057C278.42 36.3457 279.566 33.3389 281.859 30.8854C284.153 28.4319 286.903 27.2052 290.11 27.2052C293.478 27.2052 296.091 28.3758 297.952 30.7171V28.2796C297.952 28.1733 297.994 28.0713 298.069 27.9961C298.144 27.9209 298.246 27.8787 298.352 27.8787ZM286.502 44.7886C287.753 46.0581 289.34 46.6915 291.265 46.6889C293.189 46.6862 294.784 46.0528 296.051 44.7886C297.318 43.5231 297.952 41.8955 297.952 39.9057C297.952 37.9159 297.318 36.2882 296.051 35.0227C294.784 33.7572 293.189 33.1238 291.265 33.1225C289.34 33.1211 287.753 33.7545 286.502 35.0227C285.251 36.2922 284.626 37.9199 284.626 39.9057C284.626 41.8915 285.251 43.5191 286.502 44.7886Z" fill="white"/> +<path d="M309.786 51.5317V17.2148C309.786 17.1085 309.828 17.0065 309.903 16.9313C309.979 16.8561 310.081 16.8139 310.187 16.8139H315.599C315.705 16.8139 315.807 16.8561 315.883 16.9313C315.958 17.0065 316 17.1085 316 17.2148V51.5317C316 51.5844 315.99 51.6365 315.969 51.6851C315.949 51.7338 315.92 51.778 315.883 51.8152C315.845 51.8524 315.801 51.882 315.753 51.9021C315.704 51.9223 315.652 51.9326 315.599 51.9326H310.187C310.081 51.9326 309.979 51.8904 309.903 51.8152C309.828 51.74 309.786 51.6381 309.786 51.5317Z" fill="white"/> +</g> +<defs> +<clipPath id="clip0_2277_11161"> +<rect width="316" height="70" fill="white"/> +</clipPath> +</defs> +</svg> \ No newline at end of file diff --git a/examples/demo_fm/assets/onesignal_logo_icon_padded.png b/examples/demo_fm/assets/onesignal_logo_icon_padded.png new file mode 100644 index 0000000000000000000000000000000000000000..4ff809f42fb7874d4ee50b85b273e7225090ac74 GIT binary patch literal 81225 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 E0hqbCO8@`> literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/.gitignore b/examples/demo_fm/ios/.gitignore new file mode 100644 index 00000000..7a7f9873 --- /dev/null +++ b/examples/demo_fm/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/examples/demo_fm/ios/ExportOptions.plist b/examples/demo_fm/ios/ExportOptions.plist new file mode 100644 index 00000000..935873e2 --- /dev/null +++ b/examples/demo_fm/ios/ExportOptions.plist @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>method</key> + <string>development</string> + <key>teamID</key> + <string>99SW8E36CT</string> + <key>signingStyle</key> + <string>manual</string> + <key>stripSwiftSymbols</key> + <true/> + <key>provisioningProfiles</key> + <dict> + <key>com.onesignal.example</key> + <string>Appium Demo - Main</string> + <key>com.onesignal.example.NSE</key> + <string>Appium Demo - NSE</string> + <key>com.onesignal.example.LA</key> + <string>Appium Demo - Live Activity</string> + </dict> +</dict> +</plist> diff --git a/examples/demo_fm/ios/Flutter/AppFrameworkInfo.plist b/examples/demo_fm/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 00000000..1dc6cf76 --- /dev/null +++ b/examples/demo_fm/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleExecutable</key> + <string>App</string> + <key>CFBundleIdentifier</key> + <string>io.flutter.flutter.app</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>App</string> + <key>CFBundlePackageType</key> + <string>FMWK</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1.0</string> + <key>MinimumOSVersion</key> + <string>13.0</string> +</dict> +</plist> diff --git a/examples/demo_fm/ios/Flutter/Debug.xcconfig b/examples/demo_fm/ios/Flutter/Debug.xcconfig new file mode 100644 index 00000000..592ceee8 --- /dev/null +++ b/examples/demo_fm/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/examples/demo_fm/ios/Flutter/Release.xcconfig b/examples/demo_fm/ios/Flutter/Release.xcconfig new file mode 100644 index 00000000..28f8fb7e --- /dev/null +++ b/examples/demo_fm/ios/Flutter/Release.xcconfig @@ -0,0 +1,6 @@ +#include "Generated.xcconfig" + +// Skip dSYM emission in release builds. We don't ship to the App Store from +// this app and don't need symbolicated crash reports, so DWARF-only saves +// build time. +DEBUG_INFORMATION_FORMAT = dwarf diff --git a/examples/demo_fm/ios/OneSignalNotificationServiceExtension/Info.plist b/examples/demo_fm/ios/OneSignalNotificationServiceExtension/Info.plist new file mode 100644 index 00000000..57421ebf --- /dev/null +++ b/examples/demo_fm/ios/OneSignalNotificationServiceExtension/Info.plist @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>NSExtension</key> + <dict> + <key>NSExtensionPointIdentifier</key> + <string>com.apple.usernotifications.service</string> + <key>NSExtensionPrincipalClass</key> + <string>$(PRODUCT_MODULE_NAME).NotificationService</string> + </dict> +</dict> +</plist> diff --git a/examples/demo_fm/ios/OneSignalNotificationServiceExtension/NotificationService.swift b/examples/demo_fm/ios/OneSignalNotificationServiceExtension/NotificationService.swift new file mode 100644 index 00000000..ab391a33 --- /dev/null +++ b/examples/demo_fm/ios/OneSignalNotificationServiceExtension/NotificationService.swift @@ -0,0 +1,32 @@ +import UserNotifications +import OneSignalExtension + +class NotificationService: UNNotificationServiceExtension { + var contentHandler: ((UNNotificationContent) -> Void)? + var receivedRequest: UNNotificationRequest! + var bestAttemptContent: UNMutableNotificationContent? + + // Note this extension only runs when `mutable_content` is set + // Setting an attachment or action buttons automatically sets the property to true + override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { + self.receivedRequest = request + self.contentHandler = contentHandler + self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) + + if let bestAttemptContent = bestAttemptContent { + // DEBUGGING: Uncomment the 2 lines below to check this extension is executing +// print("Running NotificationServiceExtension") +// bestAttemptContent.body = "[Modified] " + bestAttemptContent.body + + OneSignalExtension.didReceiveNotificationExtensionRequest(self.receivedRequest, with: bestAttemptContent, withContentHandler: self.contentHandler) + } + } + + override func serviceExtensionTimeWillExpire() { + // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used. + if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { + OneSignalExtension.serviceExtensionTimeWillExpireRequest(self.receivedRequest, with: self.bestAttemptContent) + contentHandler(bestAttemptContent) + } + } +} diff --git a/examples/demo_fm/ios/OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements b/examples/demo_fm/ios/OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements new file mode 100644 index 00000000..c70461e8 --- /dev/null +++ b/examples/demo_fm/ios/OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>com.apple.security.application-groups</key> + <array> + <string>group.com.onesignal.example.onesignal</string> + </array> +</dict> +</plist> diff --git a/examples/demo_fm/ios/OneSignalWidget/Assets.xcassets/AccentColor.colorset/Contents.json b/examples/demo_fm/ios/OneSignalWidget/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/examples/demo_fm/ios/OneSignalWidget/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/examples/demo_fm/ios/OneSignalWidget/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/demo_fm/ios/OneSignalWidget/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..23058801 --- /dev/null +++ b/examples/demo_fm/ios/OneSignalWidget/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,35 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/examples/demo_fm/ios/OneSignalWidget/Assets.xcassets/Contents.json b/examples/demo_fm/ios/OneSignalWidget/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/examples/demo_fm/ios/OneSignalWidget/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/examples/demo_fm/ios/OneSignalWidget/Assets.xcassets/WidgetBackground.colorset/Contents.json b/examples/demo_fm/ios/OneSignalWidget/Assets.xcassets/WidgetBackground.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/examples/demo_fm/ios/OneSignalWidget/Assets.xcassets/WidgetBackground.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/examples/demo_fm/ios/OneSignalWidget/Info.plist b/examples/demo_fm/ios/OneSignalWidget/Info.plist new file mode 100644 index 00000000..0f118fb7 --- /dev/null +++ b/examples/demo_fm/ios/OneSignalWidget/Info.plist @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>NSExtension</key> + <dict> + <key>NSExtensionPointIdentifier</key> + <string>com.apple.widgetkit-extension</string> + </dict> +</dict> +</plist> diff --git a/examples/demo_fm/ios/OneSignalWidget/OneSignalWidgetBundle.swift b/examples/demo_fm/ios/OneSignalWidget/OneSignalWidgetBundle.swift new file mode 100644 index 00000000..1940bb22 --- /dev/null +++ b/examples/demo_fm/ios/OneSignalWidget/OneSignalWidgetBundle.swift @@ -0,0 +1,16 @@ +// +// OneSignalWidgetBundle.swift +// OneSignalWidgetExtension +// +// Created by Fadi George on 4/1/26. +// + +import WidgetKit +import SwiftUI + +@main +struct OneSignalWidgetBundle: WidgetBundle { + var body: some Widget { + OneSignalWidgetLiveActivity() + } +} diff --git a/examples/demo_fm/ios/OneSignalWidget/OneSignalWidgetLiveActivity.swift b/examples/demo_fm/ios/OneSignalWidget/OneSignalWidgetLiveActivity.swift new file mode 100644 index 00000000..f4a95f75 --- /dev/null +++ b/examples/demo_fm/ios/OneSignalWidget/OneSignalWidgetLiveActivity.swift @@ -0,0 +1,142 @@ +import ActivityKit +import WidgetKit +import SwiftUI +import OneSignalLiveActivities + +@available(iOS 16.2, *) +struct OneSignalWidgetLiveActivity: Widget { + + private func statusIcon(for status: String) -> String { + switch status { + case "on_the_way": return "box.truck.fill" + case "delivered": return "checkmark.circle.fill" + default: return "bag.fill" + } + } + + private func statusColor(for status: String) -> Color { + switch status { + case "on_the_way": return .blue + case "delivered": return .green + default: return .orange + } + } + + private func statusLabel(for status: String) -> String { + switch status { + case "on_the_way": return "On the Way" + case "delivered": return "Delivered" + default: return "Preparing" + } + } + + var body: some WidgetConfiguration { + ActivityConfiguration(for: DefaultLiveActivityAttributes.self) { context in + let orderNumber = context.attributes.data["orderNumber"]?.asString() ?? "Order" + let status = context.state.data["status"]?.asString() ?? "preparing" + let message = context.state.data["message"]?.asString() ?? "Your order is being prepared" + let eta = context.state.data["estimatedTime"]?.asString() ?? "" + + VStack(spacing: 10) { + HStack { + Text(orderNumber) + .font(.caption) + .foregroundColor(.gray) + Spacer() + if !eta.isEmpty { + Text(eta) + .font(.caption) + .foregroundColor(.white.opacity(0.7)) + } + } + + HStack(spacing: 12) { + Image(systemName: statusIcon(for: status)) + .font(.title2) + .foregroundColor(statusColor(for: status)) + + VStack(alignment: .leading, spacing: 2) { + Text(statusLabel(for: status)) + .font(.headline) + .foregroundColor(.white) + Text(message) + .font(.subheadline) + .foregroundColor(.white.opacity(0.8)) + .lineLimit(1) + } + Spacer() + } + + DeliveryProgressBar(status: status) + } + .padding() + .activityBackgroundTint(Color(red: 0.11, green: 0.13, blue: 0.19)) + .activitySystemActionForegroundColor(.white) + + } dynamicIsland: { context in + let status = context.state.data["status"]?.asString() ?? "preparing" + let message = context.state.data["message"]?.asString() ?? "Preparing" + let eta = context.state.data["estimatedTime"]?.asString() ?? "" + + return DynamicIsland { + DynamicIslandExpandedRegion(.leading) { + Image(systemName: statusIcon(for: status)) + .font(.title2) + .foregroundColor(statusColor(for: status)) + } + DynamicIslandExpandedRegion(.center) { + Text(statusLabel(for: status)) + .font(.headline) + } + DynamicIslandExpandedRegion(.trailing) { + if !eta.isEmpty { + Text(eta) + .font(.caption) + .foregroundColor(.secondary) + } + } + DynamicIslandExpandedRegion(.bottom) { + Text(message) + .font(.caption) + .foregroundColor(.secondary) + } + } compactLeading: { + Image(systemName: statusIcon(for: status)) + .foregroundColor(statusColor(for: status)) + } compactTrailing: { + Text(statusLabel(for: status)) + .font(.caption) + } minimal: { + Image(systemName: statusIcon(for: status)) + .foregroundColor(statusColor(for: status)) + } + } + } +} + +@available(iOS 16.2, *) +struct DeliveryProgressBar: View { + let status: String + + private var progress: CGFloat { + switch status { + case "on_the_way": return 0.6 + case "delivered": return 1.0 + default: return 0.25 + } + } + + var body: some View { + GeometryReader { geo in + ZStack(alignment: .leading) { + RoundedRectangle(cornerRadius: 3) + .fill(Color.white.opacity(0.2)) + .frame(height: 6) + RoundedRectangle(cornerRadius: 3) + .fill(progress >= 1.0 ? Color.green : Color.blue) + .frame(width: geo.size.width * progress, height: 6) + } + } + .frame(height: 6) + } +} diff --git a/examples/demo_fm/ios/Runner.xcodeproj/project.pbxproj b/examples/demo_fm/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 00000000..349e2ad2 --- /dev/null +++ b/examples/demo_fm/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,1112 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + E8C8D1902F7B0DB7006581CB /* OneSignalNotificationServiceExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = E8C8D1892F7B0DB7006581CB /* OneSignalNotificationServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + E8C8D1B32F7D9550006581CB /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8C8D1B22F7D9550006581CB /* WidgetKit.framework */; }; + E8C8D1B52F7D9550006581CB /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8C8D1B42F7D9550006581CB /* SwiftUI.framework */; }; + E8C8D1C22F7D9551006581CB /* OneSignalWidgetExtensionExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = E8C8D1B02F7D9550006581CB /* OneSignalWidgetExtensionExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; + E8C8D18E2F7B0DB7006581CB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = E8C8D1882F7B0DB7006581CB; + remoteInfo = OneSignalNotificationServiceExtension; + }; + E8C8D1C02F7D9551006581CB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = E8C8D1AF2F7D9550006581CB; + remoteInfo = OneSignalWidgetExtensionExtension; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + E8C8D1962F7B0DB7006581CB /* Embed Foundation Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + E8C8D1902F7B0DB7006581CB /* OneSignalNotificationServiceExtension.appex in Embed Foundation Extensions */, + E8C8D1C22F7D9551006581CB /* OneSignalWidgetExtensionExtension.appex in Embed Foundation Extensions */, + ); + name = "Embed Foundation Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = "<group>"; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; + E8C8D1892F7B0DB7006581CB /* OneSignalNotificationServiceExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = OneSignalNotificationServiceExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + E8C8D1B02F7D9550006581CB /* OneSignalWidgetExtensionExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = OneSignalWidgetExtensionExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + E8C8D1B22F7D9550006581CB /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; }; + E8C8D1B42F7D9550006581CB /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + E8C8D1912F7B0DB7006581CB /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, + ); + target = E8C8D1882F7B0DB7006581CB /* OneSignalNotificationServiceExtension */; + }; + E8C8D1C62F7D9551006581CB /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, + ); + target = E8C8D1AF2F7D9550006581CB /* OneSignalWidgetExtensionExtension */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + E8C8D18A2F7B0DB7006581CB /* OneSignalNotificationServiceExtension */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (E8C8D1912F7B0DB7006581CB /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = OneSignalNotificationServiceExtension; sourceTree = "<group>"; }; + E8C8D1B62F7D9550006581CB /* OneSignalWidget */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (E8C8D1C62F7D9551006581CB /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = OneSignalWidget; sourceTree = "<group>"; }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E8C8D1862F7B0DB7006581CB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E8C8D1AD2F7D9550006581CB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E8C8D1B52F7D9550006581CB /* SwiftUI.framework in Frameworks */, + E8C8D1B32F7D9550006581CB /* WidgetKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = "<group>"; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = "<group>"; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + E8C8D18A2F7B0DB7006581CB /* OneSignalNotificationServiceExtension */, + E8C8D1B62F7D9550006581CB /* OneSignalWidget */, + E8C8D1B12F7D9550006581CB /* Frameworks */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + ); + sourceTree = "<group>"; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + E8C8D1892F7B0DB7006581CB /* OneSignalNotificationServiceExtension.appex */, + E8C8D1B02F7D9550006581CB /* OneSignalWidgetExtensionExtension.appex */, + ); + name = Products; + sourceTree = "<group>"; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = "<group>"; + }; + E8C8D1B12F7D9550006581CB /* Frameworks */ = { + isa = PBXGroup; + children = ( + E8C8D1B22F7D9550006581CB /* WidgetKit.framework */, + E8C8D1B42F7D9550006581CB /* SwiftUI.framework */, + ); + name = Frameworks; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + E8C8D1962F7B0DB7006581CB /* Embed Foundation Extensions */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + E8C8D18F2F7B0DB7006581CB /* PBXTargetDependency */, + E8C8D1C12F7D9551006581CB /* PBXTargetDependency */, + ); + name = Runner; + packageProductDependencies = ( + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, + ); + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; + E8C8D1882F7B0DB7006581CB /* OneSignalNotificationServiceExtension */ = { + isa = PBXNativeTarget; + buildConfigurationList = E8C8D1922F7B0DB7006581CB /* Build configuration list for PBXNativeTarget "OneSignalNotificationServiceExtension" */; + buildPhases = ( + E8C8D1852F7B0DB7006581CB /* Sources */, + E8C8D1862F7B0DB7006581CB /* Frameworks */, + E8C8D1872F7B0DB7006581CB /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + E8C8D18A2F7B0DB7006581CB /* OneSignalNotificationServiceExtension */, + ); + name = OneSignalNotificationServiceExtension; + packageProductDependencies = ( + ); + productName = OneSignalNotificationServiceExtension; + productReference = E8C8D1892F7B0DB7006581CB /* OneSignalNotificationServiceExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; + E8C8D1AF2F7D9550006581CB /* OneSignalWidgetExtensionExtension */ = { + isa = PBXNativeTarget; + buildConfigurationList = E8C8D1C72F7D9551006581CB /* Build configuration list for PBXNativeTarget "OneSignalWidgetExtensionExtension" */; + buildPhases = ( + E8C8D1AC2F7D9550006581CB /* Sources */, + E8C8D1AD2F7D9550006581CB /* Frameworks */, + E8C8D1AE2F7D9550006581CB /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + E8C8D1B62F7D9550006581CB /* OneSignalWidget */, + ); + name = OneSignalWidgetExtensionExtension; + packageProductDependencies = ( + ); + productName = OneSignalWidgetExtensionExtension; + productReference = E8C8D1B02F7D9550006581CB /* OneSignalWidgetExtensionExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 2620; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + E8C8D1882F7B0DB7006581CB = { + CreatedOnToolsVersion = 26.2; + }; + E8C8D1AF2F7D9550006581CB = { + CreatedOnToolsVersion = 26.2; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + packageReferences = ( + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, + ); + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + E8C8D1882F7B0DB7006581CB /* OneSignalNotificationServiceExtension */, + E8C8D1AF2F7D9550006581CB /* OneSignalWidgetExtensionExtension */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E8C8D1872F7B0DB7006581CB /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E8C8D1AE2F7D9550006581CB /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E8C8D1852F7B0DB7006581CB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E8C8D1AC2F7D9550006581CB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; + E8C8D18F2F7B0DB7006581CB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = E8C8D1882F7B0DB7006581CB /* OneSignalNotificationServiceExtension */; + targetProxy = E8C8D18E2F7B0DB7006581CB /* PBXContainerItemProxy */; + }; + E8C8D1C12F7D9551006581CB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = E8C8D1AF2F7D9550006581CB /* OneSignalWidgetExtensionExtension */; + targetProxy = E8C8D1C02F7D9551006581CB /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = "<group>"; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = "<group>"; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 99SW8E36CT; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.demo.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.demo.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.demo.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 99SW8E36CT; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 99SW8E36CT; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 99SW8E36CT; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = "Appium Demo - Main"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Appium Demo - Main"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; + E8C8D1932F7B0DB7006581CB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 99SW8E36CT; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OneSignalNotificationServiceExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = OneSignalNotificationServiceExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 26.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.NSE; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + E8C8D1942F7B0DB7006581CB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 99SW8E36CT; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 99SW8E36CT; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OneSignalNotificationServiceExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = OneSignalNotificationServiceExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 26.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.NSE; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = "Appium Demo - NSE"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Appium Demo - NSE"; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + E8C8D1952F7B0DB7006581CB /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 99SW8E36CT; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OneSignalNotificationServiceExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = OneSignalNotificationServiceExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 26.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.NSE; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Profile; + }; + E8C8D1C32F7D9551006581CB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 99SW8E36CT; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OneSignalWidget/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = OneSignalWidget; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 26.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.LA; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + E8C8D1C42F7D9551006581CB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 99SW8E36CT; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OneSignalWidget/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = OneSignalWidget; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 26.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.LA; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = "Appium Demo - Live Activity"; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + E8C8D1C52F7D9551006581CB /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 99SW8E36CT; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OneSignalWidget/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = OneSignalWidget; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 26.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.LA; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Profile; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E8C8D1922F7B0DB7006581CB /* Build configuration list for PBXNativeTarget "OneSignalNotificationServiceExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E8C8D1932F7B0DB7006581CB /* Debug */, + E8C8D1942F7B0DB7006581CB /* Release */, + E8C8D1952F7B0DB7006581CB /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E8C8D1C72F7D9551006581CB /* Build configuration list for PBXNativeTarget "OneSignalWidgetExtensionExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E8C8D1C32F7D9551006581CB /* Debug */, + E8C8D1C42F7D9551006581CB /* Release */, + E8C8D1C52F7D9551006581CB /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = { + isa = XCSwiftPackageProductDependency; + productName = FlutterGeneratedPluginSwiftPackage; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/examples/demo_fm/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/examples/demo_fm/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/examples/demo_fm/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Workspace + version = "1.0"> + <FileRef + location = "self:"> + </FileRef> +</Workspace> diff --git a/examples/demo_fm/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/demo_fm/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/examples/demo_fm/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDEDidComputeMac32BitWarning</key> + <true/> +</dict> +</plist> diff --git a/examples/demo_fm/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/examples/demo_fm/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/examples/demo_fm/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>PreviewsEnabled</key> + <false/> +</dict> +</plist> diff --git a/examples/demo_fm/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/examples/demo_fm/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 00000000..c3fedb29 --- /dev/null +++ b/examples/demo_fm/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,119 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Scheme + LastUpgradeVersion = "1510" + version = "1.3"> + <BuildAction + parallelizeBuildables = "YES" + buildImplicitDependencies = "YES"> + <PreActions> + <ExecutionAction + ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction"> + <ActionContent + title = "Run Prepare Flutter Framework Script" + scriptText = "/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" prepare "> + <EnvironmentBuildable> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "97C146ED1CF9000F007C117D" + BuildableName = "Runner.app" + BlueprintName = "Runner" + ReferencedContainer = "container:Runner.xcodeproj"> + </BuildableReference> + </EnvironmentBuildable> + </ActionContent> + </ExecutionAction> + </PreActions> + <BuildActionEntries> + <BuildActionEntry + buildForTesting = "YES" + buildForRunning = "YES" + buildForProfiling = "YES" + buildForArchiving = "YES" + buildForAnalyzing = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "97C146ED1CF9000F007C117D" + BuildableName = "Runner.app" + BlueprintName = "Runner" + ReferencedContainer = "container:Runner.xcodeproj"> + </BuildableReference> + </BuildActionEntry> + </BuildActionEntries> + </BuildAction> + <TestAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" + shouldUseLaunchSchemeArgsEnv = "YES"> + <MacroExpansion> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "97C146ED1CF9000F007C117D" + BuildableName = "Runner.app" + BlueprintName = "Runner" + ReferencedContainer = "container:Runner.xcodeproj"> + </BuildableReference> + </MacroExpansion> + <Testables> + <TestableReference + skipped = "NO" + parallelizable = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "331C8080294A63A400263BE5" + BuildableName = "RunnerTests.xctest" + BlueprintName = "RunnerTests" + ReferencedContainer = "container:Runner.xcodeproj"> + </BuildableReference> + </TestableReference> + </Testables> + </TestAction> + <LaunchAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" + launchStyle = "0" + useCustomWorkingDirectory = "NO" + ignoresPersistentStateOnLaunch = "NO" + debugDocumentVersioning = "YES" + debugServiceExtension = "internal" + enableGPUValidationMode = "1" + allowLocationSimulation = "YES"> + <BuildableProductRunnable + runnableDebuggingMode = "0"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "97C146ED1CF9000F007C117D" + BuildableName = "Runner.app" + BlueprintName = "Runner" + ReferencedContainer = "container:Runner.xcodeproj"> + </BuildableReference> + </BuildableProductRunnable> + </LaunchAction> + <ProfileAction + buildConfiguration = "Profile" + shouldUseLaunchSchemeArgsEnv = "YES" + savedToolIdentifier = "" + useCustomWorkingDirectory = "NO" + debugDocumentVersioning = "YES"> + <BuildableProductRunnable + runnableDebuggingMode = "0"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "97C146ED1CF9000F007C117D" + BuildableName = "Runner.app" + BlueprintName = "Runner" + ReferencedContainer = "container:Runner.xcodeproj"> + </BuildableReference> + </BuildableProductRunnable> + </ProfileAction> + <AnalyzeAction + buildConfiguration = "Debug"> + </AnalyzeAction> + <ArchiveAction + buildConfiguration = "Release" + revealArchiveInOrganizer = "YES"> + </ArchiveAction> +</Scheme> diff --git a/examples/demo_fm/ios/Runner.xcworkspace/contents.xcworkspacedata b/examples/demo_fm/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..1d526a16 --- /dev/null +++ b/examples/demo_fm/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Workspace + version = "1.0"> + <FileRef + location = "group:Runner.xcodeproj"> + </FileRef> +</Workspace> diff --git a/examples/demo_fm/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/demo_fm/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/examples/demo_fm/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IDEDidComputeMac32BitWarning</key> + <true/> +</dict> +</plist> diff --git a/examples/demo_fm/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/examples/demo_fm/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/examples/demo_fm/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>PreviewsEnabled</key> + <false/> +</dict> +</plist> diff --git a/examples/demo_fm/ios/Runner/AppDelegate.swift b/examples/demo_fm/ios/Runner/AppDelegate.swift new file mode 100644 index 00000000..62666446 --- /dev/null +++ b/examples/demo_fm/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import Flutter +import UIKit + +@main +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..d0d98aa1 --- /dev/null +++ b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1 @@ +{"images":[{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}} \ No newline at end of file diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..d4295e38c7caa112d838caae9b644c2ab048c8d2 GIT binary patch literal 70226 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�Ir4=O#TI*?^51T+B2mlPM4YnH<^<bU-0<5< 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 WTw;Vjs!jaIK}9(=S-8xn;Qt3*#rq!s literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..97658bfead0acd7f13252b5037cebfc8c56e045a GIT binary patch literal 607 zcmV-l0-*hgP)<h;3K|Lk000e1NJLTq000yK000yS0ssI20_%!e0006eNkl<Zc${PT z|NlP&xqyXioixz=|L@-)$BzFzaq`d8rwj}X%u-Su7UmpQR*Wpn1T_D?|KLM+@4t8N zIIOKWU7Q&h82&tX_-XpgFUwa5l$Nk6DdN=p`~HJ><(2Ff=6o5Q|2}>GeeD_p0|R$R z5N}e#r&)8}Ra6OewzDcKVA1^l@81tSz3dj|{JGhmX3hS-V;2J?A{ZGt-CX#yGe7?S z|Dmf#Wby<?78Z2PKaQXH_x2rMS0_m4_MJ#!@c;YH-3<R3_|j5dC#U{6cAV4B7G3kt z6DK&Vt^R%f1hSKXfq{*UMMnDHr_cZ1ykTHq_`Yj5cW5w&we^n^C$VV$^W+()tMl)x z*C4KCk&_kf@BO}W*QY7dAPRn6yUwDd_<h%ItO52PiXmp*x%++RF4Q>u&w#7~Su?Yg z)Sm|rxdZ(fZ~!(<jjtOvF-u8e(ad3H`f1i2-lPN$XQv-~_o3<JaCBf268drEC~sN{ zHqAEHUzV@<Ja;~Sb|%BWe?RsgKu9^*@#kcHnlqP)mzUGV8jEH|78d@};&&C*3=9l> zSs8!s--mifPL?kx`_tTcKMoucY;R>`WyKm`3~VYYLLIFiJ9}QIq%r*Z4H5kJ>h<g7 zG$t-i!L}AQ6=h`g=xLixMMY%V<nIR${XB7!k(ZZ&k%7%XpWWPy)4?9uPVAaN?q_A? ta&hJY=L!Y}22Lw0Of@()6AviT3;>J|)1f?&2EhOT002ovPDHLkV1kp}Bj^AC literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b1bf42f9cfc6941681b3e2fda4352563b98466e8 GIT binary patch literal 1486 zcmV;<1u^=GP)<h;3K|Lk000e1NJLTq001Ze001Zm0ssI21Dr29000G*Nkl<Zc%1E* zdu&rx9LLW&x4pf$k9A$kqsSiwfeiw<4HJQlM0t#07z`14DX8HQaf~5~LzHdA5D^4K z1Qk$R03{kU8v_aq1KW5y+z1;RtYu6ys$=W=y6t@)b6bMic5O#UNDRL}Zf;I~_xt&s z-}#;2Jx75t29LrNkA(Ud{1_Z&Sdw_Fjc;re+U{Vt8vp=xT7}uHOi57=dJ-b^@WGPT z>n%OPSS-@r4j9P+8jb47S?cVmgiiZ#z!+oZ<SEa-66|uxfWRQ?WkLpn9FU_+yxR^j zz#SdlgWoZwW!eR=sHaSZFk*OdgC&-AZr$duIv127N2SpdC#X_WkyZ<W(ilr#FI!vZ zJ9&z$xq>|&_s(5xO-<t4s}M~+AXs8qM`1C4tsVkE^zX0FU#?6}4xI{wNUNnYGpLNQ z{EZvV?K{NVt=z>+okhh->x+;|)nhQm*tzvn{#rc%K$S5@zcL?D@(e_W!(Ua+U2l}y z+vS{_OytlMDl>yfN+Oe!jaxQ5w|~Z-sTArPx;AeyyjRd&&btNsDo*<=t09!BiSMq4 z2w{$MACOlO@ch3$*~%*S*Zb7dvUM-dLn>9`s<*lTWY3)C&R<}T9oIZRr3YY%Vcg$* z3t=F`EAt^jVwclVR4g=GBZnyn%;BH7x;jJAI>KPk=jC>^w1~G`Jth08ahZfp7cbab zR*s!c0DykQazs&><DyaT)2%kgx}u~_8xck6bC-3#Q-D1lZ)sV={CRPKF~+{*7P*Gg z)08R6008%agE6W1*tc3dCHoVWEFx1<$n;e1O0CawLN|9#cyEaS=502yy&VETPnrNB z6dewx^hi9^pfTk~H8124CKH{N#a*eDIvxDYW-@t59N_Cs!9rA}rUC%`Rn;NYMD%}x z95yWY?!Ry`*jWBCQS?<-X=mi9($fHh5M!>fDK4<k)^@KqY31g}H8g}ckRwOvm%VY% zxwVxK0RzA{Tn969AWfq_eI&bG3<$;s2fM%A5d&LL`l~(6L#~4;O;HSNaR?z{NR;e$ zDIgdJIPko$8-6779k=i{o9UBH-GM{Ci5Or6Fw$t`sJprV#sEUXXcR(qF%ZRWsd76r z26u<#4E$FDg0aDb*&NKU<ntl5S~)a@J$F6|CfvxtCd4c&+U>GnKXY7QWv~J<X6vrf zV@6Y%8J>M5(Wm$yLx>ueDOY9PRUk>S;E>RgjtnM;42A{+b~t<$74+z56uo-UQzrY4 z9F3DpXH8P{?JNJqEhpqW>-E6|#0Eoz=&Xs%p&z)5m-$<_lmiFq7B1lGu8P0^5tB;v z>!*ADRe48Qt=y%{avYN;LV}133;@tf%Vx^T0mC@A?=WuKh-lhST<Cazo!E9K8r5tz ztS>}rH5LTd=ey(~iqcHaj_4d2Oz8F6`ExzH_X^Ec=NDh<bKg|-?rq$%*|le{zv34V ze(Qmdn($o0;zdZK!5F)~+9TX-1^{U1&L#pUq<F#dq_d~8zt-@-)%q<bAwmgDmmsY+ zF@HrD$NA4zg*dCmj80sU2Oz|v;M%>HDL)1wP^Lbm$(i1rez#zVkfC68=h_d1W~=X* zg}2)DdAZ5~13<(xEP?<+zNN*rV<+F(1R+oi9%NWk5OH;5fP<YRX~Tz(4IlBfb;6CC z9eMexjIpBq&u~xij@_~GW47vCa21pzM;O+wK^k=w@ffE}q*f;t7kUo=?EU@_U|F`Z zI-;9kwFy?6{H7u`FU``vI5Wyz;{wY$CkWlFne_N)y+0oIRh$M46WLFrrpJ%h%$%Vx znPO`8;3lCk8ud#T>t0*PU90Dtn&dtl=t|_%qk;z&a`<pWl5wi_`0j*Al1fjb($nsb o=;qAsk-`IlAEG@5|Np^%1M>%2)}gNmA^-pY07*qoM6N<$f}H=siU0rr literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..76b737e04bc4dc78e170ebd733ff0865754b9be0 GIT binary patch literal 2284 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 GLSTX%mRQjM literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..b8ac6697e9ec21fceebd7cfa7f9909e6cd73cc0d GIT binary patch literal 996 zcmV<A0~`E_P)<h;3K|Lk000e1NJLTq0012T0012b0ssI2+41mL000B4Nkl<Zc%0qU zT}%{5902f{{l5KbPN*31j7N#4JyMI7G(J^5<=|+V$|=>7`cd#B#usCgCT$6!l0H_A zUnQ0j#II_LXb__(R7~0j@C~2*$kF69+$C4;Zf|$sZg;0yH53+B(8Py!o_1&c^PB(t zGn1h(#^5zH>UE(1OBb7FE;4LHqZlFRa*>6Fw08+4$yaxcWK!+yLcM)Bm73fSW!bfM zjS$*Ey4^4BYW@Ani59G?P?ouMe!9p@2!g4qxkzMu;I7tn1>FowyLa;bwJ+f+7cXT_ zpCMc>Yi30N()8p}oXcr9!<qJu)S)BBNKC5TGA9@H-^rXlL+0hV4>r+@J$fvr^<2*m z-NWfLlx3#G#|JBgsv!H`^1r`r%$&bKE-09uwcRyRsr1Pf!sT)wY@$4i)UGQ^dk4tn zo)3@2^!pFAtKH(~wL<lVdCg6U{a-3Ar`Q#xwp!a=wX+LnGScpy^kR>N{`B(<WzzLb zTRQ+i3{{KUw<;%oRDZiH*MH&YV$(#ueNdM9ihv%AS(!SwOvhPn)hfPxy?X8f>ib>V zv2F6<o8sn%|H8>6x6Th~TDx|AV*8NisUojcrRZZbnViU4>*<l}>(~#<(2Z~|5@Cvq zXLgNf6aYX!C9*?96a94YTl2ne1^}dv9z!?66aCqtdluof;`QibN7qCM06>VMRg-l3 z-}U10vB5#Etjtyl^XYvdM8Wz&V~+JDIL?YzRcr5(1Y+^$?nrFxk3Xlogd|z<nw1S; zSx1*FTxjiRco+b{_<Z`qN8p8x_W7*%h!syQTIlG~UN4lS@qxQo*ZE+D)_n~ahNDUl zd{rejjPZd%C<=5@k)sPql3Vj3y4sC;`}jb)u(?J(d)|o^YBtdxk9MoqOe9<%1tB$s zvfm3aRE@&7l(u$e`McugPl0Kwzgz;QIW<!#Y}zQ+Zqeg$rL_%ktPl#>9J@>A<w<pQ z%CY044UO*R@1)w#n39swZyF}YxSJZ;(o#JhA8lwf6-C~=hk7%A78d}(2i6-;o~WId z6Z;QH^>xg$rS`S+^U>|w=~Jy{D$RfLF<)6R9ht#}5K23?kqZix*0%HyhoLOn0uo<+ zZJln0k@xK4tAY^1Il0ehAy~=2zf!&UE9$>v8^zfy7bq8NHc|xzGfto79iryXe`DWX zc~^b*{sRCZ#+dW_xz(%bWlIT$dBMavy_=9>*b?8fZ}y$HXN{k$`)cjK=Kcd|jBxL4 S@e&vS0000<MNUMnLSTY}n)!$T literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d3de94d24a99b5c27887f075a499fd1dea744478 GIT binary patch literal 2155 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 literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f0559d2b5759df7bb275b366e7262acc92286388 GIT binary patch literal 3427 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 FV1h+2geL$1 literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..b1bf42f9cfc6941681b3e2fda4352563b98466e8 GIT binary patch literal 1486 zcmV;<1u^=GP)<h;3K|Lk000e1NJLTq001Ze001Zm0ssI21Dr29000G*Nkl<Zc%1E* zdu&rx9LLW&x4pf$k9A$kqsSiwfeiw<4HJQlM0t#07z`14DX8HQaf~5~LzHdA5D^4K z1Qk$R03{kU8v_aq1KW5y+z1;RtYu6ys$=W=y6t@)b6bMic5O#UNDRL}Zf;I~_xt&s z-}#;2Jx75t29LrNkA(Ud{1_Z&Sdw_Fjc;re+U{Vt8vp=xT7}uHOi57=dJ-b^@WGPT z>n%OPSS-@r4j9P+8jb47S?cVmgiiZ#z!+oZ<SEa-66|uxfWRQ?WkLpn9FU_+yxR^j zz#SdlgWoZwW!eR=sHaSZFk*OdgC&-AZr$duIv127N2SpdC#X_WkyZ<W(ilr#FI!vZ zJ9&z$xq>|&_s(5xO-<t4s}M~+AXs8qM`1C4tsVkE^zX0FU#?6}4xI{wNUNnYGpLNQ z{EZvV?K{NVt=z>+okhh->x+;|)nhQm*tzvn{#rc%K$S5@zcL?D@(e_W!(Ua+U2l}y z+vS{_OytlMDl>yfN+Oe!jaxQ5w|~Z-sTArPx;AeyyjRd&&btNsDo*<=t09!BiSMq4 z2w{$MACOlO@ch3$*~%*S*Zb7dvUM-dLn>9`s<*lTWY3)C&R<}T9oIZRr3YY%Vcg$* z3t=F`EAt^jVwclVR4g=GBZnyn%;BH7x;jJAI>KPk=jC>^w1~G`Jth08ahZfp7cbab zR*s!c0DykQazs&><DyaT)2%kgx}u~_8xck6bC-3#Q-D1lZ)sV={CRPKF~+{*7P*Gg z)08R6008%agE6W1*tc3dCHoVWEFx1<$n;e1O0CawLN|9#cyEaS=502yy&VETPnrNB z6dewx^hi9^pfTk~H8124CKH{N#a*eDIvxDYW-@t59N_Cs!9rA}rUC%`Rn;NYMD%}x z95yWY?!Ry`*jWBCQS?<-X=mi9($fHh5M!>fDK4<k)^@KqY31g}H8g}ckRwOvm%VY% zxwVxK0RzA{Tn969AWfq_eI&bG3<$;s2fM%A5d&LL`l~(6L#~4;O;HSNaR?z{NR;e$ zDIgdJIPko$8-6779k=i{o9UBH-GM{Ci5Or6Fw$t`sJprV#sEUXXcR(qF%ZRWsd76r z26u<#4E$FDg0aDb*&NKU<ntl5S~)a@J$F6|CfvxtCd4c&+U>GnKXY7QWv~J<X6vrf zV@6Y%8J>M5(Wm$yLx>ueDOY9PRUk>S;E>RgjtnM;42A{+b~t<$74+z56uo-UQzrY4 z9F3DpXH8P{?JNJqEhpqW>-E6|#0Eoz=&Xs%p&z)5m-$<_lmiFq7B1lGu8P0^5tB;v z>!*ADRe48Qt=y%{avYN;LV}133;@tf%Vx^T0mC@A?=WuKh-lhST<Cazo!E9K8r5tz ztS>}rH5LTd=ey(~iqcHaj_4d2Oz8F6`ExzH_X^Ec=NDh<bKg|-?rq$%*|le{zv34V ze(Qmdn($o0;zdZK!5F)~+9TX-1^{U1&L#pUq<F#dq_d~8zt-@-)%q<bAwmgDmmsY+ zF@HrD$NA4zg*dCmj80sU2Oz|v;M%>HDL)1wP^Lbm$(i1rez#zVkfC68=h_d1W~=X* zg}2)DdAZ5~13<(xEP?<+zNN*rV<+F(1R+oi9%NWk5OH;5fP<YRX~Tz(4IlBfb;6CC z9eMexjIpBq&u~xij@_~GW47vCa21pzM;O+wK^k=w@ffE}q*f;t7kUo=?EU@_U|F`Z zI-;9kwFy?6{H7u`FU``vI5Wyz;{wY$CkWlFne_N)y+0oIRh$M46WLFrrpJ%h%$%Vx znPO`8;3lCk8ud#T>t0*PU90Dtn&dtl=t|_%qk;z&a`<pWl5wi_`0j*Al1fjb($nsb o=;qAsk-`IlAEG@5|Np^%1M>%2)}gNmA^-pY07*qoM6N<$f}H=siU0rr literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..59124a76c4cd6057a0d2c3f2bf3e9acb1e02bf08 GIT binary patch literal 3166 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 Ef(W1sdjJ3c literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..dd146ada645a9f7a9103c1e02699035d64051c07 GIT binary patch literal 4841 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 literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..388750c5a5ab006ca50faa9c28323a5befa66173 GIT binary patch literal 1936 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 Ww)_R(>zqUY0000<MNUMnLSTZZeY0W! literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5ede07ab2123bf4d37d50de54a7a532e0354e770 GIT binary patch literal 4107 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 Db|Uh| literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..9edc86220d53237d4937263d215d45da64fee66b GIT binary patch literal 2171 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 literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7a6e7e459d15e2f0eeff8ed8019684c8eea82ffb GIT binary patch literal 4663 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 OkcNt`auviT^#1@pgAnQf literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..dd146ada645a9f7a9103c1e02699035d64051c07 GIT binary patch literal 4841 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 literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..8e9431389b113b51e060f93e09dbf250eb3bac53 GIT binary patch literal 7623 zcmchcRZtty(#I*5Kq0sXD=x(fl;Q-6l;Tj_TC~Lp?i#$fyK8WFclRPeN^vi4U+?4h ze&@~{dD-2WowKuN_V*7}R+PcUB*#QTLc*4ll~Vn8*ZpS$k^h}Fl`*DBNR&}>QWEN} z>Bkvvu7n@&2g_PK+}$U}=r<G7aJ$5tPTz&mY;+gUz_&uf*l2*|xlL7=%s|(iL)N71 z-14$jnRs0(AdM_A8tIiEQp%Xul}cw3fe$;Ivy&2!2;h1bCrd_k_Gx0Sv8)u~e(1## zh&wfPOIPelksZ@yu{9MfMF0z?PZi*$pYF?{4P^vj%kkP<$mWJhO5!Vk$z%V^CO!uC zRhxE8J2MF%B)zE}T1%9HXa2W<*bNJEor;KILdEI>RV%@EDhR2q$97j11Pshkmcwvq zNEY)*6!Qvx%d+`Newc?zO7`}}@%N&OcfXk1D;gvu)b0YU;X2+HcfMR>$x?5TQUj3| zXKR0&txMCdLkesl30#QzM3qcba1?mw;xcD660U}%{cQNRGqq`;-bZSO<jrV$_86I{ z2Jrgm>6ng@V47VGQB%NChBljzA+eS&wmp7bu_W&MbSJwpNZtG3?XRf$(eMk@S)DN$ z!LfCT0k}X0Ts$H*jhmHPQxrNfd8I7~hBJ`Amm{>HvPb1K_-ngF`m2fT_Gy|375)6) zfV1&ik@=t^j>4hiJ(tV%JKpb5$8wce12FO=0QCEAp?nkP2@5w&Gb`i<8`ewlKIpy8 z1@9;?HrQxyAu`{|o`*@0zFMG3ysOp5%WloxZs$7|I>t`+Hd^L3+B%Nd49=cy#|>4+ zJh^Q+tDI_>B(Ce}f*zuX%`cDLp4VQ4XjZ{uUbFj(0xRIO9;+iMf8UjYh<lg`^wKSv z>Ep$o{#Nm`_9JNT3N5h`XtQcX{zT$9nK@ifEXQac$f@t(Rg=6@OTsuq|0dkxAc1ZD zJp$8e$;9nZMKX@@yg`;_m=+Wm{p0vo*PuMjAVUm09Dqy%e(L|={nc(SIvz$vFUzw| zJRFC*Wkd<u&BeK;_KrwoSH6>v?AqH;<wMoQG_8(h`O;&7tnLOoN4|J)ZDcxfh@o=1 zg<#-e#XpSZ+W7#*?XEhPzuhf#MwuSWNA@JC#03%qAVYC!hYx3Tq`)s%s<^R{6bIz* zb5nVz-`hydl`14hpwhDn@4V+gW1XoDBZtTWZ-eBMAVD8JRq!;m`Z5JD1UhEQ0OzT9 zccwm+=3uu@)7vU3DhR$N7)U!9TX1wxS@yR}H6JeNQK+lw1-p))M(sKUAeDq09(o`{ zdQ8wG)21TRd>#7ja*S>_a=J3tR&gGbxzs<j(o8;x=?@cU)hdz79N^DU#%6CBWtdJh z5<9p7*h;Ws=jyF1PN($|4Q~@-@#|dzFAkL>{0?UNr<!XwZeZS`;MHojwo@itOc_sZ zq$NtB%KwDQ_>53x5+s&RkRp^h8zWmBTT~w2327yy%~gE+C#qv0T{K@rWBx`ONNdSM z)(Yi=p1g5wf2Lds&~><r3&MM=K!db5mNFB{ng97At=d%ns=NY>!2~+>L;3fj$Og7j zSr8!Jc&bh?HaGMLIGpUwqQXENZn{BpnStUj<9+S(gzZ6tBNeMmb?*sJGTa#uHr_{Y z=74EK89)fQe&z>9<G|+o(C?OiiUvsqp%JH?uQ7U}*HSGLC<QZ5-FHRQJw^Q|9nxRg zKekPpQ}e4UP|(r&^=%?L5$|jzOh&lKKT85A0N8I77>VA7qXKDX+tAvLI$m1!PQxZ8 zQq=Cu1LPB%$p!>1vQyEe#dAY?8-FyKuX}dYd=m4GhW{vvFUrb2Dp5HXmm={m9Dh3H z{kylX(<abnAKs%Rf#ga3NU#T8@OCM-%6@|n0e7?s-%vQ_&@fy5ByGQ2E*fulXPU$E zqRSsPp%&s_s)d=K==w`e<GwlAe!>B!jjxvE-J_4-`q&4Cg^SousKK#njGy9JIH#O! z<hovMOVb1ff2n}J-fjIe@ePMs<1b$3%~-1Bm?z)KDW^R#VAtV;c?Y`i$hrb<uA}>M zCZ+sd3hSB%)aT9m_9k3Uf`p?61i-_>upz+=rFttn8#vF(g=N}^SN}t8z7+2Z+pADk z3p~~9xw({gdh$tVUtVN}HE0H#4bv1RGV(fi5=Yi~G5gg1b<mn1+r023LO%4a$05l- zIg)H52{eHMFgn*W8kgV99>0Nx4ruEeT<zy@AW%xD6mFXMZ*@5R(2q<_c!z{<GO{<V zzAe3ecgn1z<JLa0Y@0usMI!TJDcrBp@Rgy{wlg*{gnn#0lkaA@L~4*GaLI5I;BpMw zr8K#G4R6P0X(2?##U0wjvPBTBcZ|M%HC;?Q+kidWPO(;OpFbcD92ap{{Ze*WzbxKu z6Jz(sYPs#sGLETRfHEK?O+a|10VZZxP+XF!n8Gu>l=IC5MF@gCi0*uRQK3Ibk{<S{ zjav$dC=*1Od0nZaFjx75oVRPL2xpk|4Hp)Kv9<n~`kfR>)hxp-F_QD5jb^)h13+4R z{Ol7xwS5&wlFKwK%v(hygXddIPJaa+3kq#_qj&pFc%`x%*m#Zvjtf!uTz_~LYnM-= z2*zpvQDP=g>-$9ykI^HNcU+BG9hyylA>-aYzAp68EHr3mUZSKu$AcaA{>+|aLPXJ5 zs4;TKFr#2Vj81XZCp&P%CYaMclm>I+YIX3`nU-yK7#E6u2;92zgF9!$@6V>s7NYnd zA@DK%AC6u2Kh%EhY^Da-H}TtUIv>Sb2P0JpzvuT~My0)e{IJ-1YA<uy|FiGxqh=Fy z`R4k;&vrp4%S#7Q-V9OTAycsCRB%$v!Vmx<V#N$L^jg@jre$(XDpkL}1vS*oy=;ml zJh~RbWKtX)2(P*EQ4zscnLclW*-1EGV0H~lA9g;P?X@oeq*=%zG;@t3{7T?mw{KK^ zCuHJC5JR8s(}nru6ta&2rlIu$|Ef;{Ee8jhmAPQtOXU3S^s0%N9qXlv^BJV}3a#@o zRm6Qv)D2&wqQ%M)m{a0`vw5WbVs5zA$u2eYaQ?M7UAy`*iknDgV~P8^)w;$o%0dgl z?_B=Il!lO9cqj9+(5{-^9$e_@EwLXMy0AO=&idELHACPO&xM~|x7^8wv8Vi|R)@=q zvwYUN3Lmk|QJ){K!^<JTGDs?7o!<?=oB7P|&F}HG11}f6ja%krQoiWfV|P>O+wPc! zhts4*fZVT4YQy_SdT0S5Vy4lmImeM{#3-b+I<`*{oVnH-M8I_3NdOt*xn{X1Ml)Up z-Z@*{uzPaOZ2Z*1*XoF!Qu#xBVW2-_*4V){&9}qg`y{wGqA~gY#}VC0cte5D=ZL;; zSnqTHs0j?a<p-16sb~!WDrBhBE6w~_D6||)S=9WNm=gd@fq{At^WI?6Ll=EF8V~Kp zk$~QJL@O_#jPXMM=1wN*tuyQKj|>bvUN*e>5oB}^(X@e{&AKA55&e~C1OUX=4)UnB zOhoiNY^Pggvt0}`sd9^h1k<fk|A)_B_a22iN;NJ3!hAN~SkoJ9KO~~AlX^4{DN=Mt zXvedUAnmMCX`O#q%dgG}_#A?6$(te_Wyk3Xprf-tTdMN&F+wfz7R=EK>Gk=`e1C=9 zfgO|hz2(qm86)V@UC;3kvgqcQ?3$)OocY9U1!V>(h_UF|!Nz+;kK57Y&iTE|QQhyq zp*5lJaS7}_Yta!%uZ-NyBCNp7_^3CJXnU%1>J{NcHkFPG>2>eT2n6*w(Ean-e+nO^ zp9^}QomJ}Ep5(dHq#tYnlM>D!a5h$O71BtBoO>GalE@Dig0G(meUvm!H<gH6lGv+7 zo>9Gh=Unz=P0h}j6peoY(U|;;FtN!FsFpPK!5s=|c+VDXP07^kD?3NcUnd9UV>QW$ zP&@TW_Lioj*T`psX@Ika(#?j?LWPk6u2!oSL#|)YC|<%_wl;b<r+zuzJ_pwSAQy7! zHU!XiKTUXWou}*L1^Di+eZ0R}r>zS0#;RDkO*Ox`LrdnjI=MO8gK3N#7Q+R4246?d z29dyW5R}R`?|yZ9y!R-l8J3Ae;BpvTSg#s&!#ny#lKfm+s<*_!BqKt_hx2Nb@BIEH zeY8xsOHLozZp!}}HS@;nx_>+;0`t+(%et+d(~|e=uPI6)WR!qVMnZ(8%PBWgi2yES z^T~~;(Kb%us~1J?JLsCu=4bn@qcRQ3-^`bu4Lm#3gIw~=BSv#KM^wM+h#V<TcIku% zOLotcRlqr~NxB$Ph8!d-sc!iSaY1gH6&)$@DiU_b(w9}n>S1*xV2I?;lkP}eu1=f_ zcgewv$cj0^_1s*6B|4dc*zgy0iM?NS-G=m4j!8$Q3@palFNNa^n@!0?f^4sKK6f1s z>M?q5NvVd>LH{y$sO>9KLX%~RzADCeEXx`Ar!{B=gZkMAFk-*D-(bSmXy(PSlqQ9M z>O#qti2{AIZ#uzocruL~w;zH;G})z+K@6d|90`F@RK{GQIKZoRcl5>b!AInybL6W; z%I~3cdS9gVn!}bUC2`3Gp<VjOv@cN^@5^|^-4Fnmldn3a-#YR{^H}PVqyLUU0(-57 zO=}db`LNXG!H><C$j;po{5ImGru=G40kB*fEeM`)G|VtjA~rwOwB`ZlD@P9zq3>^e zfUY|IyCUA<=oB@MBs(;om~SzD(K~nc(5L$mu?>R`e-Yoq<Wh&b?|UY%X6sVs5VV0( z(&$}bbe{JSf&(Rtpv^JuF+)5g^*HHUw%f~#T%kOgz~qIBbDIQ&#Cw~6r9*>tvIfJ0 zxwaLk(0K~VtLHB8*MFx2toQoiu2s=qpN5EC$p0PxB)s(K$(>j8m*&%4B@=q$r}rD5 zILb`YzW)HhP+nFEZpR3K)iOi{f^yDH-v;q0g6j-QU+I@M7#RWgt(x@gxeW{wq>1d$ zz%Y2?*NBhk=$*A)i5~)IYD^H>ny7=Y$xKt8)K5>8$l3Br+XdfxWfQU8gd;E+eAMw| zhIaD=KyibiaBY-Rp`Ct<-(r3|BT4CxJEP({;H_GEXJHOI<%lSGVtZW8%8Mn3AO34m zoyaZF{mC3`Jatyb#89{fo9j{2@4;8N!c;^@sxn|M_PB+R*w-o;h6#7=HjII>Y)xX4 zA)lLAw7?dlBe_;;A4)^$z|q4WBnq_74>4*+_;_POqDO-aRo<YxJmVpYvrHn$F-k)u zqet~XJJO);vJrulWMwehHWx4Xc_@au;BC=FaOCO`Ed_~I%oX<mP?R$z^&Zj6{F$PN z-=VrXI`NoMV=iYRRkGo>(kiL=j9uK{?sGa;<cmmW<>A8kbKsbSpBBx7>9$D@>z0wF z4&xXsX;>3$Ualh)SpvHD9o>!SH$(WVc)c3V<~C*4oQWZ0{%s22D?O;%9g%uOlM=5$ zY@e9Cp14`8hNXl0N3dYCCTI8Yz$poh<UGC>6H)wd#HsGYPl`<`F&X^OfP53ipsLYG zpD#o4CKWFR7*M{_Z<<6Qn8N~5(SrMebJ~te)~JE9?in9P+Dl^V394x_KV=^pWIyjs z`o^uqFAk4yCrD;keq4CvF7amwS))DmlTaiEFolEQYmYHyHfkW`>iaZ5W-%iucvDqX zwg`Gh_7hOe9xuxIDPJ=nq67a*AP$7;OGWYPO~*=tAXmz{8}KSdii<@iqmc+$QpX#J z2jD!@<RqwPkQ4-FL|HAwYkp~GEXg@oWT>h%OJDieWM9iwo~T$Fcc)Vy2c4f;?tu)8 zNs<a`<i`;M0+q8ej$a5u0<5CK@z`<ZMPattWo0yXUkjAw!BXulMyEejeS(nA%qM&^ zn<TsLkG^>SwR~JlV$HK%LGP@?%!>6M81Xw8WBDEh#wJHSkILwQJjSXe#k~5VE|XNf zvOF9$ZDhge=n7*KjO;|8mo*z!wVcC;!M(j6=_ZNO#gTuOP$`J}PuLLsiY*Iv!|?w{ z07QdCk!heuq#du;#P5v5hm;k-PTx`5sbp>8Z+>#>Dbp;d#vnrqJr<|_RJ=bNd(%+_ zJq&ws-i!_3`-;Kg29}79Gy%D(lh^l2s1jPG`bEjYnP~(4);yB`ytRY9s@0WjRcKh% zsL3r#QEcLM1LjO+Qk$fUTpi4m7C<!5<J&tlMziY#`hdmOLV?qH+}o`5a)pM7E)v6% zZ$|0UHwSVlCc<gm6^LQId_ImFJt7qqFf{zntH*)%+5Sx7oTN-`n!tgMM!=VfFKlxx z@MQGAgOe;rmAiLaj>*iPsJ<NUBq<MlN9bhC7`aH17+J9(FV~dNOX8*@8NTlaj_yGY zjU}e0>De{9Gm-Y%Qh3PS`mN`??`S0UbWO{Q)@+NJL9xcg<+^uSb_w4kTW^3rMWjDH zO!q_2e@1|gm&@{Tf6R!hEEJi_BV}(i9N&(1{TYXTw=pbBQ;6PQ9e$YgUbTUyutAMF ztK~JvJ~F4Rxh{&ol+J(GA|=^NH-J*62>$N=)(PD8?w=I;{NOyzf9#{I35K>d_|kK` z9re2;zSYIfFjaj_K51U*G>)5zy}^jeY*_W7?pW*>B*0wX-2XQaS+Bli!v+5C@3(Md zH0!r=TlYMGs&*%*o$Nn44HKr_#lZSnJ`bN>a;=N$H8>-?Tz#?_<VYEte5=FNSWI!1 z>we-`czR4_Z_E&yJn*n$yKip7`kZoqjeW8-OevTf9K#)8rG*f7tvagO)V?F@%T$9P zB?Hz|{%R0>wq9|yEkT)h39}@4^aco7CBvl^K2rcO4lfD71dM*FFif)nWDEYH&u$V8 zzu7&W^=^fl8*A&-B{fq5&oyM6>_a-jgdQG5?@5_1jE0^z#ng%v0#F%?(WXi)8{{UF z6w*L(Rirq`U4k~{M}q3*In9r1kJH$wzMD}U`GQ67;Y`H+u2_vbw<MhX)E!1XtJK2K zsi`k!cNLQ(Jdva)hUac|*6NgIMn2U7fvZxuqWXQuF<4Hw*ucoAlaNAt{5}X+ur{To z0;kdPH5@N+y<jxuXyG<4Hg{#a<DrL1$>G5S^O2rVJ=~1tr)X*ZLBVbu!-eMIYN(>p z&rGM8_hH>4NJxpa0hG-M$)k<#EWu;_+5v}25uTt{IUc8j_?kttlC+Vx?$Ie^C9{T% ze`7;4;F~Yc9@QLt-p!c4rhQK;e9Ez;p^}D0ATM1-*I6^GMifNYB-UE1%05r^9BM_Q zlE*Ojw?eDX(<Vt?Ypbkt7YN)l<JRidYh5XED2hYs!TIyI`s+O(nIl$JU26BUg9-hv zpCUjqVB&acoalp7NJXqBo?rU?OnB6yq4_0<sr)d&;upR3Kv_)?Hrw|R0Yo|*MY=Ck z@FDJ}%%nKkS0<4Dr?B(q&F6mkbFX2Nbf{O&()I7Si%Hzx{PxEh$K{zRp9RKW4HcwA zjvlrv$wff4Zek$qX_8@$7-iR~F&$E}1j<#thTNA&*uOag3F&gp1&!YtorGg64Q;Xf zhHsSj>WHBXr+9Xm%8NZZVJGv2UpAWVaw{!#{bG#NF$?^W+X{$=LwQkgt0yXvIc`Qq zmNzer#!Un$nN6X-4|lnysCg@L%8^UXJGE#_vw{z?*joy9cWn4^P4TFm!u(7st}b8O zCXiqmo5R%-;~3wvI}UT8%i6=I<csb3vl}7EO$6KHI$oGZl+e9wi>4TI;6fF%Vgz@c z+E(h2fwcOK2EY6p+YG(;Uk-lIB*7Km0wF$&NQVJ=vH>$3zta^5>onv0Bx1+YQtsCc zObO`d7PfqG3!{8a4gy2P;Z?jXIy(GMrzN%KDkD+R1cJYKE?yOS;7o=QZHjn&(>pR) zgxBA7tJEw%SIPiyN6p3vZ+1-O<f_}bLX|sRpH4%ro>(tFr)IgXzPsdGHdGPt>At%! z|A#~31u(oRAP4jE8G?M!+^(k+56|gk(xa^&9lr8!S;T8DF{`i7(;ZKQJ(u@?kjjWj zl{u=DD}noH;h%+^u&z#s)*JM%cYjAwy0r1EUC$txe}wgfO9E5I%<h9;XM__6@ms-L z>Ph$D8AowU;Rb86@wBKY@a9X1#|_&Z?lQb$ry-qHTU&dJ4rHJ2`KM&2wtuf~%$`Gq zy7RYT#zo`bly}9lo&(V|$>q8lBr>(1NjEJfTi2q<-ra38#WSNU6x&d|fW5_3MYb40 zBNla?JmcKn$ac*;x>*nN=UejEDLy2<Cb1vZVNQu34BZkqRn<iS`&SK`h5Nr%{mNuk z`)Ea-=V!(V20Y9jQ80Oi(fV_4dkSXG3Dg)BjD9u9kGOILLIy809RIvAO=<0SS*%ui zhc}lHCVEZ?Yr3^SMEPuSzrd(j4y=DJULA-nsnD_i<IsVuWGw2CzkYDt!v_m)#`J5K zJ(*SW;r+ZCeV#sT@YdEgT*As2ua!?TMilqrt>JK{plO;wjQTOD5fo2r;p+JzXS^Ac zN$R{<RnhjL7%=x<A^0{N1u6P|Os#+lhv|@v?H|BBdD<UIE-F_NvD};C%PAraM26wG zt-pvj*~vBY6vOpZ2St*A2sYY2i7Du>a5c);2;<HNgMFnfyB5PNg1wpHiy=B_g-&S0 zr;kAUDAm)No$giZk+%ec5mA(?OiFL&<hBV}FleJLW>!rOZg;`B4$V9=uu7B~u_Ly% z2Li`I>%<tk;kr60*I&30|H17ihlH1vtLR-iHR&Y9k~qVVb|&>Osp>q>AO5lwH=2On zs>21g7eXoKI?EpxyEbN1NTX-QJFjD!<fMQw&mW8To%iI;B6wu9ta&mn4}BP+c@cg1 zGC{knS0zjt^E3Yl=EsHJXK}mvgRU0r!d3v8&1lZ|xriNRRqjyKPQ;&w$;NEeWvRcC zC-sru$suvI@?rn{``u?nt%{4>olgB5jRk6i^QU%id>Te>?pRAT5_6PJ&uHfZfRZqu z;F6N=W1(KaMYeKEyQox5A-9sw=~1P>lLo_PpNe0BIgWlW`h=#r?-1Jo1ogI8rXBWk zB>pM{eG>)N0|0e@LJXP7r(EY&Yn#;_hk-CyLEP!3Hfwdww(;X>oa)X<A>D1N`?@sT ztnDS%Bd?)X2h)5kVf1i;J{pWx5wC%=^>N+4cPbr$p~&StA;wrY2y;qLCCFPbTl$>H zGS{H$>(ipi3FnDaIzpoU7mfPwA@B5$b*@Q@c(8xd(QGT`hUX!BRiy6QPF$C3Q`{aP zl;M9(di+U)n;$q1t7vakk3%ILLL?*HrVp)qgHvrr?KvNK+xRs3-@KpBc84}bc_+hT zn%E*J<jC#Svujso2cG5;FQA(TYTuq**EBk%J7Lw8$G@bG6hw}YQmNR`Jmha?g~r{w z&rg6hHZd6{rGb@nG4xmBbCu>)AA08M<=Y_5rLwAFc|DqD2UF`y9r_#U#zx02XHglx z2_=VM3T3w%as8x;0Y4P1#;qC)M$uu`D9pYwE;5A(f`K4v_o+rVd5g9C5x2@bf9BV< z+KA4qW<x{!Jb^no8+*L~Mfp6Ls0|nhgX;N1lNaD0on>|E`;$V%XIy`vW6CY!&UL(^ zGNPzLkM=%PfR)Db*IZ6}iKK@FuK!?E^&MJHn{da5RK5pqjrtg+i8O(J8b9>XEcnY? z0(xY+mR0qwCUgnhf%1R<30g4Dj#i?G6RT%wG@Ib~%RQSWG!=->wjMw$k^RES;PbS# zp);+9>MbO|l$e<7)FK@@B<M7Resx7g)>23o58c{H3rJG~FG}u1)i3`9{~2d{CZQ#S z3QC-RIJq#*wUibB6ZblzO8BfnaWR8{{<x#0>)x#eW^Z$K__S__8M*yKzYdRcMj>c3 zM;cdNU2}z;rvhr7t#NxjNka#+6v5;p{}WB}|B0W^IQRY8uA@W!4F3dLB)N}@QgDco G|Nj9*EVQKn literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..7da0bc3d940d2e32df8106b8891761a573648aa9 GIT binary patch literal 2953 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 literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..be7bd5a1fd7025b46774927d61bd7f52b2cd6f36 GIT binary patch literal 6127 zcmZvgRag|<*Tn}UhLRx#6a=KDJEU{yMnJl|hL9SBp%JA!C8UuUy1PZXyK@F`1Oz_6 z_xgYFTj%ENn|=24oV`}Grn({lE)^~S03ZM>$!Y&Pzy3c!^nYs4;C%rAynut{q;>tW z&rEy+$@G5biQP2rc91GbVWJnnh#e1e<Uhyc^Y;vfwjLkT4`9*bMrrFoBx6l<AqjAH zT#T|9{<K;=X(f9!89auM9ja|zQ)75^?W<y7(|rNx#r+l`ax%NcZePsnAU9x2BrVk@ zLkbN5po@#9SCe~#$s@;Z36rP%U)Tcx>f|Ky`BCv8C^u7iG0Qxo!vDPZUva!wa<t`t zVq%$0r||wiwg~0Z*~da>q+3>{l7XQi{HzWQai$uH*3D`<1k=jt>@k5B1%7vNe*2Yv zH|3DC)(`s1%hVXKbtpy%21e%;KcG-uk&#K0An^!`;3)M-^=cn7!$dk3aZisf%}<0y zcTGxq*%B$P_+=EcG=E4(4;NTyX|Kn_f^``|e&j9{Dci2eK#VcGbi9{jA?5E?9fV!2 z!d&fQ3=*#~hk*7)J^MQj41za;?cutQen|zb&v4P-<z9&9UKn*?9p0!;oi9rS@td^C zNq7;R316jgi8Z-;U995Nr0BK_1RFKa%z<~^fh)eq6<?zyVu3I$N9^ajnF3W^2x(&Z z?>naw32tT`3V+We$<RamGDz2JyXEA-Wlj^K3z^=!_da(#-@J3g%7RU9UdVq)I}{0+ zhi^L_X}Wf=nLN<#QP=NLds#O`2b^lD-TQ3uVSED8tJb}*eA|h1UXeD>t<gj$hC%+q zZs#&or)Urws@6I>eJ)y<^r76qf}j(PcrJaZHt|*XAK67{K0m6~bsN?kaDmgrAtwi7 z63el<;2`;ZM)(JRoinfG5R1S(G@6HUq}i{VcTZMY3%=y%Md<*K85ocP(LGvK1BS0A z_g)7C-+ysHUO{AJx_!z+xk>gXr<yoF;K$a?=@Dr%%#{daCG<2njubWJ6O*8MUm2A{ zn+n*$w)O7E4e5DPPr)C?xo9zdsEgP5u{7=0Kx4Cb4b$eTs^`n2+=*=;Jd&<vrf{?> zAFK!=MuHU;CBAOeR!n6=vz;7L+7L_PHF2ElLo~YNHBJrFT)T_l$8Kr+#<@fh`+CEJ zPR2M&vZqVG@C08?BAVWOhKw|5zuS^g09lF4OPAkk%ckOJrHF?@?!Q$;MG6&Xsl{ih zn2ggwoB4dqithr8^uwruCKdXzc6cPF*$R&QpBhbH!+Jc($3{oV*@>^>Ke0)$>qqYJ z%VHhXU)W{}R0Qwe83XMV7D~UseciT@j0c0S*NmHpnkN0$-qnph4TN>2s6v;nmn)pV zDL~za4B0t3a}b$<jp^UFy9;v+0nMKtwqHZzl$C!!Z2H=Ib68Ue2uj=(S&ZASl<VbA z7#A?C73xjM9Idt_I&d+zix|)FJ`kP=#|{kG)J!Hj@$~1<WDY*vP{O^l?ydv8F##dG z8LH6R*snP*4?~_?hdeU3vNnyGW&z?BJuA*LOa(u<i#E8YojG%ODiq)V`6C)CY9U*E zqRx-+OTbA*w{9YE=O55VM##4SrPuj=T7tf&$VB<%X$q<p899pNqB_jj-3o&g!f)C- z+h&=Ajm~6L70G}Q39+n`#p!nQ0>2W?qv48yVz+U%Ov$uaM_F@&C?FpcS?0&DaZ3R= zelc@h=1o;;0FWs-4E5WK2|S9i79@Et1`)<VN6(4prWpR?SMKqKjWOKiS3|WM$6B+; zufp(D=-<AFndjl>TB6?N&LeHne5N=($EqyA`n}ytNmu=Jrbv)u<c3`~f0?>aau;N} z!;UL2jhRMLTG&L-j;Fk7?}6A+xWxM{+^VER!)+hF;<SWoZaA|$LY_3z=%0gb*ZV1K z-mQyI0_lEsMu;!XJnnVeV0Fu^{LB~F_>G2JJzaB*WYo3EY3Mm>(qub2G^=uUchLXn z`m#6S9YQI0ry>Os%kR1gc=%aRRG`n*fItkPjkR`~6mvg%R2fY)xE7C%mhXjQL~If> zwXLOw#{#wbY0wIM`fH8q7>zmL-Y08WUimY{?Q(|C0H7(-7(3jYjlc>@(SB}6(v<8E zNmx;@h2pn`?_Zd)y4wb!f`0eeKrAi0OXi|zMJGWrSJ<z6#|&!Md0?4HUzLxU*Z|s$ zvD1o$R`@Q6Cina2HWL*hu4d@!_T<ta0gXL{Sf)dIVW7z!_G=ja&YxYruIH$d_z6?E zJs8<8!k}j0$ePU!&;n80-A|hIP6d#*TV42`47L?-I;RlU7)Yg!b#XN6XUk8Y5y&l) z33-G*cHSq~jBz_tkYXGhyk(Qj2xd-3#v3kF3B}Wp*~HgdH;GBy%M_r@+q@C+yrgL2 zG-Gvyt8LIS1W7SE#&qXjlBtAmB?ozLcD6~M#|2zUmwg`=bM5cGnY!?PxZ~|Hyuv59 zn0M2ciN$0t*49y-DPjA9GvG9^|M99rLUVY30BsXR&BDsg-ys<05E|82218`n_1A}Q zm+{&2Oc_f&yt{3r?5X8pfg$AOb2&tWS@VbgyeMTQoPzO{j@eEnOr+lR*I{BEA?JR* zFyomFluueB^2Il&m>J_refNa!N+T!g{?nUZBW+3A`zll>{p=(K2CL3GdVq-YM>rMp zr}Z4<u>?G*ZD?|{hp4CReQxQGOA}bDwStH?CTxv>;Wki3AHY}IQ?u%yoQ6fMF2^MM zA_4jq9eJ+v48h~}nBH6C4p*ll7S?0fEK#Yqc+pFI0@Pw#@zWb0OYhUn`k!dzm5W1@ z&aJwfmK*gJxNmU0Dh*?eajyOOrX*y)lBzF=<wyp^pXR*BmCUDoziuSO5t!vLkMA3Y zI4V`i&5HBl&&d*06t$26<2;?1W+%V=nKm)p4K5fm5xn47ilZ)v(fr&)st<NGCC4ag z49+yIl~D5jOsOYe-9w#|OxP}4Yfm$zP}?17tN_kW27W{gz19&fy?wAjE_uxj9QRvc zvxN>UOkA+5W{Y8K9>z;c`Zoj|xQ4y}@oGVwmo5GMUbR*!xo4ZK_-<l(XZD00?qVs) zOM&7ivffEP89h9!_J8LCpnp`#wc1g5xZG0WU}BW#gG8MSaSW5RHaRB@#xqqUP!q-1 zi*<!G2V!!BY5GpB3CoXI!l4Mg!@pIneUEEwXPeU2AKuAeg*<*DI-fA6E6;z&&euk` zcidVb_@<K0BH;I?oN60B+>lD$@jh4p(xTTO7bKiLU(>}Se$TG0R9eI<-io+?PG5X3 z-lf1|K{M|D3<Udq-sbMs>de!2OngDk>E{W@>5JrRT8l_NuB#94!2X&ru>MmK+#7^` zf;$JiBF%kMZK62VK&4h=DlET}=^gT-H}6rCB%fWZ)669kiLPCKl<uIW3@f$)X3QLk zWR@Pma)ioAbl=2DLV%W7=BoNaAI6JMJzKpBH*b(V_4h9j(~9=H+mv93yWbv<_t-^+ z_rudsZ^pf@DUiNy(8VSp^|6*9F-XfB-&&8i`3x;^*Uv8{X;|m3&yQAXi9{g8o`fV{ z#0z5xjzL&-$?>lh$5;}_#`{@YeNVLqLcaF2ISabJN+c^$!z!2qeLpfUtJU28sCP{M zeMdN8GKV=^eM2KyR5xqBXnj*`T_d*3-Bk1=RhhSnaRNgkr`gTlVAYw&REIw?CxtB4 zUd+K8pN@?*6JeoAkjURa4r}8cpX_j*(oKT<zmP>ZWv2lsVYvOkAbWlSPMT%_A&lST zU8Ys56wPzE5B}_j)cwp{nF0h%JwE%;metgG>^*(9>|YMjzk&T7Nz$u#>pK-z318Gy zDbZ8O9@fz*D&z%7+t<~-*L_~MArRo{^%kc>a<wILheu`4*}s*fuN87z$5vG#o9>56 z@(YhHX&s#-fq}J4DrH_4|2+ikDa_K**%}3Q+DCaB$cRFvQ|9&PPpL#LX?~HWM8(sR zOy*s2E+||=NS|w_4)B$hJ&#HtEt?@>dZT4q%}MN`?nqtmi-qWjn;2uJmX6ckupJ^o zwS<&z*6c3;UU{ab(-r{VD680j%O&tW7<`vXM>&0pZu%6xNa}ivYnv%d1*l2;H<XU$ zkUQs_4KSGagX?6-q0$Kk88AsMq2D=ZbTi4l=-011A!^R3Km4!2k&_k)bPO(n^u$1t z9L`nyblu_1m^k5(Zd$P)gM6amj;u3y#PtPkIr*VGsx5BOkec#m!oO2t+iXvfLa)w_ zjUHXL<iDbHl?%*}$g07GuBvkSUk11NynmXMjf)~=;g}WFl!8N)$xp8j&<$vgpuKER zjMMSVg9&V^NfdL^9EZgyX*S}<ZS1LalnZT|T+<ORK&Tu}<~(F*DN?DL?4CIK(&V+2 zG)zXmUz;UOitaP@sWeSq`8O<G+PK*h_o))+#_a~FGva!B65dD3J?iI`nN+56xUgyb zuoHE^@N|IzSQrp{p%zVDE?{+78XG6%`@#Zr&JeQ~0FJ>Dk7nyvSgv)W__rNAWIca* zi4!985hw9D1n^VT<iS|qt|W|?Dk0?x<06jPpDt4wtW|te8{!I6V@%|EEOw47Z8y>C z$f|x~9lZ#aMQqE%y7v-JeMUnL9~So=FmQk($S{$=XuwdghT<557N<0c0yAUTuU1jm z^vKBJ4<bNs1|KP#8@4-D>qjcV0k*_x+6;BMjiATBn6yeDf#&?I)dJ<6<4R$ji5d5g zLzX>Y_cv($8nF|nv}?4gDVUbod==F@<KD;b8w<)^5VyA&Qcd!Lj;C(g6b9KD*W|)O z8Ir-T=&4oRW|g@PmZ7(mc-4Fr<vZgyr&>#2&5U~yB%p5tB~8sXaJu%lld4HfAq)vW zMrGD7G)V!U|E$+>7$*=U?Kv%GTmUh+4+V0>c8YqR;`18;`NkDGU%<uEk@|R<r9C>O zM7)tnT*4!b^2OkUB3miwLFP^QB8aNC!yhni{)MZR){IM<*}9~No9#BIe1OrDdbv## zCJk7<|NRZ;4RFoGSDwfsg!UR`y;GDMbnl^3m#wT-<VZXS8HZGDgphu$vHq2pU<MHt zNI9A7<Kkzxlx`d|pF!}*2cWj(hLsAs^QkN{$5r1B(Vf(c8dUou;~hlvb&hYoDSj;c zXJ2+`sA5Tw2UF3^8sF|^Gv^^E<*8)lL<+q4GgTE)s^)0j8A*MOZeKtjBWXC6s&j5- zBj@TEl*~naHbpH+W;<|%(;vS&tdLV$l2Od63jMl1v+A>cg$O{YXr!~g5nWl}J}>w+ z%!H2)LiNj4&h9}j7Ne6K?@)Tv!~$N~-r}t*+xXoP%kg0^vW?+`U#P<Z@t5YS8c{ZF z(8V}cJg30JS9TM%0gDa$!xg{JW$O^whwk*=pVTYP7G9K5JifB)=FSX$Sk3y0TD$4{ z5<%357Wp2GObtsHPMEqkVS9JL6$2PrGG6@sL(zk5+&Z$a<=hNI`2`3=%p6cWqh}Bo z^~&xdNw`)rp4%QS9K2{xA%g3o{E;XBSJ})P4qtNa21M~ukwR=+bi7&?9aBD#7<O)2 z`4U7i%f$ZX8NUne)NL1wgm9->1vM{>w;+rxW5rEKJ*bBlDm{Fhy8x5|McC!p8e2vp z>t>FYFWs_}NA3Fr^w@aG0lG~10CNiQUvNKGZQLBrlLIp*)tpeBh3ivR36W{Ubm=D- z*&<E=tQBE(1HDV?<$<Sc$l&=T=trXJo<-ah$3h<NL?2s}Ib}G$5W(yYTv7RGnUf~& z#}O8N)}=GI6Tamy^_c;{7NS1)kyMFG%-ibMf?K)lU%%#`tSEZ-%`)SEEqdHSz%dtP zZ2#>}c9MQ(1%FNdF8&Cy$uX-08ZQ6~d``drQA|nvP%z|Tcqj4c3&GrHXp}X@TpKDs zd1D53wzGQab|fdE&1S;&gWWjw^0)$b1mr>ZPKuGqFLs4a1s#)&)W**-aVwYV_fCD_ z^$!SwSY27LrH@;;jEjJxr(B5&wM(-9!mL*wa2Y_jIA0a}Qbc<TzZLD-(Tb~3*9}}| z|I;x5hiPVPrh@4`{nno&=BfEJT*B<FXs{#M{-tbfxucVDlcywiZ-<ZgvK40ckL{Oi zJX%8bAl`>1>}s2_U7HId$@|p~E1_=EGUOAV<`5+@hLE4s-y{v~bZ^iG4jrsI4Eq#n zX4;6h>6_bjKI?lF$N%jP=Y$Q{QqN`Q+n0a2$6h_zQp2MwD-4d302qCS+i``HXd@J6 z@VG9Qmgc`mkmISZ)p6IP?%;RW2oY$gA?M=cr*Kw<3l0v6PQ+p>T=n;SWq1YVgpa10 z<$ZQPmnX4Ay(9p{@Tz|-a6X27cu-^+o5xfcUa(`U+`8+AyXLf8|2SC?kH655K8V%j zPgHjK4z-VS{b?S`;Iw+DEbOuR&R2r;GEXltE)Ut1f1XLQnnTyzVA~o^^5Hc!rj0<8 zbi(UkXezgCz`(Hz09fvPNZ+5Rk-VvlDa$Hx&}qLBa72gw^kSbv?!ViMrZ`*Vp&Hk& zG6LSMzeV(&lf>tNf_upQ!$Qq-P|roK$ifF=mA@LLH04y<s7HtiEg<JtG(CoueUC{c zpSPKpkjwmN)9SsNGT~|kPSF#C-){P3ZKON--Qhf}9cvKGzOK%L!aGr)v^A7Kv;vG< z#SV0f{(_{i1S7TWN=il@Gluc+&S#!d;5umY2Nq$6z&kD}Iw))ZSGlnlX01Z`D#3c_ zhc`I&W<vyAbMjGwf!|*8b9eHuy>k+zv)~(S-x8HP1F7%6ELF2GHn%L01^%<X-bVqw zBQv8a_Frw(>g|3seLG<(kN<i0sqEh;p`K-F)~;(II&`mU*8E=Z%;qetkHBgu@%uo% zrWCP@(}IXWmHwmsEeO?gz(0%x_ed+DJmOC_zU&I06b|GYjno@M82;bZ1{`p%eNVU( zyI`mwlkN)-$KDs-@GN2w^*#5jyfbap#&`5=qU-Bd3ts1T2i!So+0L4g9tUN6uhkzm z9i(;elpgDg4i}sHb<F<rX9sr#5s^bjcPQra@oV#|vS*&zZ{w3~4$jx&Q#O<hYHrJD z8$;CXvITUEX}W$#t_>|=3wFqFZ)2`g({frcYrI9PAzw-DbbInI7QE+N%aKhHyvGA- zCR(>mv;;*u&5+-2+gNXdy+g1@aQ=0~kxP9Z%Yt^?fRo8#q_-|ScA)R63Sq7Ux?J`i zGI*Qw_6f|8KFi^!D{3cUQGXwC+W3wqXPU`k@NIJWz4$E67TvfQvo$wEhses^nQygT zg-1Z+pB}NW(%<9a)ym|=>-m}Ykr_<tz+b9?E+E0)K=C@n7Q)%K#2cYazx|f-6Nb*J z7gX;DdXPDg*+Rlztif&r+H@L5_%G54Um<5dJU1*EnbJXg&!LlX1~(I2hN^QjPGue~ zHf<nA?08GAEt>(v#P}pMGlVpxuCi<(BG_&I#hlJcV{A~L!a-&uM(3UWVYkOJ5o+l3 zE3l)0Ky^C|pUykmiB#*A-7CIPcQ?4ziqFD6N9WH9P^6=5D6Nim18TME<sEaY@@on@ zA-36gFBiEY^%uTRwaxdDEuMs8^G_;w8$_#2`o|HDB!HjPeBP+FinCljN)RYhrMiP9 zw6*{Er_WL4$?|~LW4jZItJ<Wkdv4qOTG<pgDY4<%y;CH<?S*Eku<Rvh8g|>g?ty(j z?6>n~N8E18KUi#6B>C+N(r$l^kAN6-j!ZAZwPwy7fxWhMg~>=|G%cz3jLi-FoE)Di z_>_q;3O0)lP&>%mtG^k1m!o=#2R4a`HW}<SI3_op0Zo($y;O6GpS5&Z>!Hre$xdrA zu4^&R7aXO;L259)P)mw(6JwWq9|_BRc06*t2@jA=?g48Ia++zZjsZ+6|L@^Q2jhy> z6cP&yw*|DNbcy$|r4pTG<Q4GsBpi0F!r3A(3<Pn_m>3>`u!k<0xLOujYmrGFt<Qx@ zkZh|$d+%(k@9`8CS`q(?^qp5Wh5yO>Gzyz2BJ%%@$fOq2o#bw<?3oaR&FWu}4*<)n K%T>#mhyEY`kk`!s literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..96ba43c285d76182e5a93ba1e83e5d4ca57e2ac2 GIT binary patch literal 3107 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 literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9dd61861e64bb6213048f4391c125ffa951668b1 GIT binary patch literal 6710 zcmV-68p-8}P)<h;3K|Lk000e1NJLTq005W(005W>0ssI2m!P+H000^NNkl<Zc%1EB z33wDm+U|3D?ju7;NC*kxSRo)m1(kr@mm;hJ3hIgo?0SI0s;kH;AmR-IqOPE;zc(yP z5D~(eaHF6`Q0|085^_y4_w-f&(=#wkCR3eB=s7aZ`#efbSAA7q)tCO>uA2Y=AaS&O z5D0>JY>A?%*QiYj#|5K7kO;!qakKys9>aQmcmquh#|0xU7<a8PA{ckAF@m@uV+3)I zj1j>&N5+U?+_lCC;)aY7#5poX1mheTBZ6_)8Y74sGDZ;R$QTifb7YJN#$9WSAa2MQ zL7XFFL@>^gF(MdutucbQYmE`XxND6O!5DF^98Gg2CCnd}xaw-YqLQnrK^+d-Y9X9X zgyV%27{<!wGPMRM<amMsOH9O#MzT#CEF+zus7R|X0a~yj>9TUVu#oxv6m#YbU-}2a zvM7RptFa!B!(I)0o-^(M<MR;3aimQfS*MP~4S%7!b(6JAi%ey%8!e9`U6(G|_w04; zKY$cpy!O0702cOt$Z<$%DP3Ah@7`la5G17yb^C3K0RyOvbWgc0rEyveN3wNwj)Hy8 zz4_elr~KZ$;KPk4zEtMgu+g<)Ba)G!96DIh{|-W@i~h!G8LriJ?!0Z&CVJligki!{ zqR=))MYeyhwXOS@>~)LsucH-NS>Y+V*@$XG+JF4fw*J4|uO~b|ecz$*0OdI5&|&kT z!<NiU)!2KK{rdX4wWvarawJnxQMc+{?)Xo^QeDvD<_UuH=Pj?lY2TEqeQLTqBO}g{ zjSKR2yJh_bXYRMa<!V0Fg+NgFFgkt4^z=WeVMDbOC*THsoFk#IA3khZ^FFAqiL@ec za2&n$`^x+R^_0o#p+h3A%{4@eAz7=n?!&e8j$O^?LI4n@f=ErlTD2lmQh2pWrq^Q{ z4MMo<$Z@>ILf6*fHXD7ZjIXNVFO>m{6=@#l*=)9VRyhwI(m(k)VKg=;2dNPi9O*oJ zuJ+}npt7o|-9Z2Vkdd+;H&VTO$+~vI)6#GZ2ldPHh4QKtiXc1y?4?W0$rH{Wj?u@C zBM#>^t>7j4hPk6ZR6Y5W?)m4GH}wo%;{+LwJV)C0?YFFW2X(rTpqWh2U8AOQ`Y3Yx z$hu{r1nHNvU@B2nfiPx=k*TR<YN~SRFu-&4sZ*}~2b=}_L3IuAv1lVI*=%(S7co;G z)!seo&&!bjfV$7WaD4Gq6J#({*1MN-_)w}xHcFCym1#CGoS?dNrMh(0OrA`iJn6{W z;VjsPuv}2WJn#76L$>&$;jzD?M8w)NVg>UKhiUl==D?vK)1yj-e8?cx-FFko$&wf^ za49%0zwt(@dw2GcN%l>-j_<c2c1NR9072+&+pCI;4RdA_dVMGqYZQ^;NWii+i<WS| zo(QHVhX6qJ@28zM1=kzGrYdPPY9~LUzHglQlTV%BZ3~9B`QJ~~yg1MJ`Z7YT{!?%y zU|G|$S6R0e8|}#v>FqRACsWxyBSJj5TBCpbaeByL%ZKZj6Tf*raYfYTOG;|yEif)# zgsW9C&XK&sQL}gnTX>?;lqe-r{p~^3s8Pa9Q$!)_)Y<szE4JOcZ6B=Vtv2z*+?li0 zixwLf&c_sra4Cp{+qD7!Oe<D$h1WbP%wJ)~1l{~ORAvXijzr{oN~n6!V5)1DY0+Z- zVyU>B<xc)q^YSakMGG<apI{8S*1E60X7(LGQL%4&6aez(p88ocv8!JV%_xy~I@q#u z#AXE+D{u&3E2x}8HCmul2&)2=N_W~O*O5p{YW2ozb?<-R+_78S&9XoLVp_c>VaAg& z=vwUu4>~^kqW))$KTrfwPI^c)ejFm6t^s(blm6uw=G1BC^lAFsdBkGz&7ppG5Flz5 z*}gs5sT0w;le}j(rc?!A5UNn>XU?=`Wm#9h2RLZ|1Vs>Ld!9KxT{q_LCRL=_2$LaQ zMMajk-$6wC3@DDNpPr!_I57C$1#h>xjvTe;7qCAU0-E-DCs6n}ABtG*OyLQ(@B}~* zGl7%cy2|_J$Zxw1*9FycKv7gRbSU1+So`v;h<ju|AOM0m)_p{#rYLT{DVS`p6XD=U z&Tcm?UWzyz4XM!^00^R;IYTvI;1!o8ULpXz(;-ZfY~JGS=b`m8goXVdvK;$Uq4lRi z>%Z4g!-r}o+>dFr!PHUS^CrXG*|je%Mt#N&{4?jcy4T+%R;`dFCQ9C_e&KL%WZk-t z!R5=oHT2_16vs3(XD9~@^bD_wXUN-Zw#}Ozx!>{@s|ZUqc^b<_J9D?V@^&gl3{%~E z53V;fT1P57TfcB#?c$}tMMF!p+3Hrk+iKzb7SEB6W5-?JZxfl&KoLa!^mMhyilP8K zZ{NAY^3f-V*%Fd*9RvXmr(<KTed{*$0~6F^Mk9D5?L+m**3F$=w{VFFU$Q?Qvu@8* z4;vZ+eXk+3hU8r?^XfHXDF9GSdQdfRkl;~8d66kDHm_RE{C29IX9*FUF6+AgxC-`Z zW=xm0Z!eNi@UhuFx#^EvSF93AW?TD_yjL$W!4LvnuOPG>Y5m_OP*EYmUb35es>k1l zit?iHS|2`ae&a2~=@Or5Y7R%j!|a)JrdiLbr$43|GE}?~)I)|aCr`Tac0o(D+s&VS zZglrXV3{-wM+--?H75Ipjh+vgfc$|O6ZEs57MXSOz?z$DTl*2<K?Ih1aGYhuYObtY z`_My(Py04hRXc53&6%@o(M4E^^p2g*yGBx1-|v>hk+tu=hd7{92dGS@pEn27i+LNs zGIj5+apmm<P3%@m3&&R*m<tyYo_iKmC}C+Zg+f1nUiH(nfcq0H065P4&Z<^#zK&v8 zD3lD9AsvOkvIh^tVo?N9J^Y}oLkF=eSf+OAEA-K0k+q`m_k<$s(PK6979=cQgu+Kq z$=0p4PyECD>YFgC=gyw9@6A^Y91sd6L&cG{4gd9Pe&3&XyEI`m95RmTLG9{y>7&Q4 zpX#I%WKW%`dG$5pg8A;zy}%8k=-bb}^?UZ06R;9(n{rhH2Z(<YL=i{QB_*CEsSpwZ z>Zy}Ga~d#Sv~1es+OZo(t`S)dDeV6F@wnxaPqdRJT}x2E?gCj(d9-@gb12UTERjEV z-f`ljBCBi5;7D8Uw}9ti4pG*xue_(&sFmZ;A^W=jgs7)@ov^Lnh$beg@4OS1fXwV5 zA2QIjeJ3n|edGTWSzRSpOnO7|cDrlOURW%ukZY$+5fNvKip+1m4R~I1#iWAu{SV2s zG^%@dSOWFL39kHoh%@joEc3&UOl764b!%z0lAa^&`wt*aC#>&C4IYFW5@00?Q(Y@p z3H`+ef_~xfbL6#$Ja2wyRpNWAJ*)Q`HVD}&Q9gXAbJMqhbK^M2-hA2kana6^&b|4t zz9WjE>M?hV(13mWcJ|a6AzWY3FB~b3^giUuFI(1c(A<ANtZ~%i$2qrduRkGkEfeRS zeBJnQQO%KbRW)1qD=e1mbqkT)1{TX(t=5k}Y39=Ju*3fKdc~lDWb34Wv4l=f4eIaw zJ}+P_UtH`we}QVBA)!7JyH-bjKH~G4<L6bB!-x5OdHd#O%gqHAtH^j>w76DJm}YF> zY|uUNIIMA$Lk7FHZujd{dBgTyyW~@+1Qd)4*Xr7T5Vl|((WqtF*}kK3zJk2n=GeR? zNCy~k*LuZ6?%1UoKaTL3YxHd#*<b#Gwn+lz6#;Xm4;=<m9u2Zp!|hs`ni}r(X;>_k zb2~<ouvp7C>l<C57Ht3wWBKee!_1kGcvLZ<zx~T^0?U?Pb`}-OGt#9}MoL4{zZAlz zq5wb?efq!zd7IU_Wvhgmgbnnb0`6}Q;l@@0W2xJ2wSVz7jP=>VLPT0aO2v`1`<Mn_ zcz*&JA?x0)VL_gN>(F7~a7Kpeu2az6m(YwI>sPNU-nByqw3QL@+3x9^iR;8k&FH%W z3W_`o2S<ARYCuYm^|%owNWb*nfIYt;f>d{%g3f|{>U-~nG!9Dk?BUw6JD?z2TrAS^ z5#vanW!Z}*u&x8uyBAc@Zf6RAz0N)d3J}z22xd(>Z?*vV(zj-SJ$s(3sm2omZ+E47 z_oCf{#sN_J2WzttswOPP6oF)hWG<DVum%D^1|MCdfBp$!*y}7EZ`ZcfyQ_kEu^jsf zYF~ZxI*apz<H%9<h!Fv!WL=;Y2MEFz6%!JTyGq89Txsc*uutw+!U{Rjwk=GMK6N_C zzM}|ZdG<=eI&Jj?WwPe+rAPwy^l5bD$bgL_?6PZRM60R;3UZZIB2!wC;YhB!8aC@h zq@`gP4ijWforVcEm9b#+V!kDMQ%Fdz%;~exJ<<q5X0)T-hHNOvm6kTTxjNh&$yHRq zqOiokU*{e$=gv!|L!`i$l=3boE)TSL07Y@gFrL7#)zwnzAe|v=>tIo`ls2%{j-16T zEER7d<Ev0`99vn5r?m?hi5U}Ma(q>lR4Pcuk(k*GqdKns4qo3dS61fzAq`_Ss<zKl z$vU7YDs&dp+663;OiYAj!rAOm$B`_<z^G29*THtj@xrz#=z7VP!jZzacV#67sUs_= zV42`nYxHrX-42Vwv^uC*OB-K>0d+cIQ6zlZ9ts)JYz8DVB<^s+c0Zu-v2p;ff0H2e z@uh2&W&nks<$_W0>Px49gk!Cs5vmKA2>_BX7F+s9#e)wa_?5N4>PH_{4H^_ajzq2) z1=3JrB}N@baxxi|OWZq^0t%v(Od7@#=+@?a4rm%yVu&~rAp)=N6aowj%LEPLkgjlZ zB&Jls7QXRT$SQi_hy{&Q3PctxDT77P@UMq@Z|L<wGS^B_GVkgAetOcibqa_e?_Pl~ zW%tA9-*CECDj@+@B7XJY*#L|nmq(pz1quapVYtl-b33w><SWia;@Kz=PS+}Ye7X<& z4BW*snP6QkLamNE*NW?Ou%qMI@^aWGrLY@IMqdByM`R(G1is*yt%MHWpa#hfu9J=< zlb|)>MQVcKM7uQh+y$xBhzPKx*0_80DgXfB;Nx(xS<GfYx*<A)0Y-IvSs8$5LU!!P zxeeKJIg;$$(YG(*TaGa1b@3uB6CyPw>Nt{2PKI$LS6#!IYH&kBLqS1<&Yi%vycW%o zWXDe4zJy<ioYMiy%ArGaNl8)1kyu8$uopM*<{Q-Y>j`DQegOsLH{WD!>?DY&hWpGl zSR{M?JYcwh-3$~#@V0HG(n2yrl1e3#oP=B|3mD7%{4)YEByMblwa?(sw^W)$TPIQ( z(33x$M~=cei$JH7iO$qE2~sYHBr`LGl{-GUd&ABnM|FV;@&x34``FK4XrUY_&*|eS ztYL`&0N1f&FhQbY2l1AV3`Yui-Eaf5Z+}28L27F0;v!jkMnFM%P9NK+pLtWaAdVE2 z@7EVV4(wv9t3Xi+EN8M)$7oy*DU5D(>k2!>L%1&Rz(J288-h$prTX0F+8^xs=FtP9 z>kU-r&ahb5p~KLn_XtAu%$8CU3G<>dGl9{FK-Qr+3-)OyPK3#-|MrmU0JPfC2^2vz zk4zFt;Mfb_xvf;nI(C#$8A-R*p(u4*Z`x-Uhc6}Y7fb1)3sn2efF;UO+fse|&;|P& z3PvqQ5<R+8UAn*;hpVn)e-~DI2F#7PwKwi_C2(|cq(B%0`qNvs2IdtMb?n?Fo6;Ue z1M2(7SMNLEnW1bE9I2i-L8Ni)J9l}~1<YBI(<k^=4L3&$`rUAYIXM|AFAo^&%-f}X zU?K`x`aq^<$VUuwZrvuWN+AN(FNcEP4$3o(1HQiu)#()QJrvD@#D)}3OB_5<IPy9W zfX!yxo~Icz1}3hZ^e}zoXjI=;=LV)$X{SvUNnrbK3#c){VyQs`F$@Eeeh^51s)uqw zf5+!vdX^P6qz6atX4R;>FrVA3d~?IqYW1`!=2u>;_q;(S5#~q$RF6E28w{{vQr_vX zf4#vg(l9sqfIFJns^R8H;SQVRWV~xv?nL1GS@?=7TW+rU9@suKM46LAj~eOP^1TQ- zMV2F}J91RRhl?C)Y2C7guQS7P!#ZTjGc$u(xfw~0^g#93(dH9@uV?`XV*B(9c}`!E z2|V3D{%)$Qq>ua<3f-;~WL6jbtXU!nxVk#~*Bkr>4Sb;*9g=$oLUO2};?~}lq}Isg ziopJgVJx41n()js@Z502bI(>jH4BuLN0n<ujRyVf=P_Bm<vD&VVEyVV#Ab)8s?#a% z=qECD6-BPq<8YK?M%zC4(6@%Z9){k#&pC30JgXZlXH>38SU9ix`4^Gex+rn2h)QXg zKhJZe1WawZ=z{aRZ2+#S{H~E0L5LhQ99^ze=wpo-ZqNM|K>8s70P~8KvgL1y9A!(S zq#9p&+4RyPt{l40D{MgZI{m`=q?_Ad;2FB^?G+-Y)FXPmIy8PYgoZ>(QuE~FmU#<c zRKZ;;uYLUu!@PMSTd|0?ZH>#{HodZp`MEGedNvAS*06IY!`#{4iE$X}R<7dC7m4Jf znl=TOXrp;Ugz#{BRnKgD?_S)Iqu!caOXL1OedL&B!v^iRaUz$t;A(ZkOABh>UQX{R zXbQba#*ySLH|bw^9+%4z-voX+17O|0-MMoQ8Ypv50PEUCeU%+W8ZEjw(i_%3@^H=Z z;|RkBCLR>AfA$60rHec(OC%E%Ck)R#W9^V>`}A|*UT+s3jzncL<pcL??zsnXpF%Fu z2+W1^)_<=>1D%EFT?nt4GFhrt4J$`_AWKV=j~(m$5_*d=U^(;BWyI^t$W+lq4=Ad> z=Uzol-?|Szpbs4l^~P8f03y4)?#U;}l$1t?U%2XO(@RT0{i8|!K;1b~4xjCk1R=kP zM>pX<`tV_J0ZJac*&>|#zVu}x3A#nw10pFYVeVYV4@YfZe8rtQ143X<6aXxvoqFN~ zMNW?A0lY(qxc6zBYUVHCMaLA;<Ye7svDq$35b{gTP=e4sHN*7mzfdl~Wni8FsHm!W z{srS}uX=4MlA*F!Z^bRW90w29Eqfhxul16UBh@o!s0I)Az0pCWj)E1RpUwYKCXyjQ zQQeFuycF9~InooRI(AS_n__?O18)r*vJ_Hns(x{<VaX!0{-x%y5*4@KZcj^Pic2Kq zNIXHW8ZsovI&!8O)BJ_pA7vs$D|8(1zfW=Fjm>D`=;BB(bffO#N=jU!CkOJED@^}- zK|gN})u~fZnM&?jgU*mCxmde!F;`J3E<oJTPyZlvQG~Pz-;J*NX;Z5%mT>U%l?7Xx zYE84}sHaX=jTjj=#hMCx{$BH{HNXzNWXJ=&L#E;B8NM$~ND;ovvN3{4c;R1FPt8KA ztHpY9F50^4J?8gQy6MwB=eq_j(fuC^%cQv+iHg<{a9rKmwZf_Mjdn)0TK$~ap2Zv? zZPl=Hq&JLfwTAg~YF?a&*lYnw#hci*b5Hff68%4C5^d9bmA+P@n+M^?fi$xp30wK^ z-c(gl_ttXu*ON%2XXop5hL;zUiHX6CskShV^g@=Inef^xrnw7%2|9s(<-ol&=c=BX zr5tm&di;3zJ>?MtaJg)oHrc+}0G!vhtiph5G={|ssf_gScvLUKZAjrGHa*?2>}Au7 z^I!`nuYqA5>o+>{cB&qFKs9V=qxY*y4#0Dc{CvyDpMt9DV9bJQwT8tniQgR>B7~14 zeZy30YQoYbH80LZeQXIE?F4mZ>+1LH-)>Pq^04COTRfe-P;(>z!1=>b%g3K^MHjD3 zA41gghJi+7Sn?8eb%rF&tr}L2^bM0KZH#ZfVOp}3JAFosFTH#7ic8E3m)J5h6r=7` z^dEpxlt*tVInoowF!p@~j?G&b_f;|;Mr>3)JUv}M=LND&8^1P*S&sAtnUK(G+0vTj z@38p=K?$HJd!g8}a*gHv56Ny>?8Q=P_2Fx3tLHCZfBW6Tg~4|#$=<yT&pm@H6k+B? zUqr^Wdc&AZW_<3M+LSh~FTZZocU=q9414S+KYv(1aWh>jd;Diu=`fY3(WCTJr(hn3 zFKOen4A<%#&_DQqJuAz)ay9Qh^tGj|G)MJ%^<#fm<@6C*QTL~Ct-et8%$BcQUi;xX zI&Vj$b!i;J_Wyo4`o|w5wAu)|Q(r`jA>C(ZDHEQW?ikSDx^^8G#T%H>)D-ojla*4h z`M*v?m?IlLRQ9-0zWgogmhWtz{2%JRG`&fTb)6h35*9qFOs1STL37U-jJWm!gtKu( z!coDIeqjv5G^6fP^ts*g%?4NA4&>@B6cOY|gdnIv1J(D9CzD!7wsE4JBO8K9NHF|k z8u!2i+x9%?<}JK*=eP$C;Qpdf+&NM?Vi;jCgkOQ+5xs`=fY55SWAD}cb&UPsA?L2$ z^zoliHZ13z;W&BoO^Sg7<hS<5NHT1*QO!owab&<SN)YOPebxQ?vSzb&d!B3m0p!eC zAay_TN`~p}6n%44BZiapU%{wt98Vw`IZ`ByYc#sC_oCy*x-MU)fBJ<!ew;ab7Ae2n zfcBcekwQx(wjw%qq<UtP**)aK$~oZIHH`koiFVftgRFIH*{~tVFky)eU0cgtC}N6= z*h^(xc{yKI#T$(b!*Co&5CrN5&kMJ(VHn10by(ZBn9+zOCy{NEiOlvydIp&g)%+I> zTB;#^LF#nEo0Q$d@2{1(+DY)(63202`(~Fesx_-b{<K>tS_VhP1!IjP<ASlqk#YDT zZpauxoFijIFwT)NA{ckAF@m^jjS<1PYmE`XxND6O#0?oEh;w9&2*x=wMg-%oHAWCO zWQ-urkuf3|=g1fljJwttLEMlrf;dOUh+v!}V?;3ST4MxpL&gaHA95BRUWchsK>z>% M07*qoM6N<$f*Gm$7ytkO literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2947572c7bf997d02e53df64937a56bb5031bb38 GIT binary patch literal 7352 zcmZvhbx>PR+^>T}vCvd-Emqu$yA_9`K?@WpP@Lceic_58S_l*;6nBbKg42Xj+zG+m zdHMZ!-+S-OdCvZGzPqzKb7ps+PqenCGVv42CjbC|Smmw4yT`WVKkzXh-#4CfZ2$mu zkcxt=o=?u68G#Q-@nLaR!^?x!Nz{0(5tC7PNZ%L;Oe~}h!9O-6dH#${;z&kDhQvj7 z{RB(#PD%<}R8mBryG1X>ooVAE+_J!M|AWWw*uyNgynWrbq6Lj9mV@42th&0c%voV^ z@q-bUK&CH1E4M!KS4q_})MPR_XGRMD7hyq2hA==d{d7N^nn$N-<Q{zC7{X)LK63O_ zahUpG#hT0w`TwDV)`NNA%#SmTd<M<;RRsMr>i?wKJ*MU9+A!A(wOEcOa>f6K+_R&R z+pagRDSX=0No3@t8H3XVc1x!U1!4uKs*<;ayelh^<5p1*hM?a$2w6me9kmI;cJt0# z{c6=}^K@^ze)(SUTh{ptdmSaAe(@f3@=ybsVi~D~dZwpdq3rdH%Zq$H2vi~(Fjk>y zH6#q4rd|7&d)`}gL9GvBk(2ca?|V+Xf2F^?wT`Tr9=RfXe7K3~EXkFU6=G~ZlxWsE zFO;&xIVuZluYsE^I(H>pC%l&Fn*(tChCqog#!{w#=ZRTMLn7`E9%`=7N-H_Rwh@)S zCzKjN8VK}Q7a{8I28D%Z8HjPMA0c5Vud(F{9s218>Tm;nOq8?vFm!-YEG`~6YyFjZ z_hW9{q9&j&{_0FvI`hu>&{4S0Q+s78=%v^jXZKI@VNH$|ltS+otIe+b9t#p{^5G2u zcMUfmNusj2E_S284S-ljy%)<U1&k-ltTj;Qj=1P}$Dr)4>jd;6tS7J$2jds7&wkF; zXbbX96(T_^vFRf%iV{buzHV%y9)%V<y)X%$qj3r_1o-dNuk@!o-CaAdswaLFN~$J# zqBGihck4SH88gda2+eV!14Oh0E}A8Km`d(}Hx_ak&1lRO*wK}9PNsEf=3QhppU&8~ zA~t|l{9pB7|Hh`No&;nP^|}$&PON;0Q;Ia#GIGkuJ(qq)^1QhChw#?a-Hkn~6oU?1 zxr>&o0@S@OU()e@-9o+F<`)!-`IQ@=Aur`^(HrLJ=^_-$N0tArdJ4;{_W-=WSU{94 zkzD#D06zQ|Eu53i-EwlA8G^Z~M0U9TL}k+#lq-E_n)MCp=a9?~ZF@^vKAZ_vYmvo| zLnCJmVP_qy-7$RIncAuKPD}?$3{Fd$|7sYN$sa2G+sN14lL?}Y<QTn_1$=E;HZyx5 z≶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 literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/examples/demo_fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 00000000..0bedcf2f --- /dev/null +++ b/examples/demo_fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/examples/demo_fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/examples/demo_fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/examples/demo_fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/examples/demo_fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 00000000..89c2725b --- /dev/null +++ b/examples/demo_fm/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +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. \ No newline at end of file diff --git a/examples/demo_fm/ios/Runner/Base.lproj/LaunchScreen.storyboard b/examples/demo_fm/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..f2e259c7 --- /dev/null +++ b/examples/demo_fm/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> + <dependencies> + <deployment identifier="iOS"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/> + </dependencies> + <scenes> + <!--View Controller--> + <scene sceneID="EHf-IW-A2E"> + <objects> + <viewController id="01J-lp-oVM" sceneMemberID="viewController"> + <layoutGuides> + <viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/> + <viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/> + </layoutGuides> + <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3"> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4"> + </imageView> + </subviews> + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <constraints> + <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/> + <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/> + </constraints> + </view> + </viewController> + <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="53" y="375"/> + </scene> + </scenes> + <resources> + <image name="LaunchImage" width="168" height="185"/> + </resources> +</document> diff --git a/examples/demo_fm/ios/Runner/Base.lproj/Main.storyboard b/examples/demo_fm/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 00000000..f3c28516 --- /dev/null +++ b/examples/demo_fm/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r"> + <dependencies> + <deployment identifier="iOS"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/> + </dependencies> + <scenes> + <!--Flutter View Controller--> + <scene sceneID="tne-QT-ifu"> + <objects> + <viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController"> + <layoutGuides> + <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/> + <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> + </layoutGuides> + <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> + <rect key="frame" x="0.0" y="0.0" width="600" height="600"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> + </view> + </viewController> + <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> + </objects> + </scene> + </scenes> +</document> diff --git a/examples/demo_fm/ios/Runner/Info.plist b/examples/demo_fm/ios/Runner/Info.plist new file mode 100644 index 00000000..fd8aee7d --- /dev/null +++ b/examples/demo_fm/ios/Runner/Info.plist @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CADisableMinimumFrameDurationOnPhone</key> + <true/> + <key>CFBundleDevelopmentRegion</key> + <string>$(DEVELOPMENT_LANGUAGE)</string> + <key>CFBundleDisplayName</key> + <string>OneSignal Demo</string> + <key>CFBundleExecutable</key> + <string>$(EXECUTABLE_NAME)</string> + <key>CFBundleIdentifier</key> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>demo</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>$(FLUTTER_BUILD_NAME)</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>$(FLUTTER_BUILD_NUMBER)</string> + <key>LSRequiresIPhoneOS</key> + <true/> + <key>NSSupportsLiveActivities</key> + <true/> + <key>NSLocationWhenInUseUsageDescription</key> + <string>This app uses your location to personalize notifications and content.</string> + <key>NSLocationAlwaysAndWhenInUseUsageDescription</key> + <string>This app uses your location to personalize notifications and content, even in the background.</string> + <key>UIApplicationSupportsIndirectInputEvents</key> + <true/> + <key>UIBackgroundModes</key> + <array> + <string>remote-notification</string> + </array> + <key>UILaunchStoryboardName</key> + <string>LaunchScreen</string> + <key>UIMainStoryboardFile</key> + <string>Main</string> + <key>UISupportedInterfaceOrientations</key> + <array> + <string>UIInterfaceOrientationPortrait</string> + <string>UIInterfaceOrientationLandscapeLeft</string> + <string>UIInterfaceOrientationLandscapeRight</string> + </array> + <key>UISupportedInterfaceOrientations~ipad</key> + <array> + <string>UIInterfaceOrientationPortrait</string> + <string>UIInterfaceOrientationPortraitUpsideDown</string> + <string>UIInterfaceOrientationLandscapeLeft</string> + <string>UIInterfaceOrientationLandscapeRight</string> + </array> +</dict> +</plist> diff --git a/examples/demo_fm/ios/Runner/Runner-Bridging-Header.h b/examples/demo_fm/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 00000000..308a2a56 --- /dev/null +++ b/examples/demo_fm/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/examples/demo_fm/ios/Runner/Runner.entitlements b/examples/demo_fm/ios/Runner/Runner.entitlements new file mode 100644 index 00000000..34463649 --- /dev/null +++ b/examples/demo_fm/ios/Runner/Runner.entitlements @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>aps-environment</key> + <string>development</string> + <key>com.apple.security.application-groups</key> + <array> + <string>group.com.onesignal.example.onesignal</string> + </array> +</dict> +</plist> diff --git a/examples/demo_fm/ios/RunnerTests/RunnerTests.swift b/examples/demo_fm/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 00000000..86a7c3b1 --- /dev/null +++ b/examples/demo_fm/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/examples/demo_fm/lib/main.dart b/examples/demo_fm/lib/main.dart new file mode 100644 index 00000000..a36e3e83 --- /dev/null +++ b/examples/demo_fm/lib/main.dart @@ -0,0 +1,156 @@ +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:onesignal_flutter/onesignal_flutter.dart'; +import 'package:provider/provider.dart'; + +import 'screens/home_screen.dart'; +import 'services/onesignal_api_service.dart'; +import 'services/preferences_service.dart'; +import 'services/tooltip_helper.dart'; +import 'theme.dart'; +import 'viewmodels/app_viewmodel.dart'; + +const String _defaultAppId = '77e32082-ea27-42e3-a898-c72e141824ef'; + +// Issue #1138 reproduction: top-level background handler required by FCM. +// On Android, registering ANY FirebaseMessagingService is enough to cause +// FCM (and FlutterFire) to intercept incoming push messages, which is what +// the affected users in #1138 reported alongside the OneSignal click +// listener failure. +@pragma('vm:entry-point') +Future<void> _firebaseBackgroundHandler(RemoteMessage message) async { + await Firebase.initializeApp(); + debugPrint('[FCM bg] received: ${message.messageId} data=${message.data}'); +} + +Future<void> main() async { + WidgetsFlutterBinding.ensureInitialized(); + + try { + await dotenv.load(fileName: '.env'); + } catch (_) { + debugPrint('.env file not found, using defaults'); + } + + // Initialize Firebase + register FCM listeners BEFORE OneSignal so the + // FirebaseMessagingService is registered in the manifest and starts + // intercepting push payloads (matches the affected users' setup). + try { + await Firebase.initializeApp(); + FirebaseMessaging.onBackgroundMessage(_firebaseBackgroundHandler); + FirebaseMessaging.onMessage.listen((RemoteMessage message) { + debugPrint('[FCM fg] received: ${message.messageId} data=${message.data}'); + }); + FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { + debugPrint('[FCM open] tapped: ${message.messageId} data=${message.data}'); + }); + debugPrint('Firebase initialized (issue #1138 repro)'); + } catch (e) { + debugPrint('Firebase init failed (drop google-services.json into android/app): $e'); + } + + final prefs = PreferencesService(); + await prefs.init(); + + final envAppId = dotenv.env['ONESIGNAL_APP_ID']; + final appId = (envAppId != null && envAppId.isNotEmpty) ? envAppId : _defaultAppId; + + // Initialize OneSignal SDK + OneSignal.Debug.setLogLevel(OSLogLevel.verbose); + OneSignal.consentRequired(prefs.consentRequired); + OneSignal.consentGiven(prefs.privacyConsent); + await OneSignal.initialize(appId); + + // Issue #1138 repro: register the click listener as early as possible, + // mirroring the snippet in the bug report. + OneSignal.Notifications.addClickListener((event) { + debugPrint( + '[ISSUE-1138] addClickListener fired: title="${event.notification.title}" ' + 'notifId=${event.notification.notificationId}', + ); + }); + + OneSignal.LiveActivities.setupDefault( + options: LiveActivitySetupOptions( + enablePushToStart: true, + enablePushToUpdate: true, + ), + ); + + // Restore cached SDK states after init fully completes + OneSignal.InAppMessages.paused(prefs.iamPaused); + OneSignal.Location.setShared(prefs.locationShared); + + // Register IAM listeners + OneSignal.InAppMessages.addWillDisplayListener((event) { + debugPrint('IAM will display: ${event.message.messageId}'); + }); + OneSignal.InAppMessages.addDidDisplayListener((event) { + debugPrint('IAM did display: ${event.message.messageId}'); + }); + OneSignal.InAppMessages.addWillDismissListener((event) { + debugPrint('IAM will dismiss: ${event.message.messageId}'); + }); + OneSignal.InAppMessages.addDidDismissListener((event) { + debugPrint('IAM did dismiss: ${event.message.messageId}'); + }); + OneSignal.InAppMessages.addClickListener((event) { + debugPrint('IAM clicked: ${event.result.actionId}'); + }); + + // Register notification listeners (second, "late" listener — kept to verify + // both early and late-registered listeners behave the same for issue #1138). + OneSignal.Notifications.addClickListener((event) { + debugPrint('[ISSUE-1138 late] addClickListener fired: ${event.notification.title}'); + }); + OneSignal.Notifications.addForegroundWillDisplayListener((event) { + debugPrint( + 'Notification foreground will display: ${event.notification.title}', + ); + event.notification.display(); + }); + + // Set up API service + String apiKey = ''; + try { + apiKey = dotenv.env['ONESIGNAL_API_KEY'] ?? ''; + } catch (_) { + debugPrint('API key not found, continuing without it'); + } + final apiService = OneSignalApiService() + ..setAppId(appId) + ..setApiKey(apiKey); + + // Fetch tooltips in background + TooltipHelper().init(); + + debugPrint('OneSignal initialized with app ID: $appId'); + + runApp( + ChangeNotifierProvider( + create: (_) { + final vm = AppViewModel(apiService, prefs); + vm.setupObservers(); + vm.loadInitialState(appId); + return vm; + }, + child: const OneSignalDemoApp(), + ), + ); +} + +class OneSignalDemoApp extends StatelessWidget { + const OneSignalDemoApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'OneSignal Demo', + theme: AppTheme.light, + debugShowCheckedModeBanner: false, + home: const HomeScreen(), + ); + } +} diff --git a/examples/demo_fm/lib/models/in_app_message_type.dart b/examples/demo_fm/lib/models/in_app_message_type.dart new file mode 100644 index 00000000..983acddb --- /dev/null +++ b/examples/demo_fm/lib/models/in_app_message_type.dart @@ -0,0 +1,11 @@ +enum InAppMessageType { + topBanner('Top Banner', 'top_banner'), + bottomBanner('Bottom Banner', 'bottom_banner'), + centerModal('Center Modal', 'center_modal'), + fullScreen('Full Screen', 'full_screen'); + + final String label; + final String triggerValue; + + const InAppMessageType(this.label, this.triggerValue); +} diff --git a/examples/demo_fm/lib/models/notification_type.dart b/examples/demo_fm/lib/models/notification_type.dart new file mode 100644 index 00000000..ddaf3ac3 --- /dev/null +++ b/examples/demo_fm/lib/models/notification_type.dart @@ -0,0 +1,38 @@ +enum NotificationType { + simple( + title: 'Simple Notification', + body: 'This is a simple push notification', + ), + withImage( + title: 'Image Notification', + body: 'This notification includes an image', + bigPicture: + 'https://media.onesignal.com/automated_push_templates/ratings_template.png', + iosAttachments: { + 'image': + 'https://media.onesignal.com/automated_push_templates/ratings_template.png' + }, + ), + withSound( + title: 'Sound Notification', + body: 'This notification plays a custom sound', + iosSound: 'vine_boom.wav', + useAndroidChannel: true, + ); + + final String title; + final String body; + final String? bigPicture; + final Map<String, String>? iosAttachments; + final String? iosSound; + final bool useAndroidChannel; + + const NotificationType({ + required this.title, + required this.body, + this.bigPicture, + this.iosAttachments, + this.iosSound, + this.useAndroidChannel = false, + }); +} diff --git a/examples/demo_fm/lib/models/user_data.dart b/examples/demo_fm/lib/models/user_data.dart new file mode 100644 index 00000000..b03b46d2 --- /dev/null +++ b/examples/demo_fm/lib/models/user_data.dart @@ -0,0 +1,56 @@ +class UserData { + final Map<String, String> aliases; + final Map<String, String> tags; + final List<String> emails; + final List<String> smsNumbers; + final String? externalId; + + const UserData({ + required this.aliases, + required this.tags, + required this.emails, + required this.smsNumbers, + this.externalId, + }); + + factory UserData.fromJson(Map<String, dynamic> json) { + final identity = json['identity'] as Map<String, dynamic>? ?? {}; + final properties = json['properties'] as Map<String, dynamic>? ?? {}; + final subscriptions = json['subscriptions'] as List<dynamic>? ?? []; + final tagsRaw = properties['tags'] as Map<String, dynamic>? ?? {}; + + final aliases = <String, String>{}; + for (final entry in identity.entries) { + if (entry.key != 'external_id' && entry.key != 'onesignal_id') { + aliases[entry.key] = entry.value.toString(); + } + } + + final tags = <String, String>{}; + for (final entry in tagsRaw.entries) { + tags[entry.key] = entry.value.toString(); + } + + final emails = <String>[]; + final smsNumbers = <String>[]; + for (final sub in subscriptions) { + if (sub is Map<String, dynamic>) { + final type = sub['type'] as String?; + final token = sub['token'] as String?; + if (type == 'Email' && token != null) { + emails.add(token); + } else if (type == 'SMS' && token != null) { + smsNumbers.add(token); + } + } + } + + return UserData( + aliases: aliases, + tags: tags, + emails: emails, + smsNumbers: smsNumbers, + externalId: identity['external_id']?.toString(), + ); + } +} diff --git a/examples/demo_fm/lib/screens/home_screen.dart b/examples/demo_fm/lib/screens/home_screen.dart new file mode 100644 index 00000000..20e8894d --- /dev/null +++ b/examples/demo_fm/lib/screens/home_screen.dart @@ -0,0 +1,145 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:provider/provider.dart'; + +import '../theme.dart'; +import '../services/tooltip_helper.dart'; +import '../viewmodels/app_viewmodel.dart'; +import '../widgets/dialogs.dart'; +import '../widgets/sections/aliases_section.dart'; +import '../widgets/sections/app_section.dart'; +import '../widgets/sections/user_section.dart'; +import '../widgets/sections/emails_section.dart'; +import '../widgets/sections/in_app_section.dart'; +import '../widgets/sections/live_activities_section.dart'; +import '../widgets/sections/location_section.dart'; +import '../widgets/sections/outcomes_section.dart'; +import '../widgets/sections/push_section.dart'; +import '../widgets/sections/send_iam_section.dart'; +import '../widgets/sections/send_push_section.dart'; +import '../widgets/sections/sms_section.dart'; +import '../widgets/sections/tags_section.dart'; +import '../widgets/sections/custom_events_section.dart'; +import '../widgets/sections/triggers_section.dart'; +import 'secondary_screen.dart'; + +class HomeScreen extends StatefulWidget { + const HomeScreen({super.key}); + + @override + State<HomeScreen> createState() => _HomeScreenState(); +} + +class _HomeScreenState extends State<HomeScreen> { + @override + void initState() { + super.initState(); + // Auto-prompt push permission after frame renders + WidgetsBinding.instance.addPostFrameCallback((_) { + context.read<AppViewModel>().promptPush(); + }); + } + + void _showTooltipDialog(BuildContext context, String key) { + final tooltip = TooltipHelper().getTooltip(key); + if (tooltip != null) { + showDialog( + context: context, + builder: (_) => TooltipDialog(tooltip: tooltip), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Row( + mainAxisSize: MainAxisSize.min, + children: [ + SvgPicture.asset( + 'assets/onesignal_logo.svg', + height: 22, + colorFilter: const ColorFilter.mode( + Colors.white, + BlendMode.srcIn, + ), + ), + const SizedBox(width: 8), + Text( + 'Flutter', + style: Theme.of( + context, + ).textTheme.bodyMedium?.copyWith(color: Colors.white), + ), + ], + ), + ), + body: Semantics( + identifier: 'main_scroll_view', + child: ListView( + padding: const EdgeInsets.only(bottom: 24), + children: [ + const AppSection(), + const UserSection(), + PushSection(onInfoTap: () => _showTooltipDialog(context, 'push')), + SendPushSection( + onInfoTap: + () => _showTooltipDialog(context, 'sendPushNotification'), + ), + InAppSection( + onInfoTap: () => _showTooltipDialog(context, 'inAppMessaging'), + ), + SendIamSection( + onInfoTap: () => _showTooltipDialog(context, 'sendInAppMessage'), + ), + AliasesSection( + onInfoTap: () => _showTooltipDialog(context, 'aliases'), + ), + EmailsSection( + onInfoTap: () => _showTooltipDialog(context, 'emails'), + ), + SmsSection(onInfoTap: () => _showTooltipDialog(context, 'sms')), + TagsSection(onInfoTap: () => _showTooltipDialog(context, 'tags')), + OutcomesSection( + onInfoTap: () => _showTooltipDialog(context, 'outcomes'), + ), + TriggersSection( + onInfoTap: () => _showTooltipDialog(context, 'triggers'), + ), + CustomEventsSection( + onInfoTap: () => _showTooltipDialog(context, 'customEvents'), + ), + LocationSection( + onInfoTap: () => _showTooltipDialog(context, 'location'), + ), + if (defaultTargetPlatform == TargetPlatform.iOS) + LiveActivitiesSection( + onInfoTap: () => _showTooltipDialog(context, 'liveActivities'), + ), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute(builder: (_) => const SecondaryScreen()), + ); + }, + style: ElevatedButton.styleFrom( + backgroundColor: AppColors.osPrimary, + foregroundColor: Colors.white, + ), + child: const Text('NEXT SCREEN'), + ), + ), + const SizedBox(height: 16), + ], + ), + ), + ); + } +} diff --git a/examples/demo_fm/lib/screens/secondary_screen.dart b/examples/demo_fm/lib/screens/secondary_screen.dart new file mode 100644 index 00000000..d6232e1f --- /dev/null +++ b/examples/demo_fm/lib/screens/secondary_screen.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; + +class SecondaryScreen extends StatelessWidget { + const SecondaryScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Secondary Screen'), + centerTitle: true, + ), + body: Center( + child: Text( + 'Secondary Screen', + style: Theme.of(context).textTheme.headlineMedium, + ), + ), + ); + } +} diff --git a/examples/demo_fm/lib/services/onesignal_api_service.dart b/examples/demo_fm/lib/services/onesignal_api_service.dart new file mode 100644 index 00000000..7fe8ea46 --- /dev/null +++ b/examples/demo_fm/lib/services/onesignal_api_service.dart @@ -0,0 +1,218 @@ +import 'dart:convert'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:http/http.dart' as http; + +import '../models/notification_type.dart'; +import '../models/user_data.dart'; + +const String _defaultAndroidChannelId = 'b3b015d9-c050-4042-8548-dcc34aa44aa4'; + +String _resolveAndroidChannelId() { + String? envValue; + try { + envValue = dotenv.env['ONESIGNAL_ANDROID_CHANNEL_ID']?.trim(); + } catch (_) { + envValue = null; + } + return (envValue != null && envValue.isNotEmpty) + ? envValue + : _defaultAndroidChannelId; +} + +class OneSignalApiService { + String _appId = ''; + String _apiKey = ''; + + void setAppId(String appId) => _appId = appId; + String get appId => _appId; + + void setApiKey(String apiKey) => _apiKey = apiKey; + bool hasApiKey() => _apiKey.isNotEmpty && _apiKey != 'your_rest_api_key'; + + Future<bool> sendNotification( + NotificationType type, + String subscriptionId, + ) async { + final body = <String, dynamic>{ + 'app_id': _appId, + 'include_subscription_ids': [subscriptionId], + 'headings': {'en': type.title}, + 'contents': {'en': type.body}, + }; + if (type.bigPicture != null) { + body['big_picture'] = type.bigPicture; + } + if (type.iosAttachments != null) { + body['ios_attachments'] = type.iosAttachments; + } + if (type.iosSound != null) { + body['ios_sound'] = type.iosSound; + } + if (type.useAndroidChannel) { + body['android_channel_id'] = _resolveAndroidChannelId(); + } + + return _postNotification(body); + } + + Future<bool> sendCustomNotification( + String title, + String body, + String subscriptionId, + ) async { + final payload = <String, dynamic>{ + 'app_id': _appId, + 'include_subscription_ids': [subscriptionId], + 'headings': {'en': title}, + 'contents': {'en': body}, + }; + + return _postNotification(payload); + } + + Future<bool> _postNotification(Map<String, dynamic> payload) async { + const maxAttempts = 5; + int backoffMs(int n) => 2000 * (1 << (n - 1)); + + // Retry while the OneSignal backend hasn't yet indexed the freshly + // created subscription. The /notifications endpoint reports this race in a + // few different shapes, all of which return HTTP 200: + // - {"id":"...","recipients":0} (user just switched, push token not yet attached) + // - {"id":"...","errors":{"invalid_player_ids":[...]}} + // - {"id":"","errors":["All included players are not subscribed"]} + // - {"id":"","errors":[...]} + // Treat any 200 response with no real id, populated errors, or recipients=0 as transient. + for (var attempt = 1; attempt <= maxAttempts; attempt++) { + try { + final response = await http.post( + Uri.parse('https://onesignal.com/api/v1/notifications'), + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/vnd.onesignal.v1+json', + }, + body: jsonEncode(payload), + ); + + if (response.statusCode < 200 || response.statusCode >= 300) { + debugPrint('Send notification failed: ${response.body}'); + return false; + } + + final decoded = jsonDecode(response.body); + if (_isTransientSendFailure(decoded)) { + if (attempt < maxAttempts) { + await Future<void>.delayed(Duration(milliseconds: backoffMs(attempt))); + continue; + } + debugPrint('Send notification failed: ${response.body}'); + return false; + } + + return true; + } catch (e) { + debugPrint('Send notification error: $e'); + return false; + } + } + + return false; + } + + bool _isTransientSendFailure(dynamic decoded) { + if (decoded is! Map<String, dynamic>) return false; + final id = decoded['id']; + final errors = decoded['errors']; + final recipients = decoded['recipients']; + final hasErrors = + (errors is List && errors.isNotEmpty) || + (errors is Map && errors.isNotEmpty); + final missingId = id is! String || id.isEmpty; + final zeroRecipients = recipients is num && recipients == 0; + return hasErrors || missingId || zeroRecipients; + } + + Future<bool> updateLiveActivity( + String activityId, + Map<String, dynamic> eventUpdates, + ) async { + try { + final response = await http.post( + Uri.parse( + 'https://api.onesignal.com/apps/$_appId/live_activities/$activityId/notifications', + ), + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Key $_apiKey', + }, + body: jsonEncode({ + 'event': 'update', + 'event_updates': eventUpdates, + 'name': 'live_activity_update', + 'priority': 10, + }), + ); + + debugPrint( + 'Update live activity response: ${response.statusCode} ${response.body}', + ); + return response.statusCode >= 200 && response.statusCode < 300; + } catch (e) { + debugPrint('Update live activity error: $e'); + return false; + } + } + + Future<bool> endLiveActivity(String activityId) async { + try { + final dismissalDate = + DateTime.now().add(const Duration(seconds: 5)).millisecondsSinceEpoch ~/ + 1000; + final response = await http.post( + Uri.parse( + 'https://api.onesignal.com/apps/$_appId/live_activities/$activityId/notifications', + ), + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Key $_apiKey', + }, + body: jsonEncode({ + 'event': 'end', + 'event_updates': {'message': 'Ended'}, + 'dismissal_date': dismissalDate, + 'name': 'live_activity_end', + }), + ); + + debugPrint( + 'End live activity response: ${response.statusCode} ${response.body}', + ); + return response.statusCode >= 200 && response.statusCode < 300; + } catch (e) { + debugPrint('End live activity error: $e'); + return false; + } + } + + Future<UserData?> fetchUser(String onesignalId) async { + try { + final url = + 'https://api.onesignal.com/apps/$_appId/users/by/onesignal_id/$onesignalId'; + final response = await http.get( + Uri.parse(url), + headers: {'Accept': 'application/json'}, + ); + + if (response.statusCode == 200) { + final json = jsonDecode(response.body) as Map<String, dynamic>; + return UserData.fromJson(json); + } + debugPrint('Fetch user returned ${response.statusCode}'); + return null; + } catch (e) { + debugPrint('Fetch user error: $e'); + return null; + } + } +} diff --git a/examples/demo_fm/lib/services/preferences_service.dart b/examples/demo_fm/lib/services/preferences_service.dart new file mode 100644 index 00000000..7fe89283 --- /dev/null +++ b/examples/demo_fm/lib/services/preferences_service.dart @@ -0,0 +1,42 @@ +import 'package:shared_preferences/shared_preferences.dart'; + +class PreferencesService { + static const _keyConsentRequired = 'consent_required'; + static const _keyPrivacyConsent = 'privacy_consent'; + static const _keyExternalUserId = 'external_user_id'; + static const _keyLocationShared = 'location_shared'; + static const _keyIamPaused = 'iam_paused'; + + late final SharedPreferences _prefs; + + Future<void> init() async { + _prefs = await SharedPreferences.getInstance(); + } + + // Consent required + bool get consentRequired => _prefs.getBool(_keyConsentRequired) ?? false; + Future<void> setConsentRequired(bool value) => + _prefs.setBool(_keyConsentRequired, value); + + // Privacy consent + bool get privacyConsent => _prefs.getBool(_keyPrivacyConsent) ?? false; + Future<void> setPrivacyConsent(bool value) => + _prefs.setBool(_keyPrivacyConsent, value); + + // External user ID + String? get externalUserId => _prefs.getString(_keyExternalUserId); + Future<void> setExternalUserId(String? value) { + if (value == null) return _prefs.remove(_keyExternalUserId); + return _prefs.setString(_keyExternalUserId, value); + } + + // Location shared + bool get locationShared => _prefs.getBool(_keyLocationShared) ?? false; + Future<void> setLocationShared(bool value) => + _prefs.setBool(_keyLocationShared, value); + + // In-app messaging paused + bool get iamPaused => _prefs.getBool(_keyIamPaused) ?? false; + Future<void> setIamPaused(bool value) => + _prefs.setBool(_keyIamPaused, value); +} diff --git a/examples/demo_fm/lib/services/tooltip_helper.dart b/examples/demo_fm/lib/services/tooltip_helper.dart new file mode 100644 index 00000000..664f8121 --- /dev/null +++ b/examples/demo_fm/lib/services/tooltip_helper.dart @@ -0,0 +1,74 @@ +import 'dart:convert'; + +import 'package:flutter/foundation.dart'; +import 'package:http/http.dart' as http; + +class TooltipData { + final String title; + final String description; + final List<TooltipOption>? options; + + const TooltipData({ + required this.title, + required this.description, + this.options, + }); +} + +class TooltipOption { + final String name; + final String description; + + const TooltipOption({required this.name, required this.description}); +} + +class TooltipHelper { + static final TooltipHelper _instance = TooltipHelper._internal(); + factory TooltipHelper() => _instance; + TooltipHelper._internal(); + + Map<String, TooltipData> _tooltips = {}; + bool _initialized = false; + + static const _tooltipUrl = + 'https://raw.githubusercontent.com/OneSignal/sdk-shared/main/demo/tooltip_content.json'; + + Future<void> init() async { + if (_initialized) return; + + try { + final response = await http.get(Uri.parse(_tooltipUrl)); + if (response.statusCode == 200) { + final json = jsonDecode(response.body) as Map<String, dynamic>; + _tooltips = json.map((key, value) { + final data = value as Map<String, dynamic>; + List<TooltipOption>? options; + if (data['options'] != null) { + options = (data['options'] as List<dynamic>).map((o) { + final opt = o as Map<String, dynamic>; + return TooltipOption( + name: opt['name'] as String? ?? '', + description: opt['description'] as String? ?? '', + ); + }).toList(); + } + return MapEntry( + key, + TooltipData( + title: data['title'] as String? ?? key, + description: data['description'] as String? ?? '', + options: options, + ), + ); + }); + debugPrint('Loaded ${_tooltips.length} tooltips'); + } + } catch (e) { + debugPrint('Failed to load tooltips: $e'); + } + + _initialized = true; + } + + TooltipData? getTooltip(String key) => _tooltips[key]; +} diff --git a/examples/demo_fm/lib/theme.dart b/examples/demo_fm/lib/theme.dart new file mode 100644 index 00000000..60d10b72 --- /dev/null +++ b/examples/demo_fm/lib/theme.dart @@ -0,0 +1,125 @@ +import 'package:flutter/material.dart'; + +class AppSpacing { + static const double gap = 8; + static const gapBox = SizedBox(height: gap); + static const cardPadding = EdgeInsets.symmetric(horizontal: 12, vertical: 12); + + AppSpacing._(); +} + +class AppColors { + static const osPrimary = Color(0xFFE54B4D); + static const osSuccess = Color(0xFF34A853); + static const osGrey700 = Color(0xFF616161); + static const osGrey600 = Color(0xFF757575); + static const osGrey500 = Color(0xFF9E9E9E); + static const osLightBackground = Color(0xFFF8F9FA); + static const osCardBackground = Colors.white; + static const osCardBorder = Color(0x1A000000); // rgba(0, 0, 0, 0.1) + static const osDivider = Color(0xFFE8EAED); + static const osWarningBackground = Color(0xFFFFF8E1); + static const osBackdrop = Color(0x8A000000); + static const osLogBackground = Color(0xFF1A1B1E); + static const osLogDebug = Color(0xFF82AAFF); + static const osLogInfo = Color(0xFFC3E88D); + static const osLogWarn = Color(0xFFFFCB6B); + static const osLogError = Color(0xFFFF5370); + static const osLogTimestamp = Color(0xFF676E7B); + AppColors._(); +} + +class AppTheme { + static ThemeData get light { + return ThemeData( + useMaterial3: true, + colorScheme: ColorScheme.fromSeed( + seedColor: AppColors.osPrimary, + ).copyWith(primary: AppColors.osPrimary), + scaffoldBackgroundColor: AppColors.osLightBackground, + appBarTheme: const AppBarTheme( + backgroundColor: AppColors.osPrimary, + foregroundColor: Colors.white, + elevation: 2, + scrolledUnderElevation: 2, + shadowColor: Colors.black, + ), + cardTheme: CardThemeData( + color: AppColors.osCardBackground, + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + side: const BorderSide( + color: AppColors.osCardBorder, + width: 2, + ), + ), + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), + ), + elevatedButtonTheme: ElevatedButtonThemeData( + style: ElevatedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + minimumSize: const Size(double.infinity, 48), + textStyle: const TextStyle(fontWeight: FontWeight.w600), + ), + ), + outlinedButtonTheme: OutlinedButtonThemeData( + style: OutlinedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + minimumSize: const Size(double.infinity, 48), + textStyle: const TextStyle(fontWeight: FontWeight.w600), + ), + ), + textButtonTheme: TextButtonThemeData( + style: TextButton.styleFrom( + disabledForegroundColor: AppColors.osGrey500, + ), + ), + dialogTheme: const DialogThemeData( + backgroundColor: Colors.white, + ), + dividerColor: AppColors.osDivider, + inputDecorationTheme: InputDecorationTheme( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: const BorderSide(color: AppColors.osGrey700), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: const BorderSide(color: AppColors.osGrey700), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: const BorderSide(color: AppColors.osPrimary, width: 2), + ), + hintStyle: const TextStyle(color: AppColors.osGrey600), + contentPadding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 14, + ), + ), + ); + } + + AppTheme._(); +} + +const Duration _toastDuration = Duration(seconds: 3); + +extension AppSnackBar on BuildContext { + void showSnackBar(String message) { + ScaffoldMessenger.of(this) + ..hideCurrentSnackBar() + ..showSnackBar( + SnackBar( + content: Text(message), + duration: _toastDuration, + dismissDirection: DismissDirection.horizontal, + ), + ); + } +} diff --git a/examples/demo_fm/lib/viewmodels/app_viewmodel.dart b/examples/demo_fm/lib/viewmodels/app_viewmodel.dart new file mode 100644 index 00000000..18f7a086 --- /dev/null +++ b/examples/demo_fm/lib/viewmodels/app_viewmodel.dart @@ -0,0 +1,564 @@ +import 'package:flutter/foundation.dart'; +import 'package:onesignal_flutter/onesignal_flutter.dart'; + +import '../models/in_app_message_type.dart'; +import '../models/notification_type.dart'; +import '../services/onesignal_api_service.dart'; +import '../services/preferences_service.dart'; + +List<MapEntry<String, String>> _mergePairs( + List<MapEntry<String, String>> prev, + Map<String, String> next, +) { + final merged = <String, String>{ + for (final e in prev) e.key: e.value, + ...next, + }; + return merged.entries.toList(); +} + +List<T> _mergeUnique<T>(List<T> prev, List<T> next) => + {...prev, ...next}.toList(); + +class AppViewModel extends ChangeNotifier { + final OneSignalApiService _apiService; + final PreferencesService _prefs; + + AppViewModel(this._apiService, this._prefs); + + static const _orderStatuses = [ + { + 'status': 'preparing', + 'message': 'Your order is being prepared', + 'estimatedTime': '15 min', + }, + { + 'status': 'on_the_way', + 'message': 'Driver is heading your way', + 'estimatedTime': '10 min', + }, + {'status': 'delivered', 'message': 'Order delivered!', 'estimatedTime': ''}, + ]; + + // Loading state + bool _isLoading = false; + bool get isLoading => _isLoading; + + // Increments per fetchUserDataFromApi() call so stale results are dropped + // when a newer fetch is already in flight (e.g. cold-start fetch racing the + // user-change observer's fetch right after login). + int _fetchSequence = 0; + + // App state + String _appId = ''; + String get appId => _appId; + + bool _consentRequired = false; + bool get consentRequired => _consentRequired; + + bool _privacyConsentGiven = false; + bool get privacyConsentGiven => _privacyConsentGiven; + + String? _externalUserId; + String? get externalUserId => _externalUserId; + + bool get isLoggedIn => _externalUserId != null; + + String? _oneSignalId; + String? get oneSignalId => _oneSignalId; + + // Push state + String? _pushSubscriptionId; + // The native bridge can hand back an empty string before the subscription + // id is provisioned. Treat that as "no id yet" so the UI's `?? '—'` + // fallback renders the placeholder instead of an empty cell. + String? get pushSubscriptionId => + (_pushSubscriptionId?.isEmpty ?? true) ? null : _pushSubscriptionId; + + bool _pushEnabled = false; + bool get pushEnabled => _pushEnabled; + + bool _hasNotificationPermission = false; + bool get hasNotificationPermission => _hasNotificationPermission; + + // IAM state + bool _iamPaused = false; + bool get iamPaused => _iamPaused; + + // Location state + bool _locationShared = false; + bool get locationShared => _locationShared; + + // Live Activity state + String _activityId = 'order-1'; + String get activityId => _activityId; + + String _orderNumber = 'ORD-1234'; + String get orderNumber => _orderNumber; + + int _statusIndex = 0; + + bool _isLaUpdating = false; + bool get isLaUpdating => _isLaUpdating; + + bool get hasApiKey => _apiService.hasApiKey(); + + String get nextStatusLabel { + final nextIndex = (_statusIndex + 1) % _orderStatuses.length; + final status = _orderStatuses[nextIndex]['status']!; + return status.toUpperCase().replaceAll('_', ' '); + } + + // Data lists + List<MapEntry<String, String>> _aliasesList = []; + List<MapEntry<String, String>> get aliasesList => + List.unmodifiable(_aliasesList); + + List<String> _emailsList = []; + List<String> get emailsList => List.unmodifiable(_emailsList); + + List<String> _smsNumbersList = []; + List<String> get smsNumbersList => List.unmodifiable(_smsNumbersList); + + List<MapEntry<String, String>> _tagsList = []; + List<MapEntry<String, String>> get tagsList => List.unmodifiable(_tagsList); + + List<MapEntry<String, String>> _triggersList = []; + List<MapEntry<String, String>> get triggersList => + List.unmodifiable(_triggersList); + + // Initialize + Future<void> loadInitialState(String appId) async { + _appId = appId; + + _consentRequired = _prefs.consentRequired; + _privacyConsentGiven = _prefs.privacyConsent; + _externalUserId = _prefs.externalUserId; + + _iamPaused = _prefs.iamPaused; + _locationShared = _prefs.locationShared; + + if (_externalUserId != null) { + OneSignal.login(_externalUserId!); + } + + _pushSubscriptionId = OneSignal.User.pushSubscription.id; + _pushEnabled = OneSignal.User.pushSubscription.optedIn ?? false; + _hasNotificationPermission = OneSignal.Notifications.permission; + + final onesignalId = await OneSignal.User.getOnesignalId(); + _oneSignalId = onesignalId; + + notifyListeners(); + + if (onesignalId == null) return; + + // fetchUserDataFromApi owns _isLoading + notifyListeners. + await fetchUserDataFromApi(); + } + + // Observers + void setupObservers() { + OneSignal.User.pushSubscription.addObserver((state) { + _pushSubscriptionId = state.current.id; + _pushEnabled = state.current.optedIn; + debugPrint( + 'Push subscription changed: id=${state.current.id}, optedIn=${state.current.optedIn}', + ); + notifyListeners(); + }); + + OneSignal.Notifications.addPermissionObserver((permission) { + _hasNotificationPermission = permission; + debugPrint('Permission changed: $permission'); + notifyListeners(); + }); + + OneSignal.User.addObserver((state) { + final nextOnesignalId = state.current.onesignalId; + debugPrint( + 'User changed: onesignalId=${nextOnesignalId ?? 'null'}, externalId=${state.current.externalId ?? 'null'}', + ); + + _oneSignalId = nextOnesignalId; + notifyListeners(); + + // Drive the post-login fetch from the observer so it runs only once the + // SDK has actually assigned a new onesignalId. Logout clears it to null; + // skip the fetch in that case (logoutUser already clears local lists). + if (nextOnesignalId == null) return; + fetchUserDataFromApi(); + }); + } + + // Fetch user data from API. Owns the isLoading toggle and uses a + // request-sequence guard so stale results are dropped if a newer fetch + // started before this one finishes. + Future<void> fetchUserDataFromApi() async { + final requestId = ++_fetchSequence; + _isLoading = true; + notifyListeners(); + + try { + final onesignalId = await OneSignal.User.getOnesignalId(); + if (onesignalId == null) return; + + final userData = await _apiService.fetchUser(onesignalId); + if (userData == null) return; + + if (_fetchSequence != requestId) return; + + _aliasesList = _mergePairs(_aliasesList, userData.aliases); + _tagsList = _mergePairs(_tagsList, userData.tags); + _emailsList = _mergeUnique(_emailsList, userData.emails); + _smsNumbersList = _mergeUnique(_smsNumbersList, userData.smsNumbers); + + if (userData.externalId != null) { + _externalUserId = userData.externalId; + await _prefs.setExternalUserId(userData.externalId); + } + } catch (e) { + debugPrint('fetchUserDataFromApi error: $e'); + } finally { + if (_fetchSequence == requestId) { + _isLoading = false; + } + notifyListeners(); + } + } + + // Login / Logout + Future<void> loginUser(String externalUserId) async { + _aliasesList = []; + _emailsList = []; + _smsNumbersList = []; + _tagsList = []; + _triggersList = []; + _externalUserId = externalUserId; + _isLoading = true; + notifyListeners(); + + try { + await OneSignal.login(externalUserId); + await _prefs.setExternalUserId(externalUserId); + debugPrint('Logged in as: $externalUserId'); + // The User observer runs fetchUserDataFromApi once the new onesignalId + // is assigned; that call clears _isLoading in its finally. + } catch (e) { + debugPrint('Login error: $e'); + _isLoading = false; + notifyListeners(); + } + } + + Future<void> logoutUser() async { + _externalUserId = null; + _aliasesList = []; + _emailsList = []; + _smsNumbersList = []; + _tagsList = []; + _triggersList = []; + notifyListeners(); + + try { + await OneSignal.logout(); + await _prefs.setExternalUserId(null); + debugPrint('Logged out'); + } catch (e) { + debugPrint('Logout error: $e'); + } + } + + // Consent + Future<void> setConsentRequired(bool value) async { + _consentRequired = value; + OneSignal.consentRequired(value); + await _prefs.setConsentRequired(value); + if (!value) { + _privacyConsentGiven = false; + await _prefs.setPrivacyConsent(false); + } + notifyListeners(); + } + + Future<void> setPrivacyConsent(bool value) async { + _privacyConsentGiven = value; + OneSignal.consentGiven(value); + await _prefs.setPrivacyConsent(value); + notifyListeners(); + } + + // Push + void togglePush(bool enabled) { + if (enabled) { + OneSignal.User.pushSubscription.optIn(); + } else { + OneSignal.User.pushSubscription.optOut(); + } + _pushEnabled = enabled; + notifyListeners(); + debugPrint('Push ${enabled ? "enabled" : "disabled"}'); + } + + Future<void> promptPush() => OneSignal.Notifications.requestPermission(true); + + // Notifications + Future<void> sendNotification(NotificationType type) async { + final subscriptionId = OneSignal.User.pushSubscription.id; + if (subscriptionId == null) { + debugPrint('No subscription ID for notification'); + return; + } + final success = await _apiService.sendNotification(type, subscriptionId); + if (success) { + debugPrint('Notification sent: ${type.name}'); + } else { + debugPrint('Failed to send notification'); + } + } + + Future<void> sendCustomNotification(String title, String body) async { + final subscriptionId = OneSignal.User.pushSubscription.id; + if (subscriptionId == null) { + debugPrint('No subscription ID for custom notification'); + return; + } + final success = await _apiService.sendCustomNotification( + title, + body, + subscriptionId, + ); + if (success) { + debugPrint('Custom notification sent'); + } else { + debugPrint('Failed to send notification'); + } + } + + void clearAllNotifications() { + OneSignal.Notifications.clearAll(); + debugPrint('All notifications cleared'); + } + + // IAM + Future<void> setIamPaused(bool paused) async { + _iamPaused = paused; + OneSignal.InAppMessages.paused(paused); + await _prefs.setIamPaused(paused); + notifyListeners(); + } + + void sendInAppMessage(InAppMessageType type) { + OneSignal.InAppMessages.addTrigger('iam_type', type.triggerValue); + _triggersList = _mergePairs(_triggersList, {'iam_type': type.triggerValue}); + notifyListeners(); + debugPrint('Sent In-App Message: ${type.label}'); + } + + // Aliases + void addAlias(String label, String id) { + OneSignal.User.addAlias(label, id); + _aliasesList = _mergePairs(_aliasesList, {label: id}); + notifyListeners(); + debugPrint('Alias added: $label'); + } + + void addAliases(Map<String, String> aliases) { + OneSignal.User.addAliases(aliases); + _aliasesList = _mergePairs(_aliasesList, aliases); + notifyListeners(); + debugPrint('${aliases.length} alias(es) added'); + } + + // Emails + void addEmail(String email) { + OneSignal.User.addEmail(email); + _emailsList = _mergeUnique(_emailsList, [email]); + notifyListeners(); + debugPrint('Email added: $email'); + } + + void removeEmail(String email) { + OneSignal.User.removeEmail(email); + _emailsList = List.from(_emailsList)..remove(email); + notifyListeners(); + debugPrint('Email removed: $email'); + } + + // SMS + void addSms(String smsNumber) { + OneSignal.User.addSms(smsNumber); + _smsNumbersList = _mergeUnique(_smsNumbersList, [smsNumber]); + notifyListeners(); + debugPrint('SMS added: $smsNumber'); + } + + void removeSms(String smsNumber) { + OneSignal.User.removeSms(smsNumber); + _smsNumbersList = List.from(_smsNumbersList)..remove(smsNumber); + notifyListeners(); + debugPrint('SMS removed: $smsNumber'); + } + + // Tags + void addTag(String key, String value) { + OneSignal.User.addTagWithKey(key, value); + _tagsList = _mergePairs(_tagsList, {key: value}); + notifyListeners(); + debugPrint('Tag added: $key'); + } + + void addTags(Map<String, String> tags) { + OneSignal.User.addTags(tags); + _tagsList = _mergePairs(_tagsList, tags); + notifyListeners(); + debugPrint('${tags.length} tag(s) added'); + } + + void removeTag(String key) { + OneSignal.User.removeTag(key); + _tagsList = List.from(_tagsList)..removeWhere((e) => e.key == key); + notifyListeners(); + debugPrint('Tag removed: $key'); + } + + void removeSelectedTags(List<String> keys) { + OneSignal.User.removeTags(keys); + _tagsList = List.from(_tagsList)..removeWhere((e) => keys.contains(e.key)); + notifyListeners(); + debugPrint('${keys.length} tag(s) removed'); + } + + // Triggers (in-memory only) + void addTrigger(String key, String value) { + OneSignal.InAppMessages.addTrigger(key, value); + _triggersList = _mergePairs(_triggersList, {key: value}); + notifyListeners(); + debugPrint('Trigger added: $key'); + } + + void addTriggers(Map<String, String> triggers) { + OneSignal.InAppMessages.addTriggers(triggers); + _triggersList = _mergePairs(_triggersList, triggers); + notifyListeners(); + debugPrint('${triggers.length} trigger(s) added'); + } + + void removeTrigger(String key) { + OneSignal.InAppMessages.removeTrigger(key); + _triggersList = List.from(_triggersList)..removeWhere((e) => e.key == key); + notifyListeners(); + debugPrint('Trigger removed: $key'); + } + + void removeSelectedTriggers(List<String> keys) { + OneSignal.InAppMessages.removeTriggers(keys); + _triggersList = List.from(_triggersList) + ..removeWhere((e) => keys.contains(e.key)); + notifyListeners(); + debugPrint('${keys.length} trigger(s) removed'); + } + + void clearAllTriggers() { + OneSignal.InAppMessages.clearTriggers(); + _triggersList = []; + notifyListeners(); + debugPrint('All triggers cleared'); + } + + // Outcomes + void sendOutcome(String name) { + OneSignal.Session.addOutcome(name); + debugPrint('Outcome sent: $name'); + } + + void sendUniqueOutcome(String name) { + OneSignal.Session.addUniqueOutcome(name); + debugPrint('Unique outcome sent: $name'); + } + + void sendOutcomeWithValue(String name, double value) { + OneSignal.Session.addOutcomeWithValue(name, value); + debugPrint('Outcome sent: $name = $value'); + } + + // Custom Events + void trackEvent(String name, Map<String, dynamic>? properties) { + OneSignal.User.trackEvent(name, properties); + debugPrint('Event tracked: $name'); + } + + // Live Activities + void setActivityId(String id) { + _activityId = id; + notifyListeners(); + } + + void setOrderNumber(String number) { + _orderNumber = number; + notifyListeners(); + } + + Future<void> startLiveActivity() async { + final attributes = {'orderNumber': _orderNumber}; + final content = Map<String, dynamic>.from(_orderStatuses[0]); + _statusIndex = 0; + await OneSignal.LiveActivities.startDefault( + _activityId, + attributes, + content, + ); + notifyListeners(); + debugPrint('Started Live Activity: $_activityId'); + } + + Future<void> updateLiveActivity() async { + _isLaUpdating = true; + notifyListeners(); + + final nextIndex = (_statusIndex + 1) % _orderStatuses.length; + final content = Map<String, dynamic>.from(_orderStatuses[nextIndex]); + final eventUpdates = {'data': content}; + final success = await _apiService.updateLiveActivity( + _activityId, + eventUpdates, + ); + + _isLaUpdating = false; + if (success) { + _statusIndex = nextIndex; + debugPrint('Updated Live Activity: $_activityId'); + } else { + debugPrint('Failed to update Live Activity'); + } + notifyListeners(); + } + + Future<void> endLiveActivity() async { + final success = await _apiService.endLiveActivity(_activityId); + if (success) { + _statusIndex = 0; + debugPrint('Ended Live Activity: $_activityId'); + } else { + debugPrint('Failed to end Live Activity'); + } + notifyListeners(); + } + + // Location + Future<void> setLocationShared(bool shared) async { + _locationShared = shared; + OneSignal.Location.setShared(shared); + await _prefs.setLocationShared(shared); + notifyListeners(); + debugPrint('Location sharing ${shared ? "enabled" : "disabled"}'); + } + + void promptLocation() { + OneSignal.Location.requestPermission(); + } + + Future<bool> checkLocationShared() async { + return await OneSignal.Location.isShared(); + } +} diff --git a/examples/demo_fm/lib/widgets/action_button.dart b/examples/demo_fm/lib/widgets/action_button.dart new file mode 100644 index 00000000..9222f81c --- /dev/null +++ b/examples/demo_fm/lib/widgets/action_button.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; + +import '../theme.dart'; + +class PrimaryButton extends StatelessWidget { + final String label; + final VoidCallback? onPressed; + final IconData? icon; + final String? semanticsLabel; + + const PrimaryButton({ + super.key, + required this.label, + this.onPressed, + this.icon, + this.semanticsLabel, + }); + + @override + Widget build(BuildContext context) { + Widget button = SizedBox( + width: double.infinity, + child: ElevatedButton( + onPressed: onPressed, + style: ElevatedButton.styleFrom( + backgroundColor: AppColors.osPrimary, + foregroundColor: Colors.white, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (icon != null) ...[ + Icon(icon, size: 18), + const SizedBox(width: 8), + ], + Text(label), + ], + ), + ), + ); + if (semanticsLabel != null) { + button = Semantics(identifier: semanticsLabel, container: true, child: button); + } + return button; + } +} + +class DestructiveButton extends StatelessWidget { + final String label; + final VoidCallback? onPressed; + final String? semanticsLabel; + + const DestructiveButton({ + super.key, + required this.label, + this.onPressed, + this.semanticsLabel, + }); + + @override + Widget build(BuildContext context) { + Widget button = SizedBox( + width: double.infinity, + child: OutlinedButton( + onPressed: onPressed, + style: OutlinedButton.styleFrom( + foregroundColor: AppColors.osPrimary, + side: const BorderSide(color: AppColors.osPrimary), + ), + child: Text(label), + ), + ); + if (semanticsLabel != null) { + button = Semantics(identifier: semanticsLabel, container: true, child: button); + } + return button; + } +} diff --git a/examples/demo_fm/lib/widgets/app_text_field.dart b/examples/demo_fm/lib/widgets/app_text_field.dart new file mode 100644 index 00000000..1e541f52 --- /dev/null +++ b/examples/demo_fm/lib/widgets/app_text_field.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; + +class AppTextField extends TextField { + const AppTextField({ + super.key, + super.controller, + super.decoration, + super.keyboardType, + super.onChanged, + super.textAlign, + super.style, + super.maxLines, + super.autocorrect = false, + super.enableSuggestions = false, + super.smartQuotesType = SmartQuotesType.disabled, + super.smartDashesType = SmartDashesType.disabled, + }); +} diff --git a/examples/demo_fm/lib/widgets/dialogs.dart b/examples/demo_fm/lib/widgets/dialogs.dart new file mode 100644 index 00000000..10ad3233 --- /dev/null +++ b/examples/demo_fm/lib/widgets/dialogs.dart @@ -0,0 +1,782 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; + +import '../services/tooltip_helper.dart'; +import '../theme.dart'; +import 'app_text_field.dart'; + +// Single input dialog (login, email, sms) +class SingleInputDialog extends StatefulWidget { + final String title; + final String fieldLabel; + final String confirmLabel; + final TextInputType keyboardType; + final String? semanticsLabel; + + const SingleInputDialog({ + super.key, + required this.title, + required this.fieldLabel, + this.confirmLabel = 'Add', + this.keyboardType = TextInputType.text, + this.semanticsLabel, + }); + + @override + State<SingleInputDialog> createState() => _SingleInputDialogState(); +} + +class _SingleInputDialogState extends State<SingleInputDialog> { + final _controller = TextEditingController(); + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + insetPadding: const EdgeInsets.symmetric(horizontal: 16), + title: Text(widget.title), + content: SizedBox( + width: double.maxFinite, + child: Semantics( + identifier: widget.semanticsLabel ?? '${widget.fieldLabel}_input', + container: true, + child: AppTextField( + controller: _controller, + decoration: InputDecoration(labelText: widget.fieldLabel), + keyboardType: widget.keyboardType, + onChanged: (_) => setState(() {}), + ), + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Cancel'), + ), + Semantics( + identifier: 'singleinput_confirm_button', + container: true, + button: true, + child: TextButton( + onPressed: _controller.text.isEmpty + ? null + : () => Navigator.pop(context, _controller.text), + child: Text(widget.confirmLabel), + ), + ), + ], + ); + } +} + +// Key-value pair input dialog (single pair) +class PairInputDialog extends StatefulWidget { + final String title; + final String keyLabel; + final String valueLabel; + final String? keySemanticsLabel; + final String? valueSemanticsLabel; + + const PairInputDialog({ + super.key, + required this.title, + this.keyLabel = 'Key', + this.valueLabel = 'Value', + this.keySemanticsLabel, + this.valueSemanticsLabel, + }); + + @override + State<PairInputDialog> createState() => _PairInputDialogState(); +} + +class _PairInputDialogState extends State<PairInputDialog> { + final _keyController = TextEditingController(); + final _valueController = TextEditingController(); + + @override + void dispose() { + _keyController.dispose(); + _valueController.dispose(); + super.dispose(); + } + + bool get _isValid => + _keyController.text.isNotEmpty && _valueController.text.isNotEmpty; + + @override + Widget build(BuildContext context) { + return AlertDialog( + insetPadding: const EdgeInsets.symmetric(horizontal: 16), + title: Text(widget.title), + content: SizedBox( + width: double.maxFinite, + child: Row( + children: [ + Expanded( + child: Semantics( + identifier: widget.keySemanticsLabel ?? '${widget.keyLabel}_input', + container: true, + child: AppTextField( + controller: _keyController, + decoration: InputDecoration(labelText: widget.keyLabel), + onChanged: (_) => setState(() {}), + ), + ), + ), + const SizedBox(width: 12), + Expanded( + child: Semantics( + identifier: widget.valueSemanticsLabel ?? '${widget.valueLabel}_input', + container: true, + child: AppTextField( + controller: _valueController, + decoration: InputDecoration(labelText: widget.valueLabel), + onChanged: (_) => setState(() {}), + ), + ), + ), + ], + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Cancel'), + ), + Semantics( + identifier: 'singlepair_confirm_button', + container: true, + button: true, + child: TextButton( + onPressed: _isValid + ? () => Navigator.pop( + context, + MapEntry(_keyController.text, _valueController.text), + ) + : null, + child: const Text('Add'), + ), + ), + ], + ); + } +} + +// Multi-pair input dialog (dynamic rows) +class MultiPairInputDialog extends StatefulWidget { + final String title; + final String keyLabel; + final String valueLabel; + + const MultiPairInputDialog({ + super.key, + required this.title, + this.keyLabel = 'Key', + this.valueLabel = 'Value', + }); + + @override + State<MultiPairInputDialog> createState() => _MultiPairInputDialogState(); +} + +class _MultiPairInputDialogState extends State<MultiPairInputDialog> { + final List<TextEditingController> _keyControllers = []; + final List<TextEditingController> _valueControllers = []; + + @override + void initState() { + super.initState(); + _addRow(); + } + + @override + void dispose() { + for (final c in _keyControllers) { + c.dispose(); + } + for (final c in _valueControllers) { + c.dispose(); + } + super.dispose(); + } + + void _addRow() { + final keyC = TextEditingController(); + final valC = TextEditingController(); + keyC.addListener(() => setState(() {})); + valC.addListener(() => setState(() {})); + _keyControllers.add(keyC); + _valueControllers.add(valC); + setState(() {}); + } + + void _removeRow(int index) { + _keyControllers[index].dispose(); + _valueControllers[index].dispose(); + _keyControllers.removeAt(index); + _valueControllers.removeAt(index); + setState(() {}); + } + + bool get _allValid { + for (var i = 0; i < _keyControllers.length; i++) { + if (_keyControllers[i].text.isEmpty || + _valueControllers[i].text.isEmpty) { + return false; + } + } + return _keyControllers.isNotEmpty; + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + insetPadding: const EdgeInsets.symmetric(horizontal: 16), + title: Text(widget.title), + content: SizedBox( + width: double.maxFinite, + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + for (var i = 0; i < _keyControllers.length; i++) ...[ + if (i > 0) const Divider(), + Row( + children: [ + Expanded( + child: Semantics( + identifier: 'multipair_key_$i', + container: true, + child: AppTextField( + controller: _keyControllers[i], + decoration: InputDecoration( + labelText: widget.keyLabel, + isDense: true, + ), + ), + ), + ), + const SizedBox(width: 8), + Expanded( + child: Semantics( + identifier: 'multipair_value_$i', + container: true, + child: AppTextField( + controller: _valueControllers[i], + decoration: InputDecoration( + labelText: widget.valueLabel, + isDense: true, + ), + ), + ), + ), + if (_keyControllers.length > 1) + IconButton( + icon: const Icon(Icons.close, size: 20), + onPressed: () => _removeRow(i), + ), + ], + ), + ], + Semantics( + identifier: 'multipair_add_row_button', + container: true, + button: true, + child: TextButton.icon( + onPressed: _addRow, + icon: const Icon(Icons.add, size: 18), + label: const Text('Add Row'), + ), + ), + ], + ), + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Cancel'), + ), + Semantics( + identifier: 'multipair_confirm_button', + container: true, + button: true, + child: TextButton( + onPressed: _allValid + ? () { + final pairs = <String, String>{}; + for (var i = 0; i < _keyControllers.length; i++) { + pairs[_keyControllers[i].text] = + _valueControllers[i].text; + } + Navigator.pop(context, pairs); + } + : null, + child: const Text('Add All'), + ), + ), + ], + ); + } +} + +// Multi-select remove dialog +class MultiSelectRemoveDialog extends StatefulWidget { + final String title; + final List<MapEntry<String, String>> items; + + const MultiSelectRemoveDialog({ + super.key, + required this.title, + required this.items, + }); + + @override + State<MultiSelectRemoveDialog> createState() => + _MultiSelectRemoveDialogState(); +} + +class _MultiSelectRemoveDialogState extends State<MultiSelectRemoveDialog> { + final Set<String> _selected = {}; + + @override + Widget build(BuildContext context) { + return AlertDialog( + insetPadding: const EdgeInsets.symmetric(horizontal: 16), + title: Text(widget.title), + content: SizedBox( + width: double.maxFinite, + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: widget.items.map((item) { + return Semantics( + identifier: 'remove_checkbox_${item.key}', + container: true, + child: CheckboxListTile( + title: Text(item.key), + value: _selected.contains(item.key), + controlAffinity: ListTileControlAffinity.leading, + onChanged: (checked) { + setState(() { + if (checked == true) { + _selected.add(item.key); + } else { + _selected.remove(item.key); + } + }); + }, + contentPadding: EdgeInsets.zero, + ), + ); + }).toList(), + ), + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Cancel'), + ), + Semantics( + identifier: 'multiselect_confirm_button', + container: true, + button: true, + child: TextButton( + onPressed: _selected.isEmpty + ? null + : () => Navigator.pop(context, _selected.toList()), + child: Text('Remove (${_selected.length})'), + ), + ), + ], + ); + } +} + +// Outcome dialog +class OutcomeDialog extends StatefulWidget { + const OutcomeDialog({super.key}); + + @override + State<OutcomeDialog> createState() => _OutcomeDialogState(); +} + +enum OutcomeType { normal, unique, withValue } + +class _OutcomeDialogState extends State<OutcomeDialog> { + final _nameController = TextEditingController(); + final _valueController = TextEditingController(); + OutcomeType _type = OutcomeType.normal; + + @override + void dispose() { + _nameController.dispose(); + _valueController.dispose(); + super.dispose(); + } + + bool get _isValid { + if (_nameController.text.isEmpty) return false; + if (_type == OutcomeType.withValue) { + return double.tryParse(_valueController.text) != null; + } + return true; + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + insetPadding: const EdgeInsets.symmetric(horizontal: 16), + title: const Text('Send Outcome'), + content: SizedBox( + width: double.maxFinite, + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + RadioGroup<OutcomeType>( + groupValue: _type, + onChanged: (v) => setState(() { if (v != null) _type = v; }), + child: Column( + children: [ + Semantics( + identifier: 'outcome_type_normal_radio', + container: true, + button: true, + child: RadioListTile<OutcomeType>( + title: const Text('Normal Outcome'), + value: OutcomeType.normal, + contentPadding: EdgeInsets.zero, + ), + ), + Semantics( + identifier: 'outcome_type_unique_radio', + container: true, + button: true, + child: RadioListTile<OutcomeType>( + title: const Text('Unique Outcome'), + value: OutcomeType.unique, + contentPadding: EdgeInsets.zero, + ), + ), + Semantics( + identifier: 'outcome_type_value_radio', + container: true, + button: true, + child: RadioListTile<OutcomeType>( + title: const Text('Outcome with Value'), + value: OutcomeType.withValue, + contentPadding: EdgeInsets.zero, + ), + ), + ], + ), + ), + const SizedBox(height: 8), + Semantics( + identifier: 'outcome_name_input', + container: true, + child: AppTextField( + controller: _nameController, + decoration: const InputDecoration(labelText: 'Outcome Name'), + onChanged: (_) => setState(() {}), + ), + ), + if (_type == OutcomeType.withValue) ...[ + const SizedBox(height: 12), + Semantics( + identifier: 'outcome_value_input', + container: true, + child: AppTextField( + controller: _valueController, + decoration: const InputDecoration(labelText: 'Value'), + keyboardType: + const TextInputType.numberWithOptions(decimal: true), + onChanged: (_) => setState(() {}), + ), + ), + ], + ], + ), + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Cancel'), + ), + Semantics( + identifier: 'outcome_send_button', + container: true, + child: TextButton( + onPressed: _isValid + ? () { + Navigator.pop(context, { + 'type': _type, + 'name': _nameController.text, + 'value': _type == OutcomeType.withValue + ? double.parse(_valueController.text) + : null, + }); + } + : null, + child: const Text('Send'), + ), + ), + ], + ); + } +} + +// Track event dialog +class TrackEventDialog extends StatefulWidget { + const TrackEventDialog({super.key}); + + @override + State<TrackEventDialog> createState() => _TrackEventDialogState(); +} + +class _TrackEventDialogState extends State<TrackEventDialog> { + final _nameController = TextEditingController(); + final _propsController = TextEditingController(); + String? _jsonError; + + @override + void dispose() { + _nameController.dispose(); + _propsController.dispose(); + super.dispose(); + } + + bool get _isValid { + if (_nameController.text.isEmpty) return false; + if (_propsController.text.isNotEmpty && _jsonError != null) return false; + return true; + } + + void _validateJson(String text) { + setState(() { + if (text.isEmpty) { + _jsonError = null; + } else { + try { + jsonDecode(text); + _jsonError = null; + } catch (_) { + _jsonError = 'Invalid JSON format'; + } + } + }); + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + insetPadding: const EdgeInsets.symmetric(horizontal: 16), + title: const Text('Custom Event'), + content: SizedBox( + width: double.maxFinite, + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Semantics( + identifier: 'event_name_input', + container: true, + child: AppTextField( + controller: _nameController, + decoration: const InputDecoration(labelText: 'Event Name'), + onChanged: (_) => setState(() {}), + ), + ), + const SizedBox(height: 12), + Semantics( + identifier: 'event_properties_input', + container: true, + child: AppTextField( + controller: _propsController, + decoration: InputDecoration( + labelText: 'Properties (optional, JSON)', + hintText: '{"key": "value"}', + errorText: _jsonError, + ), + maxLines: 3, + onChanged: _validateJson, + ), + ), + ], + ), + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Cancel'), + ), + Semantics( + identifier: 'event_track_button', + container: true, + child: TextButton( + onPressed: _isValid + ? () { + Map<String, dynamic>? props; + if (_propsController.text.isNotEmpty) { + props = jsonDecode(_propsController.text) + as Map<String, dynamic>; + } + Navigator.pop(context, { + 'name': _nameController.text, + 'properties': props, + }); + } + : null, + child: const Text('Track'), + ), + ), + ], + ); + } +} + +// Custom notification dialog +class CustomNotificationDialog extends StatefulWidget { + const CustomNotificationDialog({super.key}); + + @override + State<CustomNotificationDialog> createState() => + _CustomNotificationDialogState(); +} + +class _CustomNotificationDialogState extends State<CustomNotificationDialog> { + final _titleController = TextEditingController(); + final _bodyController = TextEditingController(); + + @override + void dispose() { + _titleController.dispose(); + _bodyController.dispose(); + super.dispose(); + } + + bool get _isValid => + _titleController.text.isNotEmpty && _bodyController.text.isNotEmpty; + + @override + Widget build(BuildContext context) { + return AlertDialog( + insetPadding: const EdgeInsets.symmetric(horizontal: 16), + title: const Text('Custom Notification'), + content: SizedBox( + width: double.maxFinite, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + AppTextField( + controller: _titleController, + decoration: const InputDecoration(labelText: 'Title'), + onChanged: (_) => setState(() {}), + ), + const SizedBox(height: 12), + AppTextField( + controller: _bodyController, + decoration: const InputDecoration(labelText: 'Body'), + onChanged: (_) => setState(() {}), + ), + ], + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Cancel'), + ), + TextButton( + onPressed: _isValid + ? () => Navigator.pop(context, { + 'title': _titleController.text, + 'body': _bodyController.text, + }) + : null, + child: const Text('Send'), + ), + ], + ); + } +} + +// Tooltip dialog +class TooltipDialog extends StatelessWidget { + final TooltipData tooltip; + + const TooltipDialog({super.key, required this.tooltip}); + + @override + Widget build(BuildContext context) { + return AlertDialog( + insetPadding: const EdgeInsets.symmetric(horizontal: 16), + title: Semantics( + identifier: 'tooltip_title', + container: true, + child: Text(tooltip.title), + ), + content: SizedBox( + width: double.maxFinite, + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Semantics( + identifier: 'tooltip_description', + container: true, + child: Text(tooltip.description), + ), + if (tooltip.options != null && tooltip.options!.isNotEmpty) ...[ + const SizedBox(height: 16), + ...tooltip.options!.map((option) => Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + option.name, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + Text( + option.description, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: AppColors.osGrey600, + ), + ), + ], + ), + )), + ], + ], + ), + ), + ), + actions: [ + Semantics( + identifier: 'tooltip_ok_button', + container: true, + button: true, + child: TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('OK'), + ), + ), + ], + ); + } +} diff --git a/examples/demo_fm/lib/widgets/list_widgets.dart b/examples/demo_fm/lib/widgets/list_widgets.dart new file mode 100644 index 00000000..aa8686b5 --- /dev/null +++ b/examples/demo_fm/lib/widgets/list_widgets.dart @@ -0,0 +1,272 @@ +import 'package:flutter/material.dart'; + +import '../theme.dart'; + +class PairItem extends StatelessWidget { + final String sectionKey; + final String keyText; + final String valueText; + final VoidCallback? onDelete; + + const PairItem({ + super.key, + required this.sectionKey, + required this.keyText, + required this.valueText, + this.onDelete, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 4), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Semantics( + identifier: '${sectionKey}_pair_key_$keyText', + container: true, + child: Text( + keyText, + style: Theme.of(context).textTheme.bodyMedium, + ), + ), + Semantics( + identifier: '${sectionKey}_pair_value_$keyText', + container: true, + child: Text( + valueText, + style: Theme.of( + context, + ).textTheme.bodySmall?.copyWith(color: AppColors.osGrey600), + ), + ), + ], + ), + ), + if (onDelete != null) + Semantics( + identifier: '${sectionKey}_remove_$keyText', + container: true, + child: GestureDetector( + onTap: onDelete, + child: Icon(Icons.close, size: 18, color: AppColors.osPrimary), + ), + ), + ], + ), + ); + } +} + +class SingleItem extends StatelessWidget { + final String sectionKey; + final String text; + final VoidCallback? onDelete; + + const SingleItem({ + super.key, + required this.sectionKey, + required this.text, + this.onDelete, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 4), + child: Row( + children: [ + Expanded( + child: Semantics( + identifier: '${sectionKey}_value_$text', + container: true, + child: Text(text, style: Theme.of(context).textTheme.bodyMedium), + ), + ), + if (onDelete != null) + Semantics( + identifier: '${sectionKey}_remove_$text', + container: true, + child: GestureDetector( + onTap: onDelete, + child: Icon(Icons.close, size: 18, color: AppColors.osPrimary), + ), + ), + ], + ), + ); + } +} + +class EmptyState extends StatelessWidget { + final String text; + final String? sectionKey; + + const EmptyState({super.key, required this.text, this.sectionKey}); + + @override + Widget build(BuildContext context) { + final label = Text( + text, + style: Theme.of( + context, + ).textTheme.bodyMedium?.copyWith(color: AppColors.osGrey600), + ); + return Padding( + padding: const EdgeInsets.symmetric(vertical: 12), + child: Center( + child: sectionKey == null + ? label + : Semantics( + identifier: '${sectionKey}_empty', + container: true, + child: label, + ), + ), + ); + } +} + +class LoadingState extends StatelessWidget { + final String? sectionKey; + + const LoadingState({super.key, this.sectionKey}); + + @override + Widget build(BuildContext context) { + final indicator = SizedBox( + width: 20, + height: 20, + child: CircularProgressIndicator( + strokeWidth: 2, + color: AppColors.osPrimary, + ), + ); + return Padding( + padding: const EdgeInsets.symmetric(vertical: 12), + child: Center( + child: + sectionKey == null + ? indicator + : Semantics( + identifier: '${sectionKey}_loading', + container: true, + child: indicator, + ), + ), + ); + } +} + +class PairList extends StatelessWidget { + final String sectionKey; + final List<MapEntry<String, String>> items; + final String emptyText; + final bool loading; + final void Function(String key)? onDelete; + + const PairList({ + super.key, + required this.sectionKey, + required this.items, + required this.emptyText, + this.loading = false, + this.onDelete, + }); + + @override + Widget build(BuildContext context) { + if (items.isEmpty) { + return loading + ? LoadingState(sectionKey: sectionKey) + : EmptyState(text: emptyText, sectionKey: sectionKey); + } + + return Column( + children: [ + for (var i = 0; i < items.length; i++) ...[ + PairItem( + key: ValueKey('${items[i].key}_${items[i].value}'), + sectionKey: sectionKey, + keyText: items[i].key, + valueText: items[i].value, + onDelete: onDelete != null ? () => onDelete!(items[i].key) : null, + ), + if (i < items.length - 1) const Divider(height: 1), + ], + ], + ); + } +} + +class CollapsibleList extends StatefulWidget { + final String sectionKey; + final List<String> items; + final String emptyText; + final void Function(String item) onDelete; + final int maxVisible; + final bool loading; + + const CollapsibleList({ + super.key, + required this.sectionKey, + required this.items, + required this.emptyText, + required this.onDelete, + this.maxVisible = 5, + this.loading = false, + }); + + @override + State<CollapsibleList> createState() => _CollapsibleListState(); +} + +class _CollapsibleListState extends State<CollapsibleList> { + bool _expanded = false; + + @override + Widget build(BuildContext context) { + if (widget.items.isEmpty) { + return widget.loading + ? LoadingState(sectionKey: widget.sectionKey) + : EmptyState(text: widget.emptyText, sectionKey: widget.sectionKey); + } + + final showAll = _expanded || widget.items.length <= widget.maxVisible; + final visibleItems = + showAll ? widget.items : widget.items.take(widget.maxVisible).toList(); + final remaining = widget.items.length - widget.maxVisible; + + return Column( + children: [ + for (var i = 0; i < visibleItems.length; i++) ...[ + SingleItem( + key: ValueKey(visibleItems[i]), + sectionKey: widget.sectionKey, + text: visibleItems[i], + onDelete: () => widget.onDelete(visibleItems[i]), + ), + if (i < visibleItems.length - 1) const Divider(height: 1), + ], + if (!showAll && remaining > 0) + GestureDetector( + onTap: () => setState(() => _expanded = true), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: Text( + '$remaining more', + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + ], + ); + } +} diff --git a/examples/demo_fm/lib/widgets/section_card.dart b/examples/demo_fm/lib/widgets/section_card.dart new file mode 100644 index 00000000..5e261f87 --- /dev/null +++ b/examples/demo_fm/lib/widgets/section_card.dart @@ -0,0 +1,77 @@ +import 'package:flutter/material.dart'; + +import '../theme.dart'; + +class SectionCard extends StatelessWidget { + final String title; + final VoidCallback? onInfoTap; + final String? sectionKey; + final Widget child; + + const SectionCard({ + super.key, + required this.title, + this.onInfoTap, + this.sectionKey, + required this.child, + }); + + @override + Widget build(BuildContext context) { + return Semantics( + identifier: sectionKey != null ? '${sectionKey}_section' : null, + container: true, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Section header (outside card, ALL CAPS like reference) + Padding( + padding: EdgeInsets.only(bottom: onInfoTap != null ? 0 : AppSpacing.gap), + child: Row( + children: [ + Expanded( + child: Text( + title.toUpperCase(), + style: Theme.of(context).textTheme.bodySmall?.copyWith( + fontWeight: FontWeight.bold, + color: AppColors.osGrey700, + letterSpacing: 0.5, + ), + ), + ), + if (onInfoTap != null) + Transform.translate( + offset: const Offset(16, 0), + child: Semantics( + identifier: sectionKey != null + ? '${sectionKey}_info_icon' + : null, + container: true, + child: IconButton( + onPressed: onInfoTap, + icon: Icon( + Icons.info_outline, + size: 18, + color: AppColors.osGrey500, + ), + padding: EdgeInsets.zero, + constraints: const BoxConstraints( + minWidth: 32, + minHeight: 32, + ), + ), + ), + ), + ], + ), + ), + // Card content + child, + ], + ), + ), + ); + } +} diff --git a/examples/demo_fm/lib/widgets/sections/aliases_section.dart b/examples/demo_fm/lib/widgets/sections/aliases_section.dart new file mode 100644 index 00000000..9f0eb2ba --- /dev/null +++ b/examples/demo_fm/lib/widgets/sections/aliases_section.dart @@ -0,0 +1,82 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../theme.dart'; +import '../../viewmodels/app_viewmodel.dart'; +import '../action_button.dart'; +import '../dialogs.dart'; +import '../list_widgets.dart'; +import '../section_card.dart'; + +class AliasesSection extends StatelessWidget { + final VoidCallback? onInfoTap; + + const AliasesSection({super.key, this.onInfoTap}); + + @override + Widget build(BuildContext context) { + final vm = context.watch<AppViewModel>(); + + return SectionCard( + title: 'Aliases', + sectionKey: 'aliases', + onInfoTap: onInfoTap, + child: Column( + children: [ + Card( + margin: EdgeInsets.zero, + child: Padding( + padding: AppSpacing.cardPadding, + child: PairList( + sectionKey: 'aliases', + items: vm.aliasesList, + emptyText: 'No aliases added', + loading: vm.isLoading, + ), + ), + ), + AppSpacing.gapBox, + PrimaryButton( + label: 'ADD ALIAS', + semanticsLabel: 'add_alias_button', + onPressed: () async { + final result = await showDialog<MapEntry<String, String>>( + context: context, + builder: + (_) => const PairInputDialog( + title: 'Add Alias', + keyLabel: 'Label', + valueLabel: 'ID', + keySemanticsLabel: 'alias_label_input', + valueSemanticsLabel: 'alias_id_input', + ), + ); + if (result != null) { + vm.addAlias(result.key, result.value); + } + }, + ), + AppSpacing.gapBox, + PrimaryButton( + label: 'ADD MULTIPLE ALIASES', + semanticsLabel: 'add_multiple_aliases_button', + onPressed: () async { + final result = await showDialog<Map<String, String>>( + context: context, + builder: + (_) => const MultiPairInputDialog( + title: 'Add Multiple Aliases', + keyLabel: 'Label', + valueLabel: 'ID', + ), + ); + if (result != null) { + vm.addAliases(result); + } + }, + ), + ], + ), + ); + } +} diff --git a/examples/demo_fm/lib/widgets/sections/app_section.dart b/examples/demo_fm/lib/widgets/sections/app_section.dart new file mode 100644 index 00000000..64f86205 --- /dev/null +++ b/examples/demo_fm/lib/widgets/sections/app_section.dart @@ -0,0 +1,119 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import '../../theme.dart'; +import '../../viewmodels/app_viewmodel.dart'; +import '../section_card.dart'; +import '../toggle_row.dart'; + +class AppSection extends StatelessWidget { + final VoidCallback? onInfoTap; + + const AppSection({super.key, this.onInfoTap}); + + @override + Widget build(BuildContext context) { + final vm = context.watch<AppViewModel>(); + + return SectionCard( + title: 'App', + sectionKey: 'app', + onInfoTap: onInfoTap, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // App ID card (single row like reference) + Card( + margin: EdgeInsets.zero, + child: Padding( + padding: AppSpacing.cardPadding, + child: Row( + children: [ + Text('App ID', style: Theme.of(context).textTheme.bodyMedium), + const SizedBox(width: 12), + Expanded( + child: Semantics( + identifier: 'app_id_value', + container: true, + child: SelectableText( + vm.appId, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + fontFamily: 'monospace', + ), + textAlign: TextAlign.end, + ), + ), + ), + ], + ), + ), + ), + AppSpacing.gapBox, + + // Guidance banner + SizedBox( + width: double.infinity, + child: Card( + color: AppColors.osWarningBackground, + margin: EdgeInsets.zero, + child: Padding( + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Add your own App ID, then rebuild to fully test all functionality.', + style: Theme.of(context).textTheme.bodySmall, + ), + GestureDetector( + onTap: () => launchUrl( + Uri.parse('https://onesignal.com'), + mode: LaunchMode.externalApplication, + ), + child: Text( + 'Get your keys at onesignal.com', + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: AppColors.osPrimary, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + ), + ), + ), + AppSpacing.gapBox, + + // Consent card + Card( + margin: EdgeInsets.zero, + child: Padding( + padding: AppSpacing.cardPadding, + child: Column( + children: [ + ToggleRow( + label: 'Consent Required', + description: 'Require consent before SDK processes data', + value: vm.consentRequired, + onChanged: vm.setConsentRequired, + ), + if (vm.consentRequired) ...[ + const Divider(), + ToggleRow( + label: 'Privacy Consent', + description: 'Consent given for data collection', + value: vm.privacyConsentGiven, + onChanged: vm.setPrivacyConsent, + ), + ], + ], + ), + ), + ), + ], + ), + ); + } +} diff --git a/examples/demo_fm/lib/widgets/sections/custom_events_section.dart b/examples/demo_fm/lib/widgets/sections/custom_events_section.dart new file mode 100644 index 00000000..d09bfc62 --- /dev/null +++ b/examples/demo_fm/lib/widgets/sections/custom_events_section.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../theme.dart'; +import '../../viewmodels/app_viewmodel.dart'; +import '../action_button.dart'; +import '../dialogs.dart'; +import '../section_card.dart'; + +class CustomEventsSection extends StatelessWidget { + final VoidCallback? onInfoTap; + + const CustomEventsSection({super.key, this.onInfoTap}); + + @override + Widget build(BuildContext context) { + final vm = context.read<AppViewModel>(); + + return SectionCard( + title: 'Custom Events', + sectionKey: 'custom_events', + onInfoTap: onInfoTap, + child: PrimaryButton( + label: 'TRACK EVENT', + semanticsLabel: 'track_event_button', + onPressed: () async { + final result = await showDialog<Map<String, dynamic>>( + context: context, + builder: (_) => const TrackEventDialog(), + ); + if (result != null) { + final name = result['name'] as String; + vm.trackEvent( + name, + result['properties'] as Map<String, dynamic>?, + ); + if (context.mounted) { + context.showSnackBar('Event tracked: $name'); + } + } + }, + ), + ); + } +} diff --git a/examples/demo_fm/lib/widgets/sections/emails_section.dart b/examples/demo_fm/lib/widgets/sections/emails_section.dart new file mode 100644 index 00000000..6b9f4174 --- /dev/null +++ b/examples/demo_fm/lib/widgets/sections/emails_section.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../theme.dart'; +import '../../viewmodels/app_viewmodel.dart'; +import '../action_button.dart'; +import '../dialogs.dart'; +import '../list_widgets.dart'; +import '../section_card.dart'; + +class EmailsSection extends StatelessWidget { + final VoidCallback? onInfoTap; + + const EmailsSection({super.key, this.onInfoTap}); + + @override + Widget build(BuildContext context) { + final vm = context.watch<AppViewModel>(); + + return SectionCard( + title: 'Emails', + sectionKey: 'emails', + onInfoTap: onInfoTap, + child: Column( + children: [ + Card( + margin: EdgeInsets.zero, + child: Padding( + padding: AppSpacing.cardPadding, + child: CollapsibleList( + sectionKey: 'emails', + items: vm.emailsList, + emptyText: 'No emails added', + loading: vm.isLoading, + onDelete: vm.removeEmail, + ), + ), + ), + AppSpacing.gapBox, + PrimaryButton( + label: 'ADD EMAIL', + semanticsLabel: 'add_email_button', + onPressed: () async { + final result = await showDialog<String>( + context: context, + builder: + (_) => const SingleInputDialog( + title: 'Add Email', + fieldLabel: 'Email', + keyboardType: TextInputType.emailAddress, + semanticsLabel: 'email_input', + ), + ); + if (result != null) { + vm.addEmail(result); + } + }, + ), + ], + ), + ); + } +} diff --git a/examples/demo_fm/lib/widgets/sections/in_app_section.dart b/examples/demo_fm/lib/widgets/sections/in_app_section.dart new file mode 100644 index 00000000..c8abfed3 --- /dev/null +++ b/examples/demo_fm/lib/widgets/sections/in_app_section.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../theme.dart'; +import '../../viewmodels/app_viewmodel.dart'; +import '../section_card.dart'; +import '../toggle_row.dart'; + +class InAppSection extends StatelessWidget { + final VoidCallback? onInfoTap; + + const InAppSection({super.key, this.onInfoTap}); + + @override + Widget build(BuildContext context) { + final vm = context.watch<AppViewModel>(); + + return SectionCard( + title: 'In-App Messaging', + sectionKey: 'iam', + onInfoTap: onInfoTap, + child: Card( + margin: EdgeInsets.zero, + child: Padding( + padding: AppSpacing.cardPadding, + child: ToggleRow( + label: 'Pause In-App Messages', + description: 'Toggle in-app message display', + semanticsLabel: 'pause_iam_toggle', + value: vm.iamPaused, + onChanged: vm.setIamPaused, + ), + ), + ), + ); + } +} diff --git a/examples/demo_fm/lib/widgets/sections/live_activities_section.dart b/examples/demo_fm/lib/widgets/sections/live_activities_section.dart new file mode 100644 index 00000000..2a267b80 --- /dev/null +++ b/examples/demo_fm/lib/widgets/sections/live_activities_section.dart @@ -0,0 +1,144 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../theme.dart'; +import '../../viewmodels/app_viewmodel.dart'; +import '../app_text_field.dart'; +import '../action_button.dart'; +import '../section_card.dart'; + +class LiveActivitiesSection extends StatefulWidget { + final VoidCallback? onInfoTap; + + const LiveActivitiesSection({super.key, this.onInfoTap}); + + @override + State<LiveActivitiesSection> createState() => _LiveActivitiesSectionState(); +} + +class _LiveActivitiesSectionState extends State<LiveActivitiesSection> { + late TextEditingController _activityIdController; + late TextEditingController _orderNumberController; + + @override + void initState() { + super.initState(); + final vm = context.read<AppViewModel>(); + _activityIdController = TextEditingController(text: vm.activityId); + _orderNumberController = TextEditingController(text: vm.orderNumber); + } + + @override + void dispose() { + _activityIdController.dispose(); + _orderNumberController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final vm = context.watch<AppViewModel>(); + final activityEmpty = _activityIdController.text.isEmpty; + + return SectionCard( + title: 'Live Activities', + sectionKey: 'live_activities', + onInfoTap: widget.onInfoTap, + child: Column( + children: [ + Card( + margin: EdgeInsets.zero, + child: Padding( + padding: AppSpacing.cardPadding, + child: Column( + children: [ + _InputRow( + label: 'Activity ID', + controller: _activityIdController, + onChanged: (value) { + vm.setActivityId(value); + setState(() {}); + }, + ), + const SizedBox(height: 4), + _InputRow( + label: 'Order #', + controller: _orderNumberController, + onChanged: (value) => vm.setOrderNumber(value), + ), + ], + ), + ), + ), + AppSpacing.gapBox, + PrimaryButton( + label: 'START LIVE ACTIVITY', + semanticsLabel: 'start_live_activity_button', + onPressed: activityEmpty ? null : () => vm.startLiveActivity(), + ), + AppSpacing.gapBox, + PrimaryButton( + label: 'UPDATE → ${vm.nextStatusLabel}', + semanticsLabel: 'update_live_activity_button', + onPressed: activityEmpty || vm.isLaUpdating || !vm.hasApiKey + ? null + : () => vm.updateLiveActivity(), + ), + AppSpacing.gapBox, + DestructiveButton( + label: 'END LIVE ACTIVITY', + semanticsLabel: 'end_live_activity_button', + onPressed: activityEmpty || !vm.hasApiKey + ? null + : () => vm.endLiveActivity(), + ), + ], + ), + ); + } +} + +class _InputRow extends StatelessWidget { + final String label; + final TextEditingController controller; + final ValueChanged<String> onChanged; + + const _InputRow({ + required this.label, + required this.controller, + required this.onChanged, + }); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + SizedBox( + width: 80, + child: Text( + label, + style: const TextStyle( + fontSize: 14, + color: AppColors.osGrey600, + ), + ), + ), + Expanded( + child: AppTextField( + controller: controller, + textAlign: TextAlign.right, + style: const TextStyle(fontSize: 14, color: Color(0xFF212121)), + decoration: const InputDecoration( + border: InputBorder.none, + enabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 4), + isDense: true, + ), + onChanged: onChanged, + ), + ), + ], + ); + } +} diff --git a/examples/demo_fm/lib/widgets/sections/location_section.dart b/examples/demo_fm/lib/widgets/sections/location_section.dart new file mode 100644 index 00000000..82607c4e --- /dev/null +++ b/examples/demo_fm/lib/widgets/sections/location_section.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../theme.dart'; +import '../../viewmodels/app_viewmodel.dart'; +import '../action_button.dart'; +import '../section_card.dart'; +import '../toggle_row.dart'; + +class LocationSection extends StatelessWidget { + final VoidCallback? onInfoTap; + + const LocationSection({super.key, this.onInfoTap}); + + @override + Widget build(BuildContext context) { + final vm = context.watch<AppViewModel>(); + + return SectionCard( + title: 'Location', + sectionKey: 'location', + onInfoTap: onInfoTap, + child: Column( + children: [ + Card( + margin: EdgeInsets.zero, + child: Padding( + padding: AppSpacing.cardPadding, + child: ToggleRow( + label: 'Location Shared', + description: 'Share device location with OneSignal', + semanticsLabel: 'location_shared_toggle', + value: vm.locationShared, + onChanged: vm.setLocationShared, + ), + ), + ), + AppSpacing.gapBox, + PrimaryButton( + label: 'PROMPT LOCATION', + semanticsLabel: 'prompt_location_button', + onPressed: vm.promptLocation, + ), + AppSpacing.gapBox, + PrimaryButton( + label: 'CHECK LOCATION SHARED', + semanticsLabel: 'check_location_button', + onPressed: () async { + final shared = await vm.checkLocationShared(); + if (context.mounted) { + context.showSnackBar('Location shared: $shared'); + } + }, + ), + ], + ), + ); + } +} diff --git a/examples/demo_fm/lib/widgets/sections/outcomes_section.dart b/examples/demo_fm/lib/widgets/sections/outcomes_section.dart new file mode 100644 index 00000000..c1fb50a9 --- /dev/null +++ b/examples/demo_fm/lib/widgets/sections/outcomes_section.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../theme.dart'; +import '../../viewmodels/app_viewmodel.dart'; +import '../action_button.dart'; +import '../dialogs.dart'; +import '../section_card.dart'; + +class OutcomesSection extends StatelessWidget { + final VoidCallback? onInfoTap; + + const OutcomesSection({super.key, this.onInfoTap}); + + @override + Widget build(BuildContext context) { + final vm = context.read<AppViewModel>(); + + return SectionCard( + title: 'Outcomes', + sectionKey: 'outcomes', + onInfoTap: onInfoTap, + child: PrimaryButton( + label: 'SEND OUTCOME', + semanticsLabel: 'send_outcome_button', + onPressed: () async { + final result = await showDialog<Map<String, dynamic>>( + context: context, + builder: (_) => const OutcomeDialog(), + ); + if (result != null) { + final type = result['type'] as OutcomeType; + final name = result['name'] as String; + String snackbarMessage; + switch (type) { + case OutcomeType.normal: + vm.sendOutcome(name); + snackbarMessage = 'Outcome sent: $name'; + case OutcomeType.unique: + vm.sendUniqueOutcome(name); + snackbarMessage = 'Unique outcome sent: $name'; + case OutcomeType.withValue: + final value = result['value'] as double; + vm.sendOutcomeWithValue(name, value); + snackbarMessage = 'Outcome sent: $name = $value'; + } + if (context.mounted) { + context.showSnackBar(snackbarMessage); + } + } + }, + ), + ); + } +} diff --git a/examples/demo_fm/lib/widgets/sections/push_section.dart b/examples/demo_fm/lib/widgets/sections/push_section.dart new file mode 100644 index 00000000..ee9b3aee --- /dev/null +++ b/examples/demo_fm/lib/widgets/sections/push_section.dart @@ -0,0 +1,77 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../theme.dart'; +import '../../viewmodels/app_viewmodel.dart'; +import '../action_button.dart'; +import '../section_card.dart'; +import '../toggle_row.dart'; + +class PushSection extends StatelessWidget { + final VoidCallback? onInfoTap; + + const PushSection({super.key, this.onInfoTap}); + + @override + Widget build(BuildContext context) { + final vm = context.watch<AppViewModel>(); + + return SectionCard( + title: 'Push', + sectionKey: 'push', + onInfoTap: onInfoTap, + child: Column( + children: [ + Card( + margin: EdgeInsets.zero, + child: Padding( + padding: AppSpacing.cardPadding, + child: Column( + children: [ + Row( + children: [ + Text( + 'Push ID', + style: Theme.of(context).textTheme.bodyMedium, + ), + const SizedBox(width: 12), + Expanded( + child: Semantics( + identifier: 'push_id_value', + container: true, + child: SelectableText( + vm.pushSubscriptionId ?? '—', + style: Theme.of(context).textTheme.bodySmall?.copyWith( + fontFamily: 'monospace', + ), + textAlign: TextAlign.end, + ), + ), + ), + ], + ), + const Divider(), + ToggleRow( + label: 'Enabled', + value: vm.pushEnabled, + semanticsLabel: 'push_enabled_toggle', + onChanged: vm.hasNotificationPermission + ? vm.togglePush + : null, + ), + ], + ), + ), + ), + if (!vm.hasNotificationPermission) ...[ + AppSpacing.gapBox, + PrimaryButton( + label: 'PROMPT PUSH', + onPressed: vm.promptPush, + ), + ], + ], + ), + ); + } +} diff --git a/examples/demo_fm/lib/widgets/sections/send_iam_section.dart b/examples/demo_fm/lib/widgets/sections/send_iam_section.dart new file mode 100644 index 00000000..7830040e --- /dev/null +++ b/examples/demo_fm/lib/widgets/sections/send_iam_section.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../models/in_app_message_type.dart'; +import '../../theme.dart'; +import '../../viewmodels/app_viewmodel.dart'; +import '../action_button.dart'; +import '../section_card.dart'; + +class SendIamSection extends StatelessWidget { + final VoidCallback? onInfoTap; + + const SendIamSection({super.key, this.onInfoTap}); + + @override + Widget build(BuildContext context) { + final vm = context.read<AppViewModel>(); + + return SectionCard( + title: 'Send In-App Message', + sectionKey: 'send_iam', + onInfoTap: onInfoTap, + child: Column( + spacing: AppSpacing.gap, + children: InAppMessageType.values.map((type) { + return PrimaryButton( + label: type.label.toUpperCase(), + onPressed: () => vm.sendInAppMessage(type), + semanticsLabel: 'send_iam_${type.triggerValue}_button', + ); + }).toList(), + ), + ); + } +} diff --git a/examples/demo_fm/lib/widgets/sections/send_push_section.dart b/examples/demo_fm/lib/widgets/sections/send_push_section.dart new file mode 100644 index 00000000..3ea7a965 --- /dev/null +++ b/examples/demo_fm/lib/widgets/sections/send_push_section.dart @@ -0,0 +1,67 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../models/notification_type.dart'; +import '../../theme.dart'; +import '../../viewmodels/app_viewmodel.dart'; +import '../action_button.dart'; +import '../dialogs.dart'; +import '../section_card.dart'; + +class SendPushSection extends StatelessWidget { + final VoidCallback? onInfoTap; + + const SendPushSection({super.key, this.onInfoTap}); + + @override + Widget build(BuildContext context) { + final vm = context.read<AppViewModel>(); + + return SectionCard( + title: 'Send Push Notification', + sectionKey: 'send_push', + onInfoTap: onInfoTap, + child: Column( + children: [ + PrimaryButton( + label: 'SIMPLE', + semanticsLabel: 'send_simple_button', + onPressed: () => vm.sendNotification(NotificationType.simple), + ), + AppSpacing.gapBox, + PrimaryButton( + label: 'WITH IMAGE', + semanticsLabel: 'send_image_button', + onPressed: () => vm.sendNotification(NotificationType.withImage), + ), + AppSpacing.gapBox, + PrimaryButton( + label: 'WITH SOUND', + semanticsLabel: 'send_sound_button', + onPressed: () => vm.sendNotification(NotificationType.withSound), + ), + AppSpacing.gapBox, + PrimaryButton( + label: 'CUSTOM', + semanticsLabel: 'send_custom_button', + onPressed: () async { + final result = await showDialog<Map<String, String>>( + context: context, + builder: (_) => const CustomNotificationDialog(), + ); + if (result != null) { + vm.sendCustomNotification(result['title']!, result['body']!); + } + }, + ), + AppSpacing.gapBox, + DestructiveButton( + label: 'CLEAR ALL', + semanticsLabel: 'clear_all_button', + onPressed: vm.clearAllNotifications, + ), + ], + ), + ); + } +} diff --git a/examples/demo_fm/lib/widgets/sections/sms_section.dart b/examples/demo_fm/lib/widgets/sections/sms_section.dart new file mode 100644 index 00000000..b7426d6f --- /dev/null +++ b/examples/demo_fm/lib/widgets/sections/sms_section.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../theme.dart'; +import '../../viewmodels/app_viewmodel.dart'; +import '../action_button.dart'; +import '../dialogs.dart'; +import '../list_widgets.dart'; +import '../section_card.dart'; + +class SmsSection extends StatelessWidget { + final VoidCallback? onInfoTap; + + const SmsSection({super.key, this.onInfoTap}); + + @override + Widget build(BuildContext context) { + final vm = context.watch<AppViewModel>(); + + return SectionCard( + title: 'SMS', + sectionKey: 'sms', + onInfoTap: onInfoTap, + child: Column( + children: [ + Card( + margin: EdgeInsets.zero, + child: Padding( + padding: AppSpacing.cardPadding, + child: CollapsibleList( + sectionKey: 'sms', + items: vm.smsNumbersList, + emptyText: 'No SMS added', + loading: vm.isLoading, + onDelete: vm.removeSms, + ), + ), + ), + AppSpacing.gapBox, + PrimaryButton( + label: 'ADD SMS', + semanticsLabel: 'add_sms_button', + onPressed: () async { + final result = await showDialog<String>( + context: context, + builder: + (_) => const SingleInputDialog( + title: 'Add SMS', + fieldLabel: 'SMS Number', + keyboardType: TextInputType.phone, + semanticsLabel: 'sms_input', + ), + ); + if (result != null) { + vm.addSms(result); + } + }, + ), + ], + ), + ); + } +} diff --git a/examples/demo_fm/lib/widgets/sections/tags_section.dart b/examples/demo_fm/lib/widgets/sections/tags_section.dart new file mode 100644 index 00000000..041aa3d6 --- /dev/null +++ b/examples/demo_fm/lib/widgets/sections/tags_section.dart @@ -0,0 +1,98 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../theme.dart'; +import '../../viewmodels/app_viewmodel.dart'; +import '../action_button.dart'; +import '../dialogs.dart'; +import '../list_widgets.dart'; +import '../section_card.dart'; + +class TagsSection extends StatelessWidget { + final VoidCallback? onInfoTap; + + const TagsSection({super.key, this.onInfoTap}); + + @override + Widget build(BuildContext context) { + final vm = context.watch<AppViewModel>(); + + return SectionCard( + title: 'Tags', + sectionKey: 'tags', + onInfoTap: onInfoTap, + child: Column( + children: [ + Card( + margin: EdgeInsets.zero, + child: Padding( + padding: AppSpacing.cardPadding, + child: PairList( + sectionKey: 'tags', + items: vm.tagsList, + emptyText: 'No tags added', + loading: vm.isLoading, + onDelete: vm.removeTag, + ), + ), + ), + AppSpacing.gapBox, + PrimaryButton( + label: 'ADD TAG', + semanticsLabel: 'add_tag_button', + onPressed: () async { + final result = await showDialog<MapEntry<String, String>>( + context: context, + builder: + (_) => const PairInputDialog( + title: 'Add Tag', + keySemanticsLabel: 'tag_key_input', + valueSemanticsLabel: 'tag_value_input', + ), + ); + if (result != null) { + vm.addTag(result.key, result.value); + } + }, + ), + AppSpacing.gapBox, + PrimaryButton( + label: 'ADD MULTIPLE TAGS', + semanticsLabel: 'add_multiple_tags_button', + onPressed: () async { + final result = await showDialog<Map<String, String>>( + context: context, + builder: + (_) => + const MultiPairInputDialog(title: 'Add Multiple Tags'), + ); + if (result != null) { + vm.addTags(result); + } + }, + ), + if (vm.tagsList.isNotEmpty) ...[ + AppSpacing.gapBox, + DestructiveButton( + label: 'REMOVE TAGS', + semanticsLabel: 'remove_tags_button', + onPressed: () async { + final result = await showDialog<List<String>>( + context: context, + builder: + (_) => MultiSelectRemoveDialog( + title: 'Remove Tags', + items: vm.tagsList, + ), + ); + if (result != null) { + vm.removeSelectedTags(result); + } + }, + ), + ], + ], + ), + ); + } +} diff --git a/examples/demo_fm/lib/widgets/sections/triggers_section.dart b/examples/demo_fm/lib/widgets/sections/triggers_section.dart new file mode 100644 index 00000000..7f650ae8 --- /dev/null +++ b/examples/demo_fm/lib/widgets/sections/triggers_section.dart @@ -0,0 +1,101 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../theme.dart'; +import '../../viewmodels/app_viewmodel.dart'; +import '../action_button.dart'; +import '../dialogs.dart'; +import '../list_widgets.dart'; +import '../section_card.dart'; + +class TriggersSection extends StatelessWidget { + final VoidCallback? onInfoTap; + + const TriggersSection({super.key, this.onInfoTap}); + + @override + Widget build(BuildContext context) { + final vm = context.watch<AppViewModel>(); + + return SectionCard( + title: 'Triggers', + sectionKey: 'triggers', + onInfoTap: onInfoTap, + child: Column( + children: [ + Card( + margin: EdgeInsets.zero, + child: Padding( + padding: AppSpacing.cardPadding, + child: PairList( + sectionKey: 'triggers', + items: vm.triggersList, + emptyText: 'No triggers added', + onDelete: vm.removeTrigger, + ), + ), + ), + AppSpacing.gapBox, + PrimaryButton( + label: 'ADD TRIGGER', + semanticsLabel: 'add_trigger_button', + onPressed: () async { + final result = await showDialog<MapEntry<String, String>>( + context: context, + builder: (_) => const PairInputDialog( + title: 'Add Trigger', + keySemanticsLabel: 'trigger_key_input', + valueSemanticsLabel: 'trigger_value_input', + ), + ); + if (result != null) { + vm.addTrigger(result.key, result.value); + } + }, + ), + AppSpacing.gapBox, + PrimaryButton( + label: 'ADD MULTIPLE TRIGGERS', + semanticsLabel: 'add_multiple_triggers_button', + onPressed: () async { + final result = await showDialog<Map<String, String>>( + context: context, + builder: (_) => const MultiPairInputDialog( + title: 'Add Multiple Triggers', + ), + ); + if (result != null) { + vm.addTriggers(result); + } + }, + ), + if (vm.triggersList.isNotEmpty) ...[ + AppSpacing.gapBox, + DestructiveButton( + label: 'REMOVE TRIGGERS', + semanticsLabel: 'remove_triggers_button', + onPressed: () async { + final result = await showDialog<List<String>>( + context: context, + builder: (_) => MultiSelectRemoveDialog( + title: 'Remove Triggers', + items: vm.triggersList, + ), + ); + if (result != null) { + vm.removeSelectedTriggers(result); + } + }, + ), + AppSpacing.gapBox, + DestructiveButton( + label: 'CLEAR ALL TRIGGERS', + semanticsLabel: 'clear_triggers_button', + onPressed: vm.clearAllTriggers, + ), + ], + ], + ), + ); + } +} diff --git a/examples/demo_fm/lib/widgets/sections/user_section.dart b/examples/demo_fm/lib/widgets/sections/user_section.dart new file mode 100644 index 00000000..efd53193 --- /dev/null +++ b/examples/demo_fm/lib/widgets/sections/user_section.dart @@ -0,0 +1,108 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../theme.dart'; +import '../../viewmodels/app_viewmodel.dart'; +import '../dialogs.dart'; +import '../action_button.dart'; +import '../section_card.dart'; + +class UserSection extends StatelessWidget { + final VoidCallback? onInfoTap; + + const UserSection({super.key, this.onInfoTap}); + + @override + Widget build(BuildContext context) { + final vm = context.watch<AppViewModel>(); + + return SectionCard( + title: 'User', + sectionKey: 'user', + onInfoTap: onInfoTap, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Card( + margin: EdgeInsets.zero, + child: Padding( + padding: AppSpacing.cardPadding, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Status', style: Theme.of(context).textTheme.bodyMedium), + Semantics( + identifier: 'user_status_value', + container: true, + child: Text( + vm.isLoggedIn ? 'Logged In' : 'Anonymous', + style: Theme.of(context).textTheme.bodySmall?.copyWith( + fontFamily: 'monospace', + color: vm.isLoggedIn + ? AppColors.osSuccess + : AppColors.osGrey600, + ), + ), + ), + ], + ), + const Divider(), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'External ID', + style: Theme.of(context).textTheme.bodyMedium, + ), + Semantics( + identifier: 'user_external_id_value', + container: true, + child: SelectableText( + vm.isLoggedIn ? (vm.externalUserId ?? '') : '—', + style: Theme.of(context).textTheme.bodySmall?.copyWith( + fontFamily: 'monospace', + ), + ), + ), + ], + ), + ], + ), + ), + ), + AppSpacing.gapBox, + PrimaryButton( + label: vm.isLoggedIn ? 'SWITCH USER' : 'LOGIN USER', + semanticsLabel: 'login_user_button', + onPressed: () async { + final result = await showDialog<String>( + context: context, + builder: (_) => const SingleInputDialog( + title: 'Login User', + fieldLabel: 'External User Id', + confirmLabel: 'Login', + semanticsLabel: 'login_user_id_input', + ), + ); + if (result != null && context.mounted) { + await vm.loginUser(result); + } + }, + ), + if (vm.isLoggedIn) ...[ + AppSpacing.gapBox, + DestructiveButton( + label: 'LOGOUT USER', + semanticsLabel: 'logout_user_button', + onPressed: () async { + await vm.logoutUser(); + }, + ), + ], + ], + ), + ); + } +} diff --git a/examples/demo_fm/lib/widgets/toggle_row.dart b/examples/demo_fm/lib/widgets/toggle_row.dart new file mode 100644 index 00000000..8bfa0428 --- /dev/null +++ b/examples/demo_fm/lib/widgets/toggle_row.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; + +import '../theme.dart'; + +class ToggleRow extends StatelessWidget { + final String label; + final String? description; + final bool value; + final ValueChanged<bool>? onChanged; + final String? semanticsLabel; + + const ToggleRow({ + super.key, + required this.label, + this.description, + required this.value, + this.onChanged, + this.semanticsLabel, + }); + + @override + Widget build(BuildContext context) { + Widget tile = SwitchListTile( + title: Text(label, style: Theme.of(context).textTheme.bodyMedium), + subtitle: description != null + ? Text( + description!, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: AppColors.osGrey600, + ), + ) + : null, + value: value, + onChanged: onChanged != null ? (v) => onChanged!(v) : null, + contentPadding: EdgeInsets.zero, + dense: true, + visualDensity: VisualDensity.compact, + ); + if (semanticsLabel != null) { + tile = Semantics( + identifier: semanticsLabel, + container: true, + toggled: value, + child: tile, + ); + } + return tile; + } +} diff --git a/examples/demo_fm/pubspec.yaml b/examples/demo_fm/pubspec.yaml new file mode 100644 index 00000000..6eaf8ee7 --- /dev/null +++ b/examples/demo_fm/pubspec.yaml @@ -0,0 +1,46 @@ +name: demo +description: OneSignal Flutter SDK Demo App +publish_to: 'none' +version: 1.0.0+1 + +environment: + sdk: ^3.7.0 + +dependencies: + flutter: + sdk: flutter + # Issue #1138 reproduction: use the in-tree SDK (currently 5.5.5) — this + # is the "broken" combo where the affected users report + # addClickListener never firing on Android background/killed taps. + onesignal_flutter: + path: ../../ + # Firebase Messaging added to mimic the affected users' setup + # (they use FCM alongside OneSignal for a chat feature). + firebase_core: ^3.8.0 + firebase_messaging: ^15.1.5 + provider: ^6.1.0 + shared_preferences: ^2.3.0 + http: ^1.2.0 + url_launcher: ^6.2.0 + flutter_svg: ^2.0.0 + flutter_dotenv: ^5.2.1 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^5.0.0 + flutter_launcher_icons: ^0.14.3 + +flutter_launcher_icons: + android: true + ios: true + remove_alpha_ios: true + image_path: "assets/onesignal_logo_icon_padded.png" + adaptive_icon_background: "#FFFFFF" + adaptive_icon_foreground: "assets/onesignal_logo_icon_padded.png" + +flutter: + uses-material-design: true + assets: + - assets/onesignal_logo.svg + - .env From d820d66fadcbba786c53640887dd7b0bc7d9a7a1 Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 13:25:25 -0700 Subject: [PATCH 02/20] fix(android): [SDK-4407] deliver notification events when firebase_messaging is present (#1138) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two coexistence bugs caused OneSignal notification click / foreground events to silently vanish on Android when an app also uses firebase_messaging: Bug A — FCM hijack. OneSignal's FCMBroadcastReceiver intent filter requires a <category> matching the app package, a GCM-era convention modern FCM no longer sets. When FlutterFire registers its own FirebaseMessagingService, OneSignal's receiver never matches and pushes are dropped before OneSignal sees them. Fixed by re-declaring the receiver from the plugin manifest with tools:node="replace" and no <category>, so OneSignal's existing receiver matches the modern FCM broadcast. Bug B — channel clobber. OneSignalNotifications is a process-global singleton, but registerWith runs once per Flutter engine. FlutterFire spins up a headless background FlutterEngine and GeneratedPluginRegistrant re-registers us against it, rebinding the shared MethodChannel to the background isolate (which never ran main() and has no listeners). Native onClick/onWillDisplay callbacks were dispatched there and lost. Fixed by: - registerWith no longer rebinds an already-bound channel (ignores the extra background engine), and - onAttachedToActivity authoritatively (re)binds the channel to the engine that hosts the UI, so events always reach the isolate that registered the user's listeners (also covers killed-start where the background engine attaches first). Verified on an emulator with firebase_messaging present: background-tap notifications now fire addClickListener, and foreground pushes reach the willDisplay listener. Repro app: examples/demo_fm. Co-authored-by: Cursor <cursoragent@cursor.com> --- android/src/main/AndroidManifest.xml | 35 ++++++++ .../flutter/OneSignalNotifications.java | 83 +++++++++++++++++++ .../onesignal/flutter/OneSignalPlugin.java | 29 ++++++- 3 files changed, 144 insertions(+), 3 deletions(-) diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 16fb0728..893be882 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,3 +1,38 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" package="com.onesignal.flutter"> + <application> + <!-- + Issue #1138 — root-cause fix without a bridge service. + + OneSignal's FCMBroadcastReceiver in the OneSignal Android SDK declares + an intent filter that requires a <category> matching the app's package + name. That category was set on GCM-era ordered broadcasts but is no + longer set by modern FCM. As a result OneSignal's receiver never + matches the broadcast in apps that also have another FCM-aware plugin + (e.g. firebase_messaging / FlutterFire), and pushes are silently + dropped. + + The manifest merger lets a higher-priority manifest replace child + elements from a lower-priority one. The Flutter plugin's manifest is + merged into the consuming app's manifest at higher priority than the + OneSignal Android SDK AAR's, so re-declaring the receiver with + tools:node="replace" lets us strip the offending <category> while + preserving the rest of the receiver definition. + + If you need to debug, dump the merged manifest at + build/app/intermediates/merged_manifests/<variant>/ and confirm that + com.onesignal.notifications.receivers.FCMBroadcastReceiver's + intent-filter no longer contains the <category> element. + --> + <receiver + android:name="com.onesignal.notifications.receivers.FCMBroadcastReceiver" + android:exported="true" + android:permission="com.google.android.c2dm.permission.SEND" + tools:node="replace"> + <intent-filter android:priority="999"> + <action android:name="com.google.android.c2dm.intent.RECEIVE" /> + </intent-filter> + </receiver> + </application> </manifest> diff --git a/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java b/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java index d2ab0dd5..59848908 100644 --- a/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java +++ b/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java @@ -29,6 +29,16 @@ public class OneSignalNotifications extends FlutterMessengerResponder private final HashMap<String, INotificationWillDisplayEvent> notificationOnWillDisplayEventCache = new HashMap<>(); private final HashMap<String, INotificationWillDisplayEvent> preventedDefaultCache = new HashMap<>(); + // Tracks whether Dart has asked us to be subscribed to click events. We + // toggle the native-SDK subscription on/off across Flutter engine + host + // activity lifecycles so that, while the channel is detached, click events + // get queued by the native SDK instead of dispatched into a dead JNI. + // Issue #1138 — Android `addClickListener` silently dropped on + // background notification tap when host activity has been destroyed + // (e.g. while running alongside firebase_messaging which can perturb + // the Flutter engine lifecycle). + private boolean clickListenerRequested = false; + public static OneSignalNotifications getSharedInstance() { if (sharedInstance == null) { sharedInstance = new OneSignalNotifications(); @@ -73,6 +83,19 @@ public void resumeWith(@NonNull Object o) { static void registerWith(BinaryMessenger messenger) { OneSignalNotifications controller = getSharedInstance(); + // Issue #1138: OneSignalNotifications is a process-global singleton, but + // registerWith is invoked once per Flutter engine. When firebase_messaging + // is present, FlutterFire spins up a headless background FlutterEngine and + // GeneratedPluginRegistrant registers us against it too — which would + // otherwise REBIND the shared channel to the background isolate (that never + // ran main() and has no listeners), so native click/willDisplay callbacks + // were silently routed there and dropped. Only bind on the first engine; + // the authoritative binding is (re)asserted from onAttachedToActivity so + // the channel always points at the engine that actually hosts the UI. + if (controller.channel != null) { + Logging.debug("[ISSUE-1138] OneSignalNotifications.registerWith() — channel already bound, ignoring extra engine (likely FlutterFire background engine)", null); + return; + } controller.messenger = messenger; controller.channel = new MethodChannel(messenger, "OneSignal#notifications"); controller.channel.setMethodCallHandler(controller); @@ -175,6 +198,7 @@ private void preventDefault(MethodCall call, Result result) { @Override public void onClick(INotificationClickEvent event) { + Logging.debug("[ISSUE-1138] OneSignalNotifications.onClick() — native SDK dispatched click; forwarding to MethodChannel", null); try { invokeMethodOnUiThread( "OneSignal#onClickNotification", OneSignalSerializer.convertNotificationClickEventToMap(event)); @@ -203,6 +227,8 @@ private JSONObject getJsonFromMap(Map<String, Object> map) throws JSONException @Override public void onWillDisplay(INotificationWillDisplayEvent event) { INotification notification = event.getNotification(); + Logging.debug("[ISSUE-1138] OneSignalNotifications.onWillDisplay fired for id=" + + notification.getNotificationId() + " channel=" + (channel != null), null); notificationOnWillDisplayEventCache.put(notification.getNotificationId(), event); /// Our bridge layer needs to preventDefault() so that the Flutter listener has time to preventDefault() before // the notification is displayed @@ -211,6 +237,7 @@ public void onWillDisplay(INotificationWillDisplayEvent event) { invokeMethodOnUiThread( "OneSignal#onWillDisplayNotification", OneSignalSerializer.convertNotificationWillDisplayEventToMap(event)); + Logging.debug("[ISSUE-1138] OneSignalNotifications.onWillDisplay — invokeMethodOnUiThread posted", null); } catch (JSONException e) { e.getStackTrace(); Logging.error( @@ -236,9 +263,63 @@ void onDetachedFromEngine() { } // Unsubscribe so clicks while the engine is dead get queued by the native SDK // instead of dispatched on a detached channel. + Logging.debug("[ISSUE-1138] OneSignalNotifications.onDetachedFromEngine() — removing native click listener", null); + OneSignal.getNotifications().removeClickListener(this); + } + + /** + * Called from {@link OneSignalPlugin#onDetachedFromActivity()} to extend the + * defensive unsubscribe to the case where the Flutter engine survives but the + * host activity is destroyed (e.g. user back-pressed out of MainActivity but + * the engine is cached). Without this, clicks delivered to + * {@link com.onesignal.notifications.activities.NotificationOpenedActivity} + * before the new MainActivity attaches go to a detached JNI and are dropped. + */ + void onDetachedFromActivity() { + // Same guard as onDetachedFromEngine (#1149): activity can be torn down + // before OneSignal.initialize() has been called from Dart. + if (!OneSignal.isInitialized()) { + return; + } + Logging.debug("[ISSUE-1138] OneSignalNotifications.onDetachedFromActivity() — removing native click listener", null); OneSignal.getNotifications().removeClickListener(this); } + /** + * Called from {@link OneSignalPlugin#onAttachedToActivity} after a (re)attach. + * If Dart had previously asked us to listen for clicks (via the + * `OneSignal#addNativeClickListener` MethodChannel call), re-register the + * native listener so any clicks queued by the native SDK while we were + * detached get drained now that the channel is live again. + */ + void onAttachedToActivity(BinaryMessenger activityMessenger) { + // Issue #1138: the engine that owns the host activity is the one whose + // Dart isolate ran main() and registered the user's listeners. Re-bind the + // shared channel to THIS engine's messenger so native click/willDisplay + // callbacks are dispatched to the UI isolate — even if a background engine + // (FlutterFire) attached after us and we kept the original binding. + if (activityMessenger != null && activityMessenger != this.messenger) { + this.messenger = activityMessenger; + this.channel = new MethodChannel(activityMessenger, "OneSignal#notifications"); + this.channel.setMethodCallHandler(this); + Logging.debug("[ISSUE-1138] OneSignalNotifications.onAttachedToActivity() — rebound channel to activity engine messenger", null); + } + if (!clickListenerRequested) { + Logging.debug("[ISSUE-1138] OneSignalNotifications.onAttachedToActivity() — Dart never asked us to listen, skipping re-register", null); + return; + } + // Same guard as onDetachedFromEngine (#1149): the first attach happens + // before Dart has had a chance to call OneSignal.initialize(), but in + // that case clickListenerRequested is also false, so we're already + // skipped above. Keep the guard anyway as defense-in-depth. + if (!OneSignal.isInitialized()) { + return; + } + Logging.debug("[ISSUE-1138] OneSignalNotifications.onAttachedToActivity() — re-adding native click listener (queued events should drain)", null); + OneSignal.getNotifications().removeClickListener(this); + OneSignal.getNotifications().addClickListener(this); + } + private void lifecycleInit(Result result) { OneSignal.getNotifications().removeForegroundLifecycleListener(this); OneSignal.getNotifications().addForegroundLifecycleListener(this); @@ -250,6 +331,8 @@ private void lifecycleInit(Result result) { } private void registerClickListener() { + Logging.debug("[ISSUE-1138] OneSignalNotifications.registerClickListener() — Dart requested click listener", null); + clickListenerRequested = true; OneSignal.getNotifications().removeClickListener(this); OneSignal.getNotifications().addClickListener(this); } diff --git a/android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java b/android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java index 2c2e8f21..7ea1808f 100644 --- a/android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java +++ b/android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java @@ -4,6 +4,7 @@ import androidx.annotation.NonNull; import com.onesignal.OneSignal; import com.onesignal.common.OneSignalWrapper; +import com.onesignal.debug.internal.logging.Logging; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.embedding.engine.plugins.activity.ActivityAware; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; @@ -40,11 +41,13 @@ private void init(Context context, BinaryMessenger messenger) { @Override public void onAttachedToEngine(@NonNull FlutterPlugin.FlutterPluginBinding flutterPluginBinding) { + Logging.debug("[ISSUE-1138] OneSignalPlugin.onAttachedToEngine()", null); init(flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); } @Override public void onDetachedFromEngine(@NonNull FlutterPlugin.FlutterPluginBinding binding) { + Logging.debug("[ISSUE-1138] OneSignalPlugin.onDetachedFromEngine()", null); onDetachedFromEngine(); } @@ -54,17 +57,37 @@ private void onDetachedFromEngine() { @Override public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { + Logging.debug("[ISSUE-1138] OneSignalPlugin.onAttachedToActivity()", null); this.context = binding.getActivity(); + // Issue #1138: re-register native click listener now that the host + // activity (and therefore the MethodChannel) is live again, so any + // clicks the native SDK queued while we were detached get drained. + // Pass this engine's messenger so the shared channel is (re)bound to the + // UI isolate rather than a FlutterFire background engine. + OneSignalNotifications.getSharedInstance().onAttachedToActivity(this.messenger); } @Override - public void onDetachedFromActivity() {} + public void onDetachedFromActivity() { + Logging.debug("[ISSUE-1138] OneSignalPlugin.onDetachedFromActivity()", null); + // Issue #1138: unregister click listener while we have no host activity, + // so the native SDK queues clicks (rather than dispatching them into a + // MethodChannel whose JNI is detached) until a new MainActivity attaches. + OneSignalNotifications.getSharedInstance().onDetachedFromActivity(); + } @Override - public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {} + public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { + Logging.debug("[ISSUE-1138] OneSignalPlugin.onReattachedToActivityForConfigChanges()", null); + this.context = binding.getActivity(); + OneSignalNotifications.getSharedInstance().onAttachedToActivity(this.messenger); + } @Override - public void onDetachedFromActivityForConfigChanges() {} + public void onDetachedFromActivityForConfigChanges() { + Logging.debug("[ISSUE-1138] OneSignalPlugin.onDetachedFromActivityForConfigChanges()", null); + OneSignalNotifications.getSharedInstance().onDetachedFromActivity(); + } @Override public void onMethodCall(MethodCall call, Result result) { From b0f07c38da652da1f7523cf0da1b240783aed5cc Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 14:03:08 -0700 Subject: [PATCH 03/20] fix(android): defer click listener on engine swap --- .../onesignal/flutter/OneSignalNotifications.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java b/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java index 59848908..f4e5871c 100644 --- a/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java +++ b/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java @@ -298,12 +298,25 @@ void onAttachedToActivity(BinaryMessenger activityMessenger) { // shared channel to THIS engine's messenger so native click/willDisplay // callbacks are dispatched to the UI isolate — even if a background engine // (FlutterFire) attached after us and we kept the original binding. - if (activityMessenger != null && activityMessenger != this.messenger) { + boolean engineChanged = activityMessenger != null && activityMessenger != this.messenger; + if (engineChanged) { this.messenger = activityMessenger; this.channel = new MethodChannel(activityMessenger, "OneSignal#notifications"); this.channel.setMethodCallHandler(this); Logging.debug("[ISSUE-1138] OneSignalNotifications.onAttachedToActivity() — rebound channel to activity engine messenger", null); + // The new engine's Dart isolate has NOT re-run main()/registerClickListener + // yet, so its MethodChannel handler is not registered. Re-adding the native + // click listener now would make the native SDK replay any queued click + // immediately — into a channel whose Dart end isn't listening — and the + // click would be dropped (see #1138 back-button-then-tap repro). Dart will + // call OneSignal#addNativeClickListener once it re-initializes, which drains + // the native queue at the point the isolate is actually ready to receive. + return; } + // Same engine: the activity reattached while the Flutter engine and its Dart + // isolate stayed alive (config change, or cached-engine resume). The Dart + // handler is still live, so re-adding now safely drains any clicks the native + // SDK queued while we were detached, without losing them to a dead isolate. if (!clickListenerRequested) { Logging.debug("[ISSUE-1138] OneSignalNotifications.onAttachedToActivity() — Dart never asked us to listen, skipping re-register", null); return; From f36c9414cf19c424b30a890df6481b5d7809ac5c Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 14:12:12 -0700 Subject: [PATCH 04/20] chore(android): remove ISSUE-1138 debug logs --- .../com/onesignal/flutter/OneSignalNotifications.java | 11 ----------- .../java/com/onesignal/flutter/OneSignalPlugin.java | 7 ------- 2 files changed, 18 deletions(-) diff --git a/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java b/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java index f4e5871c..3342bec3 100644 --- a/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java +++ b/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java @@ -93,7 +93,6 @@ static void registerWith(BinaryMessenger messenger) { // the authoritative binding is (re)asserted from onAttachedToActivity so // the channel always points at the engine that actually hosts the UI. if (controller.channel != null) { - Logging.debug("[ISSUE-1138] OneSignalNotifications.registerWith() — channel already bound, ignoring extra engine (likely FlutterFire background engine)", null); return; } controller.messenger = messenger; @@ -198,7 +197,6 @@ private void preventDefault(MethodCall call, Result result) { @Override public void onClick(INotificationClickEvent event) { - Logging.debug("[ISSUE-1138] OneSignalNotifications.onClick() — native SDK dispatched click; forwarding to MethodChannel", null); try { invokeMethodOnUiThread( "OneSignal#onClickNotification", OneSignalSerializer.convertNotificationClickEventToMap(event)); @@ -227,8 +225,6 @@ private JSONObject getJsonFromMap(Map<String, Object> map) throws JSONException @Override public void onWillDisplay(INotificationWillDisplayEvent event) { INotification notification = event.getNotification(); - Logging.debug("[ISSUE-1138] OneSignalNotifications.onWillDisplay fired for id=" - + notification.getNotificationId() + " channel=" + (channel != null), null); notificationOnWillDisplayEventCache.put(notification.getNotificationId(), event); /// Our bridge layer needs to preventDefault() so that the Flutter listener has time to preventDefault() before // the notification is displayed @@ -237,7 +233,6 @@ public void onWillDisplay(INotificationWillDisplayEvent event) { invokeMethodOnUiThread( "OneSignal#onWillDisplayNotification", OneSignalSerializer.convertNotificationWillDisplayEventToMap(event)); - Logging.debug("[ISSUE-1138] OneSignalNotifications.onWillDisplay — invokeMethodOnUiThread posted", null); } catch (JSONException e) { e.getStackTrace(); Logging.error( @@ -263,7 +258,6 @@ void onDetachedFromEngine() { } // Unsubscribe so clicks while the engine is dead get queued by the native SDK // instead of dispatched on a detached channel. - Logging.debug("[ISSUE-1138] OneSignalNotifications.onDetachedFromEngine() — removing native click listener", null); OneSignal.getNotifications().removeClickListener(this); } @@ -281,7 +275,6 @@ void onDetachedFromActivity() { if (!OneSignal.isInitialized()) { return; } - Logging.debug("[ISSUE-1138] OneSignalNotifications.onDetachedFromActivity() — removing native click listener", null); OneSignal.getNotifications().removeClickListener(this); } @@ -303,7 +296,6 @@ void onAttachedToActivity(BinaryMessenger activityMessenger) { this.messenger = activityMessenger; this.channel = new MethodChannel(activityMessenger, "OneSignal#notifications"); this.channel.setMethodCallHandler(this); - Logging.debug("[ISSUE-1138] OneSignalNotifications.onAttachedToActivity() — rebound channel to activity engine messenger", null); // The new engine's Dart isolate has NOT re-run main()/registerClickListener // yet, so its MethodChannel handler is not registered. Re-adding the native // click listener now would make the native SDK replay any queued click @@ -318,7 +310,6 @@ void onAttachedToActivity(BinaryMessenger activityMessenger) { // handler is still live, so re-adding now safely drains any clicks the native // SDK queued while we were detached, without losing them to a dead isolate. if (!clickListenerRequested) { - Logging.debug("[ISSUE-1138] OneSignalNotifications.onAttachedToActivity() — Dart never asked us to listen, skipping re-register", null); return; } // Same guard as onDetachedFromEngine (#1149): the first attach happens @@ -328,7 +319,6 @@ void onAttachedToActivity(BinaryMessenger activityMessenger) { if (!OneSignal.isInitialized()) { return; } - Logging.debug("[ISSUE-1138] OneSignalNotifications.onAttachedToActivity() — re-adding native click listener (queued events should drain)", null); OneSignal.getNotifications().removeClickListener(this); OneSignal.getNotifications().addClickListener(this); } @@ -344,7 +334,6 @@ private void lifecycleInit(Result result) { } private void registerClickListener() { - Logging.debug("[ISSUE-1138] OneSignalNotifications.registerClickListener() — Dart requested click listener", null); clickListenerRequested = true; OneSignal.getNotifications().removeClickListener(this); OneSignal.getNotifications().addClickListener(this); diff --git a/android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java b/android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java index 7ea1808f..3fb1a044 100644 --- a/android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java +++ b/android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java @@ -4,7 +4,6 @@ import androidx.annotation.NonNull; import com.onesignal.OneSignal; import com.onesignal.common.OneSignalWrapper; -import com.onesignal.debug.internal.logging.Logging; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.embedding.engine.plugins.activity.ActivityAware; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; @@ -41,13 +40,11 @@ private void init(Context context, BinaryMessenger messenger) { @Override public void onAttachedToEngine(@NonNull FlutterPlugin.FlutterPluginBinding flutterPluginBinding) { - Logging.debug("[ISSUE-1138] OneSignalPlugin.onAttachedToEngine()", null); init(flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger()); } @Override public void onDetachedFromEngine(@NonNull FlutterPlugin.FlutterPluginBinding binding) { - Logging.debug("[ISSUE-1138] OneSignalPlugin.onDetachedFromEngine()", null); onDetachedFromEngine(); } @@ -57,7 +54,6 @@ private void onDetachedFromEngine() { @Override public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { - Logging.debug("[ISSUE-1138] OneSignalPlugin.onAttachedToActivity()", null); this.context = binding.getActivity(); // Issue #1138: re-register native click listener now that the host // activity (and therefore the MethodChannel) is live again, so any @@ -69,7 +65,6 @@ public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { @Override public void onDetachedFromActivity() { - Logging.debug("[ISSUE-1138] OneSignalPlugin.onDetachedFromActivity()", null); // Issue #1138: unregister click listener while we have no host activity, // so the native SDK queues clicks (rather than dispatching them into a // MethodChannel whose JNI is detached) until a new MainActivity attaches. @@ -78,14 +73,12 @@ public void onDetachedFromActivity() { @Override public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { - Logging.debug("[ISSUE-1138] OneSignalPlugin.onReattachedToActivityForConfigChanges()", null); this.context = binding.getActivity(); OneSignalNotifications.getSharedInstance().onAttachedToActivity(this.messenger); } @Override public void onDetachedFromActivityForConfigChanges() { - Logging.debug("[ISSUE-1138] OneSignalPlugin.onDetachedFromActivityForConfigChanges()", null); OneSignalNotifications.getSharedInstance().onDetachedFromActivity(); } From 42cf004751aa23610ae8f826e4e7ffb47993b242 Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 14:18:21 -0700 Subject: [PATCH 05/20] docs(demo_fm): replace placeholder README --- examples/demo_fm/README.md | 76 +++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 10 deletions(-) diff --git a/examples/demo_fm/README.md b/examples/demo_fm/README.md index dbd403a0..d810b990 100644 --- a/examples/demo_fm/README.md +++ b/examples/demo_fm/README.md @@ -1,16 +1,72 @@ -# demo +# demo_fm — OneSignal + Firebase Messaging coexistence demo -A new Flutter project. +This is a variant of [`examples/demo`](../demo) that additionally wires in +**Firebase Cloud Messaging** (`firebase_core` + `firebase_messaging`) +alongside the OneSignal Flutter SDK. -## Getting Started +It exists to reproduce and validate fixes for +[issue #1138](https://github.com/OneSignal/OneSignal-Flutter-SDK/issues/1138): +on Android, `OneSignal.Notifications.addClickListener` could stop firing on +background/killed notification taps when `firebase_messaging` is present in +the same app. FCM in the app perturbs the Flutter engine / host activity +lifecycle, which surfaced a channel-binding bug in the plugin. -This project is a starting point for a Flutter application. +> Looking for the plain OneSignal sample? Use [`examples/demo`](../demo). +> Use this project only when you need the Firebase coexistence scenario. -A few resources to get you started if this is your first Flutter project: +## How `demo_fm` differs from `demo` -- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) +| Area | `examples/demo` | `examples/demo_fm` | +| --- | --- | --- | +| Dependencies | `onesignal_flutter` (in-tree, `path: ../../`) | same **plus** `firebase_core` + `firebase_messaging` | +| `lib/main.dart` | OneSignal init only | also `Firebase.initializeApp()`, a background FCM handler, an `onMessage` foreground listener, and an early `[ISSUE-1138]`-tagged `addClickListener` | +| Android Gradle | no Firebase plugin | applies `com.google.gms.google-services` in `android/settings.gradle.kts` + `android/app/build.gradle.kts` | +| Firebase config | not needed | **requires** `android/app/google-services.json` (per-developer, not committed — the build fails without it) | +| Purpose | general SDK sample | repro harness for #1138 (OneSignal + FCM coexistence) | -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +The actual SDK fix lives in the shared in-tree plugin +(`android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java` and +`OneSignalPlugin.java`), so **both** demos consume it via the `path: ../../` +dependency. `demo_fm` is what lets you exercise the Firebase-specific failure +path that originally hid the bug. + +## Setup + +This mirrors `demo`'s setup, with two extra Firebase requirements. + +1. Add your own Firebase project's `google-services.json` to + `examples/demo_fm/android/app/google-services.json`. The build will fail + without it (the `com.google.gms.google-services` plugin is wired in). It is + not committed because it is per-developer. + +2. Make sure the Firebase project's package name matches the Android + `applicationId` (`com.onesignal.example` by default). + +3. Put your OneSignal credentials in `examples/demo_fm/.env` + (see `.env.example`): + + ``` + ONESIGNAL_APP_ID=<your-app-id> + ONESIGNAL_API_KEY=<your-rest-api-key> + ``` + +4. Run on a real Android device (or emulator with Google Play services): + + ``` + cd examples/demo_fm + flutter pub get + flutter run -d <android-device> + ``` + +## Reproducing / verifying issue #1138 + +See [`ISSUE_1138_REPRO.md`](ISSUE_1138_REPRO.md) for the detailed +reproduction matrix (foreground / background / killed taps) and the +[`UPSTREAM_ISSUE_DRAFT.md`](UPSTREAM_ISSUE_DRAFT.md) for the related +OneSignal Android SDK manifest/FCM coexistence write-up. + +Quick check — watch for the click callback after tapping a notification: + +``` +adb logcat | rg -i 'clicked|addClickListener|ISSUE-1138' +``` From cb79e3044a848a3b92ba45df42f52d5046b0522d Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 14:18:58 -0700 Subject: [PATCH 06/20] chore(demo_fm): remove issue-1138 debug listeners --- examples/demo_fm/lib/main.dart | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/examples/demo_fm/lib/main.dart b/examples/demo_fm/lib/main.dart index a36e3e83..c566b747 100644 --- a/examples/demo_fm/lib/main.dart +++ b/examples/demo_fm/lib/main.dart @@ -63,15 +63,6 @@ Future<void> main() async { OneSignal.consentGiven(prefs.privacyConsent); await OneSignal.initialize(appId); - // Issue #1138 repro: register the click listener as early as possible, - // mirroring the snippet in the bug report. - OneSignal.Notifications.addClickListener((event) { - debugPrint( - '[ISSUE-1138] addClickListener fired: title="${event.notification.title}" ' - 'notifId=${event.notification.notificationId}', - ); - }); - OneSignal.LiveActivities.setupDefault( options: LiveActivitySetupOptions( enablePushToStart: true, @@ -100,10 +91,9 @@ Future<void> main() async { debugPrint('IAM clicked: ${event.result.actionId}'); }); - // Register notification listeners (second, "late" listener — kept to verify - // both early and late-registered listeners behave the same for issue #1138). + // Register notification listeners OneSignal.Notifications.addClickListener((event) { - debugPrint('[ISSUE-1138 late] addClickListener fired: ${event.notification.title}'); + debugPrint('Notification clicked: ${event.notification.title}'); }); OneSignal.Notifications.addForegroundWillDisplayListener((event) { debugPrint( From 8fcb5ab2c0165e17f850ba95219c401e9ec68e4d Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 14:42:04 -0700 Subject: [PATCH 07/20] docs(demo_fm): expand README, drop ISSUE_1138_REPRO.md --- examples/demo_fm/ISSUE_1138_REPRO.md | 183 --------------------------- examples/demo_fm/README.md | 81 +++++++++++- examples/demo_fm/lib/main.dart | 18 +++ 3 files changed, 92 insertions(+), 190 deletions(-) delete mode 100644 examples/demo_fm/ISSUE_1138_REPRO.md diff --git a/examples/demo_fm/ISSUE_1138_REPRO.md b/examples/demo_fm/ISSUE_1138_REPRO.md deleted file mode 100644 index 6fa12581..00000000 --- a/examples/demo_fm/ISSUE_1138_REPRO.md +++ /dev/null @@ -1,183 +0,0 @@ -# Issue #1138 reproduction — Branch B-2 (manifest-override-only variant) - -Branch: `fadi/issue-1138-manifest-override-only` - -This branch keeps the demo app on the **in-tree OneSignal SDK** (currently -`5.5.5` via `path: ../..`) and adds `firebase_core` + `firebase_messaging` -to mimic the affected users' setup in -[issue #1138](https://github.com/OneSignal/OneSignal-Flutter-SDK/issues/1138). - -Use this branch as the **suspected-broken case**. According to the users -in the issue, with this combo (OneSignal >= 5.4 + FCM in the same app) -`addClickListener` does not fire on Android when the app is in the -background, even though it fires correctly when the app is killed and -when the app is in the foreground. - -Companion control branch: `fadi/issue-1138-repro-5.3.4-with-firebase`, -which is the same demo with OneSignal pinned to 5.3.4. Diffing the two -branches isolates the change set introduced between 5.3.4 and 5.5.x. - -## Setup - -1. Add your own Firebase project's `google-services.json` to - `examples/demo_fm/android/app/google-services.json`. - - The `com.google.gms.google-services` Gradle plugin is wired in - (`android/settings.gradle.kts` and `android/app/build.gradle.kts`) so the - Android build will FAIL without this file. We do not commit one because it - is per-developer. - -2. Make sure the Firebase project's package name matches the Android - `applicationId` (`com.onesignal.example` by default in this demo). - -3. Configure your OneSignal app for FCM as usual (Server Key / V1 in - OneSignal dashboard) and put the OneSignal app id in - `examples/demo_fm/.env`: - - ``` - ONESIGNAL_APP_ID=<your-app-id> - ONESIGNAL_API_KEY=<your-rest-api-key> - ``` - -4. Run on a real Android device: - - ``` - cd examples/demo_fm - flutter pub get - flutter run -d <android-device> - ``` - -## Reproduction steps - -The click listener is registered **before `runApp`**, mirroring the snippet -in the issue: - -```dart -WidgetsFlutterBinding.ensureInitialized(); -await OneSignal.initialize(appId); -OneSignal.Notifications.addClickListener((event) { - debugPrint('[ISSUE-1138] addClickListener fired ...'); -}); -``` - -For each app state, send a push from the OneSignal dashboard and tap it: - -| State | Expected (per the bug report) | -| ------------------------------ | ------------------------------------- | -| Foreground | `[ISSUE-1138] addClickListener fired` | -| **Background (home button)** | **NO log line — bug reproduces** | -| Killed (swiped away) | `[ISSUE-1138] addClickListener fired` (some users see this fail too) | - -Watch `flutter logs` (or `adb logcat | grep ISSUE-1138`) to confirm whether -the callback runs. - -## Differences from `main` - -- `examples/demo_fm/pubspec.yaml`: added `firebase_core` + `firebase_messaging`. -- `examples/demo_fm/lib/main.dart`: Firebase initialization + FCM handlers, - early `addClickListener` registration tagged `[ISSUE-1138]`. -- `examples/demo_fm/android/{settings,app/build}.gradle.kts`: apply - `com.google.gms.google-services` plugin. - -## Experimental fixes to the SDK (also on this branch) - -### Fix 1 — click-listener lifecycle - -The change extends the defensive unsubscribe added in PR #1140 (5.5.4) to -also cover the case where the host activity is destroyed but the Flutter -engine survives. - -Files changed: - -- `android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java` - - Tracks whether Dart has requested a click listener. - - Adds `onAttachedToActivity()` / `onDetachedFromActivity()` that - add/remove the native-SDK click listener so clicks delivered while - the JNI is detached get queued by the native SDK instead of being - dispatched into a dead channel. -- `android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java` - - Wires the `ActivityAware` lifecycle (previously no-ops) into the - `OneSignalNotifications` hooks above, including the - config-change variants. -- Adds verbose lifecycle logging tagged `[ISSUE-1138]` to make the - attach/detach + dispatch ordering visible in `adb logcat`. - -### Fix 2 — `firebase_messaging` coexistence (manifest-override, no bridge service) - -This branch takes a different approach than its sibling -`fadi/issue-1138-repro-current-with-firebase`. Instead of adding a -competing `FirebaseMessagingService` that wins service dispatch and -fans the message out manually, we **address the root cause** by -removing the offending `<category>` filter from OneSignal Android SDK's -`FCMBroadcastReceiver` directly, via the Android manifest merger. - -Background: OneSignal's `FCMBroadcastReceiver` is registered with an -intent filter that requires a `<category>` matching the app package -name (e.g. `<category android:name="com.onesignal.example" />`). That -category was set on the GCM-era ordered broadcast but **modern FCM no -longer sets it**, so OneSignal's receiver never matches the broadcast -when a competing `FirebaseMessagingService` (e.g. FlutterFire's) takes -over the modern dispatch path. The result: OneSignal pushes silently -disappear. - -Files changed: - -- `android/src/main/AndroidManifest.xml` - - Re-declares the `com.onesignal.notifications.receivers.FCMBroadcastReceiver` - with `tools:node="replace"`, providing an intent-filter that has - only `<action android:name="com.google.android.c2dm.intent.RECEIVE" />` - — no `<category>`. The manifest merger replaces the AAR-bundled - receiver definition with ours because the Flutter plugin's manifest - has higher merge priority than the OneSignal Android SDK AAR's. - -Trade-offs vs. the bridge-service approach on the sibling branch: - -| | Bridge service (sibling branch) | Manifest override (this branch) | -| --- | --- | --- | -| Code surface | ~80 LOC of Java + new manifest service | ~10 LOC of manifest only | -| Failure mode if OneSignal SDK changes the receiver layout | Bridge still calls `FCMBroadcastReceiver.onReceive` — generally stable | `tools:node="replace"` may diverge from upstream if they add other attributes (e.g. a new intent-filter) | -| Failure mode if modern FCM stops sending the legacy broadcast | Bridge still works (we win the service path) | Receiver stops being called — needs a real upstream fix | -| Coexistence with other FCM SDKs in the same app | Generic — bridge sees all messages | Only fixes OneSignal — other SDKs still need their own fix if they have the same category-filter bug | -| Noise in logs | NPE on `goAsync().finish()` after each push (harmless) | None | - -The bridge wins on forward-compatibility (it doesn't rely on the legacy -broadcast continuing to exist). The manifest override wins on -simplicity and on producing a clean log surface. Either is a viable -band-aid until OneSignal Android SDK fixes the upstream manifest — see -`examples/demo_fm/UPSTREAM_ISSUE_DRAFT.md` for the proposed upstream -report. - -## Verifying the fixes - -After running on Android, filter logs by `[ISSUE-1138]`: - -``` -adb logcat | rg 'ISSUE-1138|FlutterJNI was detached|NotificationWorkManager|FLTFireMsgReceiver' -``` - -A healthy **foreground** push (with `firebase_messaging` present) should -now look like: - -``` -... OneSignal: NotificationWorkManager enqueueing notification work ... -... OneSignal: Fire notificationWillShowInForegroundHandler ... -... I flutter : [FCM fg] received: <msgId> ... (FlutterFire's onMessage fires) -... I flutter : Notification foreground will display: <title> (OneSignal foreground listener fires) -``` - -A healthy **background-tap** flow should look like: - -``` -[ISSUE-1138] OneSignalFcmServiceBridge.onMessageReceived ... -[ISSUE-1138] OneSignalPlugin.onDetachedFromActivity() -[ISSUE-1138] OneSignalNotifications.onDetachedFromActivity() — removing native click listener -... (user taps notification) ... -[ISSUE-1138] OneSignalPlugin.onAttachedToActivity() -[ISSUE-1138] OneSignalNotifications.onAttachedToActivity() — re-adding native click listener (queued events should drain) -[ISSUE-1138] OneSignalNotifications.onClick() — native SDK dispatched click; forwarding to MethodChannel -[ISSUE-1138 late] addClickListener fired: ... (from main.dart) -``` - -If you still see `W/FlutterJNI ... Channel: OneSignal#notifications` AND -no `[ISSUE-1138 late] addClickListener fired`, the fix didn't help in your -scenario — capture the surrounding 50 lines of logs and we'll iterate. diff --git a/examples/demo_fm/README.md b/examples/demo_fm/README.md index d810b990..3dd05fce 100644 --- a/examples/demo_fm/README.md +++ b/examples/demo_fm/README.md @@ -19,7 +19,7 @@ lifecycle, which surfaced a channel-binding bug in the plugin. | Area | `examples/demo` | `examples/demo_fm` | | --- | --- | --- | | Dependencies | `onesignal_flutter` (in-tree, `path: ../../`) | same **plus** `firebase_core` + `firebase_messaging` | -| `lib/main.dart` | OneSignal init only | also `Firebase.initializeApp()`, a background FCM handler, an `onMessage` foreground listener, and an early `[ISSUE-1138]`-tagged `addClickListener` | +| `lib/main.dart` | OneSignal init only | same OneSignal listeners **plus** `Firebase.initializeApp()`, a background FCM handler, `onMessage` / `onMessageOpenedApp` listeners, FCM token logging, and a `getInitialMessage()` check | | Android Gradle | no Firebase plugin | applies `com.google.gms.google-services` in `android/settings.gradle.kts` + `android/app/build.gradle.kts` | | Firebase config | not needed | **requires** `android/app/google-services.json` (per-developer, not committed — the build fails without it) | | Purpose | general SDK sample | repro harness for #1138 (OneSignal + FCM coexistence) | @@ -60,13 +60,80 @@ This mirrors `demo`'s setup, with two extra Firebase requirements. ## Reproducing / verifying issue #1138 -See [`ISSUE_1138_REPRO.md`](ISSUE_1138_REPRO.md) for the detailed -reproduction matrix (foreground / background / killed taps) and the -[`UPSTREAM_ISSUE_DRAFT.md`](UPSTREAM_ISSUE_DRAFT.md) for the related -OneSignal Android SDK manifest/FCM coexistence write-up. +Send a push from the OneSignal dashboard and tap it in each app state +(foreground / background / killed). The OneSignal `addClickListener` should +fire every time — watch for `Notification clicked:` in the logs. See +[`UPSTREAM_ISSUE_DRAFT.md`](UPSTREAM_ISSUE_DRAFT.md) for the related OneSignal +Android SDK manifest/FCM coexistence write-up. -Quick check — watch for the click callback after tapping a notification: +Quick check — watch for the click callback (and the other listeners) after +tapping a notification: ``` -adb logcat | rg -i 'clicked|addClickListener|ISSUE-1138' +adb logcat -c && adb logcat | rg -i 'Notification (clicked|foreground)|IAM |\[FCM' ``` + +## Testing with non-OneSignal (direct FCM) notifications + +Pushes sent from the **OneSignal dashboard** are rendered and handled by the +OneSignal SDK (you'll see `Notification clicked:` / `Notification foreground +will display:`). They are delivered as FCM **data** messages, so FlutterFire's +`onMessageOpenedApp` never fires for them. + +To exercise the **FlutterFire** path instead, send a message **directly through +FCM**, bypassing OneSignal. This is the right way to verify the two pipelines +coexist without interfering. + +### 1. Get the device FCM token + +`main.dart` logs it on startup: + +``` +adb logcat -c && adb logcat | rg '\[FCM token\]' +``` + +### 2. Send directly via the FCM HTTP v1 API + +`<PROJECT_ID>` is in `android/app/google-services.json` (`project_info.project_id`). +Get an access token from a service account JSON (Firebase console → Project +settings → Service accounts): + +```bash +ACCESS_TOKEN=$(gcloud auth application-default print-access-token) +PROJECT_ID=<your-firebase-project-id> +TOKEN=<device-fcm-token> +``` + +**Notification message** — shows a FlutterFire tray notification; tapping it +from the background fires `onMessageOpenedApp`, from the killed state it +arrives via `getInitialMessage()`: + +```bash +curl -X POST "https://fcm.googleapis.com/v1/projects/$PROJECT_ID/messages:send" \ + -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ + -d '{"message":{"token":"'"$TOKEN"'","notification":{"title":"FCM direct","body":"non-OneSignal push"}}}' +``` + +**Data-only message** — fires `onMessage` (foreground) / `onBackgroundMessage` +(background/killed): + +```bash +curl -X POST "https://fcm.googleapis.com/v1/projects/$PROJECT_ID/messages:send" \ + -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" \ + -d '{"message":{"token":"'"$TOKEN"'","android":{"priority":"high"},"data":{"alert":"data only","source":"fcm-direct"}}}' +``` + +(Or use Firebase console → Messaging → "Send test message" and paste the token +for a quick notification-message test.) + +### 3. Expected log lines for a direct FCM push + +| App state | Notification message | Data-only message | +| --- | --- | --- | +| Foreground | `[FCM fg] received` | `[FCM fg] received` | +| Background | tray shown; tap → `[FCM open] tapped` | `[FCM bg] received` | +| Killed | tray shown; tap → `[FCM initial] launched from tap` | `[FCM bg] received` | + +Note `onMessageOpenedApp` (`[FCM open]`) only fires for a **background** tap of +a notification message; a **killed**-state tap surfaces via `getInitialMessage()` +(`[FCM initial]`) instead. diff --git a/examples/demo_fm/lib/main.dart b/examples/demo_fm/lib/main.dart index c566b747..99253dc0 100644 --- a/examples/demo_fm/lib/main.dart +++ b/examples/demo_fm/lib/main.dart @@ -46,6 +46,24 @@ Future<void> main() async { FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { debugPrint('[FCM open] tapped: ${message.messageId} data=${message.data}'); }); + + // Log the device's FCM registration token so we can target it when + // sending non-OneSignal pushes directly through the FCM HTTP v1 API / + // Firebase console (see examples/demo_fm/README.md). + final fcmToken = await FirebaseMessaging.instance.getToken(); + debugPrint('[FCM token] $fcmToken'); + + // A direct FCM "notification" message tapped from the KILLED state does + // NOT fire onMessageOpenedApp — it's delivered here as the initial + // message instead. Without this, the cold-start direct-FCM tap is + // invisible in the logs. + final initialMessage = await FirebaseMessaging.instance.getInitialMessage(); + if (initialMessage != null) { + debugPrint( + '[FCM initial] launched from tap: ${initialMessage.messageId} ' + 'data=${initialMessage.data}', + ); + } debugPrint('Firebase initialized (issue #1138 repro)'); } catch (e) { debugPrint('Firebase init failed (drop google-services.json into android/app): $e'); From 5d72c7d28a071124da568efc09f4d722376f0925 Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 14:49:18 -0700 Subject: [PATCH 08/20] revert(android): remove FCM manifest workaround --- android/src/main/AndroidManifest.xml | 35 ------ examples/demo_fm/README.md | 4 +- examples/demo_fm/UPSTREAM_ISSUE_DRAFT.md | 129 ----------------------- 3 files changed, 1 insertion(+), 167 deletions(-) delete mode 100644 examples/demo_fm/UPSTREAM_ISSUE_DRAFT.md diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 893be882..16fb0728 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,38 +1,3 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" package="com.onesignal.flutter"> - <application> - <!-- - Issue #1138 — root-cause fix without a bridge service. - - OneSignal's FCMBroadcastReceiver in the OneSignal Android SDK declares - an intent filter that requires a <category> matching the app's package - name. That category was set on GCM-era ordered broadcasts but is no - longer set by modern FCM. As a result OneSignal's receiver never - matches the broadcast in apps that also have another FCM-aware plugin - (e.g. firebase_messaging / FlutterFire), and pushes are silently - dropped. - - The manifest merger lets a higher-priority manifest replace child - elements from a lower-priority one. The Flutter plugin's manifest is - merged into the consuming app's manifest at higher priority than the - OneSignal Android SDK AAR's, so re-declaring the receiver with - tools:node="replace" lets us strip the offending <category> while - preserving the rest of the receiver definition. - - If you need to debug, dump the merged manifest at - build/app/intermediates/merged_manifests/<variant>/ and confirm that - com.onesignal.notifications.receivers.FCMBroadcastReceiver's - intent-filter no longer contains the <category> element. - --> - <receiver - android:name="com.onesignal.notifications.receivers.FCMBroadcastReceiver" - android:exported="true" - android:permission="com.google.android.c2dm.permission.SEND" - tools:node="replace"> - <intent-filter android:priority="999"> - <action android:name="com.google.android.c2dm.intent.RECEIVE" /> - </intent-filter> - </receiver> - </application> </manifest> diff --git a/examples/demo_fm/README.md b/examples/demo_fm/README.md index 3dd05fce..e05d8531 100644 --- a/examples/demo_fm/README.md +++ b/examples/demo_fm/README.md @@ -62,9 +62,7 @@ This mirrors `demo`'s setup, with two extra Firebase requirements. Send a push from the OneSignal dashboard and tap it in each app state (foreground / background / killed). The OneSignal `addClickListener` should -fire every time — watch for `Notification clicked:` in the logs. See -[`UPSTREAM_ISSUE_DRAFT.md`](UPSTREAM_ISSUE_DRAFT.md) for the related OneSignal -Android SDK manifest/FCM coexistence write-up. +fire every time — watch for `Notification clicked:` in the logs. Quick check — watch for the click callback (and the other listeners) after tapping a notification: diff --git a/examples/demo_fm/UPSTREAM_ISSUE_DRAFT.md b/examples/demo_fm/UPSTREAM_ISSUE_DRAFT.md deleted file mode 100644 index 134bed13..00000000 --- a/examples/demo_fm/UPSTREAM_ISSUE_DRAFT.md +++ /dev/null @@ -1,129 +0,0 @@ -# Draft issue for `OneSignal/OneSignal-Android-SDK` - -Suggested title: - -> Notifications silently dropped on Android when app coexists with another `FirebaseMessagingService` (e.g. `firebase_messaging` / FlutterFire) - ---- - -## Summary - -`com.onesignal.notifications.receivers.FCMBroadcastReceiver` registers an -intent filter that requires both: - -```xml -<intent-filter android:priority="999"> - <action android:name="com.google.android.c2dm.intent.RECEIVE" /> - <category android:name="<APP_PACKAGE_NAME>" /> -</intent-filter> -``` - -The `<category>` requirement is a vestige from GCM, where each broadcast -carried the target app's package name as a category. **Modern FCM -(`firebase-messaging` 22.x+) no longer sets that category on its -broadcasts**, so the filter never matches and OneSignal's receiver is -silently skipped on apps that also have another `FirebaseMessagingService` -registered. - -The reason this is invisible in OneSignal-only apps is that GMS's own -`com.google.firebase.iid.FirebaseInstanceIdReceiver` (which has no -category filter) handles the broadcast and the modern service-dispatch -path routes the payload to OneSignal indirectly. As soon as a customer -adds an FCM-based plugin that registers its own -`FirebaseMessagingService` (FlutterFire's `firebase_messaging` being the -common case, but also `aws_amplify_push_notifications`, OEM SDKs, custom -services), that other service wins service-dispatch and OneSignal's -broadcast path stops being exercised. Net result: pushes "vanish" — no -foreground listener, no notification displayed, no click event. - -## Repro (Flutter, but architecture-level — same applies to any Android app) - -1. Empty Flutter app, add `onesignal_flutter: ^5.5.5` and - `firebase_messaging: ^15.2.10`. -2. Configure Firebase (`google-services.json`) and OneSignal as normal. -3. `await OneSignal.initialize(...)`. -4. Register both - ```dart - FirebaseMessaging.onMessage.listen((m) => print('[FCM] $m')); - OneSignal.Notifications.addForegroundWillDisplayListener((e) { - print('[OS fg] ${e.notification.title}'); - e.notification.display(); - }); - ``` -5. Send a push from the OneSignal dashboard with app in foreground. - -Observed: only `[FCM]` fires. No OneSignal log, no banner. -Expected: both fire; OneSignal shows the banner. - -Full Flutter-side reproduction (with `adb logcat` evidence) lives in -[OneSignal-Flutter-SDK#1138](https://github.com/OneSignal/OneSignal-Flutter-SDK/issues/1138) -and the `fadi/issue-1138-repro-current-with-firebase` branch there. - -## Why the existing manifest filter was OK in 2016 and isn't now - -| Era | How FCM/GCM routed to apps | What OneSignal's filter saw | -|---|---|---| -| GCM (≤2018) | Ordered broadcast with `<category>` matching app package | Matched, processed, optionally aborted | -| Early FCM | Same ordered broadcast, category still set | Matched | -| Modern FCM (firebase-messaging 22+) | Either service-only dispatch, OR an ordered broadcast WITHOUT the package category | Never matches | - -`firebase-messaging` source confirms it: `FirebaseInstanceIdReceiver` -has no category filter and is the de-facto sink for the broadcast. - -## Suggested fixes (any one of these unblocks customers) - -**(a) One-line manifest fix — preferred, fully backward-compatible** - -Drop the `<category>` element from `FCMBroadcastReceiver`'s intent -filter. The remaining `android:permission="com.google.android.c2dm.permission.SEND"` -plus the app-package-scoped delivery semantics of `c2dm.intent.RECEIVE` -already prevent cross-app spoofing. No customer code changes required. - -**(b) Modern entry point — service base class** - -Ship a public `OneSignalFirebaseMessagingService extends FirebaseMessagingService` -that customers can register at higher priority than competing services, -or extend in their own service: - -```java -public class MyService extends OneSignalFirebaseMessagingService { - @Override public void onMessageReceived(RemoteMessage m) { - super.onMessageReceived(m); // OneSignal handles its payloads - if (isMine(m)) handleMine(m); - } -} -``` - -**(c) Public ingestion API — most flexible for SDK-on-SDK coexistence** - -```java -OneSignal.getNotifications().handleRemoteMessage(remoteMessage); -``` - -Callable from any `FirebaseMessagingService.onMessageReceived`. This is -what the OneSignal Flutter SDK is currently re-implementing in -[OneSignalFcmServiceBridge](https://github.com/OneSignal/OneSignal-Flutter-SDK/blob/fadi/issue-1138-repro-current-with-firebase/android/src/main/java/com/onesignal/flutter/OneSignalFcmServiceBridge.java) -by synthesizing a `c2dm.intent.RECEIVE` `Intent` and feeding it back -into `FCMBroadcastReceiver.onReceive` — which works but produces a noisy -`NullPointerException` on the receiver's `goAsync().finish()` tail -because that call is meaningless outside of a real ordered broadcast. - -## Reference workaround (Flutter plugin, until upstream lands) - -See `android/src/main/AndroidManifest.xml` and -`android/src/main/java/com/onesignal/flutter/OneSignalFcmServiceBridge.java` -on the -[`fadi/issue-1138-repro-current-with-firebase`](https://github.com/OneSignal/OneSignal-Flutter-SDK/tree/fadi/issue-1138-repro-current-with-firebase) -branch. The plugin registers its own `FirebaseMessagingService` at -`android:priority="100"`, wins the modern service dispatch race, and -synthesizes the legacy intent to feed the OneSignal SDK. This is a -band-aid we'd happily delete the moment any of (a)/(b)/(c) lands. - -## Severity - -This affects every OneSignal Android customer who also uses any other -FCM plugin or service — most Flutter + push deployments fall in this -bucket. The failure mode is silent (no exception, no log line, no -notification), so it's high-cost to diagnose and easy to misattribute -to OneSignal's foreground-listener bridge (which is the symptom, not -the cause). From b518cbcc21c2c99936fa80f7e22d190b6813e3cf Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 15:48:14 -0700 Subject: [PATCH 09/20] fix(android): extend channel-rebind fix to all singletons & guard bg detach Address PR review: - Apply the same idempotent registerWith guard + onAttachedToActivity rebind to OneSignalUser, OneSignalPushSubscription, and OneSignalInAppMessages, so a FlutterFire background engine can't clobber their channels and drop onUserStateChange / onPushSubscriptionChange / IAM lifecycle callbacks. - Gate OneSignalNotifications.onDetachedFromEngine on the detaching engine's messenger so a background engine teardown no longer removes the click listener bound to the live UI engine. - Tighten the #1138 lifecycle comments. Co-authored-by: Cursor <cursoragent@cursor.com> --- .../flutter/OneSignalInAppMessages.java | 20 ++++- .../flutter/OneSignalNotifications.java | 80 ++++++------------- .../onesignal/flutter/OneSignalPlugin.java | 31 +++---- .../flutter/OneSignalPushSubscription.java | 19 +++++ .../com/onesignal/flutter/OneSignalUser.java | 19 +++++ 5 files changed, 98 insertions(+), 71 deletions(-) diff --git a/android/src/main/java/com/onesignal/flutter/OneSignalInAppMessages.java b/android/src/main/java/com/onesignal/flutter/OneSignalInAppMessages.java index 6fe3ecb8..39907fe2 100644 --- a/android/src/main/java/com/onesignal/flutter/OneSignalInAppMessages.java +++ b/android/src/main/java/com/onesignal/flutter/OneSignalInAppMessages.java @@ -33,12 +33,30 @@ private OneSignalInAppMessages() {} static void registerWith(BinaryMessenger messenger) { OneSignalInAppMessages controller = getSharedInstance(); - + // #1138: bind only on the first engine so FlutterFire's headless background + // engine can't rebind the shared channel and drop IAM lifecycle callbacks. + if (controller.channel != null) { + return; + } controller.messenger = messenger; controller.channel = new MethodChannel(messenger, "OneSignal#inappmessages"); controller.channel.setMethodCallHandler(controller); } + /** + * #1138: rebind the shared channel to the engine hosting the activity (the UI + * isolate). Safe to re-add eagerly here — the Dart handler is registered at + * startup, not deferred behind a user API. + */ + void onAttachedToActivity(BinaryMessenger activityMessenger) { + if (activityMessenger == null || activityMessenger == this.messenger) { + return; + } + this.messenger = activityMessenger; + this.channel = new MethodChannel(activityMessenger, "OneSignal#inappmessages"); + this.channel.setMethodCallHandler(this); + } + @Override public void onMethodCall(MethodCall call, Result result) { if (call.method.contentEquals("OneSignal#addTrigger")) this.addTriggers(call, result); diff --git a/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java b/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java index 3342bec3..09534084 100644 --- a/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java +++ b/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java @@ -29,14 +29,8 @@ public class OneSignalNotifications extends FlutterMessengerResponder private final HashMap<String, INotificationWillDisplayEvent> notificationOnWillDisplayEventCache = new HashMap<>(); private final HashMap<String, INotificationWillDisplayEvent> preventedDefaultCache = new HashMap<>(); - // Tracks whether Dart has asked us to be subscribed to click events. We - // toggle the native-SDK subscription on/off across Flutter engine + host - // activity lifecycles so that, while the channel is detached, click events - // get queued by the native SDK instead of dispatched into a dead JNI. - // Issue #1138 — Android `addClickListener` silently dropped on - // background notification tap when host activity has been destroyed - // (e.g. while running alongside firebase_messaging which can perturb - // the Flutter engine lifecycle). + // #1138: tracks if Dart requested clicks, so we can queue (not drop) them + // while the channel is detached across engine/activity lifecycles. private boolean clickListenerRequested = false; public static OneSignalNotifications getSharedInstance() { @@ -83,15 +77,9 @@ public void resumeWith(@NonNull Object o) { static void registerWith(BinaryMessenger messenger) { OneSignalNotifications controller = getSharedInstance(); - // Issue #1138: OneSignalNotifications is a process-global singleton, but - // registerWith is invoked once per Flutter engine. When firebase_messaging - // is present, FlutterFire spins up a headless background FlutterEngine and - // GeneratedPluginRegistrant registers us against it too — which would - // otherwise REBIND the shared channel to the background isolate (that never - // ran main() and has no listeners), so native click/willDisplay callbacks - // were silently routed there and dropped. Only bind on the first engine; - // the authoritative binding is (re)asserted from onAttachedToActivity so - // the channel always points at the engine that actually hosts the UI. + // #1138: bind only on the first engine. FlutterFire's headless background + // engine also registers us; rebinding to it (no listeners) drops callbacks. + // onAttachedToActivity reasserts the binding to the UI engine. if (controller.channel != null) { return; } @@ -249,29 +237,26 @@ public void onNotificationPermissionChange(boolean permission) { invokeMethodOnUiThread("OneSignal#onNotificationPermissionDidChange", hash); } - void onDetachedFromEngine() { - // The Flutter engine can be torn down before OneSignal.initialize() has been - // called from Dart (cold start, fast finish, etc.). Calling getNotifications() - // in that state throws IllegalStateException from the native SDK. See #1149. + void onDetachedFromEngine(BinaryMessenger detachingMessenger) { + // #1138: ignore a FlutterFire background engine detaching — removing the + // listener bound to the live UI engine would drop the next click (the UI + // engine fires no activity event, so nothing re-adds it). + if (detachingMessenger != null && detachingMessenger != this.messenger) { + return; + } + // #1149: engine can be torn down before Dart calls initialize(). if (!OneSignal.isInitialized()) { return; } - // Unsubscribe so clicks while the engine is dead get queued by the native SDK - // instead of dispatched on a detached channel. + // Unsubscribe so clicks get queued by the native SDK, not dropped. OneSignal.getNotifications().removeClickListener(this); } /** - * Called from {@link OneSignalPlugin#onDetachedFromActivity()} to extend the - * defensive unsubscribe to the case where the Flutter engine survives but the - * host activity is destroyed (e.g. user back-pressed out of MainActivity but - * the engine is cached). Without this, clicks delivered to - * {@link com.onesignal.notifications.activities.NotificationOpenedActivity} - * before the new MainActivity attaches go to a detached JNI and are dropped. + * Same as {@link #onDetachedFromEngine} but for when the engine survives and + * only the host activity is destroyed (e.g. back-pressed out of MainActivity). */ void onDetachedFromActivity() { - // Same guard as onDetachedFromEngine (#1149): activity can be torn down - // before OneSignal.initialize() has been called from Dart. if (!OneSignal.isInitialized()) { return; } @@ -279,43 +264,26 @@ void onDetachedFromActivity() { } /** - * Called from {@link OneSignalPlugin#onAttachedToActivity} after a (re)attach. - * If Dart had previously asked us to listen for clicks (via the - * `OneSignal#addNativeClickListener` MethodChannel call), re-register the - * native listener so any clicks queued by the native SDK while we were - * detached get drained now that the channel is live again. + * #1138: rebind the shared channel to the UI engine on (re)attach and drain + * any clicks the native SDK queued while detached. */ void onAttachedToActivity(BinaryMessenger activityMessenger) { - // Issue #1138: the engine that owns the host activity is the one whose - // Dart isolate ran main() and registered the user's listeners. Re-bind the - // shared channel to THIS engine's messenger so native click/willDisplay - // callbacks are dispatched to the UI isolate — even if a background engine - // (FlutterFire) attached after us and we kept the original binding. boolean engineChanged = activityMessenger != null && activityMessenger != this.messenger; if (engineChanged) { + // New engine: rebind so callbacks hit the UI isolate. Don't re-add the + // listener yet — its Dart end hasn't run main(); replaying a queued click + // now would drop it. Dart calls OneSignal#addNativeClickListener once + // ready, which drains the queue then. this.messenger = activityMessenger; this.channel = new MethodChannel(activityMessenger, "OneSignal#notifications"); this.channel.setMethodCallHandler(this); - // The new engine's Dart isolate has NOT re-run main()/registerClickListener - // yet, so its MethodChannel handler is not registered. Re-adding the native - // click listener now would make the native SDK replay any queued click - // immediately — into a channel whose Dart end isn't listening — and the - // click would be dropped (see #1138 back-button-then-tap repro). Dart will - // call OneSignal#addNativeClickListener once it re-initializes, which drains - // the native queue at the point the isolate is actually ready to receive. return; } - // Same engine: the activity reattached while the Flutter engine and its Dart - // isolate stayed alive (config change, or cached-engine resume). The Dart - // handler is still live, so re-adding now safely drains any clicks the native - // SDK queued while we were detached, without losing them to a dead isolate. + // Same engine (config change / cached-engine resume): Dart handler is live, + // so re-adding now safely drains queued clicks. if (!clickListenerRequested) { return; } - // Same guard as onDetachedFromEngine (#1149): the first attach happens - // before Dart has had a chance to call OneSignal.initialize(), but in - // that case clickListenerRequested is also false, so we're already - // skipped above. Keep the guard anyway as defense-in-depth. if (!OneSignal.isInitialized()) { return; } diff --git a/android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java b/android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java index 3fb1a044..c01c72d2 100644 --- a/android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java +++ b/android/src/main/java/com/onesignal/flutter/OneSignalPlugin.java @@ -45,36 +45,39 @@ public void onAttachedToEngine(@NonNull FlutterPlugin.FlutterPluginBinding flutt @Override public void onDetachedFromEngine(@NonNull FlutterPlugin.FlutterPluginBinding binding) { - onDetachedFromEngine(); - } - - private void onDetachedFromEngine() { - OneSignalNotifications.getSharedInstance().onDetachedFromEngine(); + // #1138: pass the detaching engine's messenger so a background (FlutterFire) + // engine detaching doesn't tear down the listener bound to the UI engine. + OneSignalNotifications.getSharedInstance().onDetachedFromEngine(binding.getBinaryMessenger()); } @Override public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { this.context = binding.getActivity(); - // Issue #1138: re-register native click listener now that the host - // activity (and therefore the MethodChannel) is live again, so any - // clicks the native SDK queued while we were detached get drained. - // Pass this engine's messenger so the shared channel is (re)bound to the - // UI isolate rather than a FlutterFire background engine. - OneSignalNotifications.getSharedInstance().onAttachedToActivity(this.messenger); + rebindChannelsToActivityEngine(); } @Override public void onDetachedFromActivity() { - // Issue #1138: unregister click listener while we have no host activity, - // so the native SDK queues clicks (rather than dispatching them into a - // MethodChannel whose JNI is detached) until a new MainActivity attaches. + // #1138: unregister so the native SDK queues clicks until a new activity attaches. OneSignalNotifications.getSharedInstance().onDetachedFromActivity(); } @Override public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { this.context = binding.getActivity(); + rebindChannelsToActivityEngine(); + } + + /** + * #1138: (re)bind the process-global singleton channels to the engine that + * hosts the activity (the UI isolate), so native callbacks aren't routed to a + * FlutterFire background engine that has no listeners. + */ + private void rebindChannelsToActivityEngine() { OneSignalNotifications.getSharedInstance().onAttachedToActivity(this.messenger); + OneSignalUser.getSharedInstance().onAttachedToActivity(this.messenger); + OneSignalPushSubscription.getSharedInstance().onAttachedToActivity(this.messenger); + OneSignalInAppMessages.getSharedInstance().onAttachedToActivity(this.messenger); } @Override diff --git a/android/src/main/java/com/onesignal/flutter/OneSignalPushSubscription.java b/android/src/main/java/com/onesignal/flutter/OneSignalPushSubscription.java index bb5bdc2e..17e8a61a 100644 --- a/android/src/main/java/com/onesignal/flutter/OneSignalPushSubscription.java +++ b/android/src/main/java/com/onesignal/flutter/OneSignalPushSubscription.java @@ -26,11 +26,30 @@ private OneSignalPushSubscription() {} static void registerWith(BinaryMessenger messenger) { OneSignalPushSubscription controller = getSharedInstance(); + // #1138: bind only on the first engine so FlutterFire's headless background + // engine can't rebind the shared channel and drop onPushSubscriptionChange. + if (controller.channel != null) { + return; + } controller.messenger = messenger; controller.channel = new MethodChannel(messenger, "OneSignal#pushsubscription"); controller.channel.setMethodCallHandler(controller); } + /** + * #1138: rebind the shared channel to the engine hosting the activity (the UI + * isolate). Safe to re-add eagerly here — the Dart handler is registered at + * startup, not deferred behind a user API. + */ + void onAttachedToActivity(BinaryMessenger activityMessenger) { + if (activityMessenger == null || activityMessenger == this.messenger) { + return; + } + this.messenger = activityMessenger; + this.channel = new MethodChannel(activityMessenger, "OneSignal#pushsubscription"); + this.channel.setMethodCallHandler(this); + } + @Override public void onMethodCall(MethodCall call, Result result) { if (call.method.contentEquals("OneSignal#optIn")) this.optIn(call, result); diff --git a/android/src/main/java/com/onesignal/flutter/OneSignalUser.java b/android/src/main/java/com/onesignal/flutter/OneSignalUser.java index 2a7c894b..a3f71942 100644 --- a/android/src/main/java/com/onesignal/flutter/OneSignalUser.java +++ b/android/src/main/java/com/onesignal/flutter/OneSignalUser.java @@ -27,11 +27,30 @@ private OneSignalUser() {} static void registerWith(BinaryMessenger messenger) { OneSignalUser controller = getSharedInstance(); + // #1138: bind only on the first engine so FlutterFire's headless background + // engine can't rebind the shared channel and drop onUserStateChange. + if (controller.channel != null) { + return; + } controller.messenger = messenger; controller.channel = new MethodChannel(messenger, "OneSignal#user"); controller.channel.setMethodCallHandler(controller); } + /** + * #1138: rebind the shared channel to the engine hosting the activity (the UI + * isolate). Safe to re-add eagerly here — the Dart handler is registered at + * startup, not deferred behind a user API. + */ + void onAttachedToActivity(BinaryMessenger activityMessenger) { + if (activityMessenger == null || activityMessenger == this.messenger) { + return; + } + this.messenger = activityMessenger; + this.channel = new MethodChannel(activityMessenger, "OneSignal#user"); + this.channel.setMethodCallHandler(this); + } + @Override public void onMethodCall(MethodCall call, Result result) { if (call.method.contentEquals("OneSignal#setLanguage")) this.setLanguage(call, result); From a7c2d1eda0e28311165b51991d4a001d9b1d67f8 Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 16:27:49 -0700 Subject: [PATCH 10/20] fix(demo): use message.messageId in IAM click listener --- examples/demo/lib/main.dart | 2 +- examples/demo_fm/lib/main.dart | 2 +- examples/demo_pods/lib/main.dart | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/demo/lib/main.dart b/examples/demo/lib/main.dart index 898f1712..9075802c 100644 --- a/examples/demo/lib/main.dart +++ b/examples/demo/lib/main.dart @@ -59,7 +59,7 @@ Future<void> main() async { debugPrint('IAM did dismiss: ${event.message.messageId}'); }); OneSignal.InAppMessages.addClickListener((event) { - debugPrint('IAM clicked: ${event.result.actionId}'); + debugPrint('IAM clicked: ${event.message.messageId}'); }); // Register notification listeners diff --git a/examples/demo_fm/lib/main.dart b/examples/demo_fm/lib/main.dart index 99253dc0..6e08b534 100644 --- a/examples/demo_fm/lib/main.dart +++ b/examples/demo_fm/lib/main.dart @@ -106,7 +106,7 @@ Future<void> main() async { debugPrint('IAM did dismiss: ${event.message.messageId}'); }); OneSignal.InAppMessages.addClickListener((event) { - debugPrint('IAM clicked: ${event.result.actionId}'); + debugPrint('IAM clicked: ${event.message.messageId}'); }); // Register notification listeners diff --git a/examples/demo_pods/lib/main.dart b/examples/demo_pods/lib/main.dart index 898f1712..9075802c 100644 --- a/examples/demo_pods/lib/main.dart +++ b/examples/demo_pods/lib/main.dart @@ -59,7 +59,7 @@ Future<void> main() async { debugPrint('IAM did dismiss: ${event.message.messageId}'); }); OneSignal.InAppMessages.addClickListener((event) { - debugPrint('IAM clicked: ${event.result.actionId}'); + debugPrint('IAM clicked: ${event.message.messageId}'); }); // Register notification listeners From e81be6c0a9c68719c0edf6a5313b01aa0186e06e Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 16:34:20 -0700 Subject: [PATCH 11/20] refactor(android): dedupe channel bind/rebind into base helpers Address PR review nit: extract the repeated registerWith guard and onAttachedToActivity rebind logic into bindChannelIfUnbound and rebindChannelToEngine on FlutterMessengerResponder, used by all four singletons. Co-authored-by: Cursor <cursoragent@cursor.com> --- .../flutter/FlutterMessengerResponder.java | 36 +++++++++++++++++++ .../flutter/OneSignalInAppMessages.java | 22 ++---------- .../flutter/OneSignalNotifications.java | 24 ++++--------- .../flutter/OneSignalPushSubscription.java | 22 ++---------- .../com/onesignal/flutter/OneSignalUser.java | 22 ++---------- 5 files changed, 48 insertions(+), 78 deletions(-) diff --git a/android/src/main/java/com/onesignal/flutter/FlutterMessengerResponder.java b/android/src/main/java/com/onesignal/flutter/FlutterMessengerResponder.java index 8c739f6e..f220c0d6 100644 --- a/android/src/main/java/com/onesignal/flutter/FlutterMessengerResponder.java +++ b/android/src/main/java/com/onesignal/flutter/FlutterMessengerResponder.java @@ -5,6 +5,7 @@ import android.os.Looper; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodChannel; +import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import java.util.HashMap; abstract class FlutterMessengerResponder { @@ -12,6 +13,41 @@ abstract class FlutterMessengerResponder { protected MethodChannel channel; BinaryMessenger messenger; + /** + * #1138: bind the shared channel only on the first engine. These responders are + * process-global singletons but {@code registerWith} runs once per Flutter + * engine; FlutterFire's headless background engine would otherwise rebind the + * channel to an isolate with no listeners and drop native callbacks. + * + * @return true if this call performed the initial bind. + */ + boolean bindChannelIfUnbound(BinaryMessenger messenger, String channelName, MethodCallHandler handler) { + if (this.channel != null) { + return false; + } + this.messenger = messenger; + this.channel = new MethodChannel(messenger, channelName); + this.channel.setMethodCallHandler(handler); + return true; + } + + /** + * #1138: reassert the channel binding to the engine that hosts the activity (the + * UI isolate), in case a background engine attached after us. No-op if the + * messenger is unchanged. + * + * @return true if the channel was rebound to a different engine. + */ + boolean rebindChannelToEngine(BinaryMessenger activityMessenger, String channelName, MethodCallHandler handler) { + if (activityMessenger == null || activityMessenger == this.messenger) { + return false; + } + this.messenger = activityMessenger; + this.channel = new MethodChannel(activityMessenger, channelName); + this.channel.setMethodCallHandler(handler); + return true; + } + /** * MethodChannel class is home to success() method used by Result class * It has the @UiThread annotation and must be run on UI thread, otherwise a RuntimeException will be thrown diff --git a/android/src/main/java/com/onesignal/flutter/OneSignalInAppMessages.java b/android/src/main/java/com/onesignal/flutter/OneSignalInAppMessages.java index 39907fe2..c23f5634 100644 --- a/android/src/main/java/com/onesignal/flutter/OneSignalInAppMessages.java +++ b/android/src/main/java/com/onesignal/flutter/OneSignalInAppMessages.java @@ -11,7 +11,6 @@ import com.onesignal.inAppMessages.IInAppMessageWillDisplayEvent; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; import java.util.Collection; @@ -33,28 +32,11 @@ private OneSignalInAppMessages() {} static void registerWith(BinaryMessenger messenger) { OneSignalInAppMessages controller = getSharedInstance(); - // #1138: bind only on the first engine so FlutterFire's headless background - // engine can't rebind the shared channel and drop IAM lifecycle callbacks. - if (controller.channel != null) { - return; - } - controller.messenger = messenger; - controller.channel = new MethodChannel(messenger, "OneSignal#inappmessages"); - controller.channel.setMethodCallHandler(controller); + controller.bindChannelIfUnbound(messenger, "OneSignal#inappmessages", controller); } - /** - * #1138: rebind the shared channel to the engine hosting the activity (the UI - * isolate). Safe to re-add eagerly here — the Dart handler is registered at - * startup, not deferred behind a user API. - */ void onAttachedToActivity(BinaryMessenger activityMessenger) { - if (activityMessenger == null || activityMessenger == this.messenger) { - return; - } - this.messenger = activityMessenger; - this.channel = new MethodChannel(activityMessenger, "OneSignal#inappmessages"); - this.channel.setMethodCallHandler(this); + rebindChannelToEngine(activityMessenger, "OneSignal#inappmessages", this); } @Override diff --git a/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java b/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java index 09534084..07ff665b 100644 --- a/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java +++ b/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java @@ -77,15 +77,7 @@ public void resumeWith(@NonNull Object o) { static void registerWith(BinaryMessenger messenger) { OneSignalNotifications controller = getSharedInstance(); - // #1138: bind only on the first engine. FlutterFire's headless background - // engine also registers us; rebinding to it (no listeners) drops callbacks. - // onAttachedToActivity reasserts the binding to the UI engine. - if (controller.channel != null) { - return; - } - controller.messenger = messenger; - controller.channel = new MethodChannel(messenger, "OneSignal#notifications"); - controller.channel.setMethodCallHandler(controller); + controller.bindChannelIfUnbound(messenger, "OneSignal#notifications", controller); } @Override @@ -268,15 +260,11 @@ void onDetachedFromActivity() { * any clicks the native SDK queued while detached. */ void onAttachedToActivity(BinaryMessenger activityMessenger) { - boolean engineChanged = activityMessenger != null && activityMessenger != this.messenger; - if (engineChanged) { - // New engine: rebind so callbacks hit the UI isolate. Don't re-add the - // listener yet — its Dart end hasn't run main(); replaying a queued click - // now would drop it. Dart calls OneSignal#addNativeClickListener once - // ready, which drains the queue then. - this.messenger = activityMessenger; - this.channel = new MethodChannel(activityMessenger, "OneSignal#notifications"); - this.channel.setMethodCallHandler(this); + if (rebindChannelToEngine(activityMessenger, "OneSignal#notifications", this)) { + // New engine: rebound above so callbacks hit the UI isolate. Don't re-add + // the listener yet — its Dart end hasn't run main(); replaying a queued + // click now would drop it. Dart calls OneSignal#addNativeClickListener + // once ready, which drains the queue then. return; } // Same engine (config change / cached-engine resume): Dart handler is live, diff --git a/android/src/main/java/com/onesignal/flutter/OneSignalPushSubscription.java b/android/src/main/java/com/onesignal/flutter/OneSignalPushSubscription.java index 17e8a61a..498d0eae 100644 --- a/android/src/main/java/com/onesignal/flutter/OneSignalPushSubscription.java +++ b/android/src/main/java/com/onesignal/flutter/OneSignalPushSubscription.java @@ -6,7 +6,6 @@ import com.onesignal.user.subscriptions.PushSubscriptionChangedState; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; import org.json.JSONException; @@ -26,28 +25,11 @@ private OneSignalPushSubscription() {} static void registerWith(BinaryMessenger messenger) { OneSignalPushSubscription controller = getSharedInstance(); - // #1138: bind only on the first engine so FlutterFire's headless background - // engine can't rebind the shared channel and drop onPushSubscriptionChange. - if (controller.channel != null) { - return; - } - controller.messenger = messenger; - controller.channel = new MethodChannel(messenger, "OneSignal#pushsubscription"); - controller.channel.setMethodCallHandler(controller); + controller.bindChannelIfUnbound(messenger, "OneSignal#pushsubscription", controller); } - /** - * #1138: rebind the shared channel to the engine hosting the activity (the UI - * isolate). Safe to re-add eagerly here — the Dart handler is registered at - * startup, not deferred behind a user API. - */ void onAttachedToActivity(BinaryMessenger activityMessenger) { - if (activityMessenger == null || activityMessenger == this.messenger) { - return; - } - this.messenger = activityMessenger; - this.channel = new MethodChannel(activityMessenger, "OneSignal#pushsubscription"); - this.channel.setMethodCallHandler(this); + rebindChannelToEngine(activityMessenger, "OneSignal#pushsubscription", this); } @Override diff --git a/android/src/main/java/com/onesignal/flutter/OneSignalUser.java b/android/src/main/java/com/onesignal/flutter/OneSignalUser.java index a3f71942..5a4f7995 100644 --- a/android/src/main/java/com/onesignal/flutter/OneSignalUser.java +++ b/android/src/main/java/com/onesignal/flutter/OneSignalUser.java @@ -6,7 +6,6 @@ import com.onesignal.user.state.UserChangedState; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; import java.util.List; @@ -27,28 +26,11 @@ private OneSignalUser() {} static void registerWith(BinaryMessenger messenger) { OneSignalUser controller = getSharedInstance(); - // #1138: bind only on the first engine so FlutterFire's headless background - // engine can't rebind the shared channel and drop onUserStateChange. - if (controller.channel != null) { - return; - } - controller.messenger = messenger; - controller.channel = new MethodChannel(messenger, "OneSignal#user"); - controller.channel.setMethodCallHandler(controller); + controller.bindChannelIfUnbound(messenger, "OneSignal#user", controller); } - /** - * #1138: rebind the shared channel to the engine hosting the activity (the UI - * isolate). Safe to re-add eagerly here — the Dart handler is registered at - * startup, not deferred behind a user API. - */ void onAttachedToActivity(BinaryMessenger activityMessenger) { - if (activityMessenger == null || activityMessenger == this.messenger) { - return; - } - this.messenger = activityMessenger; - this.channel = new MethodChannel(activityMessenger, "OneSignal#user"); - this.channel.setMethodCallHandler(this); + rebindChannelToEngine(activityMessenger, "OneSignal#user", this); } @Override From 6aa8f9b9c5b36854ecb50a5af43a629a1e81a8bb Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 16:39:58 -0700 Subject: [PATCH 12/20] chore(demo): improve push subscription debug logging --- examples/demo/lib/viewmodels/app_viewmodel.dart | 10 +++++++++- examples/demo_fm/lib/viewmodels/app_viewmodel.dart | 10 +++++++++- examples/demo_pods/lib/viewmodels/app_viewmodel.dart | 10 +++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/examples/demo/lib/viewmodels/app_viewmodel.dart b/examples/demo/lib/viewmodels/app_viewmodel.dart index 18f7a086..afb89005 100644 --- a/examples/demo/lib/viewmodels/app_viewmodel.dart +++ b/examples/demo/lib/viewmodels/app_viewmodel.dart @@ -162,8 +162,16 @@ class AppViewModel extends ChangeNotifier { OneSignal.User.pushSubscription.addObserver((state) { _pushSubscriptionId = state.current.id; _pushEnabled = state.current.optedIn; + String fmtToken(String? t) { + if (t == null || t.isEmpty) return 'null'; + return t.length > 8 ? '${t.substring(0, 8)}…' : t; + } + debugPrint( - 'Push subscription changed: id=${state.current.id}, optedIn=${state.current.optedIn}', + 'Push subscription changed: ' + 'id=${state.previous.id ?? 'null'} → ${state.current.id ?? 'null'}, ' + 'optedIn=${state.previous.optedIn} → ${state.current.optedIn}, ' + 'token=${fmtToken(state.previous.token)} → ${fmtToken(state.current.token)}', ); notifyListeners(); }); diff --git a/examples/demo_fm/lib/viewmodels/app_viewmodel.dart b/examples/demo_fm/lib/viewmodels/app_viewmodel.dart index 18f7a086..afb89005 100644 --- a/examples/demo_fm/lib/viewmodels/app_viewmodel.dart +++ b/examples/demo_fm/lib/viewmodels/app_viewmodel.dart @@ -162,8 +162,16 @@ class AppViewModel extends ChangeNotifier { OneSignal.User.pushSubscription.addObserver((state) { _pushSubscriptionId = state.current.id; _pushEnabled = state.current.optedIn; + String fmtToken(String? t) { + if (t == null || t.isEmpty) return 'null'; + return t.length > 8 ? '${t.substring(0, 8)}…' : t; + } + debugPrint( - 'Push subscription changed: id=${state.current.id}, optedIn=${state.current.optedIn}', + 'Push subscription changed: ' + 'id=${state.previous.id ?? 'null'} → ${state.current.id ?? 'null'}, ' + 'optedIn=${state.previous.optedIn} → ${state.current.optedIn}, ' + 'token=${fmtToken(state.previous.token)} → ${fmtToken(state.current.token)}', ); notifyListeners(); }); diff --git a/examples/demo_pods/lib/viewmodels/app_viewmodel.dart b/examples/demo_pods/lib/viewmodels/app_viewmodel.dart index 1d5e5715..4d59c6b9 100644 --- a/examples/demo_pods/lib/viewmodels/app_viewmodel.dart +++ b/examples/demo_pods/lib/viewmodels/app_viewmodel.dart @@ -165,8 +165,16 @@ class AppViewModel extends ChangeNotifier { OneSignal.User.pushSubscription.addObserver((state) { _pushSubscriptionId = state.current.id; _pushEnabled = state.current.optedIn; + String fmtToken(String? t) { + if (t == null || t.isEmpty) return 'null'; + return t.length > 8 ? '${t.substring(0, 8)}…' : t; + } + debugPrint( - 'Push subscription changed: id=${state.current.id}, optedIn=${state.current.optedIn}', + 'Push subscription changed: ' + 'id=${state.previous.id ?? 'null'} → ${state.current.id ?? 'null'}, ' + 'optedIn=${state.previous.optedIn} → ${state.current.optedIn}, ' + 'token=${fmtToken(state.previous.token)} → ${fmtToken(state.current.token)}', ); notifyListeners(); }); From 5e4791b6d627c985ed2db13ca944bbfc7fd3aaf5 Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 15:06:16 -0700 Subject: [PATCH 13/20] chore(demo_fm): add direct-FCM send script Add tools/send_fcm.sh to send non-OneSignal pushes via the FCM HTTP v1 API (notif/data modes) for exercising the FlutterFire path, document it in the README, and gitignore the service-account key. Co-authored-by: Cursor <cursoragent@cursor.com> --- examples/demo_fm/.gitignore | 3 ++ examples/demo_fm/README.md | 14 +++++- examples/demo_fm/tools/send_fcm.sh | 78 ++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100755 examples/demo_fm/tools/send_fcm.sh diff --git a/examples/demo_fm/.gitignore b/examples/demo_fm/.gitignore index b841075b..b87603b4 100644 --- a/examples/demo_fm/.gitignore +++ b/examples/demo_fm/.gitignore @@ -46,3 +46,6 @@ app.*.map.json # Environment .env + +# FCM service account key for tools/send_fcm.sh (never commit) +tools/service-account.json diff --git a/examples/demo_fm/README.md b/examples/demo_fm/README.md index e05d8531..34652d6e 100644 --- a/examples/demo_fm/README.md +++ b/examples/demo_fm/README.md @@ -90,7 +90,19 @@ coexist without interfering. adb logcat -c && adb logcat | rg '\[FCM token\]' ``` -### 2. Send directly via the FCM HTTP v1 API +### 2a. Send via the helper script (easiest) + +[`tools/send_fcm.sh`](tools/send_fcm.sh) reads `project_id` from +`google-services.json` and resolves an OAuth token from `$ACCESS_TOKEN`, a +`tools/service-account.json` (gitignored), or `gcloud auth print-access-token`: + +```bash +cd examples/demo_fm +FCM_TOKEN=<device-token> tools/send_fcm.sh notif # notification message +FCM_TOKEN=<device-token> tools/send_fcm.sh data # data-only message +``` + +### 2b. Send directly via the FCM HTTP v1 API `<PROJECT_ID>` is in `android/app/google-services.json` (`project_info.project_id`). Get an access token from a service account JSON (Firebase console → Project diff --git a/examples/demo_fm/tools/send_fcm.sh b/examples/demo_fm/tools/send_fcm.sh new file mode 100755 index 00000000..113e8be6 --- /dev/null +++ b/examples/demo_fm/tools/send_fcm.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash +# +# Send a non-OneSignal push directly through the FCM HTTP v1 API, to exercise +# the FlutterFire path in examples/demo_fm (onMessage / onBackgroundMessage / +# onMessageOpenedApp / getInitialMessage). See examples/demo_fm/README.md. +# +# Usage: +# FCM_TOKEN=<device-token> ./send_fcm.sh notif # notification message +# FCM_TOKEN=<device-token> ./send_fcm.sh data # data-only message +# ./send_fcm.sh notif <device-token> # token as 2nd arg +# +# Auth (first that works wins): +# 1. $ACCESS_TOKEN if already exported +# 2. service-account.json next to this script -> minted via oauth2l/gcloud +# 3. gcloud auth print-access-token +# +# Project id is read from android/app/google-services.json. +set -euo pipefail + +here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +gs="$here/../android/app/google-services.json" + +mode="${1:-notif}" +token="${2:-${FCM_TOKEN:-}}" + +if [[ -z "$token" ]]; then + echo "ERROR: no device token. Pass as 2nd arg or set FCM_TOKEN." >&2 + echo "Grab it from logs: adb logcat | rg '\\[FCM token\\]'" >&2 + exit 1 +fi + +if [[ ! -f "$gs" ]]; then + echo "ERROR: $gs not found (drop your google-services.json there)." >&2 + exit 1 +fi + +project_id="$(grep -o '"project_id": *"[^"]*"' "$gs" | head -1 | sed 's/.*"\([^"]*\)"$/\1/')" +if [[ -z "$project_id" ]]; then + echo "ERROR: could not read project_id from $gs" >&2 + exit 1 +fi + +# Resolve an OAuth access token. +access_token="${ACCESS_TOKEN:-}" +sa="$here/service-account.json" +if [[ -z "$access_token" && -f "$sa" ]]; then + export GOOGLE_APPLICATION_CREDENTIALS="$sa" + access_token="$(gcloud auth application-default print-access-token 2>/dev/null || true)" +fi +if [[ -z "$access_token" ]]; then + access_token="$(gcloud auth print-access-token 2>/dev/null || true)" +fi +if [[ -z "$access_token" ]]; then + echo "ERROR: no access token. Export ACCESS_TOKEN, drop a service-account.json" >&2 + echo "next to this script, or run 'gcloud auth login'." >&2 + exit 1 +fi + +case "$mode" in + notif) + payload='{"message":{"token":"'"$token"'","notification":{"title":"FCM direct","body":"non-OneSignal push"}}}' + ;; + data) + payload='{"message":{"token":"'"$token"'","android":{"priority":"high"},"data":{"alert":"data only","source":"fcm-direct"}}}' + ;; + *) + echo "ERROR: unknown mode '$mode' (use 'notif' or 'data')." >&2 + exit 1 + ;; +esac + +echo "Sending '$mode' message via project $project_id ..." >&2 +curl -sS -X POST \ + "https://fcm.googleapis.com/v1/projects/$project_id/messages:send" \ + -H "Authorization: Bearer $access_token" \ + -H "Content-Type: application/json" \ + -d "$payload" +echo From e9f9dc65fae37d166ed5ba9399a89e8012c71311 Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 19:02:32 -0700 Subject: [PATCH 14/20] fix(ios): drop re-entrant willDisplay events --- .../onesignal_flutter/OSFlutterNotifications.m | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ios/onesignal_flutter/Sources/onesignal_flutter/OSFlutterNotifications.m b/ios/onesignal_flutter/Sources/onesignal_flutter/OSFlutterNotifications.m index 027596f6..d4bad151 100644 --- a/ios/onesignal_flutter/Sources/onesignal_flutter/OSFlutterNotifications.m +++ b/ios/onesignal_flutter/Sources/onesignal_flutter/OSFlutterNotifications.m @@ -138,10 +138,20 @@ - (void)onNotificationPermissionDidChange:(BOOL)permission { #pragma mark Received in Notification Lifecycle Event - (void)onWillDisplayNotification:(OSNotificationWillDisplayEvent *)event { - self.onWillDisplayEventCache[event.notification.notificationId] = event; + NSString *notificationId = event.notification.notificationId; + // A duplicate id already in the cache means this is a re-entrant willDisplay + // caused by another UNUserNotificationCenterDelegate (e.g. firebase_messaging) + // forwarding the original willPresent back into OneSignal's swizzled handler. + BOOL isReentrantDuplicate = + self.onWillDisplayEventCache[notificationId] != nil; + self.onWillDisplayEventCache[notificationId] = event; /// Our bridge layer needs to preventDefault so that the Flutter listener has /// time to preventDefault before the notification is displayed [event preventDefault]; + // Only forward the first dispatch to Flutter so the listener fires once. + if (isReentrantDuplicate) { + return; + } [self.channel invokeMethod:@"OneSignal#onWillDisplayNotification" arguments:event.toJson]; } From dc0accc19e9b2643b5f72cdb57fcbeaccf90bfa8 Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 19:51:18 -0700 Subject: [PATCH 15/20] chore(demo_fm): add 'both' mode and iOS FCM fixes --- .../ios/Runner.xcodeproj/project.pbxproj | 4 ++ examples/demo_fm/tools/send_fcm.sh | 53 ++++++++++++++++--- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/examples/demo_fm/ios/Runner.xcodeproj/project.pbxproj b/examples/demo_fm/ios/Runner.xcodeproj/project.pbxproj index 349e2ad2..188c304c 100644 --- a/examples/demo_fm/ios/Runner.xcodeproj/project.pbxproj +++ b/examples/demo_fm/ios/Runner.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + FAD0113800000000CAFEBABE /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = FAD0113800000000DEADBEEF /* GoogleService-Info.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -76,6 +77,7 @@ 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; + FAD0113800000000DEADBEEF /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = "<group>"; }; @@ -198,6 +200,7 @@ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + FAD0113800000000DEADBEEF /* GoogleService-Info.plist */, ); path = Runner; sourceTree = "<group>"; @@ -366,6 +369,7 @@ files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + FAD0113800000000CAFEBABE /* GoogleService-Info.plist in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); diff --git a/examples/demo_fm/tools/send_fcm.sh b/examples/demo_fm/tools/send_fcm.sh index 113e8be6..3e459fa7 100755 --- a/examples/demo_fm/tools/send_fcm.sh +++ b/examples/demo_fm/tools/send_fcm.sh @@ -7,8 +7,12 @@ # Usage: # FCM_TOKEN=<device-token> ./send_fcm.sh notif # notification message # FCM_TOKEN=<device-token> ./send_fcm.sh data # data-only message +# FCM_TOKEN=<device-token> ./send_fcm.sh both # notification + data # ./send_fcm.sh notif <device-token> # token as 2nd arg # +# Modes: notif (alert), data (silent/background; unreliable on iOS), both +# (alert + data payload; use to test the data path on iOS). +# # Auth (first that works wins): # 1. $ACCESS_TOKEN if already exported # 2. service-account.json next to this script -> minted via oauth2l/gcloud @@ -40,12 +44,37 @@ if [[ -z "$project_id" ]]; then exit 1 fi -# Resolve an OAuth access token. +# Mint an OAuth access token straight from the service account (scope: +# firebase.messaging) using only openssl + python3. This authenticates as the +# project's service account regardless of any ambient gcloud/ADC credentials, +# which is what FCM HTTP v1 requires (a personal/ADC token gets rejected with +# THIRD_PARTY_AUTH_ERROR). +mint_sa_token() { + local sa="$1" email aud now exp hdr claim body sig jwt + email="$(python3 -c "import json;print(json.load(open('$sa'))['client_email'])")" + aud="$(python3 -c "import json;print(json.load(open('$sa')).get('token_uri','https://oauth2.googleapis.com/token'))")" + now="$(date +%s)" + exp="$((now + 3600))" + b64url() { openssl base64 -e -A | tr '+/' '-_' | tr -d '='; } + hdr="$(printf '{"alg":"RS256","typ":"JWT"}' | b64url)" + claim="$(printf '{"iss":"%s","scope":"https://www.googleapis.com/auth/firebase.messaging","aud":"%s","iat":%s,"exp":%s}' "$email" "$aud" "$now" "$exp" | b64url)" + body="$hdr.$claim" + sig="$(printf '%s' "$body" | openssl dgst -sha256 -sign <(python3 -c "import json;print(json.load(open('$sa'))['private_key'])") | b64url)" + jwt="$body.$sig" + curl -sS -X POST "$aud" \ + -d grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer \ + --data-urlencode "assertion=$jwt" \ + | python3 -c "import sys,json;print(json.load(sys.stdin).get('access_token',''))" +} + +# Resolve an OAuth access token (first that works wins): +# 1. $ACCESS_TOKEN if exported +# 2. service-account.json next to this script (preferred) +# 3. gcloud's active credentials access_token="${ACCESS_TOKEN:-}" sa="$here/service-account.json" if [[ -z "$access_token" && -f "$sa" ]]; then - export GOOGLE_APPLICATION_CREDENTIALS="$sa" - access_token="$(gcloud auth application-default print-access-token 2>/dev/null || true)" + access_token="$(mint_sa_token "$sa" 2>/dev/null || true)" fi if [[ -z "$access_token" ]]; then access_token="$(gcloud auth print-access-token 2>/dev/null || true)" @@ -58,13 +87,25 @@ fi case "$mode" in notif) - payload='{"message":{"token":"'"$token"'","notification":{"title":"FCM direct","body":"non-OneSignal push"}}}' + # Visible notification on both platforms (iOS shows an alert via APNs). + payload='{"message":{"token":"'"$token"'","notification":{"title":"FCM direct","body":"non-OneSignal push"},"apns":{"payload":{"aps":{"sound":"default"}}}}}' ;; data) - payload='{"message":{"token":"'"$token"'","android":{"priority":"high"},"data":{"alert":"data only","source":"fcm-direct"}}}' + # Data-only message. android.priority=high + apns content-available=1 so the + # app is woken in the background/killed state on both platforms. + # NOTE: on iOS this is a silent push and is throttled/unreliable, especially + # on the simulator and in the foreground. Use 'both' to test data on iOS, or + # test 'data' on Android where data-only delivery is reliable. + payload='{"message":{"token":"'"$token"'","android":{"priority":"high"},"apns":{"headers":{"apns-priority":"5"},"payload":{"aps":{"content-available":1}}},"data":{"alert":"data only","source":"fcm-direct"}}}' + ;; + both) + # Notification + data. Delivered as a normal alert (reliable on iOS) while + # still carrying a data payload, so onMessage/onMessageOpenedApp fire with + # data populated. Use this to exercise the data path on iOS. + payload='{"message":{"token":"'"$token"'","notification":{"title":"FCM direct","body":"notification + data"},"android":{"priority":"high"},"apns":{"payload":{"aps":{"sound":"default"}}},"data":{"alert":"hello","source":"fcm-direct"}}}' ;; *) - echo "ERROR: unknown mode '$mode' (use 'notif' or 'data')." >&2 + echo "ERROR: unknown mode '$mode' (use 'notif', 'data', or 'both')." >&2 exit 1 ;; esac From 2133c51ab5a00484c24d9cb77be5ab3fae34488a Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 19:53:06 -0700 Subject: [PATCH 16/20] docs(demo_fm): document iOS FCM testing and send_fcm modes Add an iOS setup/testing section (GoogleService-Info.plist, APNs auth key, simulator caveats, log stream workflow for killed-state logs) and document the new send_fcm.sh 'both' mode plus per-platform mode reliability. Co-authored-by: Cursor <cursoragent@cursor.com> --- examples/demo_fm/README.md | 65 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/examples/demo_fm/README.md b/examples/demo_fm/README.md index 34652d6e..a5405bfd 100644 --- a/examples/demo_fm/README.md +++ b/examples/demo_fm/README.md @@ -58,6 +58,56 @@ This mirrors `demo`'s setup, with two extra Firebase requirements. flutter run -d <android-device> ``` +## iOS setup & testing + +The original #1138 bug is Android-specific, but `demo_fm` also surfaced an +**iOS** coexistence bug: with `firebase_messaging` present, the foreground +`onWillDisplayNotification` could fire **twice** for a single OneSignal push, +because Firebase's `UNUserNotificationCenter` delegate forwarding re-enters +OneSignal's swizzled `willPresent`. The fix dedupes re-entrant dispatches in +the in-tree plugin (`ios/.../OSFlutterNotifications.m`). + +To run the Firebase path on iOS: + +1. Add an **iOS app** to your Firebase project and drop its + `GoogleService-Info.plist` into `examples/demo_fm/ios/Runner/`, then add it to + the Runner target in Xcode (it's gitignored). Without it, + `Firebase.initializeApp()` throws `[core/not-initialized]`. + +2. Upload an **APNs Authentication Key** (`.p8`, with Key ID + Team ID) to + Firebase console → Project settings → Cloud Messaging → Apple app + configuration. Without it, direct FCM sends to iOS fail with + `THIRD_PARTY_AUTH_ERROR` (FCM can't relay to APNs). + +3. Prefer a **physical device** — FCM-relayed APNs delivery to the iOS + **simulator** is unreliable, and silent (`data`) pushes especially tend not + to arrive on the simulator. + +### Reading logs after the app is killed (iOS) + +`flutter run` streams logs over a debug connection to the app process, so +killing the app prints `Lost connection to device` and cold-launch logs (the +killed-state click / `getInitialMessage`) never reach that terminal. Read the +system log instead: + +```bash +xcrun simctl spawn booted log stream --level debug --style compact \ + | grep -iE 'FCM|OneSignal|flutter' +``` + +Start it **before** tapping the notification so it captures the cold launch. +On a physical device use `idevicesyslog` or Console.app (select the device). + +### Expected iOS log lines for a direct FCM push + +| App state | `notif` / `both` | `data` (silent) | +| --- | --- | --- | +| Foreground | `[FCM fg] received` | unreliable on iOS | +| Background → tap | `[FCM open] tapped` | n/a (no UI) | +| Killed → tap | `[FCM initial] launched from tap` | n/a (no UI) | + +Use `both` (not `notif`) when you want `data={...}` populated in these logs. + ## Reproducing / verifying issue #1138 Send a push from the OneSignal dashboard and tap it in each app state @@ -94,14 +144,23 @@ adb logcat -c && adb logcat | rg '\[FCM token\]' [`tools/send_fcm.sh`](tools/send_fcm.sh) reads `project_id` from `google-services.json` and resolves an OAuth token from `$ACCESS_TOKEN`, a -`tools/service-account.json` (gitignored), or `gcloud auth print-access-token`: +`tools/service-account.json` (gitignored, preferred — it mints a scoped token +directly via openssl, no `gcloud` login needed), or `gcloud auth +print-access-token`: ```bash cd examples/demo_fm -FCM_TOKEN=<device-token> tools/send_fcm.sh notif # notification message -FCM_TOKEN=<device-token> tools/send_fcm.sh data # data-only message +FCM_TOKEN=<device-token> tools/send_fcm.sh notif # notification (alert) message +FCM_TOKEN=<device-token> tools/send_fcm.sh data # data-only (silent) message +FCM_TOKEN=<device-token> tools/send_fcm.sh both # notification + data payload ``` +| Mode | iOS | Android | Use for | +| --- | --- | --- | --- | +| `notif` | reliable (alert; `data={}`) | reliable | foreground/tap delivery | +| `data` | silent push — throttled/unreliable, esp. on simulator | reliable | the silent background path (`[FCM bg]`), test on Android | +| `both` | reliable alert that also carries `data` | reliable | exercising the data payload on iOS (`[FCM fg]`/`[FCM open]`/`[FCM initial]` with `data` populated) | + ### 2b. Send directly via the FCM HTTP v1 API `<PROJECT_ID>` is in `android/app/google-services.json` (`project_info.project_id`). From f2c3f25d3144a52c8b8a401b99204cde58d2e14d Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 19:56:38 -0700 Subject: [PATCH 17/20] fix(android): register incoming-call handler on every engine messenger bindChannelIfUnbound early-returned on later engines, so a FlutterFire background isolate's messenger never got setMethodCallHandler, breaking Dart->Native calls (MissingPluginException) from an FCM background handler. Always register the incoming handler per engine while keeping the outgoing channel pinned to the first engine (preserves the #1138 Native->Dart fix). Also fix the .gitignore comment to reference examples/demo_fm. Co-authored-by: Cursor <cursoragent@cursor.com> --- .gitignore | 2 +- .../flutter/FlutterMessengerResponder.java | 18 ++++++++++++------ .../onesignal_flutter/OSFlutterNotifications.m | 5 +++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 66b98420..d23754b4 100644 --- a/.gitignore +++ b/.gitignore @@ -32,7 +32,7 @@ dlcov.log **/workspace-state.json # Per-developer Firebase config for issue #1138 repro scaffolding -# (only needed because firebase_messaging is wired into examples/demo; +# (only needed because firebase_messaging is wired into examples/demo_fm; # OneSignal itself does NOT need this file). **/google-services.json **/GoogleService-Info.plist diff --git a/android/src/main/java/com/onesignal/flutter/FlutterMessengerResponder.java b/android/src/main/java/com/onesignal/flutter/FlutterMessengerResponder.java index f220c0d6..adf21ea1 100644 --- a/android/src/main/java/com/onesignal/flutter/FlutterMessengerResponder.java +++ b/android/src/main/java/com/onesignal/flutter/FlutterMessengerResponder.java @@ -14,20 +14,26 @@ abstract class FlutterMessengerResponder { BinaryMessenger messenger; /** - * #1138: bind the shared channel only on the first engine. These responders are - * process-global singletons but {@code registerWith} runs once per Flutter - * engine; FlutterFire's headless background engine would otherwise rebind the - * channel to an isolate with no listeners and drop native callbacks. + * #1138: bind the outgoing shared channel only on the first engine. These + * responders are process-global singletons but {@code registerWith} runs once + * per Flutter engine; FlutterFire's headless background engine would otherwise + * rebind the channel to an isolate with no listeners and drop native callbacks. + * + * <p>The incoming-call handler is still registered on every engine's messenger + * so Dart->Native calls work from any isolate (e.g. an FCM background handler), + * matching the pre-#1138 behavior; only the outgoing Native->Dart channel stays + * pinned to the first engine. * * @return true if this call performed the initial bind. */ boolean bindChannelIfUnbound(BinaryMessenger messenger, String channelName, MethodCallHandler handler) { + MethodChannel channel = new MethodChannel(messenger, channelName); + channel.setMethodCallHandler(handler); if (this.channel != null) { return false; } this.messenger = messenger; - this.channel = new MethodChannel(messenger, channelName); - this.channel.setMethodCallHandler(handler); + this.channel = channel; return true; } diff --git a/ios/onesignal_flutter/Sources/onesignal_flutter/OSFlutterNotifications.m b/ios/onesignal_flutter/Sources/onesignal_flutter/OSFlutterNotifications.m index d4bad151..402f4293 100644 --- a/ios/onesignal_flutter/Sources/onesignal_flutter/OSFlutterNotifications.m +++ b/ios/onesignal_flutter/Sources/onesignal_flutter/OSFlutterNotifications.m @@ -140,8 +140,9 @@ - (void)onNotificationPermissionDidChange:(BOOL)permission { - (void)onWillDisplayNotification:(OSNotificationWillDisplayEvent *)event { NSString *notificationId = event.notification.notificationId; // A duplicate id already in the cache means this is a re-entrant willDisplay - // caused by another UNUserNotificationCenterDelegate (e.g. firebase_messaging) - // forwarding the original willPresent back into OneSignal's swizzled handler. + // caused by another UNUserNotificationCenterDelegate (e.g. + // firebase_messaging) forwarding the original willPresent back into + // OneSignal's swizzled handler. BOOL isReentrantDuplicate = self.onWillDisplayEventCache[notificationId] != nil; self.onWillDisplayEventCache[notificationId] = event; From ad72c388f9848d9bae9f72e5dda9f5cb2a363fa2 Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 20:53:49 -0700 Subject: [PATCH 18/20] fix(android): reset clickListenerRequested on new-engine attach onAttachedToActivity returned early on the new-engine branch without clearing the process-global clickListenerRequested flag, leaving the prior engine's state. A config change on the new engine before Dart re-registered would then re-add the native click listener and drain queued clicks into an isolate with empty _clickListeners, silently dropping them. Reset the flag so it tracks the current engine's Dart state. Co-authored-by: Cursor <cursoragent@cursor.com> --- .../java/com/onesignal/flutter/OneSignalNotifications.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java b/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java index 07ff665b..236e64da 100644 --- a/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java +++ b/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java @@ -264,7 +264,10 @@ void onAttachedToActivity(BinaryMessenger activityMessenger) { // New engine: rebound above so callbacks hit the UI isolate. Don't re-add // the listener yet — its Dart end hasn't run main(); replaying a queued // click now would drop it. Dart calls OneSignal#addNativeClickListener - // once ready, which drains the queue then. + // once ready, which drains the queue then. Reset the flag so it tracks the + // new engine's Dart state, not the prior engine's (a config change before + // Dart re-registers would otherwise drain queued clicks into empty listeners). + clickListenerRequested = false; return; } // Same engine (config change / cached-engine resume): Dart handler is live, From 98d8c40f21db5299f6fa56f56cd8cdf2491f2b67 Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Thu, 28 May 2026 21:33:10 -0700 Subject: [PATCH 19/20] fix(notifications): buffer clicks before listener registers --- .../flutter/OneSignalNotifications.java | 26 +++++++------------ lib/src/notifications.dart | 24 ++++++++++++++--- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java b/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java index 236e64da..8913dc22 100644 --- a/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java +++ b/android/src/main/java/com/onesignal/flutter/OneSignalNotifications.java @@ -260,22 +260,16 @@ void onDetachedFromActivity() { * any clicks the native SDK queued while detached. */ void onAttachedToActivity(BinaryMessenger activityMessenger) { - if (rebindChannelToEngine(activityMessenger, "OneSignal#notifications", this)) { - // New engine: rebound above so callbacks hit the UI isolate. Don't re-add - // the listener yet — its Dart end hasn't run main(); replaying a queued - // click now would drop it. Dart calls OneSignal#addNativeClickListener - // once ready, which drains the queue then. Reset the flag so it tracks the - // new engine's Dart state, not the prior engine's (a config change before - // Dart re-registers would otherwise drain queued clicks into empty listeners). - clickListenerRequested = false; - return; - } - // Same engine (config change / cached-engine resume): Dart handler is live, - // so re-adding now safely drains queued clicks. - if (!clickListenerRequested) { - return; - } - if (!OneSignal.isInitialized()) { + // Rebind the shared channel so callbacks hit the now-foreground engine. + rebindChannelToEngine(activityMessenger, "OneSignal#notifications", this); + // Re-add the listener so the native SDK drains any clicks queued while + // detached. Works for fresh, FCM-background, and pre-warmed cached engines + // alike: a pre-warmed engine's Dart already ran main() and won't re-call + // OneSignal#addNativeClickListener, so the rebind alone wouldn't restore it. + // Draining before this engine's Dart listeners exist is safe — the Dart + // bridge buffers clicks that arrive with no listeners and flushes them once + // addClickListener runs. + if (!clickListenerRequested || !OneSignal.isInitialized()) { return; } OneSignal.getNotifications().removeClickListener(this); diff --git a/lib/src/notifications.dart b/lib/src/notifications.dart index bc4d4fb0..366864db 100644 --- a/lib/src/notifications.dart +++ b/lib/src/notifications.dart @@ -16,6 +16,11 @@ class OneSignalNotifications { // event listeners List<OnNotificationClickListener> _clickListeners = <OnNotificationClickListener>[]; + // Clicks that arrived before a listener was registered (e.g. a cold-start / + // cached-engine attach drains the native queue before addClickListener runs). + // Buffered here instead of dropped, then flushed once a listener registers. + List<OSNotificationClickEvent> _pendingClickEvents = + <OSNotificationClickEvent>[]; List<OnNotificationWillDisplayListener> _willDisplayListeners = <OnNotificationWillDisplayListener>[]; @@ -125,9 +130,14 @@ class OneSignalNotifications { Future<Null> _handleMethod(MethodCall call) async { if (call.method == 'OneSignal#onClickNotification') { - for (var listener in _clickListeners) { - listener( - OSNotificationClickEvent(call.arguments.cast<String, dynamic>())); + var event = + OSNotificationClickEvent(call.arguments.cast<String, dynamic>()); + if (_clickListeners.isEmpty) { + _pendingClickEvents.add(event); + } else { + for (var listener in _clickListeners) { + listener(event); + } } } else if (call.method == 'OneSignal#onWillDisplayNotification') { for (var listener in _willDisplayListeners) { @@ -180,6 +190,14 @@ class OneSignalNotifications { _channel.invokeMethod("OneSignal#addNativeClickListener"); } _clickListeners.add(listener); + // Deliver any clicks that arrived before a listener existed. + if (_pendingClickEvents.isNotEmpty) { + var pending = _pendingClickEvents; + _pendingClickEvents = <OSNotificationClickEvent>[]; + for (var event in pending) { + listener(event); + } + } } void removeClickListener(OnNotificationClickListener listener) { From 62fd8d7d0eabc0c0a8df24844deb83d91f01f61c Mon Sep 17 00:00:00 2001 From: Fadi George <fadii925@gmail.com> Date: Fri, 29 May 2026 10:19:09 -0700 Subject: [PATCH 20/20] fix(notifications): bound pending-click buffer to pre-registration window Only buffer clicks before the app's first click listener registers, and cap the buffer size. Prevents unbounded growth when a listener is added then removed without re-registering, since removeClickListener doesn't stop native dispatch and _clickHandlerRegistered never resets. Co-authored-by: Cursor <cursoragent@cursor.com> --- lib/src/notifications.dart | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/lib/src/notifications.dart b/lib/src/notifications.dart index 366864db..45efa0fd 100644 --- a/lib/src/notifications.dart +++ b/lib/src/notifications.dart @@ -16,11 +16,16 @@ class OneSignalNotifications { // event listeners List<OnNotificationClickListener> _clickListeners = <OnNotificationClickListener>[]; - // Clicks that arrived before a listener was registered (e.g. a cold-start / - // cached-engine attach drains the native queue before addClickListener runs). - // Buffered here instead of dropped, then flushed once a listener registers. + // Clicks that arrived before the app's first click listener was registered + // (e.g. a cold-start / cached-engine attach drains the native queue before + // addClickListener runs). Buffered here instead of dropped, then flushed once + // a listener registers. Only filled during this initial window: after the + // first registration clicks are delivered or dropped, never buffered again. List<OSNotificationClickEvent> _pendingClickEvents = <OSNotificationClickEvent>[]; + // Upper bound on buffered pre-registration clicks so the buffer can't grow + // unbounded if a listener is never registered. Oldest events drop past this. + static const int _maxPendingClickEvents = 50; List<OnNotificationWillDisplayListener> _willDisplayListeners = <OnNotificationWillDisplayListener>[]; @@ -132,12 +137,18 @@ class OneSignalNotifications { if (call.method == 'OneSignal#onClickNotification') { var event = OSNotificationClickEvent(call.arguments.cast<String, dynamic>()); - if (_clickListeners.isEmpty) { - _pendingClickEvents.add(event); - } else { + if (_clickListeners.isNotEmpty) { for (var listener in _clickListeners) { listener(event); } + } else if (!_clickHandlerRegistered) { + // Buffer only before the app's first listener registration. Once a + // listener has been registered (and possibly removed) drop instead, so + // removing a listener doesn't silently accumulate clicks forever. + if (_pendingClickEvents.length >= _maxPendingClickEvents) { + _pendingClickEvents.removeAt(0); + } + _pendingClickEvents.add(event); } } else if (call.method == 'OneSignal#onWillDisplayNotification') { for (var listener in _willDisplayListeners) {