├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature_request.md └── workflows │ └── inactive-issues.yml ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── settings.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── rebeloid │ │ └── unity_ads │ │ ├── PlacementChannelManager.java │ │ ├── UnityAdsConstants.java │ │ ├── UnityAdsInitializationListener.java │ │ ├── UnityAdsLoadListener.java │ │ ├── UnityAdsPlugin.java │ │ ├── UnityAdsShowListener.java │ │ ├── banner │ │ ├── BannerAdFactory.java │ │ ├── BannerAdListener.java │ │ └── BannerAdView.java │ │ └── privacy │ │ └── PrivacyConsent.java │ └── kotlin │ └── com │ └── rebeloid │ └── unity_ads │ └── UnityAdsPlugin.kt ├── example ├── .gitignore ├── .metadata ├── README.md ├── analysis_options.yaml ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── rebeloid │ │ │ │ │ └── unity_ads_example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values-night │ │ │ │ └── styles.xml │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── Podfile.lock │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ ├── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ ├── Contents.json │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ │ └── LaunchImage.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ └── README.md │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h │ └── RunnerTests │ │ └── RunnerTests.swift ├── lib │ └── main.dart ├── pubspec.lock └── pubspec.yaml ├── ios ├── .gitignore ├── Assets │ └── .gitkeep ├── Classes │ ├── BannerAdFactory.swift │ ├── BannerAdListener.swift │ ├── BannerAdView.swift │ ├── PlacementChannelManager.swift │ ├── SwiftUnityAdsPlugin.swift │ ├── UnityAdsConstants.swift │ ├── UnityAdsInitializationListener.swift │ ├── UnityAdsLoadListener.swift │ ├── UnityAdsPlugin.h │ ├── UnityAdsPlugin.m │ ├── UnityAdsShowListener.swift │ └── privacy │ │ └── PrivacyConsent.swift └── unity_ads_plugin.podspec ├── lib ├── src │ ├── constants.dart │ ├── privacy_consent.dart │ ├── unity_ads.dart │ └── unity_banner_ad.dart └── unity_ads_plugin.dart ├── pubspec.lock ├── pubspec.yaml └── test └── unity_ads_test.dart /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: pavelzaichyk 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/inactive-issues.yml: -------------------------------------------------------------------------------- 1 | name: Close inactive issues 2 | on: 3 | schedule: 4 | - cron: "30 1 * * *" 5 | 6 | jobs: 7 | close-issues: 8 | runs-on: ubuntu-latest 9 | permissions: 10 | issues: write 11 | pull-requests: write 12 | steps: 13 | - uses: actions/stale@v9 14 | with: 15 | operations-per-run: 100 16 | days-before-issue-stale: 30 17 | days-before-issue-close: 14 18 | stale-issue-label: "stale" 19 | stale-issue-message: "This issue is stale because it has been open for 30 days with no activity." 20 | close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale." 21 | days-before-pr-stale: -1 22 | days-before-pr-close: -1 23 | repo-token: ${{ secrets.GITHUB_TOKEN }} 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .packages 5 | .pub/ 6 | 7 | build/ 8 | 9 | local.properties 10 | 11 | # IntelliJ related 12 | *.iml 13 | *.ipr 14 | *.iws 15 | .idea/ 16 | 17 | .gradle 18 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 84f3d28555368a70270e9ac8390a9441df95e752 8 | channel: stable 9 | 10 | project_type: plugin 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.3.25 2 | 3 | * Switched unity ads version to 4.15.0 4 | 5 | ## 0.3.24 6 | 7 | * Switched unity ads version to 4.14.1 8 | 9 | ## 0.3.23 10 | 11 | * Switched unity ads version to 4.13.0 12 | 13 | ## 0.3.22 14 | 15 | * Switched unity ads version to 4.12.5 16 | 17 | ## 0.3.21 18 | 19 | * Switched unity ads version to 4.12.3 20 | 21 | ## 0.3.20 22 | 23 | * Switched unity ads version to 4.12.2 24 | 25 | ## 0.3.19 26 | 27 | * Update examples 28 | 29 | ## 0.3.18 30 | 31 | * Switched unity ads version to 4.12.1 32 | 33 | ## 0.3.17 34 | 35 | * Switched unity ads version to 4.12.0 36 | 37 | ## 0.3.16 38 | 39 | * Switched unity ads version to 4.11.3 40 | 41 | ## 0.3.15 42 | 43 | * Switched unity ads version to 4.11.2 44 | 45 | ## 0.3.14 46 | 47 | * Switched unity ads version to 4.11.0 48 | 49 | ## 0.3.13 50 | 51 | * Switched unity ads version to 4.10.0 52 | 53 | ## 0.3.12 54 | 55 | * Switched unity ads version to 4.9.3 56 | 57 | ## 0.3.11 58 | 59 | * Switched unity ads version to 4.9.2 60 | 61 | ## 0.3.10 62 | 63 | * The problem with building a release version of the Android app has been fixed 64 | 65 | ## 0.3.9 66 | 67 | * Switched unity ads version to 4.9.1 68 | 69 | ## 0.3.8 70 | 71 | * Switched unity ads version to 4.6.1 72 | 73 | ## 0.3.7 74 | 75 | * Switched unity ads version to 4.4.1 76 | 77 | ## 0.3.6 78 | 79 | * Minor fixes. 80 | * Added `UnityAds.isInitialized()` method to check if the SDK is initialized successfully. 81 | * Updated example. 82 | 83 | ## 0.3.5 84 | 85 | * Switched unity ads version to 4.3.0 86 | 87 | ## 0.3.4 88 | 89 | * Switched unity ads version to 4.2.1. 90 | 91 | ## 0.3.3 92 | 93 | * Switched unity ads version to 4.0.1. 94 | 95 | ## 0.3.2 96 | 97 | * Added API to pass consent flags to the Unity Ads SDK. 98 | 99 | ## 0.3.1 100 | 101 | * Minor fixes 102 | 103 | ## 0.3.0 104 | 105 | * Switched unity ads version to 4.0.0. 106 | * Changed API. Added error handling. Added preload ads functionality. 107 | 108 | ## 0.2.4 109 | 110 | * Minor fixes. 111 | 112 | ## 0.2.3 113 | 114 | * Switched unity ads version to 3.7.5. 115 | 116 | ## 0.2.2 117 | 118 | * Minor fixes. 119 | * Switched unity ads version to 3.7.2. 120 | 121 | ## 0.2.1 122 | 123 | * Minor fixes 124 | 125 | ## 0.2.0 126 | 127 | * Migrated to null safety 128 | 129 | ## 0.1.2 130 | 131 | * Added serverId parameter for server-to-server redeem callbacks. 132 | 133 | ## 0.1.1 134 | 135 | * Updated readme. 136 | 137 | ## 0.1.0 138 | 139 | * Added support Unity Banner Ads and Video Ads for iOS. 140 | * Made changes to support android sdk version 19. 141 | * Switched unity ads version to 3.6.0. 142 | 143 | ## 0.0.3 144 | 145 | * Updated readme. Switched unity ads version to 3.5.1. Fixed build issue for ios. 146 | 147 | ## 0.0.2 148 | 149 | * Updated readme and documentation. 150 | 151 | ## 0.0.1 152 | 153 | * Added support Unity Banner Ads and Video Ads for Android 154 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Pavel Zaichyk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unity Ads Plugin 2 | 3 | [![Pub](https://img.shields.io/pub/v/unity_ads_plugin.svg)](https://pub.dev/packages/unity_ads_plugin) 4 | [![License](https://img.shields.io/github/license/pavelzaichyk/flutter_unity_ads)](https://github.com/pavelzaichyk/flutter_unity_ads/blob/master/LICENSE) 5 | [![Pub likes](https://badgen.net/pub/likes/unity_ads_plugin)](https://pub.dev/packages/unity_ads_plugin/score) 6 | [![Monthly downloads](https://badgen.net/pub/dm/unity_ads_plugin)](https://pub.dev/packages/unity_ads_plugin/score) 7 | [![Pub points](https://badgen.net/pub/points/unity_ads_plugin)](https://pub.dev/packages/unity_ads_plugin/score) 8 | [![Flutter platform](https://badgen.net/pub/flutter-platform/unity_ads_plugin)](https://pub.dev/packages/unity_ads_plugin) 9 | 10 | [![Buy Me A Coffee](https://img.shields.io/badge/Donate-Buy%20me%20a%20coffee-FFDD00?logo=buymeacoffee)](https://www.buymeacoffee.com/rebeloid) 11 | [![PayPal](https://img.shields.io/badge/Donate-PayPal-066BB7?logo=paypal)](https://paypal.me/pavelzaichyk) 12 | 13 | A Flutter plugin for integrating [Unity Ads](https://docs.unity.com/ads/UnityAdsHome.htm) into your mobile applications. Easily display Unity Banner Ads and Unity Video Ads (Rewarded & Interstitial) with simple Dart APIs. 14 | 15 | --- 16 | 17 | ## Features 18 | 19 | - Display Unity Banner, Rewarded, and Interstitial Video Ads 20 | - Simple initialization and ad loading 21 | - Server-to-server reward callback support 22 | - Privacy consent management 23 | - Firebase Test Lab support (Android) 24 | - Null safety 25 | 26 | --- 27 | 28 | ## Table of Contents 29 | 30 | - [Features](#features) 31 | - [Installation](#installation) 32 | - [Usage Example](#usage-example) 33 | - [Getting Started](#getting-started) 34 | - [1. Initialization](#1-initialization) 35 | - [2. Show Rewarded/Interstitial Video Ad](#2-show-rewardedinterstitial-video-ad) 36 | - [3. Show Banner Ad](#3-show-banner-ad) 37 | - [Privacy Consent](#privacy-consent) 38 | - [Donate](#donate) 39 | 40 | --- 41 | 42 | ## Installation 43 | 44 | Add the plugin to your `pubspec.yaml`: 45 | 46 | ```yaml 47 | dependencies: 48 | unity_ads_plugin: ^ 49 | ``` 50 | 51 | Then run: 52 | 53 | ```sh 54 | flutter pub get 55 | ``` 56 | 57 | --- 58 | 59 | ## Usage Example 60 | 61 | Here is a minimal example of using the plugin: 62 | 63 | ```dart 64 | import 'package:unity_ads_plugin/unity_ads_plugin.dart'; 65 | 66 | void main() { 67 | UnityAds.init( 68 | gameId: 'YOUR_GAME_ID', 69 | testMode: true, 70 | onComplete: () => print('Unity Ads Initialized'), 71 | onFailed: (error, message) => print('Unity Ads Initialization Failed: $error $message'), 72 | ); 73 | } 74 | ``` 75 | 76 | For more detailed usage, see the [Getting Started](#getting-started) section. 77 | 78 | --- 79 | 80 | ## Getting Started 81 | 82 | ### 1. Initialization 83 | 84 | ```dart 85 | UnityAds.init( 86 | gameId: 'PROJECT_GAME_ID', 87 | onComplete: () => print('Initialization Complete'), 88 | onFailed: (error, message) => print('Initialization Failed: $error $message'), 89 | ); 90 | ``` 91 | 92 | Set your Game ID. 93 | For testing purposes, set `testMode` to `true`. 94 | 95 | `UnityAds.isInitialized()` can be used to check if the SDK has initialized successfully. 96 | 97 | --- 98 | 99 | _Android only:_ To change ad behavior in Firebase Test Lab, use the `firebaseTestLabMode` parameter. Possible values: 100 | 101 | | Mode | Description | 102 | |-------------------|----------------------------------------------------------| 103 | | disableAds | Ads are not displayed in Firebase Test Lab (default) | 104 | | showAdsInTestMode | Ads are displayed in test mode. | 105 | | showAds | Real ads are displayed if `testMode` is false. | 106 | 107 | ### 2. Show Rewarded/Interstitial Video Ad 108 | 109 | ![Rewarded Video Ad](https://i.giphy.com/media/InPCZIuZspVEfmTGga/giphy.gif "Rewarded Video Ad") 110 | ![Interstitial Video Ad](https://i.giphy.com/media/8wEtgrnfLNqUY4mllS/giphy.gif "Interstitial Video Ad") 111 | 112 | Load a video ad before showing it. 113 | 114 | ```dart 115 | UnityAds.load( 116 | placementId: 'PLACEMENT_ID', 117 | onComplete: (placementId) => print('Load Complete $placementId'), 118 | onFailed: (placementId, error, message) => print('Load Failed $placementId: $error $message'), 119 | ); 120 | ``` 121 | 122 | Show a loaded ad. 123 | 124 | ```dart 125 | UnityAds.showVideoAd( 126 | placementId: 'PLACEMENT_ID', 127 | onStart: (placementId) => print('Video Ad $placementId started'), 128 | onClick: (placementId) => print('Video Ad $placementId click'), 129 | onSkipped: (placementId) => print('Video Ad $placementId skipped'), 130 | onComplete: (placementId) => print('Video Ad $placementId completed'), 131 | onFailed: (placementId, error, message) => print('Video Ad $placementId failed: $error $message'), 132 | ); 133 | ``` 134 | 135 | #### Server-to-server Redeem Callbacks 136 | 137 | `UnityAds.showVideoAd` has a `serverId` parameter. To use server-to-server callbacks, set this parameter. Read more at [docs.unity.com](https://docs.unity.com/ads/ImplementingS2SRedeemCallbacks.htm). 138 | 139 | ### 3. Show Banner Ad 140 | 141 | ![Banner Ad](https://i.giphy.com/media/aQvnz1i8xn6EWO5bo0/giphy.gif "Banner Ad") 142 | 143 | Place the `UnityBannerAd` widget in your app. 144 | 145 | ```dart 146 | UnityBannerAd( 147 | placementId: 'PLACEMENT_ID', 148 | onLoad: (placementId) => print('Banner loaded: $placementId'), 149 | onClick: (placementId) => print('Banner clicked: $placementId'), 150 | onShown: (placementId) => print('Banner shown: $placementId'), 151 | onFailed: (placementId, error, message) => print('Banner Ad $placementId failed: $error $message'), 152 | ) 153 | ``` 154 | 155 | ### Privacy Consent 156 | 157 | Read more about privacy consent in the [Unity Ads documentation](https://docs.unity.com/ads/ImplementingDataPrivacy.html). 158 | 159 | Use the following code to pass the appropriate consent flags to the Unity Ads SDK: 160 | 161 | ```dart 162 | UnityAds.setPrivacyConsent(, true) 163 | ``` 164 | 165 | --- 166 | 167 | ## Donate 168 | 169 | If you find this package helpful and would like to support its continued development, please consider making a donation. Your contributions are greatly appreciated and motivate the further enhancement of this and other plugins. 170 | 171 | [![Donate](https://www.paypalobjects.com/en_US/PL/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/donate/?hosted_button_id=QE4E8RX8FW6P4) 172 | [![Buy Me A Coffee](https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20coffee&emoji=&slug=rebeloid&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff)](https://www.buymeacoffee.com/rebeloid) 173 | [![PayPal](https://img.shields.io/badge/Donate-PayPal-066BB7?logo=paypal)](https://paypal.me/pavelzaichyk) 174 | 175 | Your support helps maintain and improve this package, ensuring it remains up-to-date and useful for the community. 176 | 177 | Thank you for your generosity! -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | group 'com.rebeloid.unity_ads' 2 | version '1.0' 3 | 4 | buildscript { 5 | repositories { 6 | google() 7 | mavenCentral() 8 | } 9 | 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:7.3.0' 12 | } 13 | } 14 | 15 | rootProject.allprojects { 16 | repositories { 17 | google() 18 | mavenCentral() 19 | } 20 | } 21 | 22 | apply plugin: 'com.android.library' 23 | 24 | android { 25 | if (project.android.hasProperty("namespace")) { 26 | namespace 'com.rebeloid.unity_ads' 27 | } 28 | 29 | compileSdk 34 30 | 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | 36 | defaultConfig { 37 | minSdkVersion 19 38 | } 39 | 40 | dependencies { 41 | implementation group: 'com.unity3d.ads', name: 'unity-ads', version: '4.15.0' 42 | 43 | testImplementation 'junit:junit:4.13.2' 44 | testImplementation 'org.mockito:mockito-core:5.0.0' 45 | } 46 | 47 | testOptions { 48 | unitTests.all { 49 | testLogging { 50 | events "passed", "skipped", "failed", "standardOut", "standardError" 51 | outputs.upToDateWhen {false} 52 | showStandardStreams = true 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip 6 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'unity_ads' 2 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /android/src/main/java/com/rebeloid/unity_ads/PlacementChannelManager.java: -------------------------------------------------------------------------------- 1 | package com.rebeloid.unity_ads; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import io.flutter.plugin.common.BinaryMessenger; 7 | import io.flutter.plugin.common.MethodChannel; 8 | 9 | public class PlacementChannelManager { 10 | private final Map placementChannels; 11 | private final BinaryMessenger binaryMessenger; 12 | 13 | public PlacementChannelManager(BinaryMessenger binaryMessenger) { 14 | this.placementChannels = new HashMap<>(); 15 | this.binaryMessenger = binaryMessenger; 16 | } 17 | 18 | public void invokeMethod(String methodName, String adUnitId) { 19 | invokeMethod(methodName, adUnitId, new HashMap<>()); 20 | } 21 | 22 | public void invokeMethod(String methodName, String adUnitId, String errorCode, String errorMessage) { 23 | Map arguments = new HashMap<>(); 24 | arguments.put(UnityAdsConstants.ERROR_CODE_PARAMETER, errorCode); 25 | arguments.put(UnityAdsConstants.ERROR_MESSAGE_PARAMETER, errorMessage); 26 | invokeMethod(methodName, adUnitId, arguments); 27 | } 28 | 29 | public void invokeMethod(String methodName, String placementId, Map arguments) { 30 | arguments.put(UnityAdsConstants.PLACEMENT_ID_PARAMETER, placementId); 31 | MethodChannel channel = placementChannels.get(placementId); 32 | if (channel == null) { 33 | channel = new MethodChannel(binaryMessenger, UnityAdsConstants.VIDEO_AD_CHANNEL + "_" + placementId); 34 | placementChannels.put(placementId, channel); 35 | } 36 | channel.invokeMethod(methodName, arguments); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /android/src/main/java/com/rebeloid/unity_ads/UnityAdsConstants.java: -------------------------------------------------------------------------------- 1 | package com.rebeloid.unity_ads; 2 | 3 | public interface UnityAdsConstants { 4 | String MAIN_CHANNEL = "com.rebeloid.unity_ads"; 5 | 6 | String BANNER_AD_CHANNEL = MAIN_CHANNEL + "/bannerAd"; 7 | String VIDEO_AD_CHANNEL = MAIN_CHANNEL + "/videoAd"; 8 | 9 | String PLACEMENT_ID_PARAMETER = "placementId"; 10 | String ERROR_CODE_PARAMETER = "errorCode"; 11 | String ERROR_MESSAGE_PARAMETER = "errorMessage"; 12 | 13 | //initialize 14 | String INIT_METHOD = "init"; 15 | String FIREBASE_TEST_LAB_MODE_PARAMETER = "firebaseTestLabMode"; 16 | String GAME_ID_PARAMETER = "gameId"; 17 | String TEST_MODE_PARAMETER = "testMode"; 18 | String INIT_COMPLETE_METHOD = "initComplete"; 19 | String INIT_FAILED_METHOD = "initFailed"; 20 | String IS_INITIALIZED_METHOD = "isInitialized"; 21 | 22 | //load 23 | String LOAD_METHOD = "load"; 24 | String LOAD_COMPLETE_METHOD = "loadComplete"; 25 | String LOAD_FAILED_METHOD = "loadFailed"; 26 | 27 | //show 28 | String SHOW_VIDEO_METHOD = "showVideo"; 29 | String SERVER_ID_PARAMETER = "serverId"; 30 | String SHOW_COMPLETE_METHOD = "showComplete"; 31 | String SHOW_FAILED_METHOD = "showFailed"; 32 | String SHOW_START_METHOD = "showStart"; 33 | String SHOW_SKIPPED_METHOD = "showSkipped"; 34 | String SHOW_CLICK_METHOD = "showClick"; 35 | 36 | //banner 37 | String HEIGHT_PARAMETER = "height"; 38 | String WIDTH_PARAMETER = "width"; 39 | String BANNER_ERROR_METHOD = "banner_error"; 40 | String BANNER_LOADED_METHOD = "banner_loaded"; 41 | String BANNER_CLICKED_METHOD = "banner_clicked"; 42 | String BANNER_SHOWN_METHOD = "banner_shown"; 43 | 44 | //privacy consent 45 | String PRIVACY_CONSENT_SET_METHOD = "privacyConsent_set"; 46 | String PRIVACY_CONSENT_TYPE_PARAMETER = "privacyConsent_type"; 47 | String PRIVACY_CONSENT_VALUE_PARAMETER = "privacyConsent_value"; 48 | } 49 | -------------------------------------------------------------------------------- /android/src/main/java/com/rebeloid/unity_ads/UnityAdsInitializationListener.java: -------------------------------------------------------------------------------- 1 | package com.rebeloid.unity_ads; 2 | 3 | import com.unity3d.ads.IUnityAdsInitializationListener; 4 | import com.unity3d.ads.UnityAds; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | import io.flutter.plugin.common.MethodChannel; 10 | 11 | public class UnityAdsInitializationListener implements IUnityAdsInitializationListener { 12 | private final MethodChannel channel; 13 | 14 | public UnityAdsInitializationListener(MethodChannel channel) { 15 | this.channel = channel; 16 | } 17 | 18 | @Override 19 | public void onInitializationComplete() { 20 | channel.invokeMethod(UnityAdsConstants.INIT_COMPLETE_METHOD, new HashMap<>()); 21 | } 22 | 23 | @Override 24 | public void onInitializationFailed(UnityAds.UnityAdsInitializationError error, String message) { 25 | Map arguments = new HashMap<>(); 26 | arguments.put(UnityAdsConstants.ERROR_CODE_PARAMETER, convertError(error)); 27 | arguments.put(UnityAdsConstants.ERROR_MESSAGE_PARAMETER, message); 28 | channel.invokeMethod(UnityAdsConstants.INIT_FAILED_METHOD, arguments); 29 | } 30 | 31 | private String convertError(UnityAds.UnityAdsInitializationError error) { 32 | switch (error) { 33 | case INTERNAL_ERROR: 34 | return "internalError"; 35 | case INVALID_ARGUMENT: 36 | return "invalidArgument"; 37 | case AD_BLOCKER_DETECTED: 38 | return "adBlockerDetected"; 39 | default: 40 | return ""; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /android/src/main/java/com/rebeloid/unity_ads/UnityAdsLoadListener.java: -------------------------------------------------------------------------------- 1 | package com.rebeloid.unity_ads; 2 | 3 | import com.unity3d.ads.IUnityAdsLoadListener; 4 | import com.unity3d.ads.UnityAds; 5 | 6 | public class UnityAdsLoadListener implements IUnityAdsLoadListener { 7 | private final PlacementChannelManager placementChannelManager; 8 | 9 | public UnityAdsLoadListener(PlacementChannelManager placementChannelManager) { 10 | this.placementChannelManager = placementChannelManager; 11 | } 12 | 13 | @Override 14 | public void onUnityAdsAdLoaded(String placementId) { 15 | placementChannelManager.invokeMethod(UnityAdsConstants.LOAD_COMPLETE_METHOD, placementId); 16 | } 17 | 18 | @Override 19 | public void onUnityAdsFailedToLoad(String placementId, UnityAds.UnityAdsLoadError error, String message) { 20 | placementChannelManager.invokeMethod(UnityAdsConstants.LOAD_FAILED_METHOD, placementId, convertError(error), message); 21 | } 22 | 23 | private String convertError(UnityAds.UnityAdsLoadError error) { 24 | switch (error) { 25 | case INITIALIZE_FAILED: 26 | return "initializeFailed"; 27 | case INTERNAL_ERROR: 28 | return "internalError"; 29 | case INVALID_ARGUMENT: 30 | return "invalidArgument"; 31 | case NO_FILL: 32 | return "noFill"; 33 | case TIMEOUT: 34 | return "timeout"; 35 | default: 36 | return ""; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /android/src/main/java/com/rebeloid/unity_ads/UnityAdsPlugin.java: -------------------------------------------------------------------------------- 1 | package com.rebeloid.unity_ads; 2 | 3 | import static com.rebeloid.unity_ads.UnityAdsConstants.PLACEMENT_ID_PARAMETER; 4 | import static com.rebeloid.unity_ads.UnityAdsConstants.SERVER_ID_PARAMETER; 5 | 6 | import android.app.Activity; 7 | import android.content.Context; 8 | import android.provider.Settings; 9 | import android.util.Log; 10 | 11 | import androidx.annotation.NonNull; 12 | 13 | import com.rebeloid.unity_ads.banner.BannerAdFactory; 14 | import com.rebeloid.unity_ads.privacy.PrivacyConsent; 15 | import com.unity3d.ads.UnityAds; 16 | import com.unity3d.ads.metadata.PlayerMetaData; 17 | 18 | import java.util.Map; 19 | 20 | import io.flutter.embedding.engine.plugins.FlutterPlugin; 21 | import io.flutter.embedding.engine.plugins.activity.ActivityAware; 22 | import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; 23 | import io.flutter.plugin.common.BinaryMessenger; 24 | import io.flutter.plugin.common.MethodCall; 25 | import io.flutter.plugin.common.MethodChannel; 26 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler; 27 | import io.flutter.plugin.common.MethodChannel.Result; 28 | 29 | /** 30 | * Unity Ads Plugin 31 | */ 32 | public class UnityAdsPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware { 33 | private static final String TAG = UnityAdsPlugin.class.getName(); 34 | private MethodChannel channel; 35 | private Context context; 36 | private Activity activity; 37 | private PlacementChannelManager placementChannelManager; 38 | private BannerAdFactory bannerAdFactory; 39 | private PrivacyConsent privacyConsent; 40 | 41 | @Override 42 | public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { 43 | channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), UnityAdsConstants.MAIN_CHANNEL); 44 | channel.setMethodCallHandler(this); 45 | context = flutterPluginBinding.getApplicationContext(); 46 | BinaryMessenger binaryMessenger = flutterPluginBinding.getBinaryMessenger(); 47 | placementChannelManager = new PlacementChannelManager(binaryMessenger); 48 | privacyConsent = new PrivacyConsent(); 49 | 50 | bannerAdFactory = new BannerAdFactory(binaryMessenger); 51 | flutterPluginBinding.getPlatformViewRegistry() 52 | .registerViewFactory(UnityAdsConstants.BANNER_AD_CHANNEL, bannerAdFactory); 53 | } 54 | 55 | @Override 56 | public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { 57 | Map arguments = (Map) call.arguments; 58 | 59 | switch (call.method) { 60 | case UnityAdsConstants.INIT_METHOD: 61 | result.success(initialize(arguments)); 62 | break; 63 | case UnityAdsConstants.LOAD_METHOD: 64 | result.success(load(arguments)); 65 | break; 66 | case UnityAdsConstants.SHOW_VIDEO_METHOD: 67 | result.success(showVideo(arguments)); 68 | break; 69 | case UnityAdsConstants.PRIVACY_CONSENT_SET_METHOD: 70 | result.success(privacyConsent.set(arguments)); 71 | break; 72 | case UnityAdsConstants.IS_INITIALIZED_METHOD: 73 | result.success(UnityAds.isInitialized()); 74 | break; 75 | default: 76 | result.notImplemented(); 77 | } 78 | } 79 | 80 | @Override 81 | public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { 82 | channel.setMethodCallHandler(null); 83 | } 84 | 85 | @Override 86 | public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { 87 | activity = binding.getActivity(); 88 | bannerAdFactory.setActivity(activity); 89 | privacyConsent.setActivity(activity); 90 | } 91 | 92 | @Override 93 | public void onDetachedFromActivityForConfigChanges() { 94 | 95 | } 96 | 97 | @Override 98 | public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { 99 | 100 | } 101 | 102 | @Override 103 | public void onDetachedFromActivity() { 104 | 105 | } 106 | 107 | private boolean initialize(Map args) { 108 | String gameId = (String) args.get(UnityAdsConstants.GAME_ID_PARAMETER); 109 | 110 | boolean firebaseTestMode = false; 111 | if (isInFirebaseTestLab()) { 112 | String firebaseTestLabMode = (String) args.get(UnityAdsConstants.FIREBASE_TEST_LAB_MODE_PARAMETER); 113 | if ("disableAds".equalsIgnoreCase(firebaseTestLabMode)) { 114 | return false; 115 | } 116 | 117 | firebaseTestMode = "showAdsInTestMode".equalsIgnoreCase(firebaseTestLabMode); 118 | } 119 | 120 | Boolean testMode = (Boolean) args.get(UnityAdsConstants.TEST_MODE_PARAMETER); 121 | if (testMode == null) { 122 | testMode = false; 123 | } 124 | 125 | UnityAds.initialize(context, gameId, testMode || firebaseTestMode, new UnityAdsInitializationListener(channel)); 126 | return true; 127 | } 128 | 129 | private boolean isInFirebaseTestLab() { 130 | String testLabSetting = Settings.System.getString(context.getContentResolver(), "firebase.test.lab"); 131 | return "true".equalsIgnoreCase(testLabSetting); 132 | } 133 | 134 | private boolean load(Map args) { 135 | final String placementId = (String) args.get(PLACEMENT_ID_PARAMETER); 136 | try { 137 | UnityAds.load(placementId, new UnityAdsLoadListener(placementChannelManager)); 138 | return true; 139 | } catch (Exception ex) { 140 | Log.e(TAG, "Exception occurs during loading ad: " + placementId, ex); 141 | placementChannelManager.invokeMethod(UnityAdsConstants.LOAD_FAILED_METHOD, placementId, "unknown", ex.getMessage()); 142 | } 143 | return false; 144 | } 145 | 146 | private boolean showVideo(Map args) { 147 | final String placementId = (String) args.get(PLACEMENT_ID_PARAMETER); 148 | 149 | final String serverId = (String) args.get(SERVER_ID_PARAMETER); 150 | if (serverId != null) { 151 | PlayerMetaData playerMetaData = new PlayerMetaData(context); 152 | playerMetaData.setServerId(serverId); 153 | playerMetaData.commit(); 154 | } 155 | try { 156 | UnityAds.show(activity, placementId, new UnityAdsShowListener(placementChannelManager)); 157 | return true; 158 | } catch (Exception ex) { 159 | Log.e(TAG, "Exception occurs during loading ad: " + placementId, ex); 160 | placementChannelManager.invokeMethod(UnityAdsConstants.SHOW_FAILED_METHOD, placementId, "unknown", ex.getMessage()); 161 | } 162 | return false; 163 | } 164 | 165 | } 166 | -------------------------------------------------------------------------------- /android/src/main/java/com/rebeloid/unity_ads/UnityAdsShowListener.java: -------------------------------------------------------------------------------- 1 | package com.rebeloid.unity_ads; 2 | 3 | import com.unity3d.ads.IUnityAdsShowListener; 4 | import com.unity3d.ads.UnityAds; 5 | 6 | public class UnityAdsShowListener implements IUnityAdsShowListener { 7 | private final PlacementChannelManager placementChannelManager; 8 | 9 | public UnityAdsShowListener(PlacementChannelManager placementChannelManager) { 10 | this.placementChannelManager = placementChannelManager; 11 | } 12 | 13 | @Override 14 | public void onUnityAdsShowFailure(String placementId, UnityAds.UnityAdsShowError error, String message) { 15 | placementChannelManager.invokeMethod(UnityAdsConstants.SHOW_FAILED_METHOD, placementId, convertError(error), message); 16 | } 17 | 18 | @Override 19 | public void onUnityAdsShowStart(String placementId) { 20 | placementChannelManager.invokeMethod(UnityAdsConstants.SHOW_START_METHOD, placementId); 21 | } 22 | 23 | @Override 24 | public void onUnityAdsShowClick(String placementId) { 25 | placementChannelManager.invokeMethod(UnityAdsConstants.SHOW_CLICK_METHOD, placementId); 26 | } 27 | 28 | @Override 29 | public void onUnityAdsShowComplete(String placementId, UnityAds.UnityAdsShowCompletionState state) { 30 | if (state == UnityAds.UnityAdsShowCompletionState.SKIPPED) { 31 | placementChannelManager.invokeMethod(UnityAdsConstants.SHOW_SKIPPED_METHOD, placementId); 32 | } else if (state == UnityAds.UnityAdsShowCompletionState.COMPLETED) { 33 | placementChannelManager.invokeMethod(UnityAdsConstants.SHOW_COMPLETE_METHOD, placementId); 34 | } 35 | } 36 | 37 | private String convertError(UnityAds.UnityAdsShowError error) { 38 | switch (error) { 39 | case NOT_INITIALIZED: 40 | return "notInitialized"; 41 | case NOT_READY: 42 | return "notReady"; 43 | case VIDEO_PLAYER_ERROR: 44 | return "videoPlayerError"; 45 | case INVALID_ARGUMENT: 46 | return "invalidArgument"; 47 | case NO_CONNECTION: 48 | return "noConnection"; 49 | case ALREADY_SHOWING: 50 | return "alreadyShowing"; 51 | case INTERNAL_ERROR: 52 | return "internalError"; 53 | case TIMEOUT: 54 | return "timeout"; 55 | default: 56 | return ""; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /android/src/main/java/com/rebeloid/unity_ads/banner/BannerAdFactory.java: -------------------------------------------------------------------------------- 1 | package com.rebeloid.unity_ads.banner; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | 6 | import java.util.Map; 7 | 8 | import io.flutter.plugin.common.BinaryMessenger; 9 | import io.flutter.plugin.common.StandardMessageCodec; 10 | import io.flutter.plugin.platform.PlatformView; 11 | import io.flutter.plugin.platform.PlatformViewFactory; 12 | 13 | public class BannerAdFactory extends PlatformViewFactory { 14 | private final BinaryMessenger messenger; 15 | private Activity activity; 16 | 17 | public BannerAdFactory(BinaryMessenger messenger) { 18 | super(StandardMessageCodec.INSTANCE); 19 | this.messenger = messenger; 20 | } 21 | 22 | public void setActivity(Activity activity) { 23 | this.activity = activity; 24 | } 25 | 26 | @Override 27 | public PlatformView create(Context context, int viewId, Object args) { 28 | return new BannerAdView(activity, viewId, (Map) args, this.messenger); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /android/src/main/java/com/rebeloid/unity_ads/banner/BannerAdListener.java: -------------------------------------------------------------------------------- 1 | package com.rebeloid.unity_ads.banner; 2 | 3 | import com.rebeloid.unity_ads.UnityAdsConstants; 4 | import com.unity3d.services.banners.BannerErrorInfo; 5 | import com.unity3d.services.banners.BannerView; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | import io.flutter.plugin.common.MethodChannel; 11 | 12 | class BannerAdListener implements BannerView.IListener { 13 | private final MethodChannel channel; 14 | 15 | public BannerAdListener(MethodChannel channel) { 16 | this.channel = channel; 17 | } 18 | 19 | /** 20 | * Called when the banner is loaded. 21 | */ 22 | @Override 23 | public void onBannerLoaded(BannerView bannerView) { 24 | Map arguments = new HashMap<>(); 25 | arguments.put(UnityAdsConstants.PLACEMENT_ID_PARAMETER, bannerView.getPlacementId()); 26 | 27 | channel.invokeMethod(UnityAdsConstants.BANNER_LOADED_METHOD, arguments); 28 | } 29 | 30 | /** 31 | * Called when the banner is shown. 32 | */ 33 | @Override 34 | public void onBannerShown(BannerView bannerView) { 35 | Map arguments = new HashMap<>(); 36 | arguments.put(UnityAdsConstants.PLACEMENT_ID_PARAMETER, bannerView.getPlacementId()); 37 | 38 | channel.invokeMethod(UnityAdsConstants.BANNER_SHOWN_METHOD, arguments); 39 | } 40 | 41 | /** 42 | * Called when the banner is clicked. 43 | */ 44 | @Override 45 | public void onBannerClick(BannerView bannerView) { 46 | Map arguments = new HashMap<>(); 47 | arguments.put(UnityAdsConstants.PLACEMENT_ID_PARAMETER, bannerView.getPlacementId()); 48 | 49 | channel.invokeMethod(UnityAdsConstants.BANNER_CLICKED_METHOD, arguments); 50 | } 51 | 52 | /** 53 | * Called when an error occurs. 54 | */ 55 | @Override 56 | public void onBannerFailedToLoad(BannerView bannerView, BannerErrorInfo errorInfo) { 57 | Map arguments = new HashMap<>(); 58 | arguments.put(UnityAdsConstants.PLACEMENT_ID_PARAMETER, bannerView.getPlacementId()); 59 | arguments.put(UnityAdsConstants.ERROR_CODE_PARAMETER, convertError(errorInfo)); 60 | arguments.put(UnityAdsConstants.ERROR_MESSAGE_PARAMETER, errorInfo.errorMessage); 61 | 62 | channel.invokeMethod(UnityAdsConstants.BANNER_ERROR_METHOD, arguments); 63 | } 64 | 65 | /** 66 | * Called when the banner links out of the application. 67 | */ 68 | @Override 69 | public void onBannerLeftApplication(BannerView bannerView) { 70 | } 71 | 72 | private String convertError(BannerErrorInfo errorInfo) { 73 | switch (errorInfo.errorCode) { 74 | case UNKNOWN: 75 | return "unknown"; 76 | case NATIVE_ERROR: 77 | return "native"; 78 | case WEBVIEW_ERROR: 79 | return "webView"; 80 | case NO_FILL: 81 | return "noFill"; 82 | default: 83 | return ""; 84 | } 85 | } 86 | 87 | } -------------------------------------------------------------------------------- /android/src/main/java/com/rebeloid/unity_ads/banner/BannerAdView.java: -------------------------------------------------------------------------------- 1 | package com.rebeloid.unity_ads.banner; 2 | 3 | import android.app.Activity; 4 | import android.view.View; 5 | 6 | import com.unity3d.services.banners.BannerView; 7 | import com.unity3d.services.banners.UnityBannerSize; 8 | 9 | import java.util.Map; 10 | 11 | import io.flutter.plugin.common.BinaryMessenger; 12 | import io.flutter.plugin.common.MethodChannel; 13 | import io.flutter.plugin.platform.PlatformView; 14 | 15 | import com.rebeloid.unity_ads.UnityAdsConstants; 16 | 17 | public class BannerAdView implements PlatformView { 18 | private static final UnityBannerSize STANDARD_SIZE = new UnityBannerSize(320, 50); 19 | private final BannerView bannerView; 20 | 21 | public BannerAdView(Activity activity, int id, Map args, BinaryMessenger messenger) { 22 | MethodChannel channel = new MethodChannel(messenger, 23 | UnityAdsConstants.BANNER_AD_CHANNEL + "_" + id); 24 | 25 | Integer width = (Integer) args.get(UnityAdsConstants.WIDTH_PARAMETER); 26 | Integer height = (Integer) args.get(UnityAdsConstants.HEIGHT_PARAMETER); 27 | UnityBannerSize size = width == null || height == null ? STANDARD_SIZE : new UnityBannerSize(width, height); 28 | 29 | bannerView = new BannerView(activity, (String) args.get(UnityAdsConstants.PLACEMENT_ID_PARAMETER), size); 30 | 31 | bannerView.setListener(new BannerAdListener(channel)); 32 | bannerView.load(); 33 | } 34 | 35 | @Override 36 | public View getView() { 37 | return bannerView; 38 | } 39 | 40 | @Override 41 | public void dispose() { 42 | 43 | } 44 | } -------------------------------------------------------------------------------- /android/src/main/java/com/rebeloid/unity_ads/privacy/PrivacyConsent.java: -------------------------------------------------------------------------------- 1 | package com.rebeloid.unity_ads.privacy; 2 | 3 | import android.content.Context; 4 | 5 | import com.rebeloid.unity_ads.UnityAdsConstants; 6 | import com.unity3d.ads.metadata.MetaData; 7 | 8 | import java.util.Map; 9 | 10 | public class PrivacyConsent { 11 | private Context activity; 12 | 13 | public boolean set(Map args) { 14 | String type = (String) args.get(UnityAdsConstants.PRIVACY_CONSENT_TYPE_PARAMETER); 15 | Boolean value = (Boolean) args.get(UnityAdsConstants.PRIVACY_CONSENT_VALUE_PARAMETER); 16 | 17 | MetaData metaData = new MetaData(activity); 18 | boolean success = metaData.set(defineType(type), value); 19 | metaData.commit(); 20 | return success; 21 | } 22 | 23 | private String defineType(String type) { 24 | if (type == null) { 25 | return null; 26 | } 27 | switch (type) { 28 | case "pipl": 29 | return "pipl.consent"; 30 | case "gdpr": 31 | return "gdpr.consent"; 32 | case "ccpa": 33 | return "privacy.consent"; 34 | case "ageGate": 35 | return "privacy.useroveragelimit"; 36 | default: 37 | return type; 38 | } 39 | } 40 | 41 | public void setActivity(Context activity) { 42 | this.activity = activity; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /android/src/main/kotlin/com/rebeloid/unity_ads/UnityAdsPlugin.kt: -------------------------------------------------------------------------------- 1 | package com.rebeloid.unity_ads 2 | 3 | import androidx.annotation.NonNull 4 | 5 | import io.flutter.embedding.engine.plugins.FlutterPlugin 6 | import io.flutter.plugin.common.MethodCall 7 | import io.flutter.plugin.common.MethodChannel 8 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler 9 | import io.flutter.plugin.common.MethodChannel.Result 10 | import io.flutter.plugin.common.PluginRegistry.Registrar 11 | 12 | /** UnityAdsPlugin */ 13 | class UnityAdsPlugin: FlutterPlugin, MethodCallHandler { 14 | /// The MethodChannel that will the communication between Flutter and native Android 15 | /// 16 | /// This local reference serves to register the plugin with the Flutter Engine and unregister it 17 | /// when the Flutter Engine is detached from the Activity 18 | private lateinit var channel : MethodChannel 19 | 20 | override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { 21 | channel = MethodChannel(flutterPluginBinding.binaryMessenger, "unity_ads") 22 | channel.setMethodCallHandler(this) 23 | } 24 | 25 | override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { 26 | if (call.method == "getPlatformVersion") { 27 | result.success("Android ${android.os.Build.VERSION.RELEASE}") 28 | } else { 29 | result.notImplemented() 30 | } 31 | } 32 | 33 | override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { 34 | channel.setMethodCallHandler(null) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | .gradle 44 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "b0850beeb25f6d5b10426284f506557f66181b36" 8 | channel: "stable" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: b0850beeb25f6d5b10426284f506557f66181b36 17 | base_revision: b0850beeb25f6d5b10426284f506557f66181b36 18 | - platform: android 19 | create_revision: b0850beeb25f6d5b10426284f506557f66181b36 20 | base_revision: b0850beeb25f6d5b10426284f506557f66181b36 21 | - platform: ios 22 | create_revision: b0850beeb25f6d5b10426284f506557f66181b36 23 | base_revision: b0850beeb25f6d5b10426284f506557f66181b36 24 | 25 | # User provided section 26 | 27 | # List of Local paths (relative to this file) that should be 28 | # ignored by the migrate tool. 29 | # 30 | # Files that are not part of the templates will be ignored by default. 31 | unmanaged_files: 32 | - 'lib/main.dart' 33 | - 'ios/Runner.xcodeproj/project.pbxproj' 34 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # unity_ads_example 2 | 3 | Demonstrates how to use the unity_ads_plugin plugin. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | app/.cxx 15 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. 5 | id "dev.flutter.flutter-gradle-plugin" 6 | } 7 | 8 | def localProperties = new Properties() 9 | def localPropertiesFile = rootProject.file("local.properties") 10 | if (localPropertiesFile.exists()) { 11 | localPropertiesFile.withReader("UTF-8") { reader -> 12 | localProperties.load(reader) 13 | } 14 | } 15 | 16 | def flutterVersionCode = localProperties.getProperty("flutter.versionCode") 17 | if (flutterVersionCode == null) { 18 | flutterVersionCode = "1" 19 | } 20 | 21 | def flutterVersionName = localProperties.getProperty("flutter.versionName") 22 | if (flutterVersionName == null) { 23 | flutterVersionName = "1.0" 24 | } 25 | 26 | android { 27 | namespace = "com.rebeloid.unity_ads_example" 28 | compileSdk = flutter.compileSdkVersion 29 | ndkVersion = "27.0.12077973" 30 | 31 | compileOptions { 32 | sourceCompatibility = JavaVersion.VERSION_11 33 | targetCompatibility = JavaVersion.VERSION_11 34 | } 35 | 36 | kotlinOptions { 37 | jvmTarget = JavaVersion.VERSION_11.toString() 38 | } 39 | 40 | defaultConfig { 41 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 42 | applicationId = "com.rebeloid.unity_ads_example" 43 | // You can update the following values to match your application needs. 44 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. 45 | minSdk = flutter.minSdkVersion 46 | targetSdk = flutter.targetSdkVersion 47 | versionCode = flutterVersionCode.toInteger() 48 | versionName = flutterVersionName 49 | } 50 | 51 | buildTypes { 52 | release { 53 | // TODO: Add your own signing config for the release build. 54 | // Signing with the debug keys for now, so `flutter run --release` works. 55 | signingConfig = signingConfigs.debug 56 | } 57 | } 58 | } 59 | 60 | flutter { 61 | source = "../.." 62 | } 63 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/rebeloid/unity_ads_example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.rebeloid.unity_ads_example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() 6 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | rootProject.buildDir = "../build" 9 | subprojects { 10 | project.buildDir = "${rootProject.buildDir}/${project.name}" 11 | } 12 | subprojects { 13 | project.evaluationDependsOn(":app") 14 | } 15 | 16 | tasks.register("clean", Delete) { 17 | delete rootProject.buildDir 18 | } 19 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip 4 | networkTimeout=10000 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | }() 9 | 10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 11 | 12 | repositories { 13 | google() 14 | mavenCentral() 15 | gradlePluginPortal() 16 | } 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 21 | id "com.android.application" version "8.7.3" apply false 22 | id "org.jetbrains.kotlin.android" version "1.8.22" apply false 23 | } 24 | 25 | include ":app" 26 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '12.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | target 'RunnerTests' do 36 | inherit! :search_paths 37 | end 38 | end 39 | 40 | post_install do |installer| 41 | installer.pods_project.targets.each do |target| 42 | flutter_additional_ios_build_settings(target) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - unity_ads_plugin (0.0.1): 4 | - Flutter 5 | - UnityAds (= 4.15.0) 6 | - UnityAds (4.15.0) 7 | 8 | DEPENDENCIES: 9 | - Flutter (from `Flutter`) 10 | - unity_ads_plugin (from `.symlinks/plugins/unity_ads_plugin/ios`) 11 | 12 | SPEC REPOS: 13 | trunk: 14 | - UnityAds 15 | 16 | EXTERNAL SOURCES: 17 | Flutter: 18 | :path: Flutter 19 | unity_ads_plugin: 20 | :path: ".symlinks/plugins/unity_ads_plugin/ios" 21 | 22 | SPEC CHECKSUMS: 23 | Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 24 | unity_ads_plugin: 719132069170bddaf48b178b09c9af2202c758ce 25 | UnityAds: 5f487a7cf0b0cd162810cff51698f3ca0b4f8e68 26 | 27 | PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796 28 | 29 | COCOAPODS: 1.15.2 30 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 12 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 13 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 14 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 15 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 16 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 17 | F9F44A7DAA01DC9236CDD945 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BAC88CB49BDDBACEF4983BC6 /* Pods_RunnerTests.framework */; }; 18 | FA82C50F504C2C8788D27720 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2392D098D7BB7D9685ADFB0 /* Pods_Runner.framework */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXContainerItemProxy section */ 22 | 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { 23 | isa = PBXContainerItemProxy; 24 | containerPortal = 97C146E61CF9000F007C117D /* Project object */; 25 | proxyType = 1; 26 | remoteGlobalIDString = 97C146ED1CF9000F007C117D; 27 | remoteInfo = Runner; 28 | }; 29 | /* End PBXContainerItemProxy section */ 30 | 31 | /* Begin PBXCopyFilesBuildPhase section */ 32 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 33 | isa = PBXCopyFilesBuildPhase; 34 | buildActionMask = 2147483647; 35 | dstPath = ""; 36 | dstSubfolderSpec = 10; 37 | files = ( 38 | ); 39 | name = "Embed Frameworks"; 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXCopyFilesBuildPhase section */ 43 | 44 | /* Begin PBXFileReference section */ 45 | 05EBE461B80CA9BEEAF979C1 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 46 | 1237574ED09198C4D9CCE88E /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; 47 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 48 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 49 | 1E3D29213C4E669E6E724FC1 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; 50 | 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 51 | 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 359A26D958A8722B94E1974F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 53 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 54 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 55 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 56 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 57 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 58 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 59 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 60 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 61 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 62 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 63 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 64 | 9940E1D502B948E4059207F4 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 65 | BAC88CB49BDDBACEF4983BC6 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 66 | C2392D098D7BB7D9685ADFB0 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 67 | CBE16868023699984540B20D /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 68 | /* End PBXFileReference section */ 69 | 70 | /* Begin PBXFrameworksBuildPhase section */ 71 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 72 | isa = PBXFrameworksBuildPhase; 73 | buildActionMask = 2147483647; 74 | files = ( 75 | FA82C50F504C2C8788D27720 /* Pods_Runner.framework in Frameworks */, 76 | ); 77 | runOnlyForDeploymentPostprocessing = 0; 78 | }; 79 | B5082085DE1A50F39D6EBBF2 /* Frameworks */ = { 80 | isa = PBXFrameworksBuildPhase; 81 | buildActionMask = 2147483647; 82 | files = ( 83 | F9F44A7DAA01DC9236CDD945 /* Pods_RunnerTests.framework in Frameworks */, 84 | ); 85 | runOnlyForDeploymentPostprocessing = 0; 86 | }; 87 | /* End PBXFrameworksBuildPhase section */ 88 | 89 | /* Begin PBXGroup section */ 90 | 331C8082294A63A400263BE5 /* RunnerTests */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 331C807B294A618700263BE5 /* RunnerTests.swift */, 94 | ); 95 | path = RunnerTests; 96 | sourceTree = ""; 97 | }; 98 | 61EF3713F82B1B9391A2F55C /* Pods */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | 359A26D958A8722B94E1974F /* Pods-Runner.debug.xcconfig */, 102 | CBE16868023699984540B20D /* Pods-Runner.release.xcconfig */, 103 | 9940E1D502B948E4059207F4 /* Pods-Runner.profile.xcconfig */, 104 | 1237574ED09198C4D9CCE88E /* Pods-RunnerTests.debug.xcconfig */, 105 | 1E3D29213C4E669E6E724FC1 /* Pods-RunnerTests.release.xcconfig */, 106 | 05EBE461B80CA9BEEAF979C1 /* Pods-RunnerTests.profile.xcconfig */, 107 | ); 108 | name = Pods; 109 | path = Pods; 110 | sourceTree = ""; 111 | }; 112 | 9740EEB11CF90186004384FC /* Flutter */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 116 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 117 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 118 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 119 | ); 120 | name = Flutter; 121 | sourceTree = ""; 122 | }; 123 | 97C146E51CF9000F007C117D = { 124 | isa = PBXGroup; 125 | children = ( 126 | 9740EEB11CF90186004384FC /* Flutter */, 127 | 97C146F01CF9000F007C117D /* Runner */, 128 | 97C146EF1CF9000F007C117D /* Products */, 129 | 331C8082294A63A400263BE5 /* RunnerTests */, 130 | 61EF3713F82B1B9391A2F55C /* Pods */, 131 | A7ADD35F543B1B5C4FE79B2E /* Frameworks */, 132 | ); 133 | sourceTree = ""; 134 | }; 135 | 97C146EF1CF9000F007C117D /* Products */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | 97C146EE1CF9000F007C117D /* Runner.app */, 139 | 331C8081294A63A400263BE5 /* RunnerTests.xctest */, 140 | ); 141 | name = Products; 142 | sourceTree = ""; 143 | }; 144 | 97C146F01CF9000F007C117D /* Runner */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 148 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 149 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 150 | 97C147021CF9000F007C117D /* Info.plist */, 151 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 152 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 153 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 154 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 155 | ); 156 | path = Runner; 157 | sourceTree = ""; 158 | }; 159 | A7ADD35F543B1B5C4FE79B2E /* Frameworks */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | C2392D098D7BB7D9685ADFB0 /* Pods_Runner.framework */, 163 | BAC88CB49BDDBACEF4983BC6 /* Pods_RunnerTests.framework */, 164 | ); 165 | name = Frameworks; 166 | sourceTree = ""; 167 | }; 168 | /* End PBXGroup section */ 169 | 170 | /* Begin PBXNativeTarget section */ 171 | 331C8080294A63A400263BE5 /* RunnerTests */ = { 172 | isa = PBXNativeTarget; 173 | buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; 174 | buildPhases = ( 175 | 3B18B49E24817C5A7E7AB924 /* [CP] Check Pods Manifest.lock */, 176 | 331C807D294A63A400263BE5 /* Sources */, 177 | 331C807F294A63A400263BE5 /* Resources */, 178 | B5082085DE1A50F39D6EBBF2 /* Frameworks */, 179 | ); 180 | buildRules = ( 181 | ); 182 | dependencies = ( 183 | 331C8086294A63A400263BE5 /* PBXTargetDependency */, 184 | ); 185 | name = RunnerTests; 186 | productName = RunnerTests; 187 | productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; 188 | productType = "com.apple.product-type.bundle.unit-test"; 189 | }; 190 | 97C146ED1CF9000F007C117D /* Runner */ = { 191 | isa = PBXNativeTarget; 192 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 193 | buildPhases = ( 194 | 60CB12F8D305CEAC0BC893FF /* [CP] Check Pods Manifest.lock */, 195 | 9740EEB61CF901F6004384FC /* Run Script */, 196 | 97C146EA1CF9000F007C117D /* Sources */, 197 | 97C146EB1CF9000F007C117D /* Frameworks */, 198 | 97C146EC1CF9000F007C117D /* Resources */, 199 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 200 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 201 | D610BE3FAC16B6034B979B62 /* [CP] Copy Pods Resources */, 202 | ); 203 | buildRules = ( 204 | ); 205 | dependencies = ( 206 | ); 207 | name = Runner; 208 | productName = Runner; 209 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 210 | productType = "com.apple.product-type.application"; 211 | }; 212 | /* End PBXNativeTarget section */ 213 | 214 | /* Begin PBXProject section */ 215 | 97C146E61CF9000F007C117D /* Project object */ = { 216 | isa = PBXProject; 217 | attributes = { 218 | BuildIndependentTargetsInParallel = YES; 219 | LastUpgradeCheck = 1510; 220 | ORGANIZATIONNAME = ""; 221 | TargetAttributes = { 222 | 331C8080294A63A400263BE5 = { 223 | CreatedOnToolsVersion = 14.0; 224 | TestTargetID = 97C146ED1CF9000F007C117D; 225 | }; 226 | 97C146ED1CF9000F007C117D = { 227 | CreatedOnToolsVersion = 7.3.1; 228 | LastSwiftMigration = 1100; 229 | }; 230 | }; 231 | }; 232 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 233 | compatibilityVersion = "Xcode 9.3"; 234 | developmentRegion = en; 235 | hasScannedForEncodings = 0; 236 | knownRegions = ( 237 | en, 238 | Base, 239 | ); 240 | mainGroup = 97C146E51CF9000F007C117D; 241 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 242 | projectDirPath = ""; 243 | projectRoot = ""; 244 | targets = ( 245 | 97C146ED1CF9000F007C117D /* Runner */, 246 | 331C8080294A63A400263BE5 /* RunnerTests */, 247 | ); 248 | }; 249 | /* End PBXProject section */ 250 | 251 | /* Begin PBXResourcesBuildPhase section */ 252 | 331C807F294A63A400263BE5 /* Resources */ = { 253 | isa = PBXResourcesBuildPhase; 254 | buildActionMask = 2147483647; 255 | files = ( 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | }; 259 | 97C146EC1CF9000F007C117D /* Resources */ = { 260 | isa = PBXResourcesBuildPhase; 261 | buildActionMask = 2147483647; 262 | files = ( 263 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 264 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 265 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 266 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 267 | ); 268 | runOnlyForDeploymentPostprocessing = 0; 269 | }; 270 | /* End PBXResourcesBuildPhase section */ 271 | 272 | /* Begin PBXShellScriptBuildPhase section */ 273 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 274 | isa = PBXShellScriptBuildPhase; 275 | alwaysOutOfDate = 1; 276 | buildActionMask = 2147483647; 277 | files = ( 278 | ); 279 | inputPaths = ( 280 | "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", 281 | ); 282 | name = "Thin Binary"; 283 | outputPaths = ( 284 | ); 285 | runOnlyForDeploymentPostprocessing = 0; 286 | shellPath = /bin/sh; 287 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 288 | }; 289 | 3B18B49E24817C5A7E7AB924 /* [CP] Check Pods Manifest.lock */ = { 290 | isa = PBXShellScriptBuildPhase; 291 | buildActionMask = 2147483647; 292 | files = ( 293 | ); 294 | inputFileListPaths = ( 295 | ); 296 | inputPaths = ( 297 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 298 | "${PODS_ROOT}/Manifest.lock", 299 | ); 300 | name = "[CP] Check Pods Manifest.lock"; 301 | outputFileListPaths = ( 302 | ); 303 | outputPaths = ( 304 | "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", 305 | ); 306 | runOnlyForDeploymentPostprocessing = 0; 307 | shellPath = /bin/sh; 308 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 309 | showEnvVarsInLog = 0; 310 | }; 311 | 60CB12F8D305CEAC0BC893FF /* [CP] Check Pods Manifest.lock */ = { 312 | isa = PBXShellScriptBuildPhase; 313 | buildActionMask = 2147483647; 314 | files = ( 315 | ); 316 | inputFileListPaths = ( 317 | ); 318 | inputPaths = ( 319 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 320 | "${PODS_ROOT}/Manifest.lock", 321 | ); 322 | name = "[CP] Check Pods Manifest.lock"; 323 | outputFileListPaths = ( 324 | ); 325 | outputPaths = ( 326 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 327 | ); 328 | runOnlyForDeploymentPostprocessing = 0; 329 | shellPath = /bin/sh; 330 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 331 | showEnvVarsInLog = 0; 332 | }; 333 | 9740EEB61CF901F6004384FC /* Run Script */ = { 334 | isa = PBXShellScriptBuildPhase; 335 | alwaysOutOfDate = 1; 336 | buildActionMask = 2147483647; 337 | files = ( 338 | ); 339 | inputPaths = ( 340 | ); 341 | name = "Run Script"; 342 | outputPaths = ( 343 | ); 344 | runOnlyForDeploymentPostprocessing = 0; 345 | shellPath = /bin/sh; 346 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 347 | }; 348 | D610BE3FAC16B6034B979B62 /* [CP] Copy Pods Resources */ = { 349 | isa = PBXShellScriptBuildPhase; 350 | buildActionMask = 2147483647; 351 | files = ( 352 | ); 353 | inputFileListPaths = ( 354 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", 355 | ); 356 | name = "[CP] Copy Pods Resources"; 357 | outputFileListPaths = ( 358 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", 359 | ); 360 | runOnlyForDeploymentPostprocessing = 0; 361 | shellPath = /bin/sh; 362 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; 363 | showEnvVarsInLog = 0; 364 | }; 365 | /* End PBXShellScriptBuildPhase section */ 366 | 367 | /* Begin PBXSourcesBuildPhase section */ 368 | 331C807D294A63A400263BE5 /* Sources */ = { 369 | isa = PBXSourcesBuildPhase; 370 | buildActionMask = 2147483647; 371 | files = ( 372 | 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, 373 | ); 374 | runOnlyForDeploymentPostprocessing = 0; 375 | }; 376 | 97C146EA1CF9000F007C117D /* Sources */ = { 377 | isa = PBXSourcesBuildPhase; 378 | buildActionMask = 2147483647; 379 | files = ( 380 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 381 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 382 | ); 383 | runOnlyForDeploymentPostprocessing = 0; 384 | }; 385 | /* End PBXSourcesBuildPhase section */ 386 | 387 | /* Begin PBXTargetDependency section */ 388 | 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { 389 | isa = PBXTargetDependency; 390 | target = 97C146ED1CF9000F007C117D /* Runner */; 391 | targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; 392 | }; 393 | /* End PBXTargetDependency section */ 394 | 395 | /* Begin PBXVariantGroup section */ 396 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 397 | isa = PBXVariantGroup; 398 | children = ( 399 | 97C146FB1CF9000F007C117D /* Base */, 400 | ); 401 | name = Main.storyboard; 402 | sourceTree = ""; 403 | }; 404 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 405 | isa = PBXVariantGroup; 406 | children = ( 407 | 97C147001CF9000F007C117D /* Base */, 408 | ); 409 | name = LaunchScreen.storyboard; 410 | sourceTree = ""; 411 | }; 412 | /* End PBXVariantGroup section */ 413 | 414 | /* Begin XCBuildConfiguration section */ 415 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 416 | isa = XCBuildConfiguration; 417 | buildSettings = { 418 | ALWAYS_SEARCH_USER_PATHS = NO; 419 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 420 | CLANG_ANALYZER_NONNULL = YES; 421 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 422 | CLANG_CXX_LIBRARY = "libc++"; 423 | CLANG_ENABLE_MODULES = YES; 424 | CLANG_ENABLE_OBJC_ARC = YES; 425 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 426 | CLANG_WARN_BOOL_CONVERSION = YES; 427 | CLANG_WARN_COMMA = YES; 428 | CLANG_WARN_CONSTANT_CONVERSION = YES; 429 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 430 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 431 | CLANG_WARN_EMPTY_BODY = YES; 432 | CLANG_WARN_ENUM_CONVERSION = YES; 433 | CLANG_WARN_INFINITE_RECURSION = YES; 434 | CLANG_WARN_INT_CONVERSION = YES; 435 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 436 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 437 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 438 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 439 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 440 | CLANG_WARN_STRICT_PROTOTYPES = YES; 441 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 442 | CLANG_WARN_UNREACHABLE_CODE = YES; 443 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 444 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 445 | COPY_PHASE_STRIP = NO; 446 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 447 | ENABLE_NS_ASSERTIONS = NO; 448 | ENABLE_STRICT_OBJC_MSGSEND = YES; 449 | ENABLE_USER_SCRIPT_SANDBOXING = NO; 450 | GCC_C_LANGUAGE_STANDARD = gnu99; 451 | GCC_NO_COMMON_BLOCKS = YES; 452 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 453 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 454 | GCC_WARN_UNDECLARED_SELECTOR = YES; 455 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 456 | GCC_WARN_UNUSED_FUNCTION = YES; 457 | GCC_WARN_UNUSED_VARIABLE = YES; 458 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 459 | MTL_ENABLE_DEBUG_INFO = NO; 460 | SDKROOT = iphoneos; 461 | SUPPORTED_PLATFORMS = iphoneos; 462 | TARGETED_DEVICE_FAMILY = "1,2"; 463 | VALIDATE_PRODUCT = YES; 464 | }; 465 | name = Profile; 466 | }; 467 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 468 | isa = XCBuildConfiguration; 469 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 470 | buildSettings = { 471 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 472 | CLANG_ENABLE_MODULES = YES; 473 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 474 | DEVELOPMENT_TEAM = YT6L53WBRM; 475 | ENABLE_BITCODE = NO; 476 | INFOPLIST_FILE = Runner/Info.plist; 477 | LD_RUNPATH_SEARCH_PATHS = ( 478 | "$(inherited)", 479 | "@executable_path/Frameworks", 480 | ); 481 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 482 | PRODUCT_NAME = "$(TARGET_NAME)"; 483 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 484 | SWIFT_VERSION = 5.0; 485 | VERSIONING_SYSTEM = "apple-generic"; 486 | }; 487 | name = Profile; 488 | }; 489 | 331C8088294A63A400263BE5 /* Debug */ = { 490 | isa = XCBuildConfiguration; 491 | baseConfigurationReference = 1237574ED09198C4D9CCE88E /* Pods-RunnerTests.debug.xcconfig */; 492 | buildSettings = { 493 | BUNDLE_LOADER = "$(TEST_HOST)"; 494 | CODE_SIGN_STYLE = Automatic; 495 | CURRENT_PROJECT_VERSION = 1; 496 | GENERATE_INFOPLIST_FILE = YES; 497 | MARKETING_VERSION = 1.0; 498 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; 499 | PRODUCT_NAME = "$(TARGET_NAME)"; 500 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 501 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 502 | SWIFT_VERSION = 5.0; 503 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 504 | }; 505 | name = Debug; 506 | }; 507 | 331C8089294A63A400263BE5 /* Release */ = { 508 | isa = XCBuildConfiguration; 509 | baseConfigurationReference = 1E3D29213C4E669E6E724FC1 /* Pods-RunnerTests.release.xcconfig */; 510 | buildSettings = { 511 | BUNDLE_LOADER = "$(TEST_HOST)"; 512 | CODE_SIGN_STYLE = Automatic; 513 | CURRENT_PROJECT_VERSION = 1; 514 | GENERATE_INFOPLIST_FILE = YES; 515 | MARKETING_VERSION = 1.0; 516 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; 517 | PRODUCT_NAME = "$(TARGET_NAME)"; 518 | SWIFT_VERSION = 5.0; 519 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 520 | }; 521 | name = Release; 522 | }; 523 | 331C808A294A63A400263BE5 /* Profile */ = { 524 | isa = XCBuildConfiguration; 525 | baseConfigurationReference = 05EBE461B80CA9BEEAF979C1 /* Pods-RunnerTests.profile.xcconfig */; 526 | buildSettings = { 527 | BUNDLE_LOADER = "$(TEST_HOST)"; 528 | CODE_SIGN_STYLE = Automatic; 529 | CURRENT_PROJECT_VERSION = 1; 530 | GENERATE_INFOPLIST_FILE = YES; 531 | MARKETING_VERSION = 1.0; 532 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; 533 | PRODUCT_NAME = "$(TARGET_NAME)"; 534 | SWIFT_VERSION = 5.0; 535 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 536 | }; 537 | name = Profile; 538 | }; 539 | 97C147031CF9000F007C117D /* Debug */ = { 540 | isa = XCBuildConfiguration; 541 | buildSettings = { 542 | ALWAYS_SEARCH_USER_PATHS = NO; 543 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 544 | CLANG_ANALYZER_NONNULL = YES; 545 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 546 | CLANG_CXX_LIBRARY = "libc++"; 547 | CLANG_ENABLE_MODULES = YES; 548 | CLANG_ENABLE_OBJC_ARC = YES; 549 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 550 | CLANG_WARN_BOOL_CONVERSION = YES; 551 | CLANG_WARN_COMMA = YES; 552 | CLANG_WARN_CONSTANT_CONVERSION = YES; 553 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 554 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 555 | CLANG_WARN_EMPTY_BODY = YES; 556 | CLANG_WARN_ENUM_CONVERSION = YES; 557 | CLANG_WARN_INFINITE_RECURSION = YES; 558 | CLANG_WARN_INT_CONVERSION = YES; 559 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 560 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 561 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 562 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 563 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 564 | CLANG_WARN_STRICT_PROTOTYPES = YES; 565 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 566 | CLANG_WARN_UNREACHABLE_CODE = YES; 567 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 568 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 569 | COPY_PHASE_STRIP = NO; 570 | DEBUG_INFORMATION_FORMAT = dwarf; 571 | ENABLE_STRICT_OBJC_MSGSEND = YES; 572 | ENABLE_TESTABILITY = YES; 573 | ENABLE_USER_SCRIPT_SANDBOXING = NO; 574 | GCC_C_LANGUAGE_STANDARD = gnu99; 575 | GCC_DYNAMIC_NO_PIC = NO; 576 | GCC_NO_COMMON_BLOCKS = YES; 577 | GCC_OPTIMIZATION_LEVEL = 0; 578 | GCC_PREPROCESSOR_DEFINITIONS = ( 579 | "DEBUG=1", 580 | "$(inherited)", 581 | ); 582 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 583 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 584 | GCC_WARN_UNDECLARED_SELECTOR = YES; 585 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 586 | GCC_WARN_UNUSED_FUNCTION = YES; 587 | GCC_WARN_UNUSED_VARIABLE = YES; 588 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 589 | MTL_ENABLE_DEBUG_INFO = YES; 590 | ONLY_ACTIVE_ARCH = YES; 591 | SDKROOT = iphoneos; 592 | TARGETED_DEVICE_FAMILY = "1,2"; 593 | }; 594 | name = Debug; 595 | }; 596 | 97C147041CF9000F007C117D /* Release */ = { 597 | isa = XCBuildConfiguration; 598 | buildSettings = { 599 | ALWAYS_SEARCH_USER_PATHS = NO; 600 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 601 | CLANG_ANALYZER_NONNULL = YES; 602 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 603 | CLANG_CXX_LIBRARY = "libc++"; 604 | CLANG_ENABLE_MODULES = YES; 605 | CLANG_ENABLE_OBJC_ARC = YES; 606 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 607 | CLANG_WARN_BOOL_CONVERSION = YES; 608 | CLANG_WARN_COMMA = YES; 609 | CLANG_WARN_CONSTANT_CONVERSION = YES; 610 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 611 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 612 | CLANG_WARN_EMPTY_BODY = YES; 613 | CLANG_WARN_ENUM_CONVERSION = YES; 614 | CLANG_WARN_INFINITE_RECURSION = YES; 615 | CLANG_WARN_INT_CONVERSION = YES; 616 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 617 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 618 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 619 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 620 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 621 | CLANG_WARN_STRICT_PROTOTYPES = YES; 622 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 623 | CLANG_WARN_UNREACHABLE_CODE = YES; 624 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 625 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 626 | COPY_PHASE_STRIP = NO; 627 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 628 | ENABLE_NS_ASSERTIONS = NO; 629 | ENABLE_STRICT_OBJC_MSGSEND = YES; 630 | ENABLE_USER_SCRIPT_SANDBOXING = NO; 631 | GCC_C_LANGUAGE_STANDARD = gnu99; 632 | GCC_NO_COMMON_BLOCKS = YES; 633 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 634 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 635 | GCC_WARN_UNDECLARED_SELECTOR = YES; 636 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 637 | GCC_WARN_UNUSED_FUNCTION = YES; 638 | GCC_WARN_UNUSED_VARIABLE = YES; 639 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 640 | MTL_ENABLE_DEBUG_INFO = NO; 641 | SDKROOT = iphoneos; 642 | SUPPORTED_PLATFORMS = iphoneos; 643 | SWIFT_COMPILATION_MODE = wholemodule; 644 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 645 | TARGETED_DEVICE_FAMILY = "1,2"; 646 | VALIDATE_PRODUCT = YES; 647 | }; 648 | name = Release; 649 | }; 650 | 97C147061CF9000F007C117D /* Debug */ = { 651 | isa = XCBuildConfiguration; 652 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 653 | buildSettings = { 654 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 655 | CLANG_ENABLE_MODULES = YES; 656 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 657 | DEVELOPMENT_TEAM = YT6L53WBRM; 658 | ENABLE_BITCODE = NO; 659 | INFOPLIST_FILE = Runner/Info.plist; 660 | LD_RUNPATH_SEARCH_PATHS = ( 661 | "$(inherited)", 662 | "@executable_path/Frameworks", 663 | ); 664 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 665 | PRODUCT_NAME = "$(TARGET_NAME)"; 666 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 667 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 668 | SWIFT_VERSION = 5.0; 669 | VERSIONING_SYSTEM = "apple-generic"; 670 | }; 671 | name = Debug; 672 | }; 673 | 97C147071CF9000F007C117D /* Release */ = { 674 | isa = XCBuildConfiguration; 675 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 676 | buildSettings = { 677 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 678 | CLANG_ENABLE_MODULES = YES; 679 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 680 | DEVELOPMENT_TEAM = YT6L53WBRM; 681 | ENABLE_BITCODE = NO; 682 | INFOPLIST_FILE = Runner/Info.plist; 683 | LD_RUNPATH_SEARCH_PATHS = ( 684 | "$(inherited)", 685 | "@executable_path/Frameworks", 686 | ); 687 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example; 688 | PRODUCT_NAME = "$(TARGET_NAME)"; 689 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 690 | SWIFT_VERSION = 5.0; 691 | VERSIONING_SYSTEM = "apple-generic"; 692 | }; 693 | name = Release; 694 | }; 695 | /* End XCBuildConfiguration section */ 696 | 697 | /* Begin XCConfigurationList section */ 698 | 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { 699 | isa = XCConfigurationList; 700 | buildConfigurations = ( 701 | 331C8088294A63A400263BE5 /* Debug */, 702 | 331C8089294A63A400263BE5 /* Release */, 703 | 331C808A294A63A400263BE5 /* Profile */, 704 | ); 705 | defaultConfigurationIsVisible = 0; 706 | defaultConfigurationName = Release; 707 | }; 708 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 709 | isa = XCConfigurationList; 710 | buildConfigurations = ( 711 | 97C147031CF9000F007C117D /* Debug */, 712 | 97C147041CF9000F007C117D /* Release */, 713 | 249021D3217E4FDB00AE95B9 /* Profile */, 714 | ); 715 | defaultConfigurationIsVisible = 0; 716 | defaultConfigurationName = Release; 717 | }; 718 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 719 | isa = XCConfigurationList; 720 | buildConfigurations = ( 721 | 97C147061CF9000F007C117D /* Debug */, 722 | 97C147071CF9000F007C117D /* Release */, 723 | 249021D4217E4FDB00AE95B9 /* Profile */, 724 | ); 725 | defaultConfigurationIsVisible = 0; 726 | defaultConfigurationName = Release; 727 | }; 728 | /* End XCConfigurationList section */ 729 | }; 730 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 731 | } 732 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 38 | 39 | 40 | 41 | 44 | 50 | 51 | 52 | 53 | 54 | 66 | 68 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | 4 | @main 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Flutter Unity Ads Example 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | unity_ads_plugin_example 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | CADisableMinimumFrameDurationOnPhone 45 | 46 | UIApplicationSupportsIndirectInputEvents 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:unity_ads_plugin/unity_ads_plugin.dart'; 4 | 5 | void main() { 6 | runApp(const UnityAdsExampleApp()); 7 | } 8 | 9 | class UnityAdsExampleApp extends StatelessWidget { 10 | const UnityAdsExampleApp({Key? key}) : super(key: key); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return MaterialApp( 15 | debugShowCheckedModeBanner: false, 16 | title: 'Unity Ads Example', 17 | home: Scaffold( 18 | appBar: AppBar( 19 | title: const Text('Unity Ads Example'), 20 | ), 21 | body: const SafeArea( 22 | child: _UnityAdsExample(), 23 | ), 24 | ), 25 | ); 26 | } 27 | } 28 | 29 | class _UnityAdsExample extends StatefulWidget { 30 | const _UnityAdsExample({Key? key}) : super(key: key); 31 | 32 | @override 33 | _UnityAdsExampleState createState() => _UnityAdsExampleState(); 34 | } 35 | 36 | class _UnityAdsExampleState extends State<_UnityAdsExample> { 37 | bool _showBanner = false; 38 | Map placements = { 39 | AdManager.interstitialVideoAdPlacementId: false, 40 | AdManager.rewardedVideoAdPlacementId: false, 41 | }; 42 | 43 | @override 44 | void initState() { 45 | super.initState(); 46 | UnityAds.init( 47 | gameId: AdManager.gameId, 48 | testMode: true, 49 | onComplete: () { 50 | print('Initialization Complete'); 51 | _loadAds(); 52 | }, 53 | onFailed: (error, message) => 54 | print('Initialization Failed: $error $message'), 55 | ); 56 | } 57 | 58 | @override 59 | Widget build(BuildContext context) { 60 | return SizedBox( 61 | width: double.infinity, 62 | child: Column( 63 | crossAxisAlignment: CrossAxisAlignment.center, 64 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 65 | children: [ 66 | Column( 67 | crossAxisAlignment: CrossAxisAlignment.center, 68 | children: [ 69 | ElevatedButton( 70 | onPressed: () { 71 | setState(() { 72 | _showBanner = !_showBanner; 73 | }); 74 | }, 75 | child: Text(_showBanner ? 'Hide Banner' : 'Show Banner'), 76 | ), 77 | ElevatedButton( 78 | onPressed: 79 | placements[AdManager.rewardedVideoAdPlacementId] == true 80 | ? () => _showAd(AdManager.rewardedVideoAdPlacementId) 81 | : null, 82 | child: const Text('Show Rewarded Video'), 83 | ), 84 | ElevatedButton( 85 | onPressed: 86 | placements[AdManager.interstitialVideoAdPlacementId] == true 87 | ? () => 88 | _showAd(AdManager.interstitialVideoAdPlacementId) 89 | : null, 90 | child: const Text('Show Interstitial Video'), 91 | ), 92 | ], 93 | ), 94 | if (_showBanner) 95 | UnityBannerAd( 96 | placementId: AdManager.bannerAdPlacementId, 97 | onLoad: (placementId) => print('Banner loaded: $placementId'), 98 | onClick: (placementId) => print('Banner clicked: $placementId'), 99 | onShown: (placementId) => print('Banner shown: $placementId'), 100 | onFailed: (placementId, error, message) => 101 | print('Banner Ad $placementId failed: $error $message'), 102 | ), 103 | ], 104 | ), 105 | ); 106 | } 107 | 108 | void _loadAds() { 109 | for (var placementId in placements.keys) { 110 | _loadAd(placementId); 111 | } 112 | } 113 | 114 | void _loadAd(String placementId) { 115 | UnityAds.load( 116 | placementId: placementId, 117 | onComplete: (placementId) { 118 | print('Load Complete $placementId'); 119 | setState(() { 120 | placements[placementId] = true; 121 | }); 122 | }, 123 | onFailed: (placementId, error, message) => 124 | print('Load Failed $placementId: $error $message'), 125 | ); 126 | } 127 | 128 | void _showAd(String placementId) { 129 | setState(() { 130 | placements[placementId] = false; 131 | }); 132 | UnityAds.showVideoAd( 133 | placementId: placementId, 134 | onComplete: (placementId) { 135 | print('Video Ad $placementId completed'); 136 | _loadAd(placementId); 137 | }, 138 | onFailed: (placementId, error, message) { 139 | print('Video Ad $placementId failed: $error $message'); 140 | _loadAd(placementId); 141 | }, 142 | onStart: (placementId) => print('Video Ad $placementId started'), 143 | onClick: (placementId) => print('Video Ad $placementId click'), 144 | onSkipped: (placementId) { 145 | print('Video Ad $placementId skipped'); 146 | _loadAd(placementId); 147 | }, 148 | ); 149 | } 150 | } 151 | 152 | class AdManager { 153 | static String get gameId { 154 | if (defaultTargetPlatform == TargetPlatform.android) { 155 | return 'your_android_game_id'; 156 | } 157 | if (defaultTargetPlatform == TargetPlatform.iOS) { 158 | return 'your_ios_game_id'; 159 | } 160 | return ''; 161 | } 162 | 163 | static String get bannerAdPlacementId { 164 | return 'your_banner_ad_placement_id'; 165 | } 166 | 167 | static String get interstitialVideoAdPlacementId { 168 | return 'your_interstitial_video_ad_placement_id'; 169 | } 170 | 171 | static String get rewardedVideoAdPlacementId { 172 | return 'your_rewarded_video_ad_placement_id'; 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.13.0" 12 | boolean_selector: 13 | dependency: transitive 14 | description: 15 | name: boolean_selector 16 | sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.1.2" 20 | characters: 21 | dependency: transitive 22 | description: 23 | name: characters 24 | sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "1.4.0" 28 | clock: 29 | dependency: transitive 30 | description: 31 | name: clock 32 | sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.1.2" 36 | collection: 37 | dependency: transitive 38 | description: 39 | name: collection 40 | sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.19.1" 44 | cupertino_icons: 45 | dependency: "direct main" 46 | description: 47 | name: cupertino_icons 48 | sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.0.6" 52 | fake_async: 53 | dependency: transitive 54 | description: 55 | name: fake_async 56 | sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "1.3.3" 60 | flutter: 61 | dependency: "direct main" 62 | description: flutter 63 | source: sdk 64 | version: "0.0.0" 65 | flutter_lints: 66 | dependency: "direct dev" 67 | description: 68 | name: flutter_lints 69 | sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" 70 | url: "https://pub.dev" 71 | source: hosted 72 | version: "5.0.0" 73 | flutter_test: 74 | dependency: "direct dev" 75 | description: flutter 76 | source: sdk 77 | version: "0.0.0" 78 | leak_tracker: 79 | dependency: transitive 80 | description: 81 | name: leak_tracker 82 | sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" 83 | url: "https://pub.dev" 84 | source: hosted 85 | version: "10.0.9" 86 | leak_tracker_flutter_testing: 87 | dependency: transitive 88 | description: 89 | name: leak_tracker_flutter_testing 90 | sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 91 | url: "https://pub.dev" 92 | source: hosted 93 | version: "3.0.9" 94 | leak_tracker_testing: 95 | dependency: transitive 96 | description: 97 | name: leak_tracker_testing 98 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" 99 | url: "https://pub.dev" 100 | source: hosted 101 | version: "3.0.1" 102 | lints: 103 | dependency: transitive 104 | description: 105 | name: lints 106 | sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413" 107 | url: "https://pub.dev" 108 | source: hosted 109 | version: "5.0.0" 110 | matcher: 111 | dependency: transitive 112 | description: 113 | name: matcher 114 | sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 115 | url: "https://pub.dev" 116 | source: hosted 117 | version: "0.12.17" 118 | material_color_utilities: 119 | dependency: transitive 120 | description: 121 | name: material_color_utilities 122 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec 123 | url: "https://pub.dev" 124 | source: hosted 125 | version: "0.11.1" 126 | meta: 127 | dependency: transitive 128 | description: 129 | name: meta 130 | sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c 131 | url: "https://pub.dev" 132 | source: hosted 133 | version: "1.16.0" 134 | path: 135 | dependency: transitive 136 | description: 137 | name: path 138 | sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" 139 | url: "https://pub.dev" 140 | source: hosted 141 | version: "1.9.1" 142 | sky_engine: 143 | dependency: transitive 144 | description: flutter 145 | source: sdk 146 | version: "0.0.0" 147 | source_span: 148 | dependency: transitive 149 | description: 150 | name: source_span 151 | sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" 152 | url: "https://pub.dev" 153 | source: hosted 154 | version: "1.10.1" 155 | stack_trace: 156 | dependency: transitive 157 | description: 158 | name: stack_trace 159 | sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" 160 | url: "https://pub.dev" 161 | source: hosted 162 | version: "1.12.1" 163 | stream_channel: 164 | dependency: transitive 165 | description: 166 | name: stream_channel 167 | sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" 168 | url: "https://pub.dev" 169 | source: hosted 170 | version: "2.1.4" 171 | string_scanner: 172 | dependency: transitive 173 | description: 174 | name: string_scanner 175 | sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" 176 | url: "https://pub.dev" 177 | source: hosted 178 | version: "1.4.1" 179 | term_glyph: 180 | dependency: transitive 181 | description: 182 | name: term_glyph 183 | sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" 184 | url: "https://pub.dev" 185 | source: hosted 186 | version: "1.2.2" 187 | test_api: 188 | dependency: transitive 189 | description: 190 | name: test_api 191 | sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd 192 | url: "https://pub.dev" 193 | source: hosted 194 | version: "0.7.4" 195 | unity_ads_plugin: 196 | dependency: "direct main" 197 | description: 198 | path: ".." 199 | relative: true 200 | source: path 201 | version: "0.3.25" 202 | vector_math: 203 | dependency: transitive 204 | description: 205 | name: vector_math 206 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 207 | url: "https://pub.dev" 208 | source: hosted 209 | version: "2.1.4" 210 | vm_service: 211 | dependency: transitive 212 | description: 213 | name: vm_service 214 | sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 215 | url: "https://pub.dev" 216 | source: hosted 217 | version: "15.0.0" 218 | sdks: 219 | dart: ">=3.7.0-0 <4.0.0" 220 | flutter: ">=3.18.0-18.0.pre.54" 221 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: unity_ads_example 2 | description: Demonstrates how to use the unity_ads_plugin plugin. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | environment: 9 | sdk: '>=2.12.0 <3.0.0' 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | 15 | unity_ads_plugin: 16 | # When depending on this package from a real application you should use: 17 | # unity_ads: ^x.y.z 18 | # See https://dart.dev/tools/pub/dependencies#version-constraints 19 | # The example app is bundled with the plugin so we use a path dependency on 20 | # the parent directory to use the current plugin's version. 21 | path: ../ 22 | 23 | # The following adds the Cupertino Icons font to your application. 24 | # Use with the CupertinoIcons class for iOS style icons. 25 | cupertino_icons: ^1.0.0 26 | 27 | dev_dependencies: 28 | flutter_test: 29 | sdk: flutter 30 | flutter_lints: ^5.0.0 31 | # For information on the generic Dart part of this file, see the 32 | # following page: https://dart.dev/tools/pub/pubspec 33 | 34 | # The following section is specific to Flutter. 35 | flutter: 36 | 37 | # The following line ensures that the Material Icons font is 38 | # included with your application, so that you can use the icons in 39 | # the material Icons class. 40 | uses-material-design: true 41 | 42 | # To add assets to your application, add an assets section, like this: 43 | # assets: 44 | # - images/a_dot_burr.jpeg 45 | # - images/a_dot_ham.jpeg 46 | 47 | # An image asset can refer to one or more resolution-specific "variants", see 48 | # https://flutter.dev/assets-and-images/#resolution-aware. 49 | 50 | # For details regarding adding assets from package dependencies, see 51 | # https://flutter.dev/assets-and-images/#from-packages 52 | 53 | # To add custom fonts to your application, add a fonts section here, 54 | # in this "flutter" section. Each entry in this list should have a 55 | # "family" key with the font family name, and a "fonts" key with a 56 | # list giving the asset and other descriptors for the font. For 57 | # example: 58 | # fonts: 59 | # - family: Schyler 60 | # fonts: 61 | # - asset: fonts/Schyler-Regular.ttf 62 | # - asset: fonts/Schyler-Italic.ttf 63 | # style: italic 64 | # - family: Trajan Pro 65 | # fonts: 66 | # - asset: fonts/TrajanPro.ttf 67 | # - asset: fonts/TrajanPro_Bold.ttf 68 | # weight: 700 69 | # 70 | # For details regarding fonts from package dependencies, 71 | # see https://flutter.dev/custom-fonts/#from-packages 72 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/Generated.xcconfig 37 | /Flutter/flutter_export_environment.sh -------------------------------------------------------------------------------- /ios/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavelzaichyk/flutter_unity_ads/4b1458c5704df6ce81761c8644a0b33331b7456b/ios/Assets/.gitkeep -------------------------------------------------------------------------------- /ios/Classes/BannerAdFactory.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UnityAds 3 | 4 | class BannerAdFactory: NSObject, FlutterPlatformViewFactory { 5 | private var messenger: FlutterBinaryMessenger 6 | 7 | init(messenger: FlutterBinaryMessenger) { 8 | self.messenger = messenger 9 | super.init() 10 | } 11 | 12 | func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol { 13 | return FlutterStandardMessageCodec.sharedInstance() 14 | } 15 | 16 | func create( 17 | withFrame frame: CGRect, 18 | viewIdentifier viewId: Int64, 19 | arguments args: Any? 20 | ) -> FlutterPlatformView { 21 | return BannerAdView( 22 | frame: frame, 23 | id: viewId, 24 | arguments: args, 25 | messenger: messenger) 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /ios/Classes/BannerAdListener.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UnityAds 3 | 4 | class BannerAdListener: NSObject, UADSBannerViewDelegate { 5 | let channel: FlutterMethodChannel 6 | 7 | init(channel: FlutterMethodChannel) { 8 | self.channel = channel 9 | } 10 | 11 | func bannerViewDidLoad(_ bannerView: UADSBannerView) { 12 | channel.invokeMethod(UnityAdsConstants.BANNER_LOADED_METHOD, 13 | arguments: [UnityAdsConstants.PLACEMENT_ID_PARAMETER: bannerView.placementId]) 14 | } 15 | 16 | func bannerViewDidShow(_ bannerView: UADSBannerView) { 17 | channel.invokeMethod(UnityAdsConstants.BANNER_SHOWN_METHOD, 18 | arguments: [UnityAdsConstants.PLACEMENT_ID_PARAMETER: bannerView.placementId]) 19 | } 20 | 21 | func bannerViewDidClick(_ bannerView: UADSBannerView) { 22 | channel.invokeMethod(UnityAdsConstants.BANNER_CLICKED_METHOD, 23 | arguments: [UnityAdsConstants.PLACEMENT_ID_PARAMETER: bannerView.placementId]) 24 | } 25 | 26 | func bannerViewDidError(_ bannerView: UADSBannerView, error: UADSBannerError) { 27 | let arguments = [ 28 | UnityAdsConstants.PLACEMENT_ID_PARAMETER: bannerView.placementId, 29 | UnityAdsConstants.ERROR_CODE_PARAMETER: convertError(error), 30 | UnityAdsConstants.ERROR_MESSAGE_PARAMETER: error.localizedDescription ]; 31 | 32 | channel.invokeMethod(UnityAdsConstants.BANNER_ERROR_METHOD, arguments: arguments); 33 | } 34 | 35 | func bannerViewDidLeaveApplication(_ bannerView: UADSBannerView) { 36 | } 37 | 38 | private func convertError(_ error: UADSBannerError) -> String { 39 | switch (error.code) { 40 | case 0: 41 | return "unknown" 42 | case 1: 43 | return "native" 44 | case 2: 45 | return "webView" 46 | case 3: 47 | return "noFill" 48 | default: 49 | return "" 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ios/Classes/BannerAdView.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UnityAds 3 | 4 | class BannerAdView: NSObject, FlutterPlatformView, UADSBannerViewDelegate { 5 | private let bannerView : UADSBannerView 6 | private let uiView : UIView 7 | private let listener : BannerAdListener 8 | 9 | init(frame: CGRect, id: Int64, arguments: Any?, messenger: FlutterBinaryMessenger) { 10 | let args = arguments as! [String: Any]? ?? [:] 11 | let placementId = args[UnityAdsConstants.PLACEMENT_ID_PARAMETER] as? String ?? "" 12 | 13 | let width = args[UnityAdsConstants.WIDTH_PARAMETER] as? CGFloat 14 | let height = args[UnityAdsConstants.HEIGHT_PARAMETER] as? CGFloat 15 | let size = CGSize(width: width ?? 320.0, height: height ?? 50.0) 16 | bannerView = UADSBannerView.init(placementId: placementId, size: size) 17 | 18 | let channel = FlutterMethodChannel( 19 | name: UnityAdsConstants.BANNER_AD_CHANNEL + "_" + id.description, binaryMessenger: messenger) 20 | listener = BannerAdListener(channel: channel) 21 | 22 | uiView = UIView(frame: frame) 23 | super.init() 24 | 25 | bannerView.delegate = listener 26 | 27 | bannerView.load() 28 | uiView.addSubview(bannerView) 29 | uiView.layoutIfNeeded() 30 | } 31 | 32 | func view() -> UIView { 33 | uiView 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /ios/Classes/PlacementChannelManager.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UnityAds 3 | 4 | public class PlacementChannelManager { 5 | 6 | var placementChannels: [String: FlutterMethodChannel]; 7 | let binaryMessenger: FlutterBinaryMessenger 8 | 9 | init(binaryMessenger: FlutterBinaryMessenger) { 10 | self.binaryMessenger = binaryMessenger 11 | self.placementChannels = [String: FlutterMethodChannel]() 12 | } 13 | 14 | public func invokeMethod(_ methodName: String, _ placementId: String) { 15 | invokeMethod(methodName, placementId, arguments: [:]) 16 | } 17 | 18 | public func invokeMethod(_ methodName: String, _ placementId: String, withErrorCode code: String, withMessage message: String) { 19 | var arguments: [String:String] = [:] 20 | arguments[UnityAdsConstants.ERROR_CODE_PARAMETER] = code 21 | arguments[UnityAdsConstants.ERROR_MESSAGE_PARAMETER] = message 22 | invokeMethod(methodName, placementId, arguments: arguments) 23 | } 24 | 25 | func invokeMethod(_ methodName: String,_ placementId: String, arguments: [String:String]){ 26 | var args = arguments; 27 | args[UnityAdsConstants.PLACEMENT_ID_PARAMETER]=placementId 28 | var channel = placementChannels[placementId] 29 | if (channel == nil) { 30 | channel = FlutterMethodChannel(name: UnityAdsConstants.VIDEO_AD_CHANNEL + "_" + placementId, binaryMessenger: binaryMessenger) 31 | placementChannels[placementId] = channel 32 | } 33 | channel?.invokeMethod(methodName, arguments: args) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ios/Classes/SwiftUnityAdsPlugin.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UnityAds 3 | 4 | public class SwiftUnityAdsPlugin: NSObject, FlutterPlugin { 5 | 6 | static var viewController : UIViewController = UIViewController(); 7 | 8 | public static func register(with registrar: FlutterPluginRegistrar) { 9 | viewController = 10 | (UIApplication.shared.delegate?.window??.rootViewController)!; 11 | let messenger = registrar.messenger() 12 | 13 | let placementChannelManager = PlacementChannelManager(binaryMessenger: messenger) 14 | let channel = FlutterMethodChannel(name: UnityAdsConstants.MAIN_CHANNEL, binaryMessenger: messenger) 15 | let privacyConsent = PrivacyConsent() 16 | channel.setMethodCallHandler({ 17 | (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in 18 | let args = call.arguments as? NSDictionary ?? [:] 19 | switch call.method { 20 | case UnityAdsConstants.INIT_METHOD: 21 | result(initialize(args, channel: channel)) 22 | case UnityAdsConstants.LOAD_METHOD: 23 | result(load(args, placementChannelManager: placementChannelManager)) 24 | case UnityAdsConstants.SHOW_VIDEO_METHOD: 25 | result(showVideo(args, placementChannelManager: placementChannelManager)) 26 | case UnityAdsConstants.PRIVACY_CONSENT_SET_METHOD: 27 | result(privacyConsent.set(args)) 28 | case UnityAdsConstants.IS_INITIALIZED_METHOD: 29 | result(UnityAds.isInitialized()) 30 | default: 31 | result(FlutterMethodNotImplemented) 32 | } 33 | }) 34 | 35 | registrar.register( 36 | BannerAdFactory(messenger: messenger), 37 | withId: UnityAdsConstants.BANNER_AD_CHANNEL 38 | ) 39 | 40 | } 41 | 42 | static func initialize(_ args: NSDictionary, channel: FlutterMethodChannel) -> Bool { 43 | let gameId = args[UnityAdsConstants.GAME_ID_PARAMETER] as! String 44 | let testMode = args[UnityAdsConstants.TEST_MODE_PARAMETER] as! Bool 45 | UnityAds.initialize(gameId, testMode: testMode, initializationDelegate: UnityAdsInitializationListener(channel: channel)) 46 | return true 47 | } 48 | 49 | static func load(_ args: NSDictionary, placementChannelManager: PlacementChannelManager) -> Bool { 50 | let placementId = args[UnityAdsConstants.PLACEMENT_ID_PARAMETER] as! String 51 | UnityAds.load(placementId, loadDelegate: UnityAdsLoadListener(placementChannelManager: placementChannelManager)) 52 | return true 53 | } 54 | 55 | static func showVideo(_ args: NSDictionary, placementChannelManager: PlacementChannelManager) -> Bool { 56 | let placementId = args[UnityAdsConstants.PLACEMENT_ID_PARAMETER] as! String 57 | let serverId = args[UnityAdsConstants.SERVER_ID_PARAMETER] as? String 58 | if (serverId != nil) { 59 | let playerMetaData = UADSPlayerMetaData() 60 | playerMetaData.setServerId(serverId) 61 | playerMetaData.commit() 62 | } 63 | UnityAds.show(viewController, placementId: placementId, showDelegate: UnityAdsShowListener(placementChannelManager: placementChannelManager)) 64 | return true 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /ios/Classes/UnityAdsConstants.swift: -------------------------------------------------------------------------------- 1 | struct UnityAdsConstants { 2 | static let MAIN_CHANNEL = "com.rebeloid.unity_ads"; 3 | 4 | static let BANNER_AD_CHANNEL = MAIN_CHANNEL + "/bannerAd"; 5 | static let VIDEO_AD_CHANNEL = MAIN_CHANNEL + "/videoAd"; 6 | 7 | static let PLACEMENT_ID_PARAMETER = "placementId"; 8 | static let ERROR_CODE_PARAMETER = "errorCode"; 9 | static let ERROR_MESSAGE_PARAMETER = "errorMessage"; 10 | 11 | //initialize 12 | static let INIT_METHOD = "init"; 13 | static let GAME_ID_PARAMETER = "gameId"; 14 | static let TEST_MODE_PARAMETER = "testMode"; 15 | static let INIT_COMPLETE_METHOD = "initComplete"; 16 | static let INIT_FAILED_METHOD = "initFailed"; 17 | static let IS_INITIALIZED_METHOD = "isInitialized"; 18 | 19 | //load 20 | static let LOAD_METHOD = "load"; 21 | static let LOAD_COMPLETE_METHOD = "loadComplete"; 22 | static let LOAD_FAILED_METHOD = "loadFailed"; 23 | 24 | //show 25 | static let SHOW_VIDEO_METHOD = "showVideo"; 26 | static let SERVER_ID_PARAMETER = "serverId"; 27 | static let SHOW_COMPLETE_METHOD = "showComplete"; 28 | static let SHOW_FAILED_METHOD = "showFailed"; 29 | static let SHOW_START_METHOD = "showStart"; 30 | static let SHOW_SKIPPED_METHOD = "showSkipped"; 31 | static let SHOW_CLICK_METHOD = "showClick"; 32 | 33 | //banner 34 | static let HEIGHT_PARAMETER = "height"; 35 | static let WIDTH_PARAMETER = "width"; 36 | static let BANNER_ERROR_METHOD = "banner_error"; 37 | static let BANNER_LOADED_METHOD = "banner_loaded"; 38 | static let BANNER_SHOWN_METHOD = "banner_shown"; 39 | static let BANNER_CLICKED_METHOD = "banner_clicked"; 40 | 41 | //privacy consent 42 | static let PRIVACY_CONSENT_SET_METHOD = "privacyConsent_set"; 43 | static let PRIVACY_CONSENT_TYPE_PARAMETER = "privacyConsent_type"; 44 | static let PRIVACY_CONSENT_VALUE_PARAMETER = "privacyConsent_value"; 45 | } 46 | -------------------------------------------------------------------------------- /ios/Classes/UnityAdsInitializationListener.swift: -------------------------------------------------------------------------------- 1 | import UnityAds 2 | 3 | public class UnityAdsInitializationListener : NSObject, UnityAdsInitializationDelegate { 4 | 5 | let channel : FlutterMethodChannel 6 | 7 | init(channel: FlutterMethodChannel) { 8 | self.channel = channel 9 | } 10 | 11 | public func initializationComplete() { 12 | channel.invokeMethod(UnityAdsConstants.INIT_COMPLETE_METHOD, arguments: []) 13 | } 14 | 15 | public func initializationFailed(_ error: UnityAdsInitializationError, withMessage message: String) { 16 | var arguments: [String:String] = [:] 17 | arguments[UnityAdsConstants.ERROR_CODE_PARAMETER]=convertError(error) 18 | arguments[UnityAdsConstants.ERROR_MESSAGE_PARAMETER]=message 19 | channel.invokeMethod(UnityAdsConstants.INIT_FAILED_METHOD, arguments: arguments) 20 | } 21 | 22 | private func convertError(_ error: UnityAdsInitializationError) -> String { 23 | switch (error) { 24 | case .initializationErrorInternalError: 25 | return "internalError"; 26 | case .initializationErrorInvalidArgument: 27 | return "invalidArgument"; 28 | case .initializationErrorAdBlockerDetected: 29 | return "adBlockerDetected"; 30 | @unknown default: 31 | return ""; 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /ios/Classes/UnityAdsLoadListener.swift: -------------------------------------------------------------------------------- 1 | import UnityAds 2 | 3 | public class UnityAdsLoadListener : NSObject, UnityAdsLoadDelegate { 4 | let placementChannelManager: PlacementChannelManager 5 | 6 | init(placementChannelManager: PlacementChannelManager) { 7 | self.placementChannelManager = placementChannelManager 8 | } 9 | 10 | public func unityAdsAdLoaded(_ placementId: String) { 11 | placementChannelManager.invokeMethod(UnityAdsConstants.LOAD_COMPLETE_METHOD, placementId) 12 | } 13 | 14 | public func unityAdsAdFailed(toLoad placementId: String, withError error: UnityAdsLoadError, withMessage message: String) { 15 | placementChannelManager.invokeMethod(UnityAdsConstants.LOAD_FAILED_METHOD, placementId, withErrorCode: convertError(error), withMessage: message) 16 | } 17 | 18 | private func convertError(_ error: UnityAdsLoadError) -> String { 19 | switch (error) { 20 | case .initializeFailed: 21 | return "initializeFailed" 22 | case .internal: 23 | return "internalError" 24 | case .invalidArgument: 25 | return "invalidArgument" 26 | case .noFill: 27 | return "noFill" 28 | case .timeout: 29 | return "timeout" 30 | @unknown default: 31 | return "" 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ios/Classes/UnityAdsPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface UnityAdsPlugin : NSObject 4 | @end 5 | -------------------------------------------------------------------------------- /ios/Classes/UnityAdsPlugin.m: -------------------------------------------------------------------------------- 1 | #import "UnityAdsPlugin.h" 2 | #if __has_include() 3 | #import 4 | #else 5 | // Support project import fallback if the generated compatibility header 6 | // is not copied when this plugin is created as a library. 7 | // https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 8 | #import "unity_ads_plugin-Swift.h" 9 | #endif 10 | 11 | @implementation UnityAdsPlugin 12 | + (void)registerWithRegistrar:(NSObject*)registrar { 13 | [SwiftUnityAdsPlugin registerWithRegistrar:registrar]; 14 | } 15 | @end 16 | -------------------------------------------------------------------------------- /ios/Classes/UnityAdsShowListener.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UnityAds 3 | 4 | public class UnityAdsShowListener : NSObject, UnityAdsShowDelegate { 5 | let placementChannelManager: PlacementChannelManager 6 | 7 | init(placementChannelManager: PlacementChannelManager) { 8 | self.placementChannelManager = placementChannelManager 9 | } 10 | 11 | public func unityAdsShowComplete(_ placementId: String, withFinish state: UnityAdsShowCompletionState) { 12 | if (state == UnityAdsShowCompletionState.showCompletionStateSkipped) { 13 | placementChannelManager.invokeMethod(UnityAdsConstants.SHOW_SKIPPED_METHOD, placementId) 14 | } else if (state == UnityAdsShowCompletionState.showCompletionStateCompleted) { 15 | placementChannelManager.invokeMethod(UnityAdsConstants.SHOW_COMPLETE_METHOD, placementId) 16 | } 17 | } 18 | 19 | public func unityAdsShowFailed(_ placementId: String, withError error: UnityAdsShowError, withMessage message: String) { 20 | placementChannelManager.invokeMethod(UnityAdsConstants.SHOW_FAILED_METHOD, placementId, withErrorCode: convertError(error), withMessage: message) 21 | } 22 | 23 | private func convertError(_ error: UnityAdsShowError) -> String { 24 | switch (error) { 25 | case .showErrorNotInitialized: 26 | return "notInitialized" 27 | case .showErrorNotReady: 28 | return "notReady" 29 | case .showErrorVideoPlayerError: 30 | return "videoPlayerError" 31 | case .showErrorInvalidArgument: 32 | return "invalidArgument" 33 | case .showErrorNoConnection: 34 | return "noConnection" 35 | case .showErrorAlreadyShowing: 36 | return "alreadyShowing" 37 | case .showErrorInternalError: 38 | return "internalError" 39 | case .showErrorTimeout: 40 | return "timeout" 41 | @unknown default: 42 | return "" 43 | } 44 | } 45 | 46 | public func unityAdsShowStart(_ placementId: String) { 47 | placementChannelManager.invokeMethod(UnityAdsConstants.SHOW_START_METHOD, placementId) 48 | } 49 | 50 | public func unityAdsShowClick(_ placementId: String) { 51 | placementChannelManager.invokeMethod(UnityAdsConstants.SHOW_CLICK_METHOD, placementId) 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /ios/Classes/privacy/PrivacyConsent.swift: -------------------------------------------------------------------------------- 1 | import UnityAds 2 | 3 | class PrivacyConsent { 4 | 5 | func set(_ args: NSDictionary) -> Bool { 6 | let type = args[UnityAdsConstants.PRIVACY_CONSENT_TYPE_PARAMETER] as! String 7 | let value = args[UnityAdsConstants.PRIVACY_CONSENT_VALUE_PARAMETER] as! Bool 8 | let metaData = UADSMetaData.init(); 9 | let success = metaData.set(defineType(type), value: value) 10 | metaData.commit(); 11 | return success; 12 | } 13 | 14 | private func defineType(_ type: String) -> String { 15 | switch (type) { 16 | case "pipl": 17 | return "pipl.consent"; 18 | case "gdpr": 19 | return "gdpr.consent"; 20 | case "ccpa": 21 | return "privacy.consent"; 22 | case "ageGate": 23 | return "privacy.useroveragelimit"; 24 | default: return type; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ios/unity_ads_plugin.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. 3 | # Run `pod lib lint unity_ads_plugin.podspec` to validate before publishing. 4 | # 5 | Pod::Spec.new do |s| 6 | s.name = 'unity_ads_plugin' 7 | s.version = '0.0.1' 8 | s.summary = 'Unity Ads plugin for Flutter Applications.' 9 | s.description = <<-DESC 10 | Flutter unity ads plugin. 11 | DESC 12 | s.homepage = 'http://example.com' 13 | s.license = { :file => '../LICENSE' } 14 | s.author = { 'Your Company' => 'email@example.com' } 15 | s.source = { :path => '.' } 16 | s.source_files = 'Classes/**/*' 17 | s.public_header_files = 'Classes/**/*.h' 18 | s.dependency 'Flutter' 19 | s.platform = :ios, '8.0' 20 | s.dependency 'UnityAds', '4.15.0' 21 | 22 | # Flutter.framework does not contain a i386 slice. 23 | # s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64'} 24 | s.swift_version = '5.0' 25 | s.static_framework = true 26 | s.ios.deployment_target = '8.0' 27 | end 28 | -------------------------------------------------------------------------------- /lib/src/constants.dart: -------------------------------------------------------------------------------- 1 | const mainChannel = 'com.rebeloid.unity_ads'; 2 | 3 | const bannerAdChannel = "$mainChannel/bannerAd"; 4 | const videoAdChannel = "$mainChannel/videoAd"; 5 | 6 | const gameIdParameter = "gameId"; 7 | const testModeParameter = "testMode"; 8 | const firebaseTestLabModeParameter = "firebaseTestLabMode"; 9 | 10 | const placementIdParameter = "placementId"; 11 | const errorCodeParameter = "errorCode"; 12 | const errorMessageParameter = "errorMessage"; 13 | 14 | //init 15 | const initMethod = "init"; 16 | const initCompleteMethod = "initComplete"; 17 | const initFailedMethod = "initFailed"; 18 | const isInitializedMethod = 'isInitialized'; 19 | 20 | //load 21 | const loadMethod = 'load'; 22 | const loadCompleteMethod = "loadComplete"; 23 | const loadFailedMethod = "loadFailed"; 24 | 25 | //show 26 | const showVideoMethod = "showVideo"; 27 | const serverIdParameter = "serverId"; 28 | const showCompleteMethod = "showComplete"; 29 | const showFailedMethod = "showFailed"; 30 | const showStartMethod = "showStart"; 31 | const showSkippedMethod = "showSkipped"; 32 | const showClickMethod = "showClick"; 33 | 34 | //banner 35 | const heightParameter = "height"; 36 | const widthParameter = "width"; 37 | const bannerErrorMethod = "banner_error"; 38 | const bannerLoadedMethod = "banner_loaded"; 39 | const bannerClickedMethod = "banner_clicked"; 40 | const bannerShownMethod = "banner_shown"; 41 | 42 | //privacy consent 43 | const privacyConsentSetMethod = "privacyConsent_set"; 44 | const privacyConsentTypeParameter = "privacyConsent_type"; 45 | const privacyConsentValueParameter = "privacyConsent_value"; 46 | -------------------------------------------------------------------------------- /lib/src/privacy_consent.dart: -------------------------------------------------------------------------------- 1 | /// Privacy consent types 2 | enum PrivacyConsentType { 3 | /// China’s Personal Information Protection Law (PIPL) https://docs.unity.com/ads/PIPLCompliance.html 4 | pipl, 5 | 6 | /// General Data Protection Regulation (GDPR) https://docs.unity.com/ads/GDPRCompliance.html 7 | gdpr, 8 | 9 | /// California Consumer Privacy Act (CCPA) https://docs.unity.com/ads/CCPACompliance.html 10 | ccpa, 11 | 12 | /// Age gate https://docs.unity.com/ads/ImplementingCustomAgeGates.html 13 | ageGate, 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/unity_ads.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | import 'package:unity_ads_plugin/src/privacy_consent.dart'; 3 | 4 | import 'constants.dart'; 5 | 6 | /// Unity Ads plugin for Flutter applications. 7 | class UnityAds { 8 | static const MethodChannel _channel = MethodChannel(mainChannel); 9 | 10 | static final Map _adChannels = {}; 11 | 12 | /// Initializes UnityAds. UnityAds should be initialized when app starts. 13 | /// 14 | /// * [gameId] - unique identifier for a game, given by Unity Ads admin tools. 15 | /// * [testMode] - if true, then only test ads are shown. 16 | /// * [firebaseTestLabMode] - mode of showing ads in Firebase Test Lab. 17 | /// * [onComplete] - called when `UnityAds` is successfully initialized 18 | /// * [onFailed] - called when `UnityAds` is failed in initialization. 19 | static Future init({ 20 | required String gameId, 21 | bool testMode = false, 22 | FirebaseTestLabMode firebaseTestLabMode = FirebaseTestLabMode.disableAds, 23 | Function? onComplete, 24 | Function(UnityAdsInitializationError error, String errorMessage)? onFailed, 25 | }) async { 26 | Map arguments = { 27 | gameIdParameter: gameId, 28 | testModeParameter: testMode, 29 | firebaseTestLabModeParameter: 30 | firebaseTestLabMode.toString().split('.').last, 31 | }; 32 | _channel.setMethodCallHandler( 33 | (call) => _initMethodCall(call, onComplete, onFailed)); 34 | await _channel.invokeMethod(initMethod, arguments); 35 | } 36 | 37 | static Future _initMethodCall( 38 | MethodCall call, 39 | Function? onComplete, 40 | Function(UnityAdsInitializationError, String)? onFailed, 41 | ) { 42 | switch (call.method) { 43 | case initCompleteMethod: 44 | onComplete?.call(); 45 | break; 46 | case initFailedMethod: 47 | onFailed?.call( 48 | _initializationErrorFromString(call.arguments[errorCodeParameter]), 49 | call.arguments[errorMessageParameter]); 50 | break; 51 | } 52 | return Future.value(true); 53 | } 54 | 55 | static UnityAdsInitializationError _initializationErrorFromString( 56 | String error) { 57 | return UnityAdsInitializationError.values.firstWhere( 58 | (e) => error == e.toString().split('.').last, 59 | orElse: () => UnityAdsInitializationError.unknown); 60 | } 61 | 62 | /// Load a placement to make it available to show. Ads generally take a few seconds to finish loading before they can be shown. 63 | /// 64 | /// * [placementId] - the placement ID, as defined in Unity Ads admin tools. 65 | /// * [onComplete] - callback triggered when a load request has successfully filled the specified placementId with an ad that is ready to show. 66 | /// * [onFailed] - called when load request has failed to load an ad for a requested placement. 67 | static Future load({ 68 | required String placementId, 69 | Function(String placementId)? onComplete, 70 | Function(String placementId, UnityAdsLoadError error, String errorMessage)? 71 | onFailed, 72 | }) async { 73 | _adChannels 74 | .putIfAbsent(placementId, () => _AdMethodChannel(placementId)) 75 | .update( 76 | onLoadComplete: onComplete, 77 | onLoadFailed: onFailed, 78 | ); 79 | 80 | final arguments = { 81 | placementIdParameter: placementId, 82 | }; 83 | await _channel.invokeMethod(loadMethod, arguments); 84 | } 85 | 86 | /// Show an ad using the provided placement ID. 87 | /// 88 | /// * [placementId] - the placement ID, as defined in Unity Ads admin tools. 89 | /// * [serverId] 90 | /// * [onStart] - Called when UnityAds has started to show ad with a specific placement. 91 | /// * [onSkipped] - Called when UnityAds skippes show operation for a placement. 92 | /// * [onClick] - Called when UnityAds has received a click while showing ad with a specific placement. 93 | /// * [onComplete] - Called when UnityAds completes show operation successfully for a placement. 94 | /// * [onFailed] - Called when UnityAds has failed to show a specific placement with an error message and error category. 95 | static Future showVideoAd({ 96 | required String placementId, 97 | String? serverId, 98 | Function(String placementId)? onStart, 99 | Function(String placementId)? onSkipped, 100 | Function(String placementId)? onClick, 101 | Function(String placementId)? onComplete, 102 | Function(String placementId, UnityAdsShowError error, String errorMessage)? 103 | onFailed, 104 | }) async { 105 | _adChannels 106 | .putIfAbsent(placementId, () => _AdMethodChannel(placementId)) 107 | .update( 108 | onAdStart: onStart, 109 | onAdClick: onClick, 110 | onAdSkipped: onSkipped, 111 | onShowFailed: onFailed, 112 | onAdComplete: onComplete, 113 | ); 114 | 115 | final args = { 116 | placementIdParameter: placementId, 117 | serverIdParameter: serverId, 118 | }; 119 | await _channel.invokeMethod(showVideoMethod, args); 120 | } 121 | 122 | /// Pass privacy consent flag to unity sdk. 123 | /// * [privacyConsentType] - provacy consent type 124 | /// * [value] - flag 125 | /// 126 | /// Returns true if the flag is set, otherwise false. 127 | /// 128 | /// Read more about Privacy Consent: https://docs.unity.com/ads/ImplementingDataPrivacy.html 129 | static Future setPrivacyConsent( 130 | PrivacyConsentType privacyConsentType, 131 | bool value, 132 | ) async { 133 | final args = { 134 | privacyConsentValueParameter: value, 135 | privacyConsentTypeParameter: privacyConsentType.toString().split('.').last 136 | }; 137 | return await _channel.invokeMethod(privacyConsentSetMethod, args); 138 | } 139 | 140 | /// Returns true if the SDK is initialized successfully, and false if it isn't. 141 | static Future isInitialized() async { 142 | return await _channel.invokeMethod(isInitializedMethod); 143 | } 144 | } 145 | 146 | enum FirebaseTestLabMode { 147 | /// Ads are not displayed in the Firebase Test Lab 148 | disableAds, 149 | 150 | /// Ads are displayed in test mode. 151 | showAdsInTestMode, 152 | 153 | /// Real ads are displayed, if [testMode] is false. 154 | showAds, 155 | } 156 | 157 | /// Error category of initialization errors 158 | enum UnityAdsInitializationError { 159 | /// Error related to environment or internal services. 160 | internalError, 161 | 162 | /// Error related to invalid arguments 163 | invalidArgument, 164 | 165 | /// Error related to url being blocked 166 | adBlockerDetected, 167 | 168 | /// Unknown error 169 | unknown 170 | } 171 | 172 | /// Error category of load errors 173 | enum UnityAdsLoadError { 174 | /// Error related to SDK not initialized 175 | initializeFailed, 176 | 177 | /// Error related to environment or internal services 178 | internalError, 179 | 180 | /// Error related to invalid arguments 181 | invalidArgument, 182 | 183 | /// Error related to there being no ads available 184 | noFill, 185 | 186 | /// Error related to there being no ads available 187 | timeout, 188 | 189 | /// Unknown error 190 | unknown 191 | } 192 | 193 | /// The error category of show errors 194 | enum UnityAdsShowError { 195 | /// Error related to SDK not initialized 196 | notInitialized, 197 | 198 | /// Error related to placement not being ready 199 | notReady, 200 | 201 | /// Error related to video player 202 | videoPlayerError, 203 | 204 | /// Error related to invalid arguments 205 | invalidArgument, 206 | 207 | /// Error related to internet connection 208 | noConnection, 209 | 210 | /// Error related to ad is already being shown 211 | alreadyShowing, 212 | 213 | /// Error related to environment or internal services 214 | internalError, 215 | 216 | /// Error related to an Ad being unable to show within a specified time frame 217 | timeout, 218 | 219 | /// Unknown error 220 | unknown 221 | } 222 | 223 | class _AdMethodChannel { 224 | final MethodChannel channel; 225 | Function(String placementId)? onLoadComplete; 226 | Function(String placementId, UnityAdsLoadError error, String errorMessage)? 227 | onLoadFailed; 228 | Function(String placementId)? onAdStart; 229 | Function(String placementId)? onAdClick; 230 | Function(String placementId)? onAdComplete; 231 | Function(String placementId)? onAdSkipped; 232 | Function(String placementId, UnityAdsShowError error, String errorMessage)? 233 | onShowFailed; 234 | 235 | _AdMethodChannel(String placementId) 236 | : channel = MethodChannel('${videoAdChannel}_$placementId') { 237 | channel.setMethodCallHandler(_methodCallHandler); 238 | } 239 | 240 | void update({ 241 | Function(String adUnitId)? onLoadComplete, 242 | Function(String adUnitId, UnityAdsLoadError error, String errorMessage)? 243 | onLoadFailed, 244 | Function(String adUnitId)? onAdStart, 245 | Function(String adUnitId)? onAdClick, 246 | Function(String placementId)? onAdComplete, 247 | Function(String placementId)? onAdSkipped, 248 | Function(String adUnitId, UnityAdsShowError error, String errorMessage)? 249 | onShowFailed, 250 | }) { 251 | this.onLoadComplete = onLoadComplete ?? this.onLoadComplete; 252 | this.onLoadFailed = onLoadFailed ?? this.onLoadFailed; 253 | this.onAdStart = onAdStart ?? this.onAdStart; 254 | this.onAdClick = onAdClick ?? this.onAdClick; 255 | this.onAdComplete = onAdComplete ?? this.onAdComplete; 256 | this.onAdSkipped = onAdSkipped ?? this.onAdSkipped; 257 | this.onShowFailed = onShowFailed ?? this.onShowFailed; 258 | } 259 | 260 | Future _methodCallHandler(MethodCall call) async { 261 | switch (call.method) { 262 | case loadCompleteMethod: 263 | onLoadComplete?.call(call.arguments[placementIdParameter]); 264 | break; 265 | case loadFailedMethod: 266 | onLoadFailed?.call( 267 | call.arguments[placementIdParameter], 268 | _loadErrorFromString(call.arguments[errorCodeParameter]), 269 | call.arguments[errorMessageParameter], 270 | ); 271 | break; 272 | case showStartMethod: 273 | onAdStart?.call(call.arguments[placementIdParameter]); 274 | break; 275 | case showSkippedMethod: 276 | onAdSkipped?.call(call.arguments[placementIdParameter]); 277 | break; 278 | case showClickMethod: 279 | onAdClick?.call(call.arguments[placementIdParameter]); 280 | break; 281 | case showCompleteMethod: 282 | onAdComplete?.call(call.arguments[placementIdParameter]); 283 | break; 284 | case showFailedMethod: 285 | onShowFailed?.call( 286 | call.arguments[placementIdParameter], 287 | _showErrorFromString(call.arguments[errorCodeParameter]), 288 | call.arguments[errorMessageParameter], 289 | ); 290 | break; 291 | } 292 | } 293 | 294 | UnityAdsLoadError _loadErrorFromString(String error) { 295 | return UnityAdsLoadError.values.firstWhere( 296 | (e) => error == e.toString().split('.').last, 297 | orElse: () => UnityAdsLoadError.unknown); 298 | } 299 | 300 | UnityAdsShowError _showErrorFromString(String error) { 301 | return UnityAdsShowError.values.firstWhere( 302 | (e) => error == e.toString().split('.').last, 303 | orElse: () => UnityAdsShowError.unknown); 304 | } 305 | } 306 | -------------------------------------------------------------------------------- /lib/src/unity_banner_ad.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:flutter/widgets.dart'; 4 | 5 | import 'constants.dart'; 6 | 7 | class UnityBannerAd extends StatefulWidget { 8 | /// Unity Ad Placement ID 9 | final String placementId; 10 | 11 | /// Size of the banner ad. 12 | final BannerSize size; 13 | 14 | /// Called when the banner is loaded and ready to be placed in the view hierarchy. 15 | final void Function(String placementId)? onLoad; 16 | 17 | /// Called when the user clicks the banner. 18 | final void Function(String placementId)? onClick; 19 | 20 | /// Called when the banner is shown. 21 | final void Function(String placementId)? onShown; 22 | 23 | /// Called when unity ads banner encounters an error. 24 | final void Function( 25 | String placementId, UnityAdsBannerError error, String errorMessage)? 26 | onFailed; 27 | 28 | /// This widget is used to contain Banner Ads. 29 | const UnityBannerAd({ 30 | Key? key, 31 | required this.placementId, 32 | this.size = BannerSize.standard, 33 | this.onLoad, 34 | this.onClick, 35 | this.onShown, 36 | this.onFailed, 37 | }) : super(key: key); 38 | 39 | @override 40 | UnityBannerAdState createState() => UnityBannerAdState(); 41 | } 42 | 43 | class UnityBannerAdState extends State { 44 | bool _isLoaded = false; 45 | 46 | @override 47 | Widget build(BuildContext context) { 48 | if (defaultTargetPlatform == TargetPlatform.android) { 49 | return SizedBox( 50 | height: widget.size.height + 0.0, 51 | width: widget.size.width + 0.0, 52 | child: OverflowBox( 53 | maxHeight: _isLoaded ? widget.size.height + 0.0 : 1, 54 | minHeight: 0.1, 55 | alignment: Alignment.bottomCenter, 56 | child: AndroidView( 57 | viewType: bannerAdChannel, 58 | creationParams: { 59 | placementIdParameter: widget.placementId, 60 | widthParameter: widget.size.width, 61 | heightParameter: widget.size.height, 62 | }, 63 | creationParamsCodec: const StandardMessageCodec(), 64 | onPlatformViewCreated: _onBannerAdViewCreated, 65 | ), 66 | ), 67 | ); 68 | } 69 | if (defaultTargetPlatform == TargetPlatform.iOS) { 70 | return SizedBox( 71 | height: widget.size.height + 0.0, 72 | width: widget.size.width + 0.0, 73 | child: OverflowBox( 74 | maxHeight: _isLoaded ? widget.size.height + 0.0 : 1, 75 | minHeight: 0.1, 76 | alignment: Alignment.bottomCenter, 77 | child: UiKitView( 78 | viewType: bannerAdChannel, 79 | creationParams: { 80 | placementIdParameter: widget.placementId, 81 | widthParameter: widget.size.width, 82 | heightParameter: widget.size.height, 83 | }, 84 | creationParamsCodec: const StandardMessageCodec(), 85 | onPlatformViewCreated: _onBannerAdViewCreated, 86 | ), 87 | ), 88 | ); 89 | } 90 | 91 | return Container(); 92 | } 93 | 94 | void _onBannerAdViewCreated(int id) { 95 | final channel = MethodChannel('${bannerAdChannel}_$id'); 96 | 97 | channel.setMethodCallHandler((call) async { 98 | switch (call.method) { 99 | case bannerErrorMethod: 100 | widget.onFailed?.call( 101 | call.arguments[placementIdParameter], 102 | _bannerErrorFromString(call.arguments[errorCodeParameter]), 103 | call.arguments[errorMessageParameter], 104 | ); 105 | break; 106 | case bannerLoadedMethod: 107 | setState(() { 108 | _isLoaded = true; 109 | }); 110 | widget.onLoad?.call(call.arguments[placementIdParameter]); 111 | break; 112 | case bannerClickedMethod: 113 | widget.onClick?.call(call.arguments[placementIdParameter]); 114 | break; 115 | case bannerShownMethod: 116 | widget.onShown?.call(call.arguments[placementIdParameter]); 117 | break; 118 | } 119 | }); 120 | } 121 | 122 | static UnityAdsBannerError _bannerErrorFromString(String error) { 123 | return UnityAdsBannerError.values.firstWhere( 124 | (e) => error == e.toString().split('.').last, 125 | orElse: () => UnityAdsBannerError.unknown); 126 | } 127 | } 128 | 129 | /// Defines the size of Banner Ad. 130 | class BannerSize { 131 | final int width; 132 | final int height; 133 | 134 | static const BannerSize standard = BannerSize(width: 320, height: 50); 135 | static const BannerSize leaderboard = BannerSize(width: 728, height: 90); 136 | static const BannerSize iabStandard = BannerSize(width: 468, height: 60); 137 | 138 | const BannerSize({this.width = 320, this.height = 50}); 139 | } 140 | 141 | enum BannerAdState { 142 | /// Banner is loaded. 143 | loaded, 144 | 145 | /// Banner is clicked. 146 | clicked, 147 | 148 | /// Error during loading banner 149 | error, 150 | } 151 | 152 | enum UnityAdsBannerError { 153 | native, 154 | 155 | webView, 156 | 157 | noFill, 158 | 159 | /// Unknown error 160 | unknown 161 | } 162 | -------------------------------------------------------------------------------- /lib/unity_ads_plugin.dart: -------------------------------------------------------------------------------- 1 | library unity_ads_plugin; 2 | 3 | export 'src/privacy_consent.dart'; 4 | export 'src/unity_ads.dart'; 5 | export 'src/unity_banner_ad.dart'; 6 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.13.0" 12 | boolean_selector: 13 | dependency: transitive 14 | description: 15 | name: boolean_selector 16 | sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.1.2" 20 | characters: 21 | dependency: transitive 22 | description: 23 | name: characters 24 | sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "1.4.0" 28 | clock: 29 | dependency: transitive 30 | description: 31 | name: clock 32 | sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.1.2" 36 | collection: 37 | dependency: transitive 38 | description: 39 | name: collection 40 | sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.19.1" 44 | fake_async: 45 | dependency: transitive 46 | description: 47 | name: fake_async 48 | sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.3.3" 52 | flutter: 53 | dependency: "direct main" 54 | description: flutter 55 | source: sdk 56 | version: "0.0.0" 57 | flutter_lints: 58 | dependency: "direct dev" 59 | description: 60 | name: flutter_lints 61 | sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" 62 | url: "https://pub.dev" 63 | source: hosted 64 | version: "5.0.0" 65 | flutter_test: 66 | dependency: "direct dev" 67 | description: flutter 68 | source: sdk 69 | version: "0.0.0" 70 | leak_tracker: 71 | dependency: transitive 72 | description: 73 | name: leak_tracker 74 | sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" 75 | url: "https://pub.dev" 76 | source: hosted 77 | version: "10.0.9" 78 | leak_tracker_flutter_testing: 79 | dependency: transitive 80 | description: 81 | name: leak_tracker_flutter_testing 82 | sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 83 | url: "https://pub.dev" 84 | source: hosted 85 | version: "3.0.9" 86 | leak_tracker_testing: 87 | dependency: transitive 88 | description: 89 | name: leak_tracker_testing 90 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" 91 | url: "https://pub.dev" 92 | source: hosted 93 | version: "3.0.1" 94 | lints: 95 | dependency: transitive 96 | description: 97 | name: lints 98 | sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413" 99 | url: "https://pub.dev" 100 | source: hosted 101 | version: "5.0.0" 102 | matcher: 103 | dependency: transitive 104 | description: 105 | name: matcher 106 | sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 107 | url: "https://pub.dev" 108 | source: hosted 109 | version: "0.12.17" 110 | material_color_utilities: 111 | dependency: transitive 112 | description: 113 | name: material_color_utilities 114 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec 115 | url: "https://pub.dev" 116 | source: hosted 117 | version: "0.11.1" 118 | meta: 119 | dependency: transitive 120 | description: 121 | name: meta 122 | sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c 123 | url: "https://pub.dev" 124 | source: hosted 125 | version: "1.16.0" 126 | path: 127 | dependency: transitive 128 | description: 129 | name: path 130 | sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" 131 | url: "https://pub.dev" 132 | source: hosted 133 | version: "1.9.1" 134 | sky_engine: 135 | dependency: transitive 136 | description: flutter 137 | source: sdk 138 | version: "0.0.0" 139 | source_span: 140 | dependency: transitive 141 | description: 142 | name: source_span 143 | sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" 144 | url: "https://pub.dev" 145 | source: hosted 146 | version: "1.10.1" 147 | stack_trace: 148 | dependency: transitive 149 | description: 150 | name: stack_trace 151 | sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" 152 | url: "https://pub.dev" 153 | source: hosted 154 | version: "1.12.1" 155 | stream_channel: 156 | dependency: transitive 157 | description: 158 | name: stream_channel 159 | sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" 160 | url: "https://pub.dev" 161 | source: hosted 162 | version: "2.1.4" 163 | string_scanner: 164 | dependency: transitive 165 | description: 166 | name: string_scanner 167 | sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" 168 | url: "https://pub.dev" 169 | source: hosted 170 | version: "1.4.1" 171 | term_glyph: 172 | dependency: transitive 173 | description: 174 | name: term_glyph 175 | sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" 176 | url: "https://pub.dev" 177 | source: hosted 178 | version: "1.2.2" 179 | test_api: 180 | dependency: transitive 181 | description: 182 | name: test_api 183 | sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd 184 | url: "https://pub.dev" 185 | source: hosted 186 | version: "0.7.4" 187 | vector_math: 188 | dependency: transitive 189 | description: 190 | name: vector_math 191 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 192 | url: "https://pub.dev" 193 | source: hosted 194 | version: "2.1.4" 195 | vm_service: 196 | dependency: transitive 197 | description: 198 | name: vm_service 199 | sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 200 | url: "https://pub.dev" 201 | source: hosted 202 | version: "15.0.0" 203 | sdks: 204 | dart: ">=3.7.0-0 <4.0.0" 205 | flutter: ">=3.18.0-18.0.pre.54" 206 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: unity_ads_plugin 2 | description: Unity Ads plugin for Flutter Applications. This plugin is able to display Unity Banner Ads and Unity Video Ads. 3 | version: 0.3.25 4 | homepage: https://github.com/pavelzaichyk/flutter_unity_ads 5 | repository: https://github.com/pavelzaichyk/flutter_unity_ads 6 | funding: 7 | - https://paypal.me/pavelzaichyk 8 | - https://www.buymeacoffee.com/rebeloid 9 | - https://www.paypal.com/donate/?hosted_button_id=EG9DHRCSB5MY4 10 | 11 | environment: 12 | sdk: '>=2.12.0 <4.0.0' 13 | flutter: ">=1.20.0" 14 | 15 | dependencies: 16 | flutter: 17 | sdk: flutter 18 | 19 | dev_dependencies: 20 | flutter_test: 21 | sdk: flutter 22 | flutter_lints: ^5.0.0 23 | 24 | flutter: 25 | plugin: 26 | platforms: 27 | android: 28 | package: com.rebeloid.unity_ads 29 | pluginClass: UnityAdsPlugin 30 | ios: 31 | pluginClass: UnityAdsPlugin 32 | -------------------------------------------------------------------------------- /test/unity_ads_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | import 'package:unity_ads_plugin/src/constants.dart'; 4 | import 'package:unity_ads_plugin/unity_ads_plugin.dart'; 5 | 6 | void main() { 7 | const MethodChannel channel = MethodChannel(mainChannel); 8 | 9 | TestWidgetsFlutterBinding.ensureInitialized(); 10 | 11 | setUp(() { 12 | channel.setMockMethodCallHandler((MethodCall methodCall) async { 13 | return true; 14 | }); 15 | }); 16 | 17 | tearDown(() { 18 | channel.setMockMethodCallHandler(null); 19 | }); 20 | 21 | test('init', () async { 22 | await UnityAds.init(gameId: 'test_game_id'); 23 | }); 24 | } 25 | --------------------------------------------------------------------------------