├── .github
├── FUNDING.yml
└── ISSUE_TEMPLATE
│ └── config.yml
├── .gitignore
├── .gitmodules
├── .idea
├── .gitignore
├── compiler.xml
├── kotlinc.xml
├── migrations.xml
├── misc.xml
└── runConfigurations.xml
├── LICENSE
├── README.md
├── admob
├── build.gradle.kts
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── org
│ └── godotengine
│ └── plugin
│ └── android
│ └── admob
│ ├── AdmobPlugin.java
│ ├── Banner.java
│ ├── Interstitial.java
│ ├── RewardedInterstitial.java
│ └── RewardedVideo.java
├── build.gradle.kts
├── demo
├── .gitignore
├── Main.gd
├── Main.gd.uid
├── Main.tscn
├── admob.png
├── android
│ └── .build_version
├── export_presets.cfg
├── project.godot
└── scene
│ ├── Scene2.gd
│ ├── Scene2.gd.uid
│ └── Scene2.tscn
├── gradle.properties
├── gradlew
├── gradlew.bat
└── settings.gradle.kts
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: cengiz-pz
2 | buy_me_a_coffee: cengizpz
3 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | # disable blank issue creation
2 | blank_issues_enabled: false
3 |
4 | contact_links:
5 | - name: Bugs
6 | url: https://github.com/godot-sdk-integrations/godot-admob/issues
7 | about: Please report bugs on the new repository.
8 |
9 | - name: Feature Requests
10 | url: https://github.com/godot-sdk-integrations/godot-admob/issues
11 | about: Please submit feature requests on the new repository.
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.aar
4 | *.ap_
5 | *.aab
6 |
7 | # Files for the ART/Dalvik VM
8 | *.dex
9 |
10 | # Java class files
11 | *.class
12 |
13 | # Generated files
14 | bin/
15 | gen/
16 | out/
17 | # Uncomment the following line in case you need and you don't have the release build type files in your app
18 | # release/
19 |
20 | # Gradle files
21 | .gradle/
22 | gradle/
23 | build/
24 |
25 | # Local configuration file (sdk path, etc)
26 | local.properties
27 |
28 | # Proguard folder generated by Eclipse
29 | proguard/
30 |
31 | # Log Files
32 | *.log
33 |
34 | # Android Studio Navigation editor temp files
35 | .navigation/
36 |
37 | # Android Studio captures folder
38 | captures/
39 |
40 | # IntelliJ
41 | *.iml
42 | .idea/workspace.xml
43 | .idea/tasks.xml
44 | .idea/gradle.xml
45 | .idea/assetWizardSettings.xml
46 | .idea/dictionaries
47 | .idea/libraries
48 | # Android Studio 3 in .gitignore file.
49 | .idea/caches
50 | .idea/modules.xml
51 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you
52 | .idea/navEditor.xml
53 |
54 | # Keystore files
55 | # Uncomment the following lines if you do not want to check your keystore files in.
56 | #*.jks
57 | #*.keystore
58 |
59 | # External native build folder generated in Android Studio 2.2 and later
60 | .externalNativeBuild
61 | .cxx/
62 |
63 | # Google Services (e.g. APIs or Firebase)
64 | # google-services.json
65 |
66 | # Freeline
67 | freeline.py
68 | freeline/
69 | freeline_project_description.json
70 |
71 | # fastlane
72 | fastlane/report.xml
73 | fastlane/Preview.html
74 | fastlane/screenshots
75 | fastlane/test_output
76 | fastlane/readme.md
77 |
78 | # Version control
79 | vcs.xml
80 |
81 | # lint
82 | lint/intermediates/
83 | lint/generated/
84 | lint/outputs/
85 | lint/tmp/
86 | # lint/reports/
87 |
88 | # Godot
89 | .godot/
90 | *.import
91 | demo/addons
92 |
93 | # Mac OS
94 | .DS_Store
95 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "addon"]
2 | path = admob/addon_template
3 | url = https://github.com/cengiz-pz/godot-admob-addon.git
4 | branch = main
5 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/migrations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Cengiz
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.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | $${\color{red}27/04/2025: \space This \space repository \space has \space moved \space under \space the \space Godot \space SDK \space Integrations \space Github \space organization.}$$
2 | $${\color{red}Future \space releases \space will \space be \space published \space at \space the \space new \space repository:}$$
3 |
4 | ### https://github.com/godot-sdk-integrations/godot-admob
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | #  Android Admob Plugin
13 |
14 | Enables AdMob functionality on Godot apps that are exported to the Android platform and allows
15 | displaying of Admob ads.
16 |
17 | _For iOS version, visit https://github.com/cengiz-pz/godot-ios-admob-plugin ._
18 |
19 | This branch contains the latest version of the plugin, which contains breaking changes to the plugin
20 | interface. The original version of the plugin can be found on the
21 | [Release 1.0 branch](https://github.com/cengiz-pz/godot-android-admob-plugin/tree/release-1.0).
22 |
23 | ##  Prerequisites
24 | Follow instructions on the following page to create a custom Android gradle build
25 | - [Create custom Android gradle build](https://docs.godotengine.org/en/stable/tutorials/export/android_gradle_build.html)
26 |
27 | Create an AdMob account at the following link:
28 | - [Google AdMob](https://admob.google.com/)
29 | - create an app in AdMob console
30 | - [create ad(s)](https://support.google.com/admob/answer/6173650?hl=en) for your app via the AdMob console
31 | - if needed, [create consent form(s)](https://support.google.com/admob/answer/10113207?hl=en) for your app via the AdMob console
32 |
33 | ##  Installation
34 | _Before installing this plugin, make sure to uninstall any previous versions of the same plugin._
35 |
36 | _If installing both Android and iOS versions of the plugin in the same project, then make sure that both versions use the same addon interface version._
37 |
38 | There are 2 ways to install the `Admob` plugin into your project:
39 | - Through the Godot Editor's AssetLib
40 | - Manually by downloading archives from Github
41 |
42 | ###  Installing via AssetLib
43 | Steps:
44 | - search for and select the `Admob` plugin in Godot Editor
45 | - click `Download` button
46 | - on the installation dialog...
47 | - keep `Change Install Folder` setting pointing to your project's root directory
48 | - keep `Ignore asset root` checkbox checked
49 | - click `Install` button
50 | - enable the plugin via the `Plugins` tab of `Project->Project Settings...` menu, in the Godot Editor
51 |
52 | ####  Installing both Android and iOS versions of the plugin in the same project
53 | When installing via AssetLib, the installer may display a warning that states "_[x number of]_ files conflict with your project and won't be installed." You can ignore this warning since both versions use the same addon code.
54 |
55 | ###  Installing manually
56 | Steps:
57 | - download release archive from Github
58 | - unzip the release archive
59 | - copy to your Godot project's root directory
60 | - enable the plugin via the `Plugins` tab of `Project->Project Settings...` menu, in the Godot Editor
61 |
62 |
63 | ##  Usage
64 | - Add `Admob` node to your main scene and populate the ID fields of the node
65 | - Debug IDs will only be used when your Godot app is run in debug mode
66 | - Real IDs will only be used when the `is_real` field of the node is set to `true`
67 |
68 | ###  Signals
69 | - register listeners for one or more of the following signals of the `Admob` node:
70 | - `initialization_completed(status_data: InitializationStatus)`
71 | - `banner_ad_loaded(ad_id: String)`
72 | - `banner_ad_failed_to_load(ad_id: String, error_data: LoadAdError)`
73 | - `banner_ad_refreshed(ad_id: String)`
74 | - `banner_ad_clicked(ad_id: String)`
75 | - `banner_ad_impression(ad_id: String)`
76 | - `banner_ad_opened(ad_id: String)`
77 | - `banner_ad_closed(ad_id: String)`
78 | - `interstitial_ad_loaded(ad_id: String)`
79 | - `interstitial_ad_failed_to_load(ad_id: String, error_data: LoadAdError)`
80 | - `interstitial_ad_refreshed(ad_id: String)`
81 | - `interstitial_ad_impression(ad_id: String)`
82 | - `interstitial_ad_clicked(ad_id: String)`
83 | - `interstitial_ad_showed_full_screen_content(ad_id: String)`
84 | - `interstitial_ad_failed_to_show_full_screen_content(ad_id: String, error_data: AdError)`
85 | - `interstitial_ad_dismissed_full_screen_content(ad_id: String)`
86 | - `rewarded_ad_loaded(ad_id: String)`
87 | - `rewarded_ad_failed_to_load(ad_id: String, error_data: LoadAdError)`
88 | - `rewarded_ad_impression(ad_id: String)`
89 | - `rewarded_ad_clicked(ad_id: String)`
90 | - `rewarded_ad_showed_full_screen_content(ad_id: String)`
91 | - `rewarded_ad_failed_to_show_full_screen_content(ad_id: String, error_data: AdError)`
92 | - `rewarded_ad_dismissed_full_screen_content(ad_id: String)`
93 | - `rewarded_ad_user_earned_reward(ad_id: String, reward_data: RewardItem)`
94 | - `rewarded_interstitial_ad_loaded(ad_id: String)`
95 | - `rewarded_interstitial_ad_failed_to_load(ad_id: String, error_data: LoadAdError)`
96 | - `rewarded_interstitial_ad_impression(ad_id: String)`
97 | - `rewarded_interstitial_ad_clicked(ad_id: String)`
98 | - `rewarded_interstitial_ad_showed_full_screen_content(ad_id: String)`
99 | - `rewarded_interstitial_ad_failed_to_show_full_screen_content(ad_id: String, error_data: AdError)`
100 | - `rewarded_interstitial_ad_dismissed_full_screen_content(ad_id: String)`
101 | - `rewarded_interstitial_ad_user_earned_reward(ad_id: String, reward_data: RewardItem)`
102 | - `consent_form_loaded`
103 | - `consent_form_dismissed(error_data: FormError)`
104 | - `consent_form_failed_to_load(error_data: FormError)`
105 | - `consent_info_updated`
106 | - `consent_info_update_failed(error_data: FormError)`
107 |
108 | ###  Loading and displaying ads
109 | - initialize the plugin
110 | - call the `initialize()` method of the `Admob` node
111 | - wait for the `initialization_completed` signal
112 | - use one or more of the following `load_*()` methods to load ads from the `Admob` node:
113 | - `load_banner_ad(ad_request: LoadAdRequest)`
114 | - `load_interstitia_adl(ad_request: LoadAdRequest)`
115 | - `load_rewarded_ad(ad_request: LoadAdRequest)`
116 | - `load_rewarded_interstitial_ad(ad_request: LoadAdRequest)`
117 | - the `Admob` node will emit the following signals once ads have been loaded or failed to load:
118 | - `banner_ad_loaded(ad_id: String)`
119 | - `banner_ad_failed_to_load(ad_id: String, error_data: LoadAdError)`
120 | - `interstitial_ad_loaded(ad_id: String)`
121 | - `interstitial_ad_failed_to_load(ad_id: String, error_data: LoadAdError)`
122 | - `rewarded_ad_loaded(ad_id: String)`
123 | - `rewarded_ad_failed_to_load(ad_id: String, error_data: LoadAdError)`
124 | - `rewarded_interstitial_ad_loaded(ad_id: String)`
125 | - `rewarded_interstitial_ad_failed_to_load(ad_id: String, error_data: LoadAdError)`
126 | - once ads have been loaded, call corresponding `show_*()` method from the `Admob` node with the `ad_id` received:
127 | - `show_banner_ad(ad_id: String)`
128 | - `show_interstitial_ad(ad_id: String)`
129 | - `show_rewarded_ad(ad_id: String)`
130 | - `show_rewarded_interstitial_ad(ad_id: String)`
131 |
132 | ###  Banner Size
133 | - The following methods return the size of a Banner ad:
134 | - `get_banner_dimension()`
135 | - `get_banner_dimension_in_pixels()`
136 | - These methods are not supported for `FLUID` sized ads. For banner ads of size `FLUID`, the `get_banner_dimension()` method will return `(-3, -4)` and the `get_banner_dimension_in_pixels()` method will return `(-1, -1)`.
137 |
138 | ###  User Consent
139 | - Methods:
140 | - `get_consent_status()` - Returns a consent status value defined in `ConsentInformation.gd`
141 | - `update_consent_info(params: ConsentRequestParameters)` - To be called if `get_consent_status()` returns status UNKNOWN (0).
142 | - `reset_consent_info()` - To be used only when testing and debugging your application.
143 | - `is_consent_form_available()`
144 | - `load_consent_form()` - To be called if `get_consent_status()` returns status REQUIRED (2) and `is_consent_form_available()` returns `false`.
145 | - `show_consent_form()` - To be called after `consent_form_loaded` signal has been emitted or `is_consent_form_available()` returns `true`.
146 |
147 |
148 | ##  Android Export
149 | Android export requires several configuration settings.
150 |
151 | ###  File-based Export Configuration
152 | In order to enable file-based export configuration, an `export.cfg` file should be placed in the `addons/AdmobPlugin` directory with the following content:
153 |
154 | ```
155 | [General]
156 | is_real = false
157 |
158 | [Debug]
159 | app_id = "ca-app-pub-3940256099942544~3347511713"
160 |
161 | [Release]
162 | app_id = "ca-app-pub-3940256099942544~3347511713"
163 | ```
164 |
165 | The `is_real` and `app_id` configuration items are mandatory and if not found in the `export.cfg` file, then the plugin will fall back to node-based configuration.
166 |
167 | ###  Node-based Export Configuration
168 | If `export.cfg` file is not found or file-based configuration fails, then the plugin will attempt to load node-based configuration.
169 |
170 | During Android export, the plugin searches for an `Admob` node in the scene that is open in the Godot Editor. If not found, then the plugin searches for an `Admob` node in the project's main scene. Therefore;
171 | - Make sure that the scene that contains the `Admob` node is selected in the Godot Editor when building and exporting for Android, or
172 | - Make sure that your Godot project's main scene contains an `Admob` node
173 |
174 |
175 | ##  Troubleshooting
176 |
177 | ### Missing APP ID
178 | If your game crashes due to missing APP ID, then make sure that you enter your Admob APP ID in the Admob node and pay attention to the [Android Export section](#android-export).
179 |
180 | ### ADB logcat
181 | `adb logcat` is one of the best tools for troubleshooting unexpected behavior
182 | - use `$> adb logcat | grep 'godot'` on Linux
183 | - `adb logcat *:W` to see warnings and errors
184 | - `adb logcat *:E` to see only errors
185 | - `adb logcat | grep 'godot|somethingElse'` to filter using more than one string at the same time
186 | - use `#> adb.exe logcat | select-string "godot"` on powershell (Windows)
187 |
188 | Also check out:
189 | https://docs.godotengine.org/en/stable/tutorials/platform/android/android_plugin.html#troubleshooting
190 |
191 |
192 |
193 | ---
194 | #  Credits
195 | Based on [Shin-NiL](https://github.com/Shin-NiL)'s [Godot Admob Plugin](https://github.com/Shin-NiL/Godot-Android-Admob-Plugin)
196 |
197 | Developed by [Cengiz](https://github.com/cengiz-pz)
198 |
199 | Original repository: [Godot Android Admob Plugin](https://github.com/cengiz-pz/godot-android-admob-plugin)
200 |
201 |
202 |
203 | ---
204 | #  Tutorials
205 | The following is a video tutorial by [16BitDev](https://www.youtube.com/@16bitdev) that covers the whole process of setting up Admob for your Godot app on Android.
206 |
207 | [](https://www.youtube.com/watch?v=V9_Gpy0R3RE)
208 |
209 |
210 |
211 | ___
212 |
213 | #  Contribution
214 |
215 | This section provides information on how to build the plugin for contributors.
216 |
217 |
218 |
219 | ___
220 |
221 | ##  Prerequisites
222 |
223 | - [Install AndroidStudio](https://developer.android.com/studio)
224 |
225 |
226 |
227 | ___
228 |
229 | ##  Refreshing addon submodule
230 |
231 | - Remove `admob/addon_template` directory
232 | - Run `git submodule update --remote --merge`
233 |
234 |
235 |
236 | ---
237 | #  All Plugins
238 |
239 | | Plugin | Android | iOS |
240 | | :---: | :--- | :--- |
241 | | Notification Scheduler | https://github.com/cengiz-pz/godot-android-notification-scheduler-plugin | https://github.com/cengiz-pz/godot-ios-notification-scheduler-plugin |
242 | | Admob | https://github.com/cengiz-pz/godot-android-admob-plugin | https://github.com/cengiz-pz/godot-ios-admob-plugin |
243 | | Deeplink | https://github.com/cengiz-pz/godot-android-deeplink-plugin | https://github.com/cengiz-pz/godot-ios-deeplink-plugin |
244 | | Share | https://github.com/cengiz-pz/godot-android-share-plugin | https://github.com/cengiz-pz/godot-ios-share-plugin |
245 | | In-App Review | https://github.com/cengiz-pz/godot-android-inapp-review-plugin | https://github.com/cengiz-pz/godot-ios-inapp-review-plugin |
246 |
--------------------------------------------------------------------------------
/admob/build.gradle.kts:
--------------------------------------------------------------------------------
1 | //
2 | // © 2024-present https://github.com/cengiz-pz
3 | //
4 |
5 | import com.android.build.gradle.internal.tasks.factory.dependsOn
6 | import org.apache.tools.ant.filters.ReplaceTokens
7 |
8 | plugins {
9 | id("com.android.library")
10 | id("org.jetbrains.kotlin.android") version "2.0.10"
11 | }
12 |
13 | val pluginNodeName = "Admob"
14 | val pluginName = pluginNodeName + "Plugin"
15 | val pluginPackageName = "org.godotengine.plugin.android.admob"
16 | val godotVersion = "4.4.1"
17 | val pluginVersion = "4.0"
18 | val targetOs = "android"
19 | val demoAddOnsDirectory = "../demo/addons"
20 | val templateDirectory = "addon_template"
21 | val pluginDependencies = arrayOf(
22 | "androidx.appcompat:appcompat:1.7.0",
23 | "com.google.android.gms:play-services-ads:24.0.0"
24 | )
25 |
26 | android {
27 | namespace = pluginPackageName
28 | compileSdk = 34
29 |
30 | buildFeatures {
31 | buildConfig = true
32 | }
33 |
34 | defaultConfig {
35 | minSdk = 23
36 |
37 | manifestPlaceholders["godotPluginName"] = pluginName
38 | manifestPlaceholders["godotPluginPackageName"] = pluginPackageName
39 | buildConfigField("String", "GODOT_PLUGIN_NAME", "\"${pluginName}\"")
40 | setProperty("archivesBaseName", "$pluginName")
41 | }
42 |
43 | compileOptions {
44 | sourceCompatibility = JavaVersion.VERSION_17
45 | targetCompatibility = JavaVersion.VERSION_17
46 | }
47 |
48 | kotlinOptions {
49 | jvmTarget = "17"
50 | }
51 | }
52 |
53 | dependencies {
54 | implementation("org.godotengine:godot:$godotVersion.stable")
55 | pluginDependencies.forEach { implementation(it) }
56 | }
57 |
58 | val copyDebugAARToDemoAddons by tasks.registering(Copy::class) {
59 | description = "Copies the generated debug AAR binary to the plugin's addons directory"
60 | from("build/outputs/aar")
61 | include("$pluginName-debug.aar")
62 | into("$demoAddOnsDirectory/$pluginName/bin/debug")
63 | }
64 |
65 | val copyReleaseAARToDemoAddons by tasks.registering(Copy::class) {
66 | description = "Copies the generated release AAR binary to the plugin's addons directory"
67 | from("build/outputs/aar")
68 | include("$pluginName-release.aar")
69 | into("$demoAddOnsDirectory/$pluginName/bin/release")
70 | }
71 |
72 | val cleanDemoAddons by tasks.registering(Delete::class) {
73 | delete("$demoAddOnsDirectory/$pluginName")
74 | }
75 |
76 | val copyPngsToDemo by tasks.registering(Copy::class) {
77 | description = "Copies the PNG images to the plugin's addons directory"
78 | from(templateDirectory)
79 | into("$demoAddOnsDirectory/$pluginName")
80 | include("**/*.png")
81 | }
82 |
83 | val copyAddonsToDemo by tasks.registering(Copy::class) {
84 | description = "Copies the export scripts templates to the plugin's addons directory"
85 |
86 | dependsOn(cleanDemoAddons)
87 | finalizedBy(copyDebugAARToDemoAddons)
88 | finalizedBy(copyReleaseAARToDemoAddons)
89 | finalizedBy(copyPngsToDemo)
90 |
91 | from(templateDirectory)
92 | into("$demoAddOnsDirectory/$pluginName")
93 | include("**/*.gd")
94 | include("**/*.cfg")
95 | var dependencyString = ""
96 | for (i in pluginDependencies.indices) {
97 | dependencyString += "\"${pluginDependencies[i]}\""
98 | if (i < pluginDependencies.size-1) dependencyString += ", "
99 | }
100 | filter(ReplaceTokens::class,
101 | "tokens" to mapOf(
102 | "pluginName" to pluginName,
103 | "pluginNodeName" to pluginNodeName,
104 | "pluginVersion" to pluginVersion,
105 | "pluginPackage" to pluginPackageName,
106 | "targetOs" to targetOs,
107 | "pluginDependencies" to dependencyString))
108 | }
109 |
110 | tasks.register("packageDistribution") {
111 | archiveFileName.set("${pluginName}-${pluginVersion}.zip")
112 | destinationDirectory.set(layout.buildDirectory.dir("dist"))
113 |
114 | from("../demo/addons/${pluginName}") {
115 | into("${pluginName}-root/addons/${pluginName}")
116 | }
117 | }
118 |
119 | tasks.named("clean").apply {
120 | dependsOn(cleanDemoAddons)
121 | }
122 |
123 | afterEvaluate {
124 | tasks.named("assembleDebug").configure {
125 | finalizedBy(copyAddonsToDemo)
126 | }
127 | tasks.named("assembleRelease").configure {
128 | finalizedBy(copyAddonsToDemo)
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/admob/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/admob/src/main/java/org/godotengine/plugin/android/admob/AdmobPlugin.java:
--------------------------------------------------------------------------------
1 | //
2 | // © 2024-present https://github.com/cengiz-pz
3 | //
4 |
5 | package org.godotengine.plugin.android.admob;
6 |
7 | import static com.google.android.gms.ads.RequestConfiguration.TAG_FOR_CHILD_DIRECTED_TREATMENT_TRUE;
8 |
9 | import android.annotation.SuppressLint;
10 | import android.app.Activity;
11 | import android.os.Bundle;
12 | import android.provider.Settings;
13 | import android.util.DisplayMetrics;
14 | import android.util.Log;
15 | import android.view.Display;
16 | import android.view.View;
17 | import android.view.WindowManager;
18 | import android.widget.FrameLayout;
19 |
20 | import androidx.annotation.NonNull;
21 | import androidx.collection.ArraySet;
22 |
23 | import com.google.android.gms.ads.AdError;
24 | import com.google.android.gms.ads.AdListener;
25 | import com.google.android.gms.ads.AdRequest;
26 | import com.google.android.gms.ads.AdSize;
27 | import com.google.android.gms.ads.LoadAdError;
28 | import com.google.android.gms.ads.MobileAds;
29 | import com.google.android.gms.ads.RequestConfiguration;
30 | import com.google.android.gms.ads.ResponseInfo;
31 | import com.google.android.gms.ads.initialization.AdapterStatus;
32 | import com.google.android.gms.ads.initialization.InitializationStatus;
33 | import com.google.android.gms.ads.initialization.OnInitializationCompleteListener;
34 | import com.google.android.gms.ads.rewarded.RewardItem;
35 | import com.google.android.gms.ads.rewarded.ServerSideVerificationOptions;
36 | import com.google.android.ump.ConsentDebugSettings;
37 | import com.google.android.ump.ConsentForm;
38 | import com.google.android.ump.ConsentInformation;
39 | import com.google.android.ump.ConsentRequestParameters;
40 | import com.google.android.ump.FormError;
41 | import com.google.android.ump.UserMessagingPlatform;
42 |
43 | import org.godotengine.godot.Dictionary;
44 | import org.godotengine.godot.Godot;
45 | import org.godotengine.godot.plugin.GodotPlugin;
46 | import org.godotengine.godot.plugin.SignalInfo;
47 | import org.godotengine.godot.plugin.UsedByGodot;
48 |
49 | import java.security.MessageDigest;
50 | import java.security.NoSuchAlgorithmException;
51 | import java.util.ArrayList;
52 | import java.util.Arrays;
53 | import java.util.HashMap;
54 | import java.util.List;
55 | import java.util.Locale;
56 | import java.util.Map;
57 | import java.util.Set;
58 |
59 | public class AdmobPlugin extends GodotPlugin {
60 | static final String CLASS_NAME = AdmobPlugin.class.getSimpleName();
61 | private static final String LOG_TAG = "godot::" + CLASS_NAME;
62 |
63 | private static final String SIGNAL_INITIALIZATION_COMPLETED = "initialization_completed";
64 | private static final String SIGNAL_BANNER_AD_LOADED = "banner_ad_loaded";
65 | private static final String SIGNAL_BANNER_AD_FAILED_TO_LOAD = "banner_ad_failed_to_load";
66 | private static final String SIGNAL_BANNER_AD_REFRESHED = "banner_ad_refreshed";
67 | private static final String SIGNAL_BANNER_AD_IMPRESSION = "banner_ad_impression";
68 | private static final String SIGNAL_BANNER_AD_CLICKED = "banner_ad_clicked";
69 | private static final String SIGNAL_BANNER_AD_OPENED = "banner_ad_opened";
70 | private static final String SIGNAL_BANNER_AD_CLOSED = "banner_ad_closed";
71 | private static final String SIGNAL_INTERSTITIAL_AD_LOADED = "interstitial_ad_loaded";
72 | private static final String SIGNAL_INTERSTITIAL_AD_FAILED_TO_LOAD = "interstitial_ad_failed_to_load";
73 | private static final String SIGNAL_INTERSTITIAL_AD_REFRESHED = "interstitial_ad_refreshed";
74 | private static final String SIGNAL_INTERSTITIAL_AD_IMPRESSION = "interstitial_ad_impression";
75 | private static final String SIGNAL_INTERSTITIAL_AD_CLICKED = "interstitial_ad_clicked";
76 | private static final String SIGNAL_INTERSTITIAL_AD_SHOWED_FULL_SCREEN_CONTENT = "interstitial_ad_showed_full_screen_content";
77 | private static final String SIGNAL_INTERSTITIAL_AD_FAILED_TO_SHOW_FULL_SCREEN_CONTENT = "interstitial_ad_failed_to_show_full_screen_content";
78 | private static final String SIGNAL_INTERSTITIAL_AD_DISMISSED_FULL_SCREEN_CONTENT = "interstitial_ad_dismissed_full_screen_content";
79 | private static final String SIGNAL_REWARDED_AD_LOADED = "rewarded_ad_loaded";
80 | private static final String SIGNAL_REWARDED_AD_FAILED_TO_LOAD = "rewarded_ad_failed_to_load";
81 | private static final String SIGNAL_REWARDED_AD_IMPRESSION = "rewarded_ad_impression";
82 | private static final String SIGNAL_REWARDED_AD_CLICKED = "rewarded_ad_clicked";
83 | private static final String SIGNAL_REWARDED_AD_SHOWED_FULL_SCREEN_CONTENT = "rewarded_ad_showed_full_screen_content";
84 | private static final String SIGNAL_REWARDED_AD_FAILED_TO_SHOW_FULL_SCREEN_CONTENT = "rewarded_ad_failed_to_show_full_screen_content";
85 | private static final String SIGNAL_REWARDED_AD_DISMISSED_FULL_SCREEN_CONTENT = "rewarded_ad_dismissed_full_screen_content";
86 | private static final String SIGNAL_REWARDED_AD_USER_EARNED_REWARD = "rewarded_ad_user_earned_reward";
87 | private static final String SIGNAL_REWARDED_INTERSTITIAL_AD_LOADED = "rewarded_interstitial_ad_loaded";
88 | private static final String SIGNAL_REWARDED_INTERSTITIAL_AD_FAILED_TO_LOAD = "rewarded_interstitial_ad_failed_to_load";
89 | private static final String SIGNAL_REWARDED_INTERSTITIAL_AD_IMPRESSION = "rewarded_interstitial_ad_impression";
90 | private static final String SIGNAL_REWARDED_INTERSTITIAL_AD_CLICKED = "rewarded_interstitial_ad_clicked";
91 | private static final String SIGNAL_REWARDED_INTERSTITIAL_AD_SHOWED_FULL_SCREEN_CONTENT = "rewarded_interstitial_ad_showed_full_screen_content";
92 | private static final String SIGNAL_REWARDED_INTERSTITIAL_AD_FAILED_TO_SHOW_FULL_SCREEN_CONTENT = "rewarded_interstitial_ad_failed_to_show_full_screen_content";
93 | private static final String SIGNAL_REWARDED_INTERSTITIAL_AD_DISMISSED_FULL_SCREEN_CONTENT = "rewarded_interstitial_ad_dismissed_full_screen_content";
94 | private static final String SIGNAL_REWARDED_INTERSTITIAL_AD_USER_EARNED_REWARD = "rewarded_interstitial_ad_user_earned_reward";
95 | private static final String SIGNAL_CONSENT_FORM_LOADED = "consent_form_loaded";
96 | private static final String SIGNAL_CONSENT_FORM_FAILED_TO_LOAD = "consent_form_failed_to_load";
97 | private static final String SIGNAL_CONSENT_FORM_DISMISSED = "consent_form_dismissed";
98 | private static final String SIGNAL_CONSENT_INFO_UPDATED = "consent_info_updated";
99 | private static final String SIGNAL_CONSENT_INFO_UPDATE_FAILED = "consent_info_update_failed";
100 |
101 | private Activity activity;
102 |
103 | /**
104 | * Whether app is being tested (isReal=false) or app is in production (isReal=true)
105 | */
106 | private boolean isReal = false;
107 |
108 |
109 | private boolean isForChildDirectedTreatment = false;
110 |
111 | /**
112 | * Ads are personalized by default, GDPR compliance within the European Economic Area may require disabling of personalization.
113 | */
114 | private boolean isPersonalized = true;
115 | private String maxAdContentRating = "";
116 | private Bundle extras = null;
117 |
118 | private FrameLayout layout = null;
119 |
120 | private int bannerAdIdSequence;
121 | private int interstitialAdIdSequence;
122 | private int rewardedAdIdSequence;
123 | private int rewardedInterstitialAdIdSequence;
124 |
125 | private boolean isInitialized;
126 |
127 | private Map bannerAds;
128 | private Map interstitialAds;
129 | private Map rewardedAds;
130 | private Map rewardedInterstitialAds;
131 |
132 | private ConsentForm consentForm;
133 |
134 |
135 | public AdmobPlugin(Godot godot) {
136 | super(godot);
137 |
138 | bannerAds = new HashMap<>();
139 | interstitialAds = new HashMap<>();
140 | rewardedAds = new HashMap<>();
141 | rewardedInterstitialAds = new HashMap<>();
142 |
143 | isInitialized = false;
144 | }
145 |
146 | @NonNull
147 | @Override
148 | public String getPluginName() {
149 | return CLASS_NAME;
150 | }
151 |
152 | @NonNull
153 | @Override
154 | public Set getPluginSignals() {
155 | Set signals = new ArraySet<>();
156 |
157 | signals.add(new SignalInfo(SIGNAL_INITIALIZATION_COMPLETED, Dictionary.class));
158 |
159 | signals.add(new SignalInfo(SIGNAL_BANNER_AD_LOADED, String.class));
160 | signals.add(new SignalInfo(SIGNAL_BANNER_AD_FAILED_TO_LOAD, String.class, Dictionary.class));
161 | signals.add(new SignalInfo(SIGNAL_BANNER_AD_REFRESHED, String.class));
162 | signals.add(new SignalInfo(SIGNAL_BANNER_AD_IMPRESSION, String.class));
163 | signals.add(new SignalInfo(SIGNAL_BANNER_AD_CLICKED, String.class));
164 | signals.add(new SignalInfo(SIGNAL_BANNER_AD_OPENED, String.class));
165 | signals.add(new SignalInfo(SIGNAL_BANNER_AD_CLOSED, String.class));
166 |
167 | signals.add(new SignalInfo(SIGNAL_INTERSTITIAL_AD_LOADED, String.class));
168 | signals.add(new SignalInfo(SIGNAL_INTERSTITIAL_AD_FAILED_TO_LOAD, String.class, Dictionary.class));
169 | signals.add(new SignalInfo(SIGNAL_INTERSTITIAL_AD_REFRESHED, String.class));
170 | signals.add(new SignalInfo(SIGNAL_INTERSTITIAL_AD_IMPRESSION, String.class));
171 | signals.add(new SignalInfo(SIGNAL_INTERSTITIAL_AD_CLICKED, String.class));
172 | signals.add(new SignalInfo(SIGNAL_INTERSTITIAL_AD_SHOWED_FULL_SCREEN_CONTENT, String.class));
173 | signals.add(new SignalInfo(SIGNAL_INTERSTITIAL_AD_FAILED_TO_SHOW_FULL_SCREEN_CONTENT, String.class, Dictionary.class));
174 | signals.add(new SignalInfo(SIGNAL_INTERSTITIAL_AD_DISMISSED_FULL_SCREEN_CONTENT, String.class));
175 |
176 | signals.add(new SignalInfo(SIGNAL_REWARDED_AD_LOADED, String.class));
177 | signals.add(new SignalInfo(SIGNAL_REWARDED_AD_FAILED_TO_LOAD, String.class, Dictionary.class));
178 | signals.add(new SignalInfo(SIGNAL_REWARDED_AD_IMPRESSION, String.class));
179 | signals.add(new SignalInfo(SIGNAL_REWARDED_AD_CLICKED, String.class));
180 | signals.add(new SignalInfo(SIGNAL_REWARDED_AD_SHOWED_FULL_SCREEN_CONTENT, String.class));
181 | signals.add(new SignalInfo(SIGNAL_REWARDED_AD_FAILED_TO_SHOW_FULL_SCREEN_CONTENT, String.class, Dictionary.class));
182 | signals.add(new SignalInfo(SIGNAL_REWARDED_AD_DISMISSED_FULL_SCREEN_CONTENT, String.class));
183 | signals.add(new SignalInfo(SIGNAL_REWARDED_AD_USER_EARNED_REWARD, String.class, Dictionary.class));
184 |
185 | signals.add(new SignalInfo(SIGNAL_REWARDED_INTERSTITIAL_AD_LOADED, String.class));
186 | signals.add(new SignalInfo(SIGNAL_REWARDED_INTERSTITIAL_AD_FAILED_TO_LOAD, String.class, Dictionary.class));
187 | signals.add(new SignalInfo(SIGNAL_REWARDED_INTERSTITIAL_AD_IMPRESSION, String.class));
188 | signals.add(new SignalInfo(SIGNAL_REWARDED_INTERSTITIAL_AD_CLICKED, String.class));
189 | signals.add(new SignalInfo(SIGNAL_REWARDED_INTERSTITIAL_AD_SHOWED_FULL_SCREEN_CONTENT, String.class));
190 | signals.add(new SignalInfo(SIGNAL_REWARDED_INTERSTITIAL_AD_FAILED_TO_SHOW_FULL_SCREEN_CONTENT, String.class, Dictionary.class));
191 | signals.add(new SignalInfo(SIGNAL_REWARDED_INTERSTITIAL_AD_DISMISSED_FULL_SCREEN_CONTENT, String.class));
192 | signals.add(new SignalInfo(SIGNAL_REWARDED_INTERSTITIAL_AD_USER_EARNED_REWARD, String.class, Dictionary.class));
193 |
194 | signals.add(new SignalInfo(SIGNAL_CONSENT_FORM_LOADED));
195 | signals.add(new SignalInfo(SIGNAL_CONSENT_FORM_FAILED_TO_LOAD, Dictionary.class));
196 | signals.add(new SignalInfo(SIGNAL_CONSENT_FORM_DISMISSED, Dictionary.class));
197 |
198 | signals.add(new SignalInfo(SIGNAL_CONSENT_INFO_UPDATED));
199 | signals.add(new SignalInfo(SIGNAL_CONSENT_INFO_UPDATE_FAILED, Dictionary.class));
200 |
201 | return signals;
202 | }
203 |
204 | @UsedByGodot
205 | public void initialize() {
206 | Log.d(LOG_TAG, "initialize()");
207 |
208 | bannerAdIdSequence = 0;
209 | interstitialAdIdSequence = 0;
210 | rewardedAdIdSequence = 0;
211 | rewardedInterstitialAdIdSequence = 0;
212 |
213 | bannerAds.clear();
214 | interstitialAds.clear();
215 | rewardedAds.clear();
216 | rewardedInterstitialAds.clear();
217 |
218 | isInitialized = false;
219 |
220 | MobileAds.initialize(activity, new OnInitializationCompleteListener() {
221 | @Override
222 | public void onInitializationComplete(InitializationStatus initializationStatus) {
223 | isInitialized = true;
224 | emitSignal(SIGNAL_INITIALIZATION_COMPLETED, convert(initializationStatus));
225 | }
226 | });
227 | }
228 |
229 | @UsedByGodot
230 | public void set_request_configuration(Dictionary configData) {
231 | Log.d(LOG_TAG, "set_request_configuration()");
232 | MobileAds.setRequestConfiguration(createRequestConfiguration(configData));
233 | }
234 |
235 | @UsedByGodot
236 | public Dictionary get_initialization_status() {
237 | Log.d(LOG_TAG, "get_initialization_status()");
238 | return convert(MobileAds.getInitializationStatus());
239 | }
240 |
241 | @UsedByGodot
242 | public Dictionary get_current_adaptive_banner_size(int width) {
243 | Log.d(LOG_TAG, "get_current_adaptive_banner_size()");
244 | int currentWidth = (width == AdSize.FULL_WIDTH) ? Banner.getAdWidth(activity) : width;
245 | return convert(AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(activity, currentWidth));
246 | }
247 |
248 | @UsedByGodot
249 | public Dictionary get_portrait_adaptive_banner_size(int width) {
250 | Log.d(LOG_TAG, "get_portrait_adaptive_banner_size()");
251 | int currentWidth = (width == AdSize.FULL_WIDTH) ? Banner.getAdWidth(activity) : width;
252 | return convert(AdSize.getPortraitAnchoredAdaptiveBannerAdSize(activity, currentWidth));
253 | }
254 |
255 | @UsedByGodot
256 | public Dictionary get_landscape_adaptive_banner_size(int width) {
257 | Log.d(LOG_TAG, "get_landscape_adaptive_banner_size()");
258 | int currentWidth = (width == AdSize.FULL_WIDTH) ? Banner.getAdWidth(activity) : width;
259 | return convert(AdSize.getLandscapeAnchoredAdaptiveBannerAdSize(activity, currentWidth));
260 | }
261 |
262 | @UsedByGodot
263 | public void load_banner_ad(Dictionary adData) {
264 | if (isInitialized) {
265 | Log.d(LOG_TAG, "load_banner_ad()");
266 |
267 | if (adData.containsKey("ad_unit_id")) {
268 | String adUnitId = (String) adData.get("ad_unit_id");
269 | String adId = String.format("%s-%d", adUnitId, ++bannerAdIdSequence);
270 | Banner banner = new Banner(adId, adUnitId, adData, createAdRequest(adData), activity, layout,
271 | new BannerListener() {
272 | @Override
273 | public void onAdLoaded(String adId) {
274 | emitSignal(SIGNAL_BANNER_AD_LOADED, adId);
275 | }
276 |
277 | @Override
278 | public void onAdRefreshed(String adId) {
279 | Log.d(LOG_TAG, String.format("onAdRefreshed(%s) banner", adId));
280 | emitSignal(SIGNAL_BANNER_AD_REFRESHED, adId);
281 | }
282 |
283 | @Override
284 | public void onAdFailedToLoad(String adId, LoadAdError adError) {
285 | emitSignal(SIGNAL_BANNER_AD_FAILED_TO_LOAD, adId, convert(adError));
286 | }
287 |
288 | @Override
289 | public void onAdClicked(String adId) {
290 | emitSignal(SIGNAL_BANNER_AD_CLICKED, adId);
291 | }
292 |
293 | @Override
294 | public void onAdClosed(String adId) {
295 | emitSignal(SIGNAL_BANNER_AD_CLOSED, adId);
296 | }
297 |
298 | @Override
299 | public void onAdImpression(String adId) {
300 | emitSignal(SIGNAL_BANNER_AD_IMPRESSION, adId);
301 | }
302 |
303 | @Override
304 | public void onAdOpened(String adId) {
305 | emitSignal(SIGNAL_BANNER_AD_OPENED, adId);
306 | }
307 | });
308 | bannerAds.put(adId, banner);
309 | activity.runOnUiThread(() -> {
310 | banner.load();
311 | });
312 | } else {
313 | Log.e(LOG_TAG, "load_banner_ad(): Error: Ad unit id is required!");
314 | }
315 | }
316 | else {
317 | Log.e(LOG_TAG, "load_banner_ad(): Error: Plugin is not initialized!");
318 | }
319 | }
320 |
321 | @UsedByGodot
322 | public void show_banner_ad(String adId) {
323 | activity.runOnUiThread(() -> {
324 | if (bannerAds.containsKey(adId)) {
325 | Log.d(LOG_TAG, String.format("show_banner_ad(): %s", adId));
326 | Banner bannerAd = bannerAds.get(adId);
327 | bannerAd.show();
328 | }
329 | else {
330 | Log.e(LOG_TAG, String.format("show_banner_ad(): Error: banner ad %s not found", adId));
331 | }
332 | });
333 | }
334 |
335 | @UsedByGodot
336 | public void hide_banner_ad(String adId) {
337 | activity.runOnUiThread(() -> {
338 | if (bannerAds.containsKey(adId)) {
339 | Log.d(LOG_TAG, String.format("hide_banner_ad(): %s", adId));
340 | Banner bannerAd = bannerAds.get(adId);
341 | bannerAd.hide();
342 | }
343 | else {
344 | Log.e(LOG_TAG, String.format("hide_banner_ad(): Error: banner ad %s not found", adId));
345 | }
346 | });
347 | }
348 |
349 | @UsedByGodot
350 | public void remove_banner_ad(String adId) {
351 | activity.runOnUiThread(() -> {
352 | if (bannerAds.containsKey(adId)) {
353 | Log.d(LOG_TAG, String.format("remove_banner_ad(): %s", adId));
354 | Banner bannerAd = bannerAds.remove(adId);
355 | bannerAd.remove();
356 | }
357 | else {
358 | Log.e(LOG_TAG, String.format("remove_banner_ad(): Error: banner ad %s not found", adId));
359 | }
360 | });
361 | }
362 |
363 | @UsedByGodot
364 | public int get_banner_width(String adId) {
365 | int result = 0;
366 |
367 | if (bannerAds.containsKey(adId)) {
368 | Log.d(LOG_TAG, String.format("get_banner_width(): %s", adId));
369 | Banner bannerAd = bannerAds.get(adId);
370 | result = bannerAd.getWidth();
371 | }
372 | else {
373 | Log.e(LOG_TAG, String.format("get_banner_width(): Error: banner ad %s not found", adId));
374 | }
375 |
376 | return result;
377 | }
378 |
379 | @UsedByGodot
380 | public int get_banner_height(String adId) {
381 | int result = 0;
382 |
383 | if (bannerAds.containsKey(adId)) {
384 | Log.d(LOG_TAG, String.format("get_banner_height(): %s", adId));
385 | Banner bannerAd = bannerAds.get(adId);
386 | result = bannerAd.getHeight();
387 | }
388 | else {
389 | Log.e(LOG_TAG, String.format("get_banner_height(): Error: banner ad %s not found", adId));
390 | }
391 |
392 | return result;
393 | }
394 |
395 | @UsedByGodot
396 | public int get_banner_width_in_pixels(String adId) {
397 | int result = 0;
398 |
399 | if (bannerAds.containsKey(adId)) {
400 | Banner bannerAd = bannerAds.get(adId);
401 | result = bannerAd.getWidthInPixels();
402 | Log.d(LOG_TAG, String.format("get_banner_width_in_pixels(): %s - %d", adId, result));
403 | }
404 | else {
405 | Log.e(LOG_TAG, String.format("get_banner_width_in_pixels(): Error: banner ad %s not found", adId));
406 | }
407 |
408 | return result;
409 | }
410 |
411 | @UsedByGodot
412 | public int get_banner_height_in_pixels(String adId) {
413 | int result = 0;
414 |
415 | if (bannerAds.containsKey(adId)) {
416 | Banner bannerAd = bannerAds.get(adId);
417 | result = bannerAd.getHeightInPixels();
418 | Log.d(LOG_TAG, String.format("get_banner_height_in_pixels(): %s - %d", adId, result));
419 | }
420 | else {
421 | Log.e(LOG_TAG, String.format("get_banner_height_in_pixels(): Error: banner ad %s not found", adId));
422 | }
423 |
424 | return result;
425 | }
426 |
427 | @UsedByGodot
428 | public void load_interstitial_ad(Dictionary adData) {
429 | if (isInitialized) {
430 | Log.d(LOG_TAG, "load_interstitial_ad()");
431 |
432 | if (adData.containsKey("ad_unit_id")) {
433 | String adUnitId = (String) adData.get("ad_unit_id");
434 | String adId = String.format("%s-%d", adUnitId, ++interstitialAdIdSequence);
435 |
436 | activity.runOnUiThread(() -> {
437 | Interstitial ad = new Interstitial(adId, adUnitId, createAdRequest(adData), activity, new InterstitialListener() {
438 | @Override
439 | public void onInterstitialLoaded(String adId) {
440 | emitSignal(SIGNAL_INTERSTITIAL_AD_LOADED, adId);
441 | }
442 |
443 | @Override
444 | public void onInterstitialReloaded(String adId) {
445 | emitSignal(SIGNAL_INTERSTITIAL_AD_REFRESHED, adId);
446 | }
447 |
448 | @Override
449 | public void onInterstitialFailedToLoad(String adId, LoadAdError loadAdError) {
450 | emitSignal(SIGNAL_INTERSTITIAL_AD_FAILED_TO_LOAD, adId, convert(loadAdError));
451 | }
452 |
453 | @Override
454 | public void onInterstitialFailedToShow(String adId, AdError adError) {
455 | emitSignal(SIGNAL_INTERSTITIAL_AD_FAILED_TO_SHOW_FULL_SCREEN_CONTENT, adId, convert(adError));
456 | }
457 |
458 | @Override
459 | public void onInterstitialOpened(String adId) {
460 | emitSignal(SIGNAL_INTERSTITIAL_AD_SHOWED_FULL_SCREEN_CONTENT, adId);
461 | }
462 |
463 | @Override
464 | public void onInterstitialClosed(String adId) {
465 | emitSignal(SIGNAL_INTERSTITIAL_AD_DISMISSED_FULL_SCREEN_CONTENT, adId);
466 | }
467 |
468 | @Override
469 | public void onInterstitialClicked(String adId) {
470 | emitSignal(SIGNAL_INTERSTITIAL_AD_CLICKED, adId);
471 | }
472 |
473 | @Override
474 | public void onInterstitialImpression(String adId) {
475 | emitSignal(SIGNAL_INTERSTITIAL_AD_IMPRESSION, adId);
476 | }
477 | });
478 | interstitialAds.put(adId, ad);
479 | Log.d(LOG_TAG, String.format("load_interstitial_ad(): %s", adId));
480 | ad.load();
481 | });
482 | } else {
483 | Log.e(LOG_TAG, "load_interstitial_ad(): Error: Ad unit id is required!");
484 | }
485 | }
486 | else {
487 | Log.e(LOG_TAG, "load_interstitial_ad(): Error: Plugin is not initialized!");
488 | }
489 | }
490 |
491 | @UsedByGodot
492 | public void show_interstitial_ad(String adId) {
493 | activity.runOnUiThread(() -> {
494 | if (interstitialAds.containsKey(adId)) {
495 | Log.d(LOG_TAG, String.format("show_interstitial_ad(): %s", adId));
496 | Interstitial ad = interstitialAds.get(adId);
497 | assert ad != null;
498 | ad.show();
499 | }
500 | else {
501 | Log.e(LOG_TAG, String.format("show_interstitial_ad(): Error: ad %s not found", adId));
502 | }
503 | });
504 | }
505 |
506 | @UsedByGodot
507 | public void remove_interstitial_ad(String adId) {
508 | if (interstitialAds.containsKey(adId)) {
509 | Log.d(LOG_TAG, String.format("remove_interstitial_ad(): %s", adId));
510 | interstitialAds.remove(adId);
511 | }
512 | else {
513 | Log.e(LOG_TAG, String.format("remove_interstitial_ad(): Error: ad %s not found", adId));
514 | }
515 | }
516 |
517 | @UsedByGodot
518 | public void load_rewarded_ad(Dictionary adData) {
519 | if (isInitialized) {
520 | Log.d(LOG_TAG, "load_rewarded_ad()");
521 |
522 | if (adData.containsKey("ad_unit_id")) {
523 | String adUnitId = (String) adData.get("ad_unit_id");
524 | String adId = String.format("%s-%d", adUnitId, ++rewardedAdIdSequence);
525 |
526 | activity.runOnUiThread(() -> {
527 | RewardedVideo ad = new RewardedVideo(adId, adUnitId, createAdRequest(adData), activity, new RewardedVideoListener() {
528 | @Override
529 | public void onRewardedVideoLoaded(String adId) {
530 | emitSignal(SIGNAL_REWARDED_AD_LOADED, adId);
531 | }
532 |
533 | @Override
534 | public void onRewardedVideoFailedToLoad(String adId, LoadAdError loadAdError) {
535 | emitSignal(SIGNAL_REWARDED_AD_FAILED_TO_LOAD, adId, convert(loadAdError));
536 | }
537 |
538 | @Override
539 | public void onRewardedVideoOpened(String adId) {
540 | emitSignal(SIGNAL_REWARDED_AD_SHOWED_FULL_SCREEN_CONTENT, adId);
541 | }
542 |
543 | @Override
544 | public void onRewardedVideoFailedToShow(String adId, AdError adError) {
545 | emitSignal(SIGNAL_REWARDED_AD_FAILED_TO_SHOW_FULL_SCREEN_CONTENT, adId, convert(adError));
546 | }
547 |
548 | @Override
549 | public void onRewardedVideoClosed(String adId) {
550 | emitSignal(SIGNAL_REWARDED_AD_DISMISSED_FULL_SCREEN_CONTENT, adId);
551 | }
552 |
553 | @Override
554 | public void onRewardedClicked(String adId) {
555 | emitSignal(SIGNAL_REWARDED_AD_CLICKED, adId);
556 | }
557 |
558 | @Override
559 | public void onRewardedAdImpression(String adId) {
560 | emitSignal(SIGNAL_REWARDED_AD_IMPRESSION, adId);
561 | }
562 |
563 | @Override
564 | public void onRewarded(String adId, RewardItem reward) {
565 | emitSignal(SIGNAL_REWARDED_AD_USER_EARNED_REWARD, adId, convert(reward));
566 | }
567 | });
568 | ad.setServerSideVerificationOptions(createSSVO(adData));
569 | rewardedAds.put(adId, ad);
570 | Log.d(LOG_TAG, String.format("load_rewarded_ad(): %s", adId));
571 | ad.load();
572 | });
573 | } else {
574 | Log.e(LOG_TAG, "load_rewarded_ad(): Error: Ad unit id is required!");
575 | }
576 | }
577 | else {
578 | Log.e(LOG_TAG, "load_rewarded_ad(): Error: Plugin is not initialized!");
579 | }
580 | }
581 |
582 | @UsedByGodot
583 | public void show_rewarded_ad(String adId) {
584 | activity.runOnUiThread(() -> {
585 | if (rewardedAds.containsKey(adId)) {
586 | Log.d(LOG_TAG, String.format("show_rewarded_ad(): %s", adId));
587 | RewardedVideo ad = rewardedAds.get(adId);
588 | ad.show();
589 | }
590 | else {
591 | Log.e(LOG_TAG, String.format("show_rewarded_ad(): Error: ad %s not found", adId));
592 | }
593 | });
594 | }
595 |
596 | @UsedByGodot
597 | public void remove_rewarded_ad(String adId) {
598 | if (rewardedAds.containsKey(adId)) {
599 | Log.d(LOG_TAG, String.format("remove_rewarded_ad(): %s", adId));
600 | rewardedAds.remove(adId);
601 | }
602 | else {
603 | Log.e(LOG_TAG, String.format("remove_rewarded_ad(): Error: ad %s not found", adId));
604 | }
605 | }
606 |
607 | @UsedByGodot
608 | public void load_rewarded_interstitial_ad(Dictionary adData) {
609 | if (isInitialized) {
610 | Log.d(LOG_TAG, "load_rewarded_interstitial_ad()");
611 |
612 | if (adData.containsKey("ad_unit_id")) {
613 | String adUnitId = (String) adData.get("ad_unit_id");
614 | String adId = String.format("%s-%d", adUnitId, ++rewardedInterstitialAdIdSequence);
615 |
616 | activity.runOnUiThread(() -> {
617 | RewardedInterstitial ad = new RewardedInterstitial(adId, adUnitId, createAdRequest(adData), activity,
618 | new RewardedInterstitialListener() {
619 | @Override
620 | public void onRewardedInterstitialLoaded(String adId) {
621 | emitSignal(SIGNAL_REWARDED_INTERSTITIAL_AD_LOADED, adId);
622 | }
623 |
624 | @Override
625 | public void onRewardedInterstitialFailedToLoad(String adId, LoadAdError loadAdError) {
626 | emitSignal(SIGNAL_REWARDED_INTERSTITIAL_AD_FAILED_TO_LOAD, adId, convert(loadAdError));
627 | }
628 |
629 | @Override
630 | public void onRewardedInterstitialOpened(String adId) {
631 | emitSignal(SIGNAL_REWARDED_INTERSTITIAL_AD_SHOWED_FULL_SCREEN_CONTENT, adId);
632 | }
633 |
634 | @Override
635 | public void onRewardedInterstitialFailedToShow(String adId, AdError adError) {
636 | emitSignal(SIGNAL_REWARDED_INTERSTITIAL_AD_FAILED_TO_SHOW_FULL_SCREEN_CONTENT, adId, convert(adError));
637 | }
638 |
639 | @Override
640 | public void onRewardedInterstitialClosed(String adId) {
641 | emitSignal(SIGNAL_REWARDED_INTERSTITIAL_AD_DISMISSED_FULL_SCREEN_CONTENT, adId);
642 | }
643 |
644 | @Override
645 | public void onRewardedClicked(String adId) {
646 | emitSignal(SIGNAL_REWARDED_INTERSTITIAL_AD_CLICKED, adId);
647 | }
648 |
649 | @Override
650 | public void onRewardedAdImpression(String adId) {
651 | emitSignal(SIGNAL_REWARDED_INTERSTITIAL_AD_IMPRESSION, adId);
652 | }
653 |
654 | @Override
655 | public void onRewarded(String adId, RewardItem reward) {
656 | emitSignal(SIGNAL_REWARDED_INTERSTITIAL_AD_USER_EARNED_REWARD, adId, convert(reward));
657 | }
658 | });
659 | ad.setServerSideVerificationOptions(createSSVO(adData));
660 | rewardedInterstitialAds.put(adId, ad);
661 | Log.d(LOG_TAG, String.format("load_rewarded_interstitial_ad(): %s", adId));
662 | ad.load();
663 | });
664 | } else {
665 | Log.e(LOG_TAG, "load_rewarded_interstitial_ad(): Error: Ad unit id is required!");
666 | }
667 | }
668 | else {
669 | Log.e(LOG_TAG, "load_rewarded_interstitial_ad(): Error: Plugin is not initialized!");
670 | }
671 | }
672 |
673 | @UsedByGodot
674 | public void show_rewarded_interstitial_ad(String adId) {
675 | activity.runOnUiThread(() -> {
676 | if (rewardedInterstitialAds.containsKey(adId)) {
677 | Log.d(LOG_TAG, String.format("show_rewarded_interstitial_ad(): %s", adId));
678 | RewardedInterstitial ad = rewardedInterstitialAds.get(adId);
679 | ad.show();
680 | } else {
681 | Log.e(LOG_TAG, String.format("show_rewarded_interstitial_ad(): Error: ad %s not found", adId));
682 | }
683 | });
684 | }
685 |
686 | @UsedByGodot
687 | public void remove_rewarded_interstitial_ad(String adId) {
688 | if (rewardedInterstitialAds.containsKey(adId)) {
689 | Log.d(LOG_TAG, String.format("remove_rewarded_interstitial_ad(): %s", adId));
690 | rewardedInterstitialAds.remove(adId);
691 | }
692 | else {
693 | Log.e(LOG_TAG, String.format("remove_rewarded_interstitial_ad(): Error: ad %s not found", adId));
694 | }
695 | }
696 |
697 | @UsedByGodot
698 | public void load_consent_form() {
699 | Log.d(LOG_TAG, "load_consent_form()");
700 | activity.runOnUiThread(() -> {
701 | UserMessagingPlatform.loadConsentForm(
702 | activity,
703 | (UserMessagingPlatform.OnConsentFormLoadSuccessListener) loadedForm -> {
704 | consentForm = loadedForm;
705 | emitSignal(SIGNAL_CONSENT_FORM_LOADED);
706 | },
707 | (UserMessagingPlatform.OnConsentFormLoadFailureListener) formError -> {
708 | emitSignal(SIGNAL_CONSENT_FORM_FAILED_TO_LOAD, convert(formError));
709 | }
710 | );
711 | });
712 | }
713 |
714 | @UsedByGodot
715 | public void show_consent_form() {
716 | activity.runOnUiThread(() -> {
717 | if (consentForm == null) {
718 | Log.e(LOG_TAG, "show_consent_form(): Error: consent form not found!");
719 | } else {
720 | Log.d(LOG_TAG, "show_consent_form()");
721 | consentForm.show(activity, (ConsentForm.OnConsentFormDismissedListener) formError -> {
722 | emitSignal(SIGNAL_CONSENT_FORM_DISMISSED, convert(formError));
723 | });
724 | }
725 | });
726 | }
727 |
728 | @UsedByGodot
729 | public int get_consent_status() {
730 | Log.d(LOG_TAG, "get_consent_status()");
731 | return UserMessagingPlatform.getConsentInformation(activity).getConsentStatus();
732 | }
733 |
734 | @UsedByGodot
735 | public boolean is_consent_form_available() {
736 | Log.d(LOG_TAG, "is_consent_form_available()");
737 | return UserMessagingPlatform.getConsentInformation(activity).isConsentFormAvailable();
738 | }
739 |
740 | @UsedByGodot
741 | public void update_consent_info(Dictionary consentRequestParameters) {
742 | Log.d(LOG_TAG, "update_consent_info()");
743 | ConsentInformation consentInformation = UserMessagingPlatform.getConsentInformation(activity);
744 |
745 | consentInformation.requestConsentInfoUpdate(
746 | activity,
747 | createConsentRequestParameters(consentRequestParameters),
748 | (ConsentInformation.OnConsentInfoUpdateSuccessListener) () -> {
749 | emitSignal(SIGNAL_CONSENT_INFO_UPDATED);
750 | },
751 | (ConsentInformation.OnConsentInfoUpdateFailureListener) requestConsentError -> {
752 | emitSignal(SIGNAL_CONSENT_INFO_UPDATE_FAILED, convert(requestConsentError));
753 | Log.w(LOG_TAG, String.format("%s: %s", requestConsentError.getErrorCode(), requestConsentError.getMessage()));
754 | }
755 | );
756 | }
757 |
758 | @UsedByGodot
759 | public void reset_consent_info() {
760 | Log.d(LOG_TAG, "reset_consent_info()");
761 | UserMessagingPlatform.getConsentInformation(activity).reset();
762 | }
763 |
764 |
765 | @Override
766 | public View onMainCreate(Activity activity) {
767 | this.activity = activity;
768 | this.activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
769 | this.layout = new FrameLayout(activity); // create and add a new layout to Godot
770 | return layout;
771 | }
772 |
773 |
774 | private Dictionary convert(InitializationStatus initializationStatus) {
775 | Dictionary dict = new Dictionary();
776 |
777 | Map adapterMap = initializationStatus.getAdapterStatusMap();
778 | for (String adapterClass : adapterMap.keySet()) {
779 | AdapterStatus adapterStatus = adapterMap.get(adapterClass);
780 |
781 | Dictionary statusDict = new Dictionary();
782 | statusDict.put("latency", adapterStatus.getLatency());
783 | statusDict.put("initializationState", adapterStatus.getInitializationState());
784 | statusDict.put("description", adapterStatus.getDescription());
785 |
786 | dict.put(adapterClass, statusDict);
787 | }
788 |
789 | return dict;
790 | }
791 |
792 | private Dictionary convert(AdSize size) {
793 | Dictionary dict = new Dictionary();
794 |
795 | dict.put("width", size.getWidth());
796 | dict.put("height", size.getHeight());
797 |
798 | return dict;
799 | }
800 |
801 | private Dictionary convert(AdError error) {
802 | Dictionary dict = new Dictionary();
803 |
804 | dict.put("code", error.getCode());
805 | dict.put("domain", error.getDomain());
806 | dict.put("message", error.getMessage());
807 | dict.put("cause", error.getCause() == null ? new Dictionary() : convert(error.getCause()));
808 |
809 | return dict;
810 | }
811 |
812 | private Dictionary convert(LoadAdError error) {
813 | Dictionary dict = convert((AdError) error);
814 |
815 | dict.put("response_info", error.getResponseInfo().toString());
816 |
817 | return dict;
818 | }
819 |
820 | private Dictionary convert(FormError error) {
821 | Dictionary dict = new Dictionary();
822 |
823 | if (error == null) {
824 | dict.put("code", 0);
825 | dict.put("message", "");
826 | } else {
827 | dict.put("code", error.getErrorCode());
828 | dict.put("message", error.getMessage());
829 | }
830 |
831 | return dict;
832 | }
833 |
834 | private Dictionary convert(RewardItem item) {
835 | Dictionary dict = new Dictionary();
836 |
837 | dict.put("amount", item.getAmount());
838 | dict.put("type", item.getType());
839 |
840 | return dict;
841 | }
842 |
843 | private RequestConfiguration createRequestConfiguration(Dictionary data) {
844 | RequestConfiguration.Builder builder = MobileAds.getRequestConfiguration().toBuilder();
845 |
846 | if (data.containsKey("max_ad_content_rating"))
847 | builder.setMaxAdContentRating((String) data.get("max_ad_content_rating"));
848 |
849 | if (data.containsKey("tag_for_child_directed_treatment"))
850 | builder.setTagForChildDirectedTreatment((int) data.get("tag_for_child_directed_treatment"));
851 |
852 | if (data.containsKey("tag_for_under_age_of_consent"))
853 | builder.setTagForUnderAgeOfConsent((int) data.get("tag_for_under_age_of_consent"));
854 |
855 | if (data.containsKey("personalization_state"))
856 | builder.setPublisherPrivacyPersonalizationState(getPublisherPrivacyPersonalizationState((int) data.get("personalization_state")));
857 |
858 | ArrayList testDeviceIds = new ArrayList<>();
859 | if (data.containsKey("test_device_ids"))
860 | testDeviceIds.addAll(Arrays.asList((String[]) data.get("test_device_ids")));
861 |
862 | if (data.containsKey("is_real")) {
863 | if ((boolean) data.get("is_real") == false) {
864 | testDeviceIds.add(AdRequest.DEVICE_ID_EMULATOR);
865 | testDeviceIds.add(getAdMobDeviceId());
866 | }
867 | }
868 |
869 | if (testDeviceIds.isEmpty() == false)
870 | builder.setTestDeviceIds(testDeviceIds);
871 |
872 | return builder.build();
873 | }
874 |
875 | private AdRequest createAdRequest(Dictionary data) {
876 | AdRequest.Builder builder = new AdRequest.Builder();
877 |
878 | if (data.containsKey("request_agent")) {
879 | String requestAgent = (String) data.get("request_agent");
880 | if (requestAgent != null && !requestAgent.isEmpty()) {
881 | builder.setRequestAgent(requestAgent);
882 | }
883 | }
884 |
885 | // TODO: mediation support
886 |
887 | if (data.containsKey("keywords")) {
888 | for (String keyword : (String[]) data.get("keywords")) {
889 | builder.addKeyword(keyword);
890 | }
891 | }
892 |
893 | return builder.build();
894 | }
895 |
896 | private ServerSideVerificationOptions createSSVO(Dictionary data) {
897 | ServerSideVerificationOptions.Builder builder = new ServerSideVerificationOptions.Builder();
898 |
899 | if (data.containsKey("custom_data")) {
900 | builder.setCustomData((String) data.get("custom_data"));
901 | }
902 |
903 | if (data.containsKey("user_id")) {
904 | builder.setUserId((String) data.get("user_id"));
905 | }
906 |
907 | return builder.build();
908 | }
909 |
910 | private ConsentRequestParameters createConsentRequestParameters(Dictionary data) {
911 | ConsentRequestParameters.Builder builder = new ConsentRequestParameters.Builder();
912 |
913 | if (data.containsKey("tag_for_under_age_of_consent")) {
914 | builder.setTagForUnderAgeOfConsent((boolean) data.get("tag_for_under_age_of_consent"));
915 | }
916 |
917 | if (data.containsKey("is_real") && (boolean) data.get("is_real") == false) {
918 | Log.d(LOG_TAG, "Creating debug settings for user consent.");
919 | ConsentDebugSettings.Builder debugSettingsBuilder = new ConsentDebugSettings.Builder(activity);
920 |
921 | if (data.containsKey("debug_geography")) {
922 | debugSettingsBuilder.setDebugGeography((int) data.get("debug_geography"));
923 | }
924 |
925 | debugSettingsBuilder.addTestDeviceHashedId(getAdMobDeviceId());
926 |
927 | builder.setConsentDebugSettings(debugSettingsBuilder.build());
928 | }
929 |
930 | return builder.build();
931 | }
932 |
933 | private RequestConfiguration.PublisherPrivacyPersonalizationState getPublisherPrivacyPersonalizationState(int intValue) {
934 | return switch (intValue) {
935 | case 1 -> RequestConfiguration.PublisherPrivacyPersonalizationState.ENABLED;
936 | case 2 -> RequestConfiguration.PublisherPrivacyPersonalizationState.DISABLED;
937 | default -> RequestConfiguration.PublisherPrivacyPersonalizationState.DEFAULT;
938 | };
939 | }
940 |
941 | /**
942 | * Generate MD5 for the deviceID
943 | *
944 | * @param s The string for which to generate the MD5
945 | * @return String The generated MD5
946 | */
947 | private static String md5(final String s) {
948 | try {
949 | // Create MD5 Hash
950 | MessageDigest digest = MessageDigest.getInstance("MD5");
951 | digest.update(s.getBytes());
952 | byte[] messageDigest = digest.digest();
953 |
954 | // Create Hex String
955 | StringBuilder hexString = new StringBuilder();
956 | for (byte b : messageDigest) {
957 | StringBuilder h = new StringBuilder(Integer.toHexString(0xFF & b));
958 | while (h.length() < 2)
959 | h.insert(0, "0");
960 | hexString.append(h);
961 | }
962 | return hexString.toString();
963 | } catch (NoSuchAlgorithmException e) {
964 | Log.e(LOG_TAG, "md5() - no such algorithm");
965 | }
966 | return "";
967 | }
968 |
969 | /**
970 | * Get the Device ID for AdMob
971 | *
972 | * @return String Device ID
973 | */
974 | private String getAdMobDeviceId() {
975 | @SuppressLint("HardwareIds") String androidId = Settings.Secure.getString(activity.getContentResolver(), Settings.Secure.ANDROID_ID);
976 | return md5(androidId).toUpperCase(Locale.US);
977 | }
978 | }
979 |
--------------------------------------------------------------------------------
/admob/src/main/java/org/godotengine/plugin/android/admob/Banner.java:
--------------------------------------------------------------------------------
1 | //
2 | // © 2024-present https://github.com/cengiz-pz
3 | //
4 |
5 | package org.godotengine.plugin.android.admob;
6 |
7 | import android.app.Activity;
8 | import android.graphics.Color;
9 | import android.os.Build;
10 | import android.util.DisplayMetrics;
11 | import android.util.Log;
12 | import android.view.Display;
13 | import android.view.Gravity;
14 | import android.view.View;
15 | import android.widget.FrameLayout;
16 |
17 | import androidx.annotation.NonNull;
18 |
19 | import com.google.android.gms.ads.AdListener;
20 | import com.google.android.gms.ads.AdRequest;
21 | import com.google.android.gms.ads.AdSize;
22 | import com.google.android.gms.ads.AdView;
23 | import com.google.android.gms.ads.LoadAdError;
24 |
25 | import org.godotengine.godot.Dictionary;
26 |
27 | interface BannerListener {
28 | void onAdLoaded(String adId);
29 | void onAdRefreshed(String adId);
30 | void onAdFailedToLoad(String adId, LoadAdError loadAdError);
31 | void onAdImpression(String adId);
32 | void onAdClicked(String adId);
33 | void onAdOpened(String adId);
34 | void onAdClosed(String adId);
35 | }
36 |
37 |
38 | public class Banner {
39 | private static final String CLASS_NAME = Banner.class.getSimpleName();
40 | private static final String LOG_TAG = "godot::" + AdmobPlugin.CLASS_NAME + "::" + CLASS_NAME;
41 |
42 | private static final String AD_SIZE_PROPERTY = "ad_size";
43 | private static final String AD_POSITION_PROPERTY = "ad_position";
44 |
45 | enum BannerSize {
46 | BANNER,
47 | LARGE_BANNER,
48 | MEDIUM_RECTANGLE,
49 | FULL_BANNER,
50 | LEADERBOARD,
51 | SKYSCRAPER,
52 | FLUID
53 | }
54 |
55 | enum AdPosition {
56 | TOP,
57 | BOTTOM,
58 | LEFT,
59 | RIGHT,
60 | TOP_LEFT,
61 | TOP_RIGHT,
62 | BOTTOM_LEFT,
63 | BOTTOM_RIGHT,
64 | CENTER
65 | }
66 |
67 | private final String adId;
68 | private final String adUnitId;
69 | private final AdRequest adRequest;
70 | private final Activity activity;
71 | private final FrameLayout layout;
72 | private final BannerSize bannerSize;
73 | private AdPosition adPosition;
74 | private AdView adView; // Banner view
75 | private FrameLayout.LayoutParams adParams;
76 | private AdListener adListener;
77 |
78 | private boolean firstLoad;
79 |
80 |
81 | Banner(final String adId, final String adUnitId, final Dictionary adData, final AdRequest adRequest,
82 | final Activity activity, final FrameLayout layout, BannerListener listener) {
83 | this.adId = adId;
84 | this.adUnitId = adUnitId;
85 |
86 | if (adData.containsKey(AD_SIZE_PROPERTY)) {
87 | this.bannerSize = BannerSize.valueOf((String) adData.get(AD_SIZE_PROPERTY));
88 | }
89 | else {
90 | this.bannerSize = BannerSize.BANNER;
91 | Log.e(LOG_TAG, "Error: Banner size is required!");
92 | }
93 |
94 | if (adData.containsKey(AD_POSITION_PROPERTY)) {
95 | this.adPosition = AdPosition.valueOf((String) adData.get(AD_POSITION_PROPERTY));
96 | }
97 | else {
98 | this.adPosition = AdPosition.TOP;
99 | Log.w(LOG_TAG, "Warning: Ad position not specified.");
100 | }
101 |
102 | this.adRequest = adRequest;
103 | this.activity = activity;
104 | this.layout = layout;
105 |
106 | firstLoad = true;
107 |
108 | this.adListener = new AdListener() {
109 | @Override
110 | public void onAdLoaded() {
111 | if (Banner.this.firstLoad) {
112 | Banner.this.firstLoad = false;
113 | listener.onAdLoaded(Banner.this.adId);
114 | }
115 | else {
116 | listener.onAdRefreshed(Banner.this.adId);
117 | }
118 | }
119 |
120 | @Override
121 | public void onAdFailedToLoad(@NonNull LoadAdError error) {
122 | listener.onAdFailedToLoad(Banner.this.adId, error);
123 | }
124 |
125 | public void onAdImpression() {
126 | listener.onAdImpression(Banner.this.adId);
127 | }
128 |
129 | public void onAdClicked() {
130 | listener.onAdClicked(Banner.this.adId);
131 | }
132 |
133 | public void onAdOpened() {
134 | listener.onAdOpened(Banner.this.adId);
135 | }
136 |
137 | public void onAdClosed() {
138 | listener.onAdClosed(Banner.this.adId);
139 | }
140 | };
141 |
142 | this.adView = null;
143 | this.adParams = null;
144 | }
145 |
146 | void load() {
147 | addBanner(getGravity(adPosition), getAdSize(bannerSize));
148 | }
149 |
150 | void show() {
151 | if (adView == null) {
152 | Log.w(LOG_TAG, "show(): Warning: banner ad not loaded.");
153 | }
154 | else if (adView.getVisibility() == View.VISIBLE) {
155 | Log.w(LOG_TAG, "show(): Warning: banner ad already visible.");
156 | }
157 | else {
158 | Log.d(LOG_TAG, String.format("show(): %s", this.adId));
159 | adView.setVisibility(View.VISIBLE);
160 | adView.resume();
161 |
162 | // Add to layout and load ad
163 | layout.addView(adView, adParams);
164 | }
165 | }
166 |
167 | void move(final String position) {
168 | if (layout == null || adView == null || adParams == null) {
169 | Log.w(LOG_TAG, "move(): Warning: banner ad not loaded.");
170 | }
171 | else {
172 | Log.d(LOG_TAG, "banner ad moved");
173 |
174 | layout.removeView(adView); // Remove the old view
175 |
176 | adPosition = AdPosition.valueOf(position);
177 | addBanner(getGravity(adPosition), adView.getAdSize());
178 |
179 | // Add to layout and load ad
180 | layout.addView(adView, adParams);
181 | }
182 | }
183 |
184 | void resize() {
185 | if (layout == null || adView == null || adParams == null) {
186 | Log.w(LOG_TAG, "move(): Warning: banner ad not loaded.");
187 | }
188 | else {
189 | Log.d(LOG_TAG, String.format("resize(): %s", this.adId));
190 |
191 | layout.removeView(adView); // Remove the old view
192 |
193 | addBanner(adParams.gravity, getAdSize(bannerSize));
194 |
195 | // Add to layout and load ad
196 | layout.addView(adView, adParams);
197 | }
198 | }
199 |
200 | private void addBanner(final int gravity, final AdSize size) {
201 | adParams = new FrameLayout.LayoutParams(
202 | FrameLayout.LayoutParams.WRAP_CONTENT,
203 | FrameLayout.LayoutParams.WRAP_CONTENT
204 | );
205 | adParams.gravity = gravity;
206 |
207 | // Create new view & set old params
208 | adView = new AdView(activity);
209 | adView.setAdUnitId(adUnitId);
210 | adView.setBackgroundColor(Color.TRANSPARENT);
211 | adView.setAdSize(size);
212 | adView.setAdListener(adListener);
213 | adView.setVisibility(View.GONE);
214 | adView.pause();
215 |
216 | // Request
217 | adView.loadAd(adRequest);
218 | }
219 |
220 | public void remove() {
221 | if (adView == null) {
222 | Log.w(LOG_TAG, "remove(): Warning: adView is null.");
223 | }
224 | else {
225 | layout.removeView(adView);
226 | }
227 | }
228 |
229 | public void hide() {
230 | if (adView.getVisibility() != View.GONE) {
231 | adView.setVisibility(View.GONE);
232 | adView.pause();
233 | layout.removeView(adView);
234 | }
235 | else {
236 | Log.e(LOG_TAG, "Error: can't hide banner ad. Ad is not visible.");
237 | }
238 | }
239 |
240 | static int getAdWidth(Activity activity) {
241 | DisplayMetrics outMetrics = activity.getApplicationContext().getResources().getDisplayMetrics();
242 | return Math.round((float) outMetrics.widthPixels / outMetrics.density);
243 | }
244 |
245 | private AdSize getAdSize(final BannerSize bannerSize) {
246 | AdSize result;
247 | Log.d(LOG_TAG, String.format("getAdSize(): for value '%s'.", bannerSize.name()));
248 | result = switch (bannerSize) {
249 | case BANNER -> AdSize.BANNER;
250 | case LARGE_BANNER -> AdSize.LARGE_BANNER;
251 | case MEDIUM_RECTANGLE -> AdSize.MEDIUM_RECTANGLE;
252 | case FULL_BANNER -> AdSize.FULL_BANNER;
253 | case LEADERBOARD -> AdSize.LEADERBOARD;
254 | case SKYSCRAPER -> AdSize.WIDE_SKYSCRAPER;
255 | case FLUID -> AdSize.FLUID;
256 | default -> AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(activity, getAdWidth(activity));
257 | };
258 | Log.d(LOG_TAG, String.format("getAdSize(): ad size [width: %d; height: %d].", result.getWidth(), result.getHeight()));
259 | return result;
260 | }
261 |
262 | private int getGravity(final AdPosition position) {
263 | int result;
264 | Log.d(LOG_TAG, String.format("getGravity(): for value '%s'.", position.name()));
265 | result = switch (position) {
266 | case TOP -> Gravity.TOP | Gravity.CENTER_HORIZONTAL;
267 | case BOTTOM -> Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
268 | case LEFT -> Gravity.START | Gravity.CENTER_VERTICAL;
269 | case RIGHT -> Gravity.END | Gravity.CENTER_VERTICAL;
270 | case TOP_LEFT -> Gravity.TOP | Gravity.START;
271 | case TOP_RIGHT -> Gravity.TOP | Gravity.END;
272 | case BOTTOM_LEFT -> Gravity.BOTTOM | Gravity.START;
273 | case BOTTOM_RIGHT -> Gravity.BOTTOM | Gravity.END;
274 | case CENTER -> Gravity.CENTER;
275 | };
276 | Log.d(LOG_TAG, String.format("getGravity(): result = %d.", result));
277 | return result;
278 | }
279 |
280 | public int getWidth() {
281 | return getAdSize(bannerSize).getWidth();
282 | }
283 |
284 | public int getHeight() {
285 | return getAdSize(bannerSize).getHeight();
286 | }
287 |
288 | public int getWidthInPixels() {
289 | return getAdSize(bannerSize).getWidthInPixels(activity);
290 | }
291 |
292 | public int getHeightInPixels() {
293 | return getAdSize(bannerSize).getHeightInPixels(activity);
294 | }
295 | }
296 |
--------------------------------------------------------------------------------
/admob/src/main/java/org/godotengine/plugin/android/admob/Interstitial.java:
--------------------------------------------------------------------------------
1 | //
2 | // © 2024-present https://github.com/cengiz-pz
3 | //
4 |
5 | package org.godotengine.plugin.android.admob;
6 |
7 | import android.app.Activity;
8 | import android.util.Log;
9 |
10 | import androidx.annotation.NonNull;
11 |
12 | import com.google.android.gms.ads.AdError;
13 | import com.google.android.gms.ads.AdRequest;
14 | import com.google.android.gms.ads.FullScreenContentCallback;
15 | import com.google.android.gms.ads.LoadAdError;
16 | import com.google.android.gms.ads.interstitial.InterstitialAd;
17 | import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback;
18 |
19 | interface InterstitialListener {
20 | void onInterstitialLoaded(String adId);
21 | void onInterstitialReloaded(String adId);
22 | void onInterstitialFailedToLoad(String adId, LoadAdError loadAdError);
23 | void onInterstitialFailedToShow(String adId, AdError adError);
24 | void onInterstitialOpened(String adId);
25 | void onInterstitialClosed(String adId);
26 | void onInterstitialClicked(String adId);
27 | void onInterstitialImpression(String adId);
28 | }
29 |
30 | public class Interstitial {
31 | private static final String CLASS_NAME = Interstitial.class.getSimpleName();
32 | private static final String LOG_TAG = "godot::" + AdmobPlugin.CLASS_NAME + "::" + CLASS_NAME;
33 |
34 | private final String adId;
35 | private final String adUnitId;
36 | private final AdRequest adRequest;
37 | private final Activity activity;
38 | private final InterstitialListener listener;
39 |
40 | private InterstitialAd interstitialAd = null;
41 |
42 | boolean firstLoad;
43 |
44 | Interstitial(final String adId, final String adUnitId, final AdRequest adRequest, final Activity activity,
45 | final InterstitialListener listener) {
46 | this.adId = adId;
47 | this.adUnitId = adUnitId;
48 | this.adRequest = adRequest;
49 | this.activity = activity;
50 | this.listener = listener;
51 | this.firstLoad = true;
52 | }
53 |
54 | void show() {
55 | if (interstitialAd != null) {
56 | interstitialAd.show(activity);
57 | }
58 | else {
59 | Log.w(LOG_TAG, "show(): interstitial not loaded");
60 | }
61 | }
62 |
63 | private void setAd(InterstitialAd interstitialAd) {
64 | if (interstitialAd == this.interstitialAd) {
65 | Log.w(LOG_TAG, "setAd(): interstitial already set");
66 | }
67 | else {
68 | // Avoid memory leaks
69 | if (this.interstitialAd != null) {
70 | this.interstitialAd.setFullScreenContentCallback(null);
71 | this.interstitialAd.setOnPaidEventListener(null);
72 | }
73 |
74 | if (interstitialAd != null) {
75 | interstitialAd.setFullScreenContentCallback(new FullScreenContentCallback() {
76 | @Override
77 | public void onAdClicked() {
78 | super.onAdClicked();
79 | Log.i(LOG_TAG, "interstitial ad clicked");
80 | listener.onInterstitialClicked(Interstitial.this.adId);
81 | }
82 |
83 | @Override
84 | public void onAdDismissedFullScreenContent() {
85 | super.onAdDismissedFullScreenContent();
86 | setAd(null);
87 | Log.w(LOG_TAG, "interstitial ad dismissed full screen content");
88 | listener.onInterstitialClosed(Interstitial.this.adId);
89 | load();
90 | }
91 |
92 | @Override
93 | public void onAdFailedToShowFullScreenContent(@NonNull AdError adError) {
94 | super.onAdFailedToShowFullScreenContent(adError);
95 | Log.e(LOG_TAG, "interstitial ad failed to show full screen content");
96 | listener.onInterstitialFailedToShow(Interstitial.this.adId, adError);
97 | }
98 |
99 | @Override
100 | public void onAdShowedFullScreenContent() {
101 | super.onAdShowedFullScreenContent();
102 | Log.i(LOG_TAG, "interstitial ad showed full screen content");
103 | listener.onInterstitialOpened(Interstitial.this.adId);
104 | }
105 |
106 | @Override
107 | public void onAdImpression() {
108 | super.onAdImpression();
109 | Log.i(LOG_TAG, "interstitial ad impression");
110 | listener.onInterstitialImpression(Interstitial.this.adId);
111 | }
112 | });
113 | }
114 |
115 | this.interstitialAd = interstitialAd;
116 | }
117 | }
118 |
119 | void load() {
120 | InterstitialAd.load(activity, adUnitId, adRequest, new InterstitialAdLoadCallback() {
121 | @Override
122 | public void onAdLoaded(@NonNull InterstitialAd interstitialAd) {
123 | super.onAdLoaded(interstitialAd);
124 | setAd(interstitialAd);
125 | if (firstLoad) {
126 | Log.i(LOG_TAG, "interstitial ad loaded");
127 | firstLoad = false;
128 | listener.onInterstitialLoaded(Interstitial.this.adId);
129 | }
130 | else {
131 | Log.i(LOG_TAG, "interstitial ad refreshed");
132 | listener.onInterstitialReloaded(Interstitial.this.adId);
133 | }
134 | }
135 |
136 | @Override
137 | public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
138 | super.onAdFailedToLoad(loadAdError);
139 | setAd(null); // safety
140 | Log.e(LOG_TAG, "interstitial ad failed to load - error code: " + loadAdError.getCode());
141 | listener.onInterstitialFailedToLoad(Interstitial.this.adId, loadAdError);
142 | }
143 | });
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/admob/src/main/java/org/godotengine/plugin/android/admob/RewardedInterstitial.java:
--------------------------------------------------------------------------------
1 | //
2 | // © 2024-present https://github.com/cengiz-pz
3 | //
4 |
5 | package org.godotengine.plugin.android.admob;
6 |
7 | import android.app.Activity;
8 | import android.util.Log;
9 |
10 | import androidx.annotation.NonNull;
11 |
12 | import com.google.android.gms.ads.AdError;
13 | import com.google.android.gms.ads.AdRequest;
14 | import com.google.android.gms.ads.FullScreenContentCallback;
15 | import com.google.android.gms.ads.LoadAdError;
16 | import com.google.android.gms.ads.rewarded.RewardItem;
17 | import com.google.android.gms.ads.rewarded.ServerSideVerificationOptions;
18 | import com.google.android.gms.ads.rewardedinterstitial.RewardedInterstitialAd;
19 | import com.google.android.gms.ads.rewardedinterstitial.RewardedInterstitialAdLoadCallback;
20 |
21 | interface RewardedInterstitialListener {
22 | void onRewardedInterstitialLoaded(String adId);
23 | void onRewardedInterstitialFailedToLoad(String adId, LoadAdError loadAdError);
24 | void onRewardedInterstitialOpened(String adId);
25 | void onRewardedInterstitialFailedToShow(String adId, AdError adError);
26 | void onRewardedInterstitialClosed(String adId);
27 | void onRewardedClicked(String adId);
28 | void onRewardedAdImpression(String adId);
29 | void onRewarded(String adId, RewardItem reward);
30 | }
31 |
32 | public class RewardedInterstitial {
33 | private static final String CLASS_NAME = RewardedInterstitial.class.getSimpleName();
34 | private static final String LOG_TAG = "godot::" + AdmobPlugin.CLASS_NAME + "::" + CLASS_NAME;
35 |
36 | private final String adId;
37 | private final String adUnitId;
38 | private final AdRequest adRequest;
39 | private final Activity activity;
40 | private final RewardedInterstitialListener listener;
41 |
42 | private RewardedInterstitialAd rewardedAd;
43 | private ServerSideVerificationOptions serverSideVerificationOptions;
44 |
45 | RewardedInterstitial(final String adId, final String adUnitId, final AdRequest adRequest, Activity activity,
46 | final RewardedInterstitialListener listener) {
47 | this.adId = adId;
48 | this.adUnitId = adUnitId;
49 | this.adRequest = adRequest;
50 | this.activity = activity;
51 | this.listener = listener;
52 | this.rewardedAd = null;
53 | this.serverSideVerificationOptions = null;
54 | }
55 |
56 | void load() {
57 | RewardedInterstitialAd.load(activity, adUnitId, adRequest, new RewardedInterstitialAdLoadCallback() {
58 | @Override
59 | public void onAdLoaded(@NonNull RewardedInterstitialAd rewardedAd) {
60 | super.onAdLoaded(rewardedAd);
61 | setAd(rewardedAd);
62 | Log.i(LOG_TAG, "rewarded interstitial ad loaded");
63 | listener.onRewardedInterstitialLoaded(RewardedInterstitial.this.adId);
64 | }
65 |
66 | @Override
67 | public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
68 | super.onAdFailedToLoad(loadAdError);
69 |
70 | setAd(null); // safety
71 | Log.e(LOG_TAG, "rewarded interstitial ad failed to load. errorCode: " + loadAdError.getCode());
72 | listener.onRewardedInterstitialFailedToLoad(RewardedInterstitial.this.adId, loadAdError);
73 | }
74 | });
75 | }
76 |
77 | void show() {
78 | if (rewardedAd != null) {
79 | rewardedAd.show(activity, rewardItem -> {
80 | Log.i(LOG_TAG, String.format("rewarded interstitial ad rewarded! currency: %s amount: %d", rewardItem.getType(), rewardItem.getAmount()));
81 | listener.onRewarded(RewardedInterstitial.this.adId, rewardItem);
82 | });
83 | }
84 | }
85 |
86 | private void setAd(RewardedInterstitialAd rewardedAd) {
87 | if (rewardedAd == this.rewardedAd) {
88 | Log.w(LOG_TAG, "setAd(): rewarded interstitial already set");
89 | }
90 | else {
91 | // Avoid memory leaks.
92 | if (this.rewardedAd != null)
93 | this.rewardedAd.setFullScreenContentCallback(null);
94 |
95 | if (rewardedAd != null) {
96 | rewardedAd.setFullScreenContentCallback(new FullScreenContentCallback() {
97 | @Override
98 | public void onAdClicked() {
99 | super.onAdClicked();
100 | Log.i(LOG_TAG, "rewarded interstitial ad clicked");
101 | listener.onRewardedClicked(RewardedInterstitial.this.adId);
102 | }
103 |
104 | @Override
105 | public void onAdDismissedFullScreenContent() {
106 | super.onAdDismissedFullScreenContent();
107 | Log.w(LOG_TAG, "rewarded interstitial ad dismissed full screen content");
108 | listener.onRewardedInterstitialClosed(RewardedInterstitial.this.adId);
109 | }
110 |
111 | @Override
112 | public void onAdFailedToShowFullScreenContent(@NonNull AdError adError) {
113 | super.onAdFailedToShowFullScreenContent(adError);
114 | Log.e(LOG_TAG, "rewarded interstitial ad failed to show full screen content");
115 | listener.onRewardedInterstitialFailedToShow(RewardedInterstitial.this.adId, adError);
116 | }
117 |
118 | @Override
119 | public void onAdImpression() {
120 | super.onAdImpression();
121 | Log.i(LOG_TAG, "rewarded interstitial ad impression");
122 | listener.onRewardedAdImpression(RewardedInterstitial.this.adId);
123 | }
124 |
125 | @Override
126 | public void onAdShowedFullScreenContent() {
127 | super.onAdShowedFullScreenContent();
128 | Log.i(LOG_TAG, "rewarded interstitial ad showed full screen content");
129 | listener.onRewardedInterstitialOpened(RewardedInterstitial.this.adId);
130 | }
131 | });
132 | }
133 |
134 | if (serverSideVerificationOptions != null) {
135 | rewardedAd.setServerSideVerificationOptions(serverSideVerificationOptions);
136 | }
137 |
138 | this.rewardedAd = rewardedAd;
139 | }
140 | }
141 |
142 | void setServerSideVerificationOptions(ServerSideVerificationOptions ssvo) {
143 | this.serverSideVerificationOptions = ssvo;
144 |
145 | if (rewardedAd == null) {
146 | Log.w(LOG_TAG, "setServerSideVerificationOptions(): Ad is null. SSVO will be set when ad is loaded.");
147 | }
148 | else {
149 | rewardedAd.setServerSideVerificationOptions(ssvo);
150 | }
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/admob/src/main/java/org/godotengine/plugin/android/admob/RewardedVideo.java:
--------------------------------------------------------------------------------
1 | //
2 | // © 2024-present https://github.com/cengiz-pz
3 | //
4 |
5 | package org.godotengine.plugin.android.admob;
6 |
7 | import android.app.Activity;
8 | import android.util.Log;
9 |
10 | import androidx.annotation.NonNull;
11 |
12 | import com.google.android.gms.ads.AdError;
13 | import com.google.android.gms.ads.AdRequest;
14 | import com.google.android.gms.ads.FullScreenContentCallback;
15 | import com.google.android.gms.ads.LoadAdError;
16 | import com.google.android.gms.ads.rewarded.RewardItem;
17 | import com.google.android.gms.ads.rewarded.RewardedAd;
18 | import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback;
19 | import com.google.android.gms.ads.rewarded.ServerSideVerificationOptions;
20 |
21 | interface RewardedVideoListener {
22 | void onRewardedVideoLoaded(String adId);
23 | void onRewardedVideoFailedToLoad(String adId, LoadAdError loadAdError);
24 | void onRewardedVideoOpened(String adId);
25 | void onRewardedVideoFailedToShow(String adId, AdError adError);
26 | void onRewardedVideoClosed(String adId);
27 | void onRewardedClicked(String adId);
28 | void onRewardedAdImpression(String adId);
29 | void onRewarded(String adId, RewardItem reward);
30 | }
31 |
32 | public class RewardedVideo {
33 | private static final String CLASS_NAME = RewardedVideo.class.getSimpleName();
34 | private static final String LOG_TAG = "godot::" + AdmobPlugin.CLASS_NAME + "::" + CLASS_NAME;
35 |
36 | private final String adId;
37 | private final String adUnitId;
38 | private final AdRequest adRequest;
39 | private final Activity activity;
40 | private final RewardedVideoListener listener;
41 |
42 | private RewardedAd rewardedAd;
43 | private ServerSideVerificationOptions serverSideVerificationOptions;
44 |
45 | RewardedVideo(final String adId, final String adUnitId, final AdRequest adRequest, Activity activity,
46 | final RewardedVideoListener listener) {
47 | this.adId = adId;
48 | this.adUnitId = adUnitId;
49 | this.adRequest = adRequest;
50 | this.activity = activity;
51 | this.listener = listener;
52 | this.rewardedAd = null;
53 | this.serverSideVerificationOptions = null;
54 | }
55 |
56 | void load() {
57 | RewardedAd.load(activity, adUnitId, adRequest, new RewardedAdLoadCallback() {
58 | @Override
59 | public void onAdLoaded(@NonNull RewardedAd rewardedAd) {
60 | super.onAdLoaded(rewardedAd);
61 | setAd(rewardedAd);
62 | Log.i(LOG_TAG, "rewarded video ad loaded");
63 | listener.onRewardedVideoLoaded(RewardedVideo.this.adId);
64 | }
65 |
66 | @Override
67 | public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
68 | super.onAdFailedToLoad(loadAdError);
69 | // safety
70 | setAd(null);
71 | Log.e(LOG_TAG, "rewarded video ad failed to load. errorCode: " + loadAdError.getCode());
72 | listener.onRewardedVideoFailedToLoad(RewardedVideo.this.adId, loadAdError);
73 | }
74 | });
75 | }
76 |
77 | void show() {
78 | if (rewardedAd != null) {
79 | rewardedAd.show(activity, rewardItem -> {
80 | Log.i(LOG_TAG, String.format("rewarded video ad reward received! currency: %s amount: %d", rewardItem.getType(), rewardItem.getAmount()));
81 | listener.onRewarded(RewardedVideo.this.adId, rewardItem);
82 | });
83 | }
84 | }
85 |
86 | private void setAd(RewardedAd rewardedAd) {
87 | if (rewardedAd == this.rewardedAd) {
88 | Log.w(LOG_TAG, "setAd(): rewarded already set");
89 | }
90 | else {
91 | // Avoid memory leaks.
92 | if (this.rewardedAd != null)
93 | this.rewardedAd.setFullScreenContentCallback(null);
94 |
95 | if (rewardedAd != null) {
96 | rewardedAd.setFullScreenContentCallback(new FullScreenContentCallback() {
97 | @Override
98 | public void onAdClicked() {
99 | super.onAdClicked();
100 | Log.i(LOG_TAG, "rewarded video ad clicked");
101 | listener.onRewardedClicked(RewardedVideo.this.adId);
102 | }
103 |
104 | @Override
105 | public void onAdDismissedFullScreenContent() {
106 | super.onAdDismissedFullScreenContent();
107 | Log.w(LOG_TAG, "rewarded video ad dismissed full screen content");
108 | listener.onRewardedVideoClosed(RewardedVideo.this.adId);
109 | }
110 |
111 | @Override
112 | public void onAdFailedToShowFullScreenContent(@NonNull AdError adError) {
113 | super.onAdFailedToShowFullScreenContent(adError);
114 | Log.e(LOG_TAG, "rewarded video ad failed to show full screen content");
115 | listener.onRewardedVideoFailedToShow(RewardedVideo.this.adId, adError);
116 | }
117 |
118 | @Override
119 | public void onAdImpression() {
120 | super.onAdImpression();
121 | Log.i(LOG_TAG, "rewarded video ad impression");
122 | listener.onRewardedAdImpression(RewardedVideo.this.adId);
123 | }
124 |
125 | @Override
126 | public void onAdShowedFullScreenContent() {
127 | super.onAdShowedFullScreenContent();
128 | Log.i(LOG_TAG, "rewarded video ad showed full screen content");
129 | listener.onRewardedVideoOpened(RewardedVideo.this.adId);
130 | }
131 | });
132 | }
133 |
134 | if (serverSideVerificationOptions != null) {
135 | rewardedAd.setServerSideVerificationOptions(serverSideVerificationOptions);
136 | }
137 |
138 | this.rewardedAd = rewardedAd;
139 | }
140 | }
141 |
142 | void setServerSideVerificationOptions(ServerSideVerificationOptions ssvo) {
143 | this.serverSideVerificationOptions = ssvo;
144 |
145 | if (rewardedAd == null) {
146 | Log.w(LOG_TAG, "setServerSideVerificationOptions(): Ad is null. SSVO will be set when ad is loaded.");
147 | }
148 | else {
149 | rewardedAd.setServerSideVerificationOptions(ssvo);
150 | }
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | //
2 | // © 2024-present https://github.com/cengiz-pz
3 | //
4 |
5 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
6 | plugins {
7 | id("com.android.library") version "8.4.0" apply false
8 | }
9 |
10 | val cleanBuildDir by tasks.registering(Delete::class) {
11 | delete(rootProject.buildDir)
12 | }
13 |
14 | allprojects {
15 | tasks.withType {
16 | options.compilerArgs.add("-Xlint:unchecked")
17 | options.compilerArgs.add("-Xlint:deprecation")
18 | }
19 | }
--------------------------------------------------------------------------------
/demo/.gitignore:
--------------------------------------------------------------------------------
1 | # Godot 4+ specific ignores
2 | .godot/
3 |
4 | # Godot-specific ignores
5 | .import/
6 | export.cfg
7 | export_presets.cfg
8 |
9 | # Dummy HTML5 export presets file for continuous integration
10 | !.github/dist/export_presets.cfg
11 |
12 | # Android builds
13 | android/
14 |
15 | # Imported translations (automatically generated from CSV files)
16 | *.translation
17 |
18 | # Mono-specific ignores
19 | .mono/
20 | data_*/
21 | mono_crash.*.json
22 |
23 | # System/tool-specific ignores
24 | .directory
25 | .DS_Store
26 | *~
27 | *.blend1
28 |
29 | # Logs
30 | *.log
31 |
--------------------------------------------------------------------------------
/demo/Main.gd:
--------------------------------------------------------------------------------
1 | #
2 | # © 2024-present https://github.com/cengiz-pz
3 | #
4 |
5 | extends Node
6 |
7 | @onready var admob: Admob = $Admob as Admob
8 | @onready var show_banner_button: Button = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer/ShowBannerButton
9 | @onready var hide_banner_button: Button = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer/HideBannerButton
10 | @onready var reload_banner_button: Button = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer/ReloadBannerButton
11 | @onready var banner_position_option_button: OptionButton = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/PositionHBoxContainer/OptionButton
12 | @onready var banner_size_option_button: OptionButton = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/SizeHBoxContainer/OptionButton
13 | @onready var interstitial_button: Button = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other/InterstitialButton
14 | @onready var rewarded_button: Button = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other/RewardedButton
15 | @onready var rewarded_interstitial_button: Button = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other/RewardedInterstitialButton
16 | @onready var _label: RichTextLabel = $CanvasLayer/CenterContainer/VBoxContainer/RichTextLabel as RichTextLabel
17 | @onready var _geography_option_button: OptionButton = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/GeographyHBoxContainer/OptionButton
18 |
19 | var _is_banner_loaded: bool = false
20 | var _is_interstitial_loaded: bool = false
21 | var _is_rewarded_video_loaded: bool = false
22 | var _is_rewarded_interstitial_loaded: bool = false
23 |
24 |
25 | func _ready() -> void:
26 | admob.initialize()
27 |
28 | var __index: int = 0
29 | for __item: String in LoadAdRequest.AdPosition.keys():
30 | banner_position_option_button.add_item(__item)
31 | if __item.casecmp_to(LoadAdRequest.AdPosition.keys()[admob.banner_position]) == 0:
32 | banner_position_option_button.select(__index)
33 | __index += 1
34 |
35 | __index = 0
36 | for __item in LoadAdRequest.AdSize.keys():
37 | banner_size_option_button.add_item(__item)
38 | if __item.casecmp_to(LoadAdRequest.AdSize.keys()[admob.banner_size]) == 0:
39 | banner_size_option_button.select(__index)
40 | __index += 1
41 |
42 |
43 | func _on_admob_initialization_completed(_status_data: InitializationStatus) -> void:
44 | _process_consent_status(admob.get_consent_status())
45 | admob.load_banner_ad()
46 | admob.load_interstitial_ad()
47 | admob.load_rewarded_ad()
48 | admob.load_rewarded_interstitial_ad()
49 |
50 |
51 | func _on_size_button_pressed() -> void:
52 | print(" ------- Get banner size button PRESSED")
53 | if _is_banner_loaded:
54 | _print_to_screen("Banner size: " + str(admob.get_banner_dimension()))
55 |
56 |
57 | func _on_pixel_size_button_pressed() -> void:
58 | print(" ------- Get banner pixel size button PRESSED")
59 | if _is_banner_loaded:
60 | _print_to_screen("Banner size in pixels: " + str(admob.get_banner_dimension_in_pixels()))
61 |
62 |
63 | func _on_show_banner_button_pressed() -> void:
64 | print(" ------- Show banner button PRESSED")
65 | if _is_banner_loaded:
66 | show_banner_button.disabled = true
67 | hide_banner_button.disabled = false
68 | admob.show_banner_ad()
69 |
70 |
71 | func _on_hide_banner_button_pressed() -> void:
72 | print(" ------- Hide banner button PRESSED")
73 | if _is_banner_loaded:
74 | show_banner_button.disabled = false
75 | hide_banner_button.disabled = true
76 | admob.hide_banner_ad()
77 |
78 |
79 | func _on_reload_banner_button_pressed() -> void:
80 | print(" ------- Reload banner button PRESSED")
81 | if _is_banner_loaded:
82 | _is_banner_loaded = false
83 | show_banner_button.disabled = true
84 | reload_banner_button.disabled = true
85 | admob.remove_banner_ad(admob._active_banner_ads[0])
86 | admob.banner_position = LoadAdRequest.AdPosition[banner_position_option_button.get_item_text(banner_position_option_button.selected)]
87 | admob.banner_size = LoadAdRequest.AdSize[banner_size_option_button.get_item_text(banner_size_option_button.selected)]
88 | admob.load_banner_ad()
89 |
90 |
91 | func _on_interstitial_button_pressed() -> void:
92 | print(" ------- Interstitial button PRESSED")
93 | if _is_interstitial_loaded:
94 | _is_interstitial_loaded = false
95 | interstitial_button.disabled = true
96 | admob.show_interstitial_ad()
97 | else:
98 | admob.load_interstitial_ad()
99 |
100 |
101 | func _on_rewarded_video_button_pressed() -> void:
102 | print(" ------- Rewarded button PRESSED")
103 | if _is_rewarded_video_loaded:
104 | _is_rewarded_video_loaded = false
105 | rewarded_button.disabled = true
106 | admob.show_rewarded_ad()
107 | else:
108 | admob.load_rewarded_ad()
109 |
110 |
111 | func _on_rewarded_interstitial_button_pressed() -> void:
112 | print(" ------- Rewarded interstitial button PRESSED")
113 | if _is_rewarded_interstitial_loaded:
114 | _is_rewarded_interstitial_loaded = false
115 | rewarded_interstitial_button.disabled = true
116 | admob.show_rewarded_interstitial_ad()
117 | else:
118 | admob.load_rewarded_interstitial_ad()
119 |
120 |
121 | func _on_reset_consent_button_pressed() -> void:
122 | admob.reset_consent_info()
123 |
124 |
125 | func _on_admob_banner_ad_loaded(ad_id: String) -> void:
126 | _is_banner_loaded = true
127 | show_banner_button.disabled = false
128 | reload_banner_button.disabled = false
129 | _print_to_screen("banner loaded: %s" % ad_id)
130 |
131 |
132 | func _on_admob_banner_ad_refreshed(ad_id: String) -> void:
133 | _print_to_screen("banner refreshed: %s" % ad_id)
134 |
135 |
136 | func _on_admob_banner_ad_failed_to_load(ad_id: String, error_data: LoadAdError) -> void:
137 | _print_to_screen("banner %s failed to load. error: %d, message: %s" %
138 | [ad_id, error_data.get_code(), error_data.get_message()], true)
139 |
140 |
141 | func _on_admob_interstitial_ad_loaded(ad_id: String) -> void:
142 | _is_interstitial_loaded = true
143 | interstitial_button.disabled = false
144 | _print_to_screen("interstitial loaded: %s" % ad_id)
145 |
146 |
147 | func _on_admob_interstitial_ad_failed_to_load(ad_id: String, error_data: LoadAdError) -> void:
148 | _print_to_screen("interstitial %s failed to load. error: %d, message: %s" %
149 | [ad_id, error_data.get_code(), error_data.get_message()], true)
150 |
151 |
152 | func _on_admob_interstitial_ad_refreshed(ad_id: String) -> void:
153 | _print_to_screen("interstitial refreshed: %s" % ad_id)
154 |
155 |
156 | func _on_admob_interstitial_ad_dismissed_full_screen_content(ad_id: String) -> void:
157 | _print_to_screen("interstitial closed: %s" % ad_id)
158 |
159 |
160 | func _on_admob_rewarded_ad_loaded(ad_id: String) -> void:
161 | _is_rewarded_video_loaded = true
162 | rewarded_button.disabled = false
163 | _print_to_screen("rewarded video loaded: %s" % ad_id)
164 |
165 |
166 | func _on_admob_rewarded_ad_failed_to_load(ad_id: String, error_data: LoadAdError) -> void:
167 | _print_to_screen("rewarded video %s failed to load. error: %d, message: %s" %
168 | [ad_id, error_data.get_code(), error_data.get_message()], true)
169 |
170 |
171 | func _on_admob_rewarded_ad_user_earned_reward(ad_id: String, reward_data: RewardItem) -> void:
172 | _print_to_screen("user rewarded for rewarded ad '%s' with %d %s" %
173 | [ad_id, reward_data.get_amount(), reward_data.get_type()])
174 |
175 |
176 | func _on_admob_rewarded_interstitial_ad_loaded(ad_id: String) -> void:
177 | _is_rewarded_interstitial_loaded = true
178 | rewarded_interstitial_button.disabled = false
179 | _print_to_screen("rewarded interstitial loaded: %s" % ad_id)
180 |
181 |
182 | func _on_admob_rewarded_interstitial_ad_failed_to_load(ad_id: String, error_data: LoadAdError) -> void:
183 | _print_to_screen("rewarded interstitial %s failed to load. error: %d, message: %s" %
184 | [ad_id, error_data.get_code(), error_data.get_message()], true)
185 |
186 |
187 | func _on_admob_rewarded_interstitial_ad_user_earned_reward(ad_id: String, reward_data: RewardItem) -> void:
188 | _print_to_screen("user rewarded for rewarded interstitial ad '%s' with %d %s" %
189 | [ad_id, reward_data.get_amount(), reward_data.get_type()])
190 |
191 |
192 | func _on_admob_consent_info_updated() -> void:
193 | _print_to_screen("consent info updated")
194 | _process_consent_status(admob.get_consent_status())
195 |
196 |
197 | func _on_admob_consent_info_update_failed(a_error_data: FormError) -> void:
198 | _print_to_screen("consent info failed to update: %s" % a_error_data.get_message())
199 |
200 |
201 | func _process_consent_status(a_consent_status: int) -> void:
202 | _print_to_screen("_process_consent_status(): consent status = %d" % a_consent_status)
203 | match a_consent_status:
204 | ConsentInformation.ConsentStatus.UNKNOWN:
205 | _print_to_screen("consent status is unknown")
206 | admob.update_consent_info(ConsentRequestParameters.new()
207 | .set_debug_geography(ConsentRequestParameters.DebugGeography.values()[_geography_option_button.selected])
208 | .add_test_device_hashed_id(OS.get_unique_id()))
209 | ConsentInformation.ConsentStatus.NOT_REQUIRED:
210 | _print_to_screen("consent is not required")
211 | ConsentInformation.ConsentStatus.REQUIRED:
212 | _print_to_screen("consent is required")
213 | admob.load_consent_form()
214 | ConsentInformation.ConsentStatus.OBTAINED:
215 | _print_to_screen("consent has already been obtained")
216 |
217 |
218 | func _on_admob_consent_form_loaded() -> void:
219 | _print_to_screen("consent form has been loaded")
220 | admob.show_consent_form()
221 |
222 |
223 | func _on_admob_consent_form_failed_to_load(a_error_data: FormError) -> void:
224 | _print_to_screen("consent form failed to load %s" % a_error_data.get_message())
225 |
226 |
227 | func _on_admob_consent_form_dismissed(a_error_data: FormError) -> void:
228 | _print_to_screen("consent form has been dismissed %s" % a_error_data.get_message())
229 |
230 |
231 | func _on_update_consent_info_button_pressed() -> void:
232 | print("selected consent geography: %d" % _geography_option_button.selected)
233 | admob.update_consent_info(ConsentRequestParameters.new()
234 | .set_debug_geography(ConsentRequestParameters.DebugGeography.values()[_geography_option_button.selected])
235 | .add_test_device_hashed_id(OS.get_unique_id()))
236 |
237 |
238 | func _on_scene_2_button_pressed() -> void:
239 | get_tree().change_scene_to_file("res://scene/Scene2.tscn")
240 |
241 |
242 | func _print_to_screen(a_message: String, a_is_error: bool = false) -> void:
243 | _label.add_text("%s\n\n" % a_message)
244 | if a_is_error:
245 | printerr(a_message)
246 | else:
247 | print(a_message)
248 |
--------------------------------------------------------------------------------
/demo/Main.gd.uid:
--------------------------------------------------------------------------------
1 | uid://bcqb5hwnjbtob
2 |
--------------------------------------------------------------------------------
/demo/Main.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://daro5x6n3pd26"]
2 |
3 | [ext_resource type="Script" uid="uid://bcqb5hwnjbtob" path="res://Main.gd" id="1_wt50o"]
4 | [ext_resource type="Script" uid="uid://b8ayp8io5uvmn" path="res://addons/AdmobPlugin/Admob.gd" id="2_4x6et"]
5 | [ext_resource type="Texture2D" uid="uid://bdjwuj5g73wl3" path="res://admob.png" id="2_qti4s"]
6 |
7 | [node name="Main" type="Node"]
8 | script = ExtResource("1_wt50o")
9 |
10 | [node name="CanvasLayer" type="CanvasLayer" parent="."]
11 |
12 | [node name="CenterContainer" type="CenterContainer" parent="CanvasLayer"]
13 | anchors_preset = 15
14 | anchor_right = 1.0
15 | anchor_bottom = 1.0
16 | grow_horizontal = 2
17 | grow_vertical = 2
18 | size_flags_horizontal = 3
19 | size_flags_vertical = 3
20 |
21 | [node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/CenterContainer"]
22 | custom_minimum_size = Vector2(400, 0)
23 | layout_mode = 2
24 | theme_override_constants/separation = 20
25 |
26 | [node name="TextureRect" type="TextureRect" parent="CanvasLayer/CenterContainer/VBoxContainer"]
27 | custom_minimum_size = Vector2(0, 128)
28 | layout_mode = 2
29 | texture = ExtResource("2_qti4s")
30 | expand_mode = 3
31 | stretch_mode = 5
32 |
33 | [node name="HBoxContainer" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer"]
34 | layout_mode = 2
35 |
36 | [node name="Label" type="Label" parent="CanvasLayer/CenterContainer/VBoxContainer/HBoxContainer"]
37 | layout_mode = 2
38 | size_flags_horizontal = 3
39 | theme_override_font_sizes/font_size = 24
40 | text = "Admob Demo (Main Scene)"
41 | horizontal_alignment = 1
42 |
43 | [node name="Scene2Button" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/HBoxContainer"]
44 | layout_mode = 2
45 | text = "Switch"
46 |
47 | [node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer"]
48 | layout_mode = 2
49 | theme_override_constants/separation = 11
50 |
51 | [node name="TabContainer" type="TabContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer"]
52 | custom_minimum_size = Vector2(0, 165)
53 | layout_mode = 2
54 | current_tab = 0
55 |
56 | [node name="Banner" type="VBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer"]
57 | layout_mode = 2
58 | theme_override_constants/separation = 6
59 | metadata/_tab_index = 0
60 |
61 | [node name="PositionHBoxContainer" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner"]
62 | layout_mode = 2
63 | theme_override_constants/separation = 10
64 |
65 | [node name="Label" type="Label" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/PositionHBoxContainer"]
66 | layout_mode = 2
67 | text = "Banner Position:"
68 |
69 | [node name="OptionButton" type="OptionButton" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/PositionHBoxContainer"]
70 | layout_mode = 2
71 | size_flags_horizontal = 3
72 |
73 | [node name="SizeHBoxContainer" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner"]
74 | layout_mode = 2
75 | theme_override_constants/separation = 10
76 |
77 | [node name="Label" type="Label" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/SizeHBoxContainer"]
78 | layout_mode = 2
79 | text = "Banner Size:"
80 |
81 | [node name="OptionButton" type="OptionButton" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/SizeHBoxContainer"]
82 | layout_mode = 2
83 | size_flags_horizontal = 3
84 |
85 | [node name="SizeButtonHBoxContainer" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner"]
86 | layout_mode = 2
87 | theme_override_constants/separation = 30
88 |
89 | [node name="SizeButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/SizeButtonHBoxContainer"]
90 | layout_mode = 2
91 | size_flags_horizontal = 3
92 | text = "Get Size"
93 |
94 | [node name="PixelSizeButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/SizeButtonHBoxContainer"]
95 | layout_mode = 2
96 | size_flags_horizontal = 3
97 | text = "Get Size In Pixels"
98 |
99 | [node name="ButtonsHBoxContainer" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner"]
100 | layout_mode = 2
101 | theme_override_constants/separation = 45
102 |
103 | [node name="ShowBannerButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer"]
104 | custom_minimum_size = Vector2(100, 0)
105 | layout_mode = 2
106 | disabled = true
107 | text = "Show"
108 |
109 | [node name="HideBannerButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer"]
110 | custom_minimum_size = Vector2(100, 0)
111 | layout_mode = 2
112 | disabled = true
113 | text = "Hide"
114 |
115 | [node name="ReloadBannerButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer"]
116 | custom_minimum_size = Vector2(100, 0)
117 | layout_mode = 2
118 | disabled = true
119 | text = "Reload"
120 |
121 | [node name="Other" type="VBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer"]
122 | visible = false
123 | layout_mode = 2
124 | theme_override_constants/separation = 15
125 | metadata/_tab_index = 1
126 |
127 | [node name="InterstitialButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other"]
128 | layout_mode = 2
129 | disabled = true
130 | text = "Show Interstitial Ad"
131 |
132 | [node name="RewardedButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other"]
133 | layout_mode = 2
134 | disabled = true
135 | text = "Show Rewarded Ad"
136 |
137 | [node name="RewardedInterstitialButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other"]
138 | layout_mode = 2
139 | disabled = true
140 | text = "Show Rewarded Interstitial Ad"
141 |
142 | [node name="GeographyHBoxContainer" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer"]
143 | layout_mode = 2
144 |
145 | [node name="Label" type="Label" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/GeographyHBoxContainer"]
146 | layout_mode = 2
147 | text = "Debug Geography: "
148 |
149 | [node name="OptionButton" type="OptionButton" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/GeographyHBoxContainer"]
150 | layout_mode = 2
151 | size_flags_horizontal = 3
152 | selected = 1
153 | item_count = 3
154 | popup/item_0/text = "DISABLED"
155 | popup/item_0/id = 0
156 | popup/item_1/text = "EEA"
157 | popup/item_1/id = 1
158 | popup/item_2/text = "NOT EEA"
159 | popup/item_2/id = 2
160 |
161 | [node name="HBoxContainer" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer"]
162 | layout_mode = 2
163 | theme_override_constants/separation = 10
164 |
165 | [node name="Label" type="Label" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/HBoxContainer"]
166 | layout_mode = 2
167 | text = "Consent Info: "
168 |
169 | [node name="UpdateConsentInfoButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/HBoxContainer"]
170 | layout_mode = 2
171 | size_flags_horizontal = 3
172 | text = "Update"
173 |
174 | [node name="ResetConsentButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/HBoxContainer"]
175 | layout_mode = 2
176 | size_flags_horizontal = 3
177 | text = "Reset"
178 |
179 | [node name="RichTextLabel" type="RichTextLabel" parent="CanvasLayer/CenterContainer/VBoxContainer"]
180 | custom_minimum_size = Vector2(0, 210)
181 | layout_mode = 2
182 | theme_override_font_sizes/normal_font_size = 14
183 | scroll_following = true
184 |
185 | [node name="Admob" type="Node" parent="."]
186 | script = ExtResource("2_4x6et")
187 | debug_application_id = "ca-app-pub-3940256099942544~3347511713"
188 | debug_banner_id = "ca-app-pub-3940256099942544/6300978111"
189 | debug_interstitial_id = "ca-app-pub-3940256099942544/1033173712"
190 | debug_rewarded_id = "ca-app-pub-3940256099942544/5224354917"
191 | debug_rewarded_interstitial_id = "ca-app-pub-3940256099942544/5354046379"
192 |
193 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/HBoxContainer/Scene2Button" to="." method="_on_scene_2_button_pressed"]
194 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/SizeButtonHBoxContainer/SizeButton" to="." method="_on_size_button_pressed"]
195 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/SizeButtonHBoxContainer/PixelSizeButton" to="." method="_on_pixel_size_button_pressed"]
196 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer/ShowBannerButton" to="." method="_on_show_banner_button_pressed"]
197 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer/HideBannerButton" to="." method="_on_hide_banner_button_pressed"]
198 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer/ReloadBannerButton" to="." method="_on_reload_banner_button_pressed"]
199 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other/InterstitialButton" to="." method="_on_interstitial_button_pressed"]
200 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other/RewardedButton" to="." method="_on_rewarded_video_button_pressed"]
201 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other/RewardedInterstitialButton" to="." method="_on_rewarded_interstitial_button_pressed"]
202 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/HBoxContainer/UpdateConsentInfoButton" to="." method="_on_update_consent_info_button_pressed"]
203 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/HBoxContainer/ResetConsentButton" to="." method="_on_reset_consent_button_pressed"]
204 | [connection signal="banner_ad_failed_to_load" from="Admob" to="." method="_on_admob_banner_ad_failed_to_load"]
205 | [connection signal="banner_ad_loaded" from="Admob" to="." method="_on_admob_banner_ad_loaded"]
206 | [connection signal="banner_ad_refreshed" from="Admob" to="." method="_on_admob_banner_ad_refreshed"]
207 | [connection signal="consent_form_dismissed" from="Admob" to="." method="_on_admob_consent_form_dismissed"]
208 | [connection signal="consent_form_failed_to_load" from="Admob" to="." method="_on_admob_consent_form_failed_to_load"]
209 | [connection signal="consent_form_loaded" from="Admob" to="." method="_on_admob_consent_form_loaded"]
210 | [connection signal="consent_info_update_failed" from="Admob" to="." method="_on_admob_consent_info_update_failed"]
211 | [connection signal="consent_info_updated" from="Admob" to="." method="_on_admob_consent_info_updated"]
212 | [connection signal="initialization_completed" from="Admob" to="." method="_on_admob_initialization_completed"]
213 | [connection signal="interstitial_ad_dismissed_full_screen_content" from="Admob" to="." method="_on_admob_interstitial_ad_dismissed_full_screen_content"]
214 | [connection signal="interstitial_ad_failed_to_load" from="Admob" to="." method="_on_admob_interstitial_ad_failed_to_load"]
215 | [connection signal="interstitial_ad_loaded" from="Admob" to="." method="_on_admob_interstitial_ad_loaded"]
216 | [connection signal="interstitial_ad_refreshed" from="Admob" to="." method="_on_admob_interstitial_ad_refreshed"]
217 | [connection signal="rewarded_ad_failed_to_load" from="Admob" to="." method="_on_admob_rewarded_ad_failed_to_load"]
218 | [connection signal="rewarded_ad_loaded" from="Admob" to="." method="_on_admob_rewarded_ad_loaded"]
219 | [connection signal="rewarded_ad_user_earned_reward" from="Admob" to="." method="_on_admob_rewarded_ad_user_earned_reward"]
220 | [connection signal="rewarded_interstitial_ad_failed_to_load" from="Admob" to="." method="_on_admob_rewarded_interstitial_ad_failed_to_load"]
221 | [connection signal="rewarded_interstitial_ad_loaded" from="Admob" to="." method="_on_admob_rewarded_interstitial_ad_loaded"]
222 | [connection signal="rewarded_interstitial_ad_user_earned_reward" from="Admob" to="." method="_on_admob_rewarded_interstitial_ad_user_earned_reward"]
223 |
--------------------------------------------------------------------------------
/demo/admob.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cengiz-pz/godot-android-admob-plugin/febdd2292550c666577141f27f4a87f2f3bd5562/demo/admob.png
--------------------------------------------------------------------------------
/demo/android/.build_version:
--------------------------------------------------------------------------------
1 | 4.4.1.stable
2 |
--------------------------------------------------------------------------------
/demo/export_presets.cfg:
--------------------------------------------------------------------------------
1 | [preset.0]
2 |
3 | name="Android"
4 | platform="Android"
5 | runnable=true
6 | dedicated_server=false
7 | custom_features=""
8 | export_filter="all_resources"
9 | include_filter=""
10 | exclude_filter=""
11 | export_path=""
12 | encryption_include_filters=""
13 | encryption_exclude_filters=""
14 | encrypt_pck=false
15 | encrypt_directory=false
16 |
17 | [preset.0.options]
18 |
19 | custom_template/debug=""
20 | custom_template/release=""
21 | gradle_build/use_gradle_build=true
22 | gradle_build/export_format=0
23 | gradle_build/min_sdk=""
24 | gradle_build/target_sdk=""
25 | architectures/armeabi-v7a=false
26 | architectures/arm64-v8a=true
27 | architectures/x86=false
28 | architectures/x86_64=false
29 | version/code=1
30 | version/name=""
31 | package/unique_name="org.godotengine.admobdemo"
32 | package/name=""
33 | package/signed=true
34 | package/app_category=2
35 | package/retain_data_on_uninstall=false
36 | package/exclude_from_recents=false
37 | package/show_in_android_tv=false
38 | package/show_in_app_library=true
39 | package/show_as_launcher_app=false
40 | launcher_icons/main_192x192=""
41 | launcher_icons/adaptive_foreground_432x432=""
42 | launcher_icons/adaptive_background_432x432=""
43 | graphics/opengl_debug=false
44 | xr_features/xr_mode=0
45 | screen/immersive_mode=true
46 | screen/support_small=true
47 | screen/support_normal=true
48 | screen/support_large=true
49 | screen/support_xlarge=true
50 | user_data_backup/allow=false
51 | command_line/extra_args=""
52 | apk_expansion/enable=false
53 | apk_expansion/SALT=""
54 | apk_expansion/public_key=""
55 | permissions/custom_permissions=PackedStringArray()
56 | permissions/access_checkin_properties=false
57 | permissions/access_coarse_location=false
58 | permissions/access_fine_location=false
59 | permissions/access_location_extra_commands=false
60 | permissions/access_mock_location=false
61 | permissions/access_network_state=false
62 | permissions/access_surface_flinger=false
63 | permissions/access_wifi_state=false
64 | permissions/account_manager=false
65 | permissions/add_voicemail=false
66 | permissions/authenticate_accounts=false
67 | permissions/battery_stats=false
68 | permissions/bind_accessibility_service=false
69 | permissions/bind_appwidget=false
70 | permissions/bind_device_admin=false
71 | permissions/bind_input_method=false
72 | permissions/bind_nfc_service=false
73 | permissions/bind_notification_listener_service=false
74 | permissions/bind_print_service=false
75 | permissions/bind_remoteviews=false
76 | permissions/bind_text_service=false
77 | permissions/bind_vpn_service=false
78 | permissions/bind_wallpaper=false
79 | permissions/bluetooth=false
80 | permissions/bluetooth_admin=false
81 | permissions/bluetooth_privileged=false
82 | permissions/brick=false
83 | permissions/broadcast_package_removed=false
84 | permissions/broadcast_sms=false
85 | permissions/broadcast_sticky=false
86 | permissions/broadcast_wap_push=false
87 | permissions/call_phone=false
88 | permissions/call_privileged=false
89 | permissions/camera=false
90 | permissions/capture_audio_output=false
91 | permissions/capture_secure_video_output=false
92 | permissions/capture_video_output=false
93 | permissions/change_component_enabled_state=false
94 | permissions/change_configuration=false
95 | permissions/change_network_state=false
96 | permissions/change_wifi_multicast_state=false
97 | permissions/change_wifi_state=false
98 | permissions/clear_app_cache=false
99 | permissions/clear_app_user_data=false
100 | permissions/control_location_updates=false
101 | permissions/delete_cache_files=false
102 | permissions/delete_packages=false
103 | permissions/device_power=false
104 | permissions/diagnostic=false
105 | permissions/disable_keyguard=false
106 | permissions/dump=false
107 | permissions/expand_status_bar=false
108 | permissions/factory_test=false
109 | permissions/flashlight=false
110 | permissions/force_back=false
111 | permissions/get_accounts=false
112 | permissions/get_package_size=false
113 | permissions/get_tasks=false
114 | permissions/get_top_activity_info=false
115 | permissions/global_search=false
116 | permissions/hardware_test=false
117 | permissions/inject_events=false
118 | permissions/install_location_provider=false
119 | permissions/install_packages=false
120 | permissions/install_shortcut=false
121 | permissions/internal_system_window=false
122 | permissions/internet=true
123 | permissions/kill_background_processes=false
124 | permissions/location_hardware=false
125 | permissions/manage_accounts=false
126 | permissions/manage_app_tokens=false
127 | permissions/manage_documents=false
128 | permissions/manage_external_storage=false
129 | permissions/master_clear=false
130 | permissions/media_content_control=false
131 | permissions/modify_audio_settings=false
132 | permissions/modify_phone_state=false
133 | permissions/mount_format_filesystems=false
134 | permissions/mount_unmount_filesystems=false
135 | permissions/nfc=false
136 | permissions/persistent_activity=false
137 | permissions/process_outgoing_calls=false
138 | permissions/read_calendar=false
139 | permissions/read_call_log=false
140 | permissions/read_contacts=false
141 | permissions/read_external_storage=false
142 | permissions/read_frame_buffer=false
143 | permissions/read_history_bookmarks=false
144 | permissions/read_input_state=false
145 | permissions/read_logs=false
146 | permissions/read_phone_state=false
147 | permissions/read_profile=false
148 | permissions/read_sms=false
149 | permissions/read_social_stream=false
150 | permissions/read_sync_settings=false
151 | permissions/read_sync_stats=false
152 | permissions/read_user_dictionary=false
153 | permissions/reboot=false
154 | permissions/receive_boot_completed=false
155 | permissions/receive_mms=false
156 | permissions/receive_sms=false
157 | permissions/receive_wap_push=false
158 | permissions/record_audio=false
159 | permissions/reorder_tasks=false
160 | permissions/restart_packages=false
161 | permissions/send_respond_via_message=false
162 | permissions/send_sms=false
163 | permissions/set_activity_watcher=false
164 | permissions/set_alarm=false
165 | permissions/set_always_finish=false
166 | permissions/set_animation_scale=false
167 | permissions/set_debug_app=false
168 | permissions/set_orientation=false
169 | permissions/set_pointer_speed=false
170 | permissions/set_preferred_applications=false
171 | permissions/set_process_limit=false
172 | permissions/set_time=false
173 | permissions/set_time_zone=false
174 | permissions/set_wallpaper=false
175 | permissions/set_wallpaper_hints=false
176 | permissions/signal_persistent_processes=false
177 | permissions/status_bar=false
178 | permissions/subscribed_feeds_read=false
179 | permissions/subscribed_feeds_write=false
180 | permissions/system_alert_window=false
181 | permissions/transmit_ir=false
182 | permissions/uninstall_shortcut=false
183 | permissions/update_device_stats=false
184 | permissions/use_credentials=false
185 | permissions/use_sip=false
186 | permissions/vibrate=false
187 | permissions/wake_lock=false
188 | permissions/write_apn_settings=false
189 | permissions/write_calendar=false
190 | permissions/write_call_log=false
191 | permissions/write_contacts=false
192 | permissions/write_external_storage=false
193 | permissions/write_gservices=false
194 | permissions/write_history_bookmarks=false
195 | permissions/write_profile=false
196 | permissions/write_secure_settings=false
197 | permissions/write_settings=false
198 | permissions/write_sms=false
199 | permissions/write_social_stream=false
200 | permissions/write_sync_settings=false
201 | permissions/write_user_dictionary=false
202 |
--------------------------------------------------------------------------------
/demo/project.godot:
--------------------------------------------------------------------------------
1 | ; Engine configuration file.
2 | ; It's best edited using the editor UI and not directly,
3 | ; since the parameters that go here are not all obvious.
4 | ;
5 | ; Format:
6 | ; [section] ; section goes between []
7 | ; param=value ; assign values to parameters
8 |
9 | config_version=5
10 |
11 | [application]
12 |
13 | config/name="Admob Demo"
14 | run/main_scene="res://Main.tscn"
15 | config/features=PackedStringArray("4.4", "GL Compatibility")
16 | config/icon="res://admob.png"
17 |
18 | [debug]
19 |
20 | settings/stdout/verbose_stdout=true
21 |
22 | [display]
23 |
24 | window/size/viewport_width=450
25 | window/size/viewport_height=800
26 | window/stretch/mode="canvas_items"
27 | window/stretch/aspect="ignore"
28 | window/handheld/orientation=1
29 |
30 | [editor_plugins]
31 |
32 | enabled=PackedStringArray("res://addons/AdmobPlugin/plugin.cfg")
33 |
34 | [rendering]
35 |
36 | renderer/rendering_method="gl_compatibility"
37 | renderer/rendering_method.mobile="gl_compatibility"
38 | textures/vram_compression/import_etc2_astc=true
39 |
--------------------------------------------------------------------------------
/demo/scene/Scene2.gd:
--------------------------------------------------------------------------------
1 | #
2 | # © 2024-present https://github.com/cengiz-pz
3 | #
4 |
5 | extends Node
6 |
7 | @onready var admob: Admob = $Admob as Admob
8 | @onready var show_banner_button: Button = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer/ShowBannerButton
9 | @onready var hide_banner_button: Button = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer/HideBannerButton
10 | @onready var reload_banner_button: Button = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer/ReloadBannerButton
11 | @onready var banner_position_option_button: OptionButton = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/PositionHBoxContainer/OptionButton
12 | @onready var banner_size_option_button: OptionButton = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/SizeHBoxContainer/OptionButton
13 | @onready var interstitial_button: Button = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other/InterstitialButton
14 | @onready var rewarded_button: Button = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other/RewardedButton
15 | @onready var rewarded_interstitial_button: Button = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other/RewardedInterstitialButton
16 | @onready var _label: RichTextLabel = $CanvasLayer/CenterContainer/VBoxContainer/RichTextLabel as RichTextLabel
17 | @onready var _geography_option_button: OptionButton = $CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/GeographyHBoxContainer/OptionButton
18 |
19 | var _is_banner_loaded: bool = false
20 | var _is_interstitial_loaded: bool = false
21 | var _is_rewarded_video_loaded: bool = false
22 | var _is_rewarded_interstitial_loaded: bool = false
23 |
24 |
25 | func _ready() -> void:
26 | admob.initialize()
27 |
28 | var __index: int = 0
29 | for __item: String in LoadAdRequest.AdPosition.keys():
30 | banner_position_option_button.add_item(__item)
31 | if __item.casecmp_to(LoadAdRequest.AdPosition.keys()[admob.banner_position]) == 0:
32 | banner_position_option_button.select(__index)
33 | __index += 1
34 |
35 | __index = 0
36 | for __item in LoadAdRequest.AdSize.keys():
37 | banner_size_option_button.add_item(__item)
38 | if __item.casecmp_to(LoadAdRequest.AdSize.keys()[admob.banner_size]) == 0:
39 | banner_size_option_button.select(__index)
40 | __index += 1
41 |
42 |
43 | func _on_admob_initialization_completed(_status_data: InitializationStatus) -> void:
44 | _process_consent_status(admob.get_consent_status())
45 | admob.load_banner_ad()
46 | admob.load_interstitial_ad()
47 | admob.load_rewarded_ad()
48 | admob.load_rewarded_interstitial_ad()
49 |
50 |
51 | func _on_size_button_pressed() -> void:
52 | print(" ------- Get banner size button PRESSED")
53 | if _is_banner_loaded:
54 | _print_to_screen("Banner size: " + str(admob.get_banner_dimension()))
55 |
56 |
57 | func _on_pixel_size_button_pressed() -> void:
58 | print(" ------- Get banner pixel size button PRESSED")
59 | if _is_banner_loaded:
60 | _print_to_screen("Banner size in pixels: " + str(admob.get_banner_dimension_in_pixels()))
61 |
62 |
63 | func _on_show_banner_button_pressed() -> void:
64 | print(" ------- Show banner button PRESSED")
65 | if _is_banner_loaded:
66 | show_banner_button.disabled = true
67 | hide_banner_button.disabled = false
68 | admob.show_banner_ad()
69 |
70 |
71 | func _on_hide_banner_button_pressed() -> void:
72 | print(" ------- Hide banner button PRESSED")
73 | if _is_banner_loaded:
74 | show_banner_button.disabled = false
75 | hide_banner_button.disabled = true
76 | admob.hide_banner_ad()
77 |
78 |
79 | func _on_reload_banner_button_pressed() -> void:
80 | print(" ------- Reload banner button PRESSED")
81 | if _is_banner_loaded:
82 | _is_banner_loaded = false
83 | show_banner_button.disabled = true
84 | reload_banner_button.disabled = true
85 | admob.remove_banner_ad(admob._active_banner_ads[0])
86 | admob.banner_position = LoadAdRequest.AdPosition[banner_position_option_button.get_item_text(banner_position_option_button.selected)]
87 | admob.banner_size = LoadAdRequest.AdSize[banner_size_option_button.get_item_text(banner_size_option_button.selected)]
88 | admob.load_banner_ad()
89 |
90 |
91 | func _on_interstitial_button_pressed() -> void:
92 | print(" ------- Interstitial button PRESSED")
93 | if _is_interstitial_loaded:
94 | _is_interstitial_loaded = false
95 | interstitial_button.disabled = true
96 | admob.show_interstitial_ad()
97 | else:
98 | admob.load_interstitial_ad()
99 |
100 |
101 | func _on_rewarded_video_button_pressed() -> void:
102 | print(" ------- Rewarded button PRESSED")
103 | if _is_rewarded_video_loaded:
104 | _is_rewarded_video_loaded = false
105 | rewarded_button.disabled = true
106 | admob.show_rewarded_ad()
107 | else:
108 | admob.load_rewarded_ad()
109 |
110 |
111 | func _on_rewarded_interstitial_button_pressed() -> void:
112 | print(" ------- Rewarded interstitial button PRESSED")
113 | if _is_rewarded_interstitial_loaded:
114 | _is_rewarded_interstitial_loaded = false
115 | rewarded_interstitial_button.disabled = true
116 | admob.show_rewarded_interstitial_ad()
117 | else:
118 | admob.load_rewarded_interstitial_ad()
119 |
120 |
121 | func _on_reset_consent_button_pressed() -> void:
122 | admob.reset_consent_info()
123 |
124 |
125 | func _on_admob_banner_ad_loaded(ad_id: String) -> void:
126 | _is_banner_loaded = true
127 | show_banner_button.disabled = false
128 | reload_banner_button.disabled = false
129 | _print_to_screen("banner loaded: %s" % ad_id)
130 |
131 |
132 | func _on_admob_banner_ad_refreshed(ad_id: String) -> void:
133 | _print_to_screen("banner refreshed: %s" % ad_id)
134 |
135 |
136 | func _on_admob_banner_ad_failed_to_load(ad_id: String, error_data: LoadAdError) -> void:
137 | _print_to_screen("banner %s failed to load. error: %d, message: %s" %
138 | [ad_id, error_data.get_code(), error_data.get_message()], true)
139 |
140 |
141 | func _on_admob_interstitial_ad_loaded(ad_id: String) -> void:
142 | _is_interstitial_loaded = true
143 | interstitial_button.disabled = false
144 | _print_to_screen("interstitial loaded: %s" % ad_id)
145 |
146 |
147 | func _on_admob_interstitial_ad_failed_to_load(ad_id: String, error_data: LoadAdError) -> void:
148 | _print_to_screen("interstitial %s failed to load. error: %d, message: %s" %
149 | [ad_id, error_data.get_code(), error_data.get_message()], true)
150 |
151 |
152 | func _on_admob_interstitial_ad_refreshed(ad_id: String) -> void:
153 | _print_to_screen("interstitial refreshed: %s" % ad_id)
154 |
155 |
156 | func _on_admob_interstitial_ad_dismissed_full_screen_content(ad_id: String) -> void:
157 | _print_to_screen("interstitial closed: %s" % ad_id)
158 |
159 |
160 | func _on_admob_rewarded_ad_loaded(ad_id: String) -> void:
161 | _is_rewarded_video_loaded = true
162 | rewarded_button.disabled = false
163 | _print_to_screen("rewarded video loaded: %s" % ad_id)
164 |
165 |
166 | func _on_admob_rewarded_ad_failed_to_load(ad_id: String, error_data: LoadAdError) -> void:
167 | _print_to_screen("rewarded video %s failed to load. error: %d, message: %s" %
168 | [ad_id, error_data.get_code(), error_data.get_message()], true)
169 |
170 |
171 | func _on_admob_rewarded_ad_user_earned_reward(ad_id: String, reward_data: RewardItem) -> void:
172 | _print_to_screen("user rewarded for rewarded ad '%s' with %d %s" %
173 | [ad_id, reward_data.get_amount(), reward_data.get_type()])
174 |
175 |
176 | func _on_admob_rewarded_interstitial_ad_loaded(ad_id: String) -> void:
177 | _is_rewarded_interstitial_loaded = true
178 | rewarded_interstitial_button.disabled = false
179 | _print_to_screen("rewarded interstitial loaded: %s" % ad_id)
180 |
181 |
182 | func _on_admob_rewarded_interstitial_ad_failed_to_load(ad_id: String, error_data: LoadAdError) -> void:
183 | _print_to_screen("rewarded interstitial %s failed to load. error: %d, message: %s" %
184 | [ad_id, error_data.get_code(), error_data.get_message()], true)
185 |
186 |
187 | func _on_admob_rewarded_interstitial_ad_user_earned_reward(ad_id: String, reward_data: RewardItem) -> void:
188 | _print_to_screen("user rewarded for rewarded interstitial ad '%s' with %d %s" %
189 | [ad_id, reward_data.get_amount(), reward_data.get_type()])
190 |
191 |
192 | func _on_admob_consent_info_updated() -> void:
193 | _print_to_screen("consent info updated")
194 | _process_consent_status(admob.get_consent_status())
195 |
196 |
197 | func _on_admob_consent_info_update_failed(a_error_data: FormError) -> void:
198 | _print_to_screen("consent info failed to update: %s" % a_error_data.get_message())
199 |
200 |
201 | func _process_consent_status(a_consent_status: int) -> void:
202 | _print_to_screen("_process_consent_status(): consent status = %d" % a_consent_status)
203 | match a_consent_status:
204 | ConsentInformation.ConsentStatus.UNKNOWN:
205 | _print_to_screen("consent status is unknown")
206 | admob.update_consent_info(ConsentRequestParameters.new()
207 | .set_debug_geography(ConsentRequestParameters.DebugGeography.values()[_geography_option_button.selected])
208 | .add_test_device_hashed_id(OS.get_unique_id()))
209 | ConsentInformation.ConsentStatus.NOT_REQUIRED:
210 | _print_to_screen("consent is not required")
211 | ConsentInformation.ConsentStatus.REQUIRED:
212 | _print_to_screen("consent is required")
213 | admob.load_consent_form()
214 | ConsentInformation.ConsentStatus.OBTAINED:
215 | _print_to_screen("consent has already been obtained")
216 |
217 |
218 | func _on_admob_consent_form_loaded() -> void:
219 | _print_to_screen("consent form has been loaded")
220 | admob.show_consent_form()
221 |
222 |
223 | func _on_admob_consent_form_failed_to_load(a_error_data: FormError) -> void:
224 | _print_to_screen("consent form failed to load %s" % a_error_data.get_message())
225 |
226 |
227 | func _on_admob_consent_form_dismissed(a_error_data: FormError) -> void:
228 | _print_to_screen("consent form has been dismissed %s" % a_error_data.get_message())
229 |
230 |
231 | func _on_update_consent_info_button_pressed() -> void:
232 | print("selected consent geography: %d" % _geography_option_button.selected)
233 | admob.update_consent_info(ConsentRequestParameters.new()
234 | .set_debug_geography(ConsentRequestParameters.DebugGeography.values()[_geography_option_button.selected])
235 | .add_test_device_hashed_id(OS.get_unique_id()))
236 |
237 |
238 | func _on_main_scene_button_pressed() -> void:
239 | get_tree().change_scene_to_file("res://Main.tscn")
240 |
241 |
242 | func _print_to_screen(a_message: String, a_is_error: bool = false) -> void:
243 | _label.add_text("%s\n\n" % a_message)
244 | if a_is_error:
245 | printerr(a_message)
246 | else:
247 | print(a_message)
248 |
--------------------------------------------------------------------------------
/demo/scene/Scene2.gd.uid:
--------------------------------------------------------------------------------
1 | uid://d1sj8uyx056mr
2 |
--------------------------------------------------------------------------------
/demo/scene/Scene2.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://ob3wnlx8tywe"]
2 |
3 | [ext_resource type="Script" uid="uid://d1sj8uyx056mr" path="res://scene/Scene2.gd" id="1_vwd77"]
4 | [ext_resource type="Texture2D" uid="uid://bdjwuj5g73wl3" path="res://admob.png" id="2_uma2v"]
5 | [ext_resource type="Script" uid="uid://b8ayp8io5uvmn" path="res://addons/AdmobPlugin/Admob.gd" id="3_2ewgo"]
6 |
7 | [node name="Main" type="Node"]
8 | script = ExtResource("1_vwd77")
9 |
10 | [node name="CanvasLayer" type="CanvasLayer" parent="."]
11 |
12 | [node name="CenterContainer" type="CenterContainer" parent="CanvasLayer"]
13 | anchors_preset = 15
14 | anchor_right = 1.0
15 | anchor_bottom = 1.0
16 | grow_horizontal = 2
17 | grow_vertical = 2
18 | size_flags_horizontal = 3
19 | size_flags_vertical = 3
20 |
21 | [node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/CenterContainer"]
22 | custom_minimum_size = Vector2(400, 0)
23 | layout_mode = 2
24 | theme_override_constants/separation = 20
25 |
26 | [node name="TextureRect" type="TextureRect" parent="CanvasLayer/CenterContainer/VBoxContainer"]
27 | custom_minimum_size = Vector2(0, 128)
28 | layout_mode = 2
29 | texture = ExtResource("2_uma2v")
30 | expand_mode = 3
31 | stretch_mode = 5
32 |
33 | [node name="HBoxContainer" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer"]
34 | layout_mode = 2
35 |
36 | [node name="Label" type="Label" parent="CanvasLayer/CenterContainer/VBoxContainer/HBoxContainer"]
37 | layout_mode = 2
38 | size_flags_horizontal = 3
39 | theme_override_font_sizes/font_size = 24
40 | text = "Admob Demo (Scene 2)"
41 | horizontal_alignment = 1
42 |
43 | [node name="MainSceneButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/HBoxContainer"]
44 | layout_mode = 2
45 | text = "Switch"
46 |
47 | [node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer"]
48 | layout_mode = 2
49 | theme_override_constants/separation = 11
50 |
51 | [node name="TabContainer" type="TabContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer"]
52 | custom_minimum_size = Vector2(0, 165)
53 | layout_mode = 2
54 | current_tab = 0
55 |
56 | [node name="Banner" type="VBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer"]
57 | layout_mode = 2
58 | theme_override_constants/separation = 6
59 | metadata/_tab_index = 0
60 |
61 | [node name="PositionHBoxContainer" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner"]
62 | layout_mode = 2
63 | theme_override_constants/separation = 10
64 |
65 | [node name="Label" type="Label" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/PositionHBoxContainer"]
66 | layout_mode = 2
67 | text = "Banner Position:"
68 |
69 | [node name="OptionButton" type="OptionButton" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/PositionHBoxContainer"]
70 | layout_mode = 2
71 | size_flags_horizontal = 3
72 |
73 | [node name="SizeHBoxContainer" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner"]
74 | layout_mode = 2
75 | theme_override_constants/separation = 10
76 |
77 | [node name="Label" type="Label" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/SizeHBoxContainer"]
78 | layout_mode = 2
79 | text = "Banner Size:"
80 |
81 | [node name="OptionButton" type="OptionButton" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/SizeHBoxContainer"]
82 | layout_mode = 2
83 | size_flags_horizontal = 3
84 |
85 | [node name="SizeButtonHBoxContainer" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner"]
86 | layout_mode = 2
87 | theme_override_constants/separation = 30
88 |
89 | [node name="SizeButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/SizeButtonHBoxContainer"]
90 | layout_mode = 2
91 | size_flags_horizontal = 3
92 | text = "Get Size"
93 |
94 | [node name="PixelSizeButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/SizeButtonHBoxContainer"]
95 | layout_mode = 2
96 | size_flags_horizontal = 3
97 | text = "Get Size In Pixels"
98 |
99 | [node name="ButtonsHBoxContainer" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner"]
100 | layout_mode = 2
101 | theme_override_constants/separation = 45
102 |
103 | [node name="ShowBannerButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer"]
104 | custom_minimum_size = Vector2(100, 0)
105 | layout_mode = 2
106 | disabled = true
107 | text = "Show"
108 |
109 | [node name="HideBannerButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer"]
110 | custom_minimum_size = Vector2(100, 0)
111 | layout_mode = 2
112 | disabled = true
113 | text = "Hide"
114 |
115 | [node name="ReloadBannerButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer"]
116 | custom_minimum_size = Vector2(100, 0)
117 | layout_mode = 2
118 | disabled = true
119 | text = "Reload"
120 |
121 | [node name="Other" type="VBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer"]
122 | visible = false
123 | layout_mode = 2
124 | theme_override_constants/separation = 15
125 | metadata/_tab_index = 1
126 |
127 | [node name="InterstitialButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other"]
128 | layout_mode = 2
129 | disabled = true
130 | text = "Show Interstitial Ad"
131 |
132 | [node name="RewardedButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other"]
133 | layout_mode = 2
134 | disabled = true
135 | text = "Show Rewarded Ad"
136 |
137 | [node name="RewardedInterstitialButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other"]
138 | layout_mode = 2
139 | disabled = true
140 | text = "Show Rewarded Interstitial Ad"
141 |
142 | [node name="GeographyHBoxContainer" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer"]
143 | layout_mode = 2
144 |
145 | [node name="Label" type="Label" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/GeographyHBoxContainer"]
146 | layout_mode = 2
147 | text = "Debug Geography: "
148 |
149 | [node name="OptionButton" type="OptionButton" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/GeographyHBoxContainer"]
150 | layout_mode = 2
151 | size_flags_horizontal = 3
152 | selected = 1
153 | item_count = 3
154 | popup/item_0/text = "DISABLED"
155 | popup/item_0/id = 0
156 | popup/item_1/text = "EEA"
157 | popup/item_1/id = 1
158 | popup/item_2/text = "NOT EEA"
159 | popup/item_2/id = 2
160 |
161 | [node name="HBoxContainer" type="HBoxContainer" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer"]
162 | layout_mode = 2
163 | theme_override_constants/separation = 10
164 |
165 | [node name="Label" type="Label" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/HBoxContainer"]
166 | layout_mode = 2
167 | text = "Consent Info: "
168 |
169 | [node name="UpdateConsentInfoButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/HBoxContainer"]
170 | layout_mode = 2
171 | size_flags_horizontal = 3
172 | text = "Update"
173 |
174 | [node name="ResetConsentButton" type="Button" parent="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/HBoxContainer"]
175 | layout_mode = 2
176 | size_flags_horizontal = 3
177 | text = "Reset"
178 |
179 | [node name="RichTextLabel" type="RichTextLabel" parent="CanvasLayer/CenterContainer/VBoxContainer"]
180 | custom_minimum_size = Vector2(0, 210)
181 | layout_mode = 2
182 | theme_override_font_sizes/normal_font_size = 14
183 | scroll_following = true
184 |
185 | [node name="Admob" type="Node" parent="."]
186 | script = ExtResource("3_2ewgo")
187 | debug_application_id = "ca-app-pub-3940256099942544~3347511713"
188 | debug_banner_id = "ca-app-pub-3940256099942544/6300978111"
189 | debug_interstitial_id = "ca-app-pub-3940256099942544/1033173712"
190 | debug_rewarded_id = "ca-app-pub-3940256099942544/5224354917"
191 | debug_rewarded_interstitial_id = "ca-app-pub-3940256099942544/5354046379"
192 |
193 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/HBoxContainer/MainSceneButton" to="." method="_on_main_scene_button_pressed"]
194 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/SizeButtonHBoxContainer/SizeButton" to="." method="_on_size_button_pressed"]
195 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/SizeButtonHBoxContainer/PixelSizeButton" to="." method="_on_pixel_size_button_pressed"]
196 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer/ShowBannerButton" to="." method="_on_show_banner_button_pressed"]
197 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer/HideBannerButton" to="." method="_on_hide_banner_button_pressed"]
198 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Banner/ButtonsHBoxContainer/ReloadBannerButton" to="." method="_on_reload_banner_button_pressed"]
199 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other/InterstitialButton" to="." method="_on_interstitial_button_pressed"]
200 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other/RewardedButton" to="." method="_on_rewarded_video_button_pressed"]
201 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/TabContainer/Other/RewardedInterstitialButton" to="." method="_on_rewarded_interstitial_button_pressed"]
202 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/HBoxContainer/UpdateConsentInfoButton" to="." method="_on_update_consent_info_button_pressed"]
203 | [connection signal="pressed" from="CanvasLayer/CenterContainer/VBoxContainer/VBoxContainer/HBoxContainer/ResetConsentButton" to="." method="_on_reset_consent_button_pressed"]
204 | [connection signal="banner_ad_failed_to_load" from="Admob" to="." method="_on_admob_banner_ad_failed_to_load"]
205 | [connection signal="banner_ad_loaded" from="Admob" to="." method="_on_admob_banner_ad_loaded"]
206 | [connection signal="banner_ad_refreshed" from="Admob" to="." method="_on_admob_banner_ad_refreshed"]
207 | [connection signal="consent_form_dismissed" from="Admob" to="." method="_on_admob_consent_form_dismissed"]
208 | [connection signal="consent_form_failed_to_load" from="Admob" to="." method="_on_admob_consent_form_failed_to_load"]
209 | [connection signal="consent_form_loaded" from="Admob" to="." method="_on_admob_consent_form_loaded"]
210 | [connection signal="consent_info_update_failed" from="Admob" to="." method="_on_admob_consent_info_update_failed"]
211 | [connection signal="consent_info_updated" from="Admob" to="." method="_on_admob_consent_info_updated"]
212 | [connection signal="initialization_completed" from="Admob" to="." method="_on_admob_initialization_completed"]
213 | [connection signal="interstitial_ad_dismissed_full_screen_content" from="Admob" to="." method="_on_admob_interstitial_ad_dismissed_full_screen_content"]
214 | [connection signal="interstitial_ad_failed_to_load" from="Admob" to="." method="_on_admob_interstitial_ad_failed_to_load"]
215 | [connection signal="interstitial_ad_loaded" from="Admob" to="." method="_on_admob_interstitial_ad_loaded"]
216 | [connection signal="interstitial_ad_refreshed" from="Admob" to="." method="_on_admob_interstitial_ad_refreshed"]
217 | [connection signal="rewarded_ad_failed_to_load" from="Admob" to="." method="_on_admob_rewarded_ad_failed_to_load"]
218 | [connection signal="rewarded_ad_loaded" from="Admob" to="." method="_on_admob_rewarded_ad_loaded"]
219 | [connection signal="rewarded_ad_user_earned_reward" from="Admob" to="." method="_on_admob_rewarded_ad_user_earned_reward"]
220 | [connection signal="rewarded_interstitial_ad_failed_to_load" from="Admob" to="." method="_on_admob_rewarded_interstitial_ad_failed_to_load"]
221 | [connection signal="rewarded_interstitial_ad_loaded" from="Admob" to="." method="_on_admob_rewarded_interstitial_ad_loaded"]
222 | [connection signal="rewarded_interstitial_ad_user_earned_reward" from="Admob" to="." method="_on_admob_rewarded_interstitial_ad_user_earned_reward"]
223 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Kotlin code style for this project: "official" or "obsolete":
19 | kotlin.code.style=official
20 | # Enables namespacing of each library's R class so that its R class includes only the
21 | # resources declared in the library itself and none from the library's dependencies,
22 | # thereby reducing the size of the R class for that library
23 | android.nonTransitiveRClass=true
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | //
2 | // © 2024-present https://github.com/cengiz-pz
3 | //
4 |
5 | pluginManagement {
6 | repositories {
7 | gradlePluginPortal()
8 | google()
9 | mavenCentral()
10 | }
11 | }
12 |
13 | dependencyResolutionManagement {
14 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
15 | repositories {
16 | google()
17 | mavenCentral()
18 | }
19 | }
20 |
21 | rootProject.name = "godot-android-admob-plugin"
22 |
23 | include(":admob")
24 |
--------------------------------------------------------------------------------