├── .gitignore ├── LICENSE ├── README.md ├── admob ├── SCsub ├── android │ ├── AndroidManifestChunk.xml │ └── GodotAdMob.java ├── config-firebase.py ├── config.py ├── ios │ ├── lib │ │ ├── put_GoogleAppMeasurement.framework_here │ │ ├── put_GoogleMobileAds.framework_here │ │ ├── put_GoogleUtilities.xcframework_here │ │ ├── put_PromisesObjC.xcframework_here │ │ └── put_nanopb.xcframework_here │ └── src │ │ ├── AdmobBanner.h │ │ ├── AdmobBanner.mm │ │ ├── AdmobInterstitial.h │ │ ├── AdmobInterstitial.mm │ │ ├── AdmobRewarded.h │ │ ├── AdmobRewarded.mm │ │ ├── godotAdmob.h │ │ └── godotAdmob.mm ├── register_types.cpp └── register_types.h ├── examples ├── README.md ├── godot-2 │ ├── engine.cfg │ ├── icon.png │ ├── main.gd │ └── main.tscn └── godot-3 │ ├── icon.png │ ├── main.gd │ ├── main.tscn │ └── project.godot ├── issue_template.md └── templates ├── README.md ├── android_debug.apk └── android_release.apk /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | .DS_Store 3 | *.import 4 | .import 5 | *.o 6 | *.d 7 | *.framework 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Javier López Úbeda 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 | AdMob 2 | ===== 3 | This is the AdMob module for Godot Engine (https://github.com/okamstudio/godot) 4 | - Android & iOS 5 | - Banner 6 | - Interstitial 7 | - Rewarded Video 8 | 9 | How to use 10 | ---------- 11 | 12 | ### Android 13 | To use this module you'll need a custom template for Android. You can build it by yourself or download a precompiled one. 14 | Another option available for Godot 3.2+ is the [new Android plugin system](https://godotengine.org/article/godot-3-2-will-get-new-android-plugin-system), much easier to use (no recompilation needed). You can find a port of this module using this system [here](https://github.com/Shin-NiL/Godot-Android-Admob-Plugin). 15 | 16 | #### Compiling the template (First Option) 17 | This is harder, but you'll have more control over the building process. You can, for example, include any other module you want. 18 | For that, do the following steps: 19 | - Clone or download this repository. 20 | - Clone or download the [Godot Engine repository](https://github.com/godotengine/godot/). One important note here is that this must match the same version of the Godot editor you're using to develop your game. 21 | - Drop the "admob" directory inside the "modules" directory on the Godot source. 22 | - Recompile the android export template following the [official instructions](http://docs.godotengine.org/en/latest/reference/compiling_for_android.html#compiling-export-templates). 23 | 24 | #### Using precompiled templates (Second Option) 25 | If you don't want or can't build the template by yourself, you can find a precompiled template with this module [here](https://github.com/Shin-NiL/godot-custom-mobile-template). Go to the release tab and download the zip file. 26 | 27 | #### Export configuration 28 | - In your project goto Export > Target > Android: 29 | - Options: 30 | - Custom Package: 31 | - place the template apk you had compiled (or downloaded) 32 | - Permissions on: 33 | - Access Network State 34 | - Internet 35 | ### iOS 36 | - Drop the "admob" directory inside the "modules" directory on the Godot source; 37 | - Download and extract the [Google Mobile Ads SDK](https://developers.google.com/admob/ios/download) **(>= 7.60.0)** inside the directory "admob/ios/lib"; (If you are unable to download the version informed above, you can alternatively download it through [Cocoapods](https://cocoapods.org/#install) or [HERE](https://srv-file6.gofile.io/download/iLaAUS/GoogleMobileAds_framework_7_60_0.zip)) 38 | - Follow the instructions provided by Google to [add the GADApplicationIdentifier to your Info.plist in XCode](https://developers.google.com/admob/ios/quick-start#update_your_infoplist). It is not necessary to add the frameworks to your XCode project, as they will be compiled and linked into the godot engine directly. 39 | - [Recompile the iOS export template](http://docs.godotengine.org/en/stable/development/compiling/compiling_for_ios.html). (If you get some error, check this [issue](https://github.com/kloder-games/godot-admob/issues/87)) 40 | 41 | Configuring your game 42 | --------------------- 43 | 44 | ### Android 45 | To enable the module on Android, add the path to the module to the "modules" property on the [android] section of your ```engine.cfg``` file (Godot 2) or ```project.godot``` (Godot 3). It should look like this: 46 | 47 | [android] 48 | modules="org/godotengine/godot/GodotAdMob" 49 | 50 | If you have more separate by comma. 51 | 52 | ### iOS 53 | Follow the [exporting to iOS official documentation](http://docs.godotengine.org/en/stable/learning/workflow/export/exporting_for_ios.html). 54 | 55 | #### Godot 2 56 | Just make sure you're using your custom template (compiled in the previous step), for that rename it to "godot_opt.iphone" and replace the file with same name inside the Xcode project. 57 | 58 | #### Godot 3 59 | - Tutorial: https://www.youtube.com/watch?v=s5sNrOM3Oeo 60 | - Export your project from Godot, it'll create an Xcode project; 61 | - Copy the library (.a) you have compiled following the official documentation inside the exported Xcode project. You must override the 'your_project_name.a' file with this file. 62 | - Copy the following frameworks inside the exported Xcode project folder and link it using the "Link Binary with Libraries" option. In the case of xcframework, framework folder exists in the folder like `GoogleUtilities.xcframework/ios-armv7_arm64/GoogleUtilities.framework`; 63 | - GoogleMobileAds.framework 64 | - GoogleAppMeasurement.framework 65 | - GoogleUtilities.framework 66 | - PromisesObjC.framework 67 | - nanopb.framework 68 | - Add the following frameworks to the project: 69 | - StoreKit 70 | - GameKit 71 | - CoreVideo 72 | - AdSupport 73 | - MessageUI 74 | - CoreTelephony 75 | - CFNetwork 76 | - MobileCoreServices 77 | - SQLite (libsqlite3.0.tbd) 78 | - If you are using the version 7.65.0 >=, then also add this framework? 79 | - JavaScriptCore 80 | - Add the -ObjC linker flag to Other Linker Flags in your project's build settings: 81 | ![-ObjC](https://developers.google.com/admob/images/ios/objc_linker_flag.png) 82 | - Update your GAMENAME-Info.plist file, add a GADApplicationIdentifier key with a string value of your [AdMob app ID](https://support.google.com/admob/answer/7356431): 83 | ![plist](https://i.imgur.com/1tcKXx5.png) 84 | 85 | 86 | API Reference (Android & iOS) 87 | ------------- 88 | 89 | The following methods are available: 90 | ```python 91 | 92 | # Init AdMob 93 | # @param bool isReal Show real ad or test ad 94 | # @param int instance_id The instance id from Godot (get_instance_ID()) 95 | init(isReal, instance_id) 96 | 97 | # Init AdMob with additional Content Rating parameters (Android and iOS) 98 | # @param bool isReal Show real ad or test ad 99 | # @param int instance_id The instance id from Godot (get_instance_ID()) 100 | # @param boolean isForChildDirectedTreatment If isForChildDirectedTreatment is true, maxAdContetRating will be ignored (your maxAdContentRating would can not be other than "G") 101 | # @param boolean isPersonalized Ads are personalized by default, GDPR compliance within the European Economic Area may require you to disable personalization." 102 | # @param String maxAdContentRating It's value must be "G", "PG", "T" or "MA". If the rating of your app in Play Console and your config of maxAdContentRating in AdMob are not matched, your app can be banned by Google. 103 | initWithContentRating(isReal, instance_id, isForChildDirectedTreatment, isPersonalized, maxAdContentRating) 104 | 105 | 106 | # Banner Methods 107 | # -------------- 108 | 109 | # Load Banner Ads (and show inmediatly) 110 | # @param String id The banner unit id 111 | # @param boolean isTop Show the banner on top or bottom 112 | loadBanner(id, isTop) 113 | 114 | # Show the banner 115 | showBanner() 116 | 117 | # Hide the banner 118 | hideBanner() 119 | 120 | # Resize the banner (when orientation change for example) 121 | resize() 122 | 123 | # Get the Banner width 124 | # @return int Banner width 125 | getBannerWidth() 126 | 127 | # Get the Banner height 128 | # @return int Banner height 129 | getBannerHeight() 130 | 131 | # Callback on ad loaded (Banner) 132 | _on_admob_ad_loaded() 133 | 134 | # Callback on ad network error (Banner) 135 | _on_admob_network_error() 136 | 137 | # Callback for banner on ad failed to load (other than network error) 138 | _on_admob_banner_failed_to_load() 139 | 140 | # Interstitial Methods 141 | # -------------------- 142 | 143 | # Load Interstitial Ads 144 | # @param String id The interstitial unit id 145 | loadInterstitial(id) 146 | 147 | # Show the interstitial ad 148 | showInterstitial() 149 | 150 | # Callback for interstitial ad fail on load 151 | _on_interstitial_not_loaded() 152 | 153 | # Callback for interstitial loaded 154 | _on_interstitial_loaded 155 | 156 | # Callback for insterstitial ad close action 157 | _on_interstitial_close() 158 | 159 | # Rewarded Videos Methods 160 | # ----------------------- 161 | 162 | # Load rewarded videos ads 163 | # @param String id The rewarded video unit id 164 | loadRewardedVideo(id) 165 | 166 | # Show the rewarded video ad 167 | showRewardedVideo() 168 | 169 | # Callback for rewarded video ad left application 170 | _on_rewarded_video_ad_left_application() 171 | 172 | # Callback for rewarded video ad closed 173 | _on_rewarded_video_ad_closed() 174 | 175 | # Callback for rewarded video ad failed to load 176 | # @param int errorCode the code of error 177 | _on_rewarded_video_ad_failed_to_load(errorCode) 178 | 179 | # Callback for rewarded video ad loaded 180 | _on_rewarded_video_ad_loaded() 181 | 182 | # Callback for rewarded video ad opened 183 | _on_rewarded_video_ad_opened() 184 | 185 | # Callback for rewarded video ad reward user 186 | # @param String currency The reward item description, ex: coin 187 | # @param int amount The reward item amount 188 | _on_rewarded(currency, amount) 189 | 190 | # Callback for rewarded video ad started do play 191 | _on_rewarded_video_started() 192 | ``` 193 | 194 | Known Issues 195 | -------------- 196 | * You can't use Rewarded Video and any other ad type (Banner and/or Interstitial) at same time on iOS or your app will crash with the error ```Multiple locks on web thread not allowed``` when the Reward is closed. To fix this, we need help from an iOS developer as I don't have any Apple hardware to do it by myself. You can see more details about this issue [here](https://github.com/kloder-games/godot-admob/issues/53). You can find a workaround for this issue [here](https://github.com/kloder-games/godot-admob/issues/53#issuecomment-501540139). 197 | 198 | 199 | Troubleshooting 200 | -------------- 201 | 202 | * First of all, please make sure you're able to compile the custom template without the Admob module, this way we can isolate the cause of the issue. 203 | 204 | * Using the Xcode debug console for iOS and logcat for Android is the best way to troubleshoot most issues. You can filter Godot only messages with logcat using the command: ```adb logcat -s godot``` 205 | 206 | * _ERROR_CODE_NO_FILL_ is a common issue with Admob, but out of the scope to this module. Here's the description on the API page: [ERROR_CODE_NO_FILL: The ad request was successful, but no ad was returned due to lack of ad inventory.](https://developers.google.com/android/reference/com/google/android/gms/ads/AdRequest.html#ERROR_CODE_NO_FILL) 207 | 208 | * If you're getting the error ```Undefined symbols for architecture armv7``` compiling for iOS, you should try open up the project in xcode, go to "General" tab, remove "GoogleMobileAds.framework" from frameworks, then re-add it. Should build then. Also, make sure you have directory godot/modules/admob/ios/lib added to framework search path (“Build Settings”). More info [here](https://github.com/kloder-games/godot-admob/issues/90#issuecomment-501608259). 209 | 210 | References 211 | ------------- 212 | Based on the work of: 213 | * https://github.com/Mavhod/GodotAdmob 214 | 215 | License 216 | ------------- 217 | MIT license 218 | -------------------------------------------------------------------------------- /admob/SCsub: -------------------------------------------------------------------------------- 1 | 2 | Import('env') 3 | 4 | sources = [ 5 | 'register_types.cpp', 6 | 'ios/src/godotAdmob.mm', 7 | 'ios/src/AdmobBanner.mm', 8 | 'ios/src/AdmobInterstitial.mm', 9 | 'ios/src/AdmobRewarded.mm' 10 | ] 11 | 12 | if (env["platform"] == "iphone"): 13 | env.add_source_files(env.modules_sources, sources) 14 | 15 | -------------------------------------------------------------------------------- /admob/android/AndroidManifestChunk.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /admob/android/GodotAdMob.java: -------------------------------------------------------------------------------- 1 | package org.godotengine.godot; 2 | 3 | import com.google.android.gms.ads.*; 4 | 5 | 6 | import java.security.MessageDigest; 7 | import java.security.NoSuchAlgorithmException; 8 | 9 | import android.app.Activity; 10 | import android.widget.FrameLayout; 11 | import android.view.ViewGroup.LayoutParams; 12 | import android.provider.Settings; 13 | import android.graphics.Color; 14 | import android.util.Log; 15 | import java.util.Locale; 16 | import android.view.Gravity; 17 | import android.view.View; 18 | import android.os.Bundle; 19 | 20 | import com.google.android.gms.ads.AdRequest; 21 | import com.google.android.gms.ads.MobileAds; 22 | import com.google.ads.mediation.admob.AdMobAdapter; 23 | import com.google.android.gms.ads.reward.RewardItem; 24 | import com.google.android.gms.ads.reward.RewardedVideoAd; 25 | import com.google.android.gms.ads.reward.RewardedVideoAdListener; 26 | 27 | public class GodotAdMob extends Godot.SingletonBase 28 | { 29 | 30 | private Activity activity = null; // The main activity of the game 31 | private int instance_id = 0; 32 | 33 | private InterstitialAd interstitialAd = null; // Interstitial object 34 | private AdView adView = null; // Banner view 35 | 36 | private boolean isReal = false; // Store if is real or not 37 | private boolean isForChildDirectedTreatment = false; // Store if is children directed treatment desired 38 | private boolean isPersonalized = true; // ads are personalized by default, GDPR compliance within the European Economic Area may require you to disable personalization. 39 | private String maxAdContentRating = ""; // Store maxAdContentRating ("G", "PG", "T" or "MA") 40 | private Bundle extras = null; 41 | 42 | 43 | private FrameLayout layout = null; // Store the layout 44 | private FrameLayout.LayoutParams adParams = null; // Store the layout params 45 | 46 | private RewardedVideoAd rewardedVideoAd = null; // Rewarded Video object 47 | 48 | /* Init 49 | * ********************************************************************** */ 50 | 51 | /** 52 | * Prepare for work with AdMob 53 | * @param boolean isReal Tell if the enviroment is for real or test 54 | * @param int gdscript instance id 55 | */ 56 | public void init(boolean isReal, int instance_id) { 57 | this.initWithContentRating(isReal, instance_id, false, true, ""); 58 | } 59 | /** 60 | * Init with content rating additional options 61 | * @param boolean isReal Tell if the enviroment is for real or test 62 | * @param int gdscript instance id 63 | * @param boolean isPersonalized If ads should be personalized or not. 64 | * GDPR compliance within the European Economic Area requires that you 65 | * disable ad personalization if the user does not wish to opt into 66 | * ad personalization. 67 | * @param String maxAdContentRating must be "G", "PG", "T" or "MA" 68 | */ 69 | public void initWithContentRating(boolean isReal, int instance_id, boolean isForChildDirectedTreatment, boolean isPersonalized, String maxAdContentRating) 70 | { 71 | this.isReal = isReal; 72 | this.instance_id = instance_id; 73 | this.isForChildDirectedTreatment = isForChildDirectedTreatment; 74 | this.isPersonalized = isPersonalized; 75 | this.maxAdContentRating = maxAdContentRating; 76 | if (maxAdContentRating != null && maxAdContentRating != "") 77 | { 78 | extras = new Bundle(); 79 | extras.putString("max_ad_content_rating", maxAdContentRating); 80 | } 81 | if(!isPersonalized) 82 | { 83 | // https://developers.google.com/admob/android/eu-consent#forward_consent_to_the_google_mobile_ads_sdk 84 | if(extras == null) 85 | { 86 | extras = new Bundle(); 87 | } 88 | extras.putString("npa", "1"); 89 | } 90 | Log.d("godot", "AdMob: init with content rating options"); 91 | } 92 | 93 | 94 | 95 | /** 96 | * Returns AdRequest object constructed considering the parameters set in constructor of this class. 97 | * @return AdRequest object 98 | */ 99 | private AdRequest getAdRequest() 100 | { 101 | AdRequest.Builder adBuilder = new AdRequest.Builder(); 102 | AdRequest adRequest; 103 | if (!this.isForChildDirectedTreatment && extras != null) 104 | { 105 | adBuilder.addNetworkExtrasBundle(AdMobAdapter.class, extras); 106 | } 107 | if (this.isForChildDirectedTreatment) 108 | { 109 | adBuilder.tagForChildDirectedTreatment(true); 110 | } 111 | if (!isReal) { 112 | adBuilder.addTestDevice(AdRequest.DEVICE_ID_EMULATOR); 113 | adBuilder.addTestDevice(getAdmobDeviceId()); 114 | } 115 | adRequest = adBuilder.build(); 116 | return adRequest; 117 | } 118 | 119 | /* Rewarded Video 120 | * ********************************************************************** */ 121 | private void initRewardedVideo() 122 | { 123 | activity.runOnUiThread(new Runnable() 124 | { 125 | @Override public void run() 126 | { 127 | MobileAds.initialize(activity); 128 | rewardedVideoAd = MobileAds.getRewardedVideoAdInstance(activity); 129 | rewardedVideoAd.setRewardedVideoAdListener(new RewardedVideoAdListener() 130 | { 131 | @Override 132 | public void onRewardedVideoAdLeftApplication() { 133 | Log.w("godot", "AdMob: onRewardedVideoAdLeftApplication"); 134 | GodotLib.calldeferred(instance_id, "_on_rewarded_video_ad_left_application", new Object[] { }); 135 | } 136 | 137 | @Override 138 | public void onRewardedVideoAdClosed() { 139 | Log.w("godot", "AdMob: onRewardedVideoAdClosed"); 140 | GodotLib.calldeferred(instance_id, "_on_rewarded_video_ad_closed", new Object[] { }); 141 | } 142 | 143 | @Override 144 | public void onRewardedVideoAdFailedToLoad(int errorCode) { 145 | Log.w("godot", "AdMob: onRewardedVideoAdFailedToLoad. errorCode: " + errorCode); 146 | GodotLib.calldeferred(instance_id, "_on_rewarded_video_ad_failed_to_load", new Object[] { errorCode }); 147 | } 148 | 149 | @Override 150 | public void onRewardedVideoAdLoaded() { 151 | Log.w("godot", "AdMob: onRewardedVideoAdLoaded"); 152 | GodotLib.calldeferred(instance_id, "_on_rewarded_video_ad_loaded", new Object[] { }); 153 | } 154 | 155 | @Override 156 | public void onRewardedVideoAdOpened() { 157 | Log.w("godot", "AdMob: onRewardedVideoAdOpened"); 158 | GodotLib.calldeferred(instance_id, "_on_rewarded_video_ad_opened", new Object[] { }); 159 | } 160 | 161 | @Override 162 | public void onRewarded(RewardItem reward) { 163 | Log.w("godot", "AdMob: " + String.format(" onRewarded! currency: %s amount: %d", reward.getType(), 164 | reward.getAmount())); 165 | GodotLib.calldeferred(instance_id, "_on_rewarded", new Object[] { reward.getType(), reward.getAmount() }); 166 | } 167 | 168 | @Override 169 | public void onRewardedVideoStarted() { 170 | Log.w("godot", "AdMob: onRewardedVideoStarted"); 171 | GodotLib.calldeferred(instance_id, "_on_rewarded_video_started", new Object[] { }); 172 | } 173 | 174 | @Override 175 | public void onRewardedVideoCompleted() { 176 | Log.w("godot", "AdMob: onRewardedVideoCompleted"); 177 | GodotLib.calldeferred(instance_id, "_on_rewarded_video_completed", new Object[] { }); 178 | } 179 | }); 180 | 181 | } 182 | }); 183 | 184 | } 185 | 186 | /** 187 | * Load a Rewarded Video 188 | * @param String id AdMod Rewarded video ID 189 | */ 190 | public void loadRewardedVideo(final String id) { 191 | activity.runOnUiThread(new Runnable() 192 | { 193 | @Override public void run() 194 | { 195 | if (rewardedVideoAd == null) { 196 | initRewardedVideo(); 197 | } 198 | 199 | if (!rewardedVideoAd.isLoaded()) { 200 | rewardedVideoAd.loadAd(id, getAdRequest()); 201 | } 202 | } 203 | }); 204 | } 205 | 206 | /** 207 | * Show a Rewarded Video 208 | */ 209 | public void showRewardedVideo() { 210 | activity.runOnUiThread(new Runnable() 211 | { 212 | @Override public void run() 213 | { 214 | if (rewardedVideoAd.isLoaded()) { 215 | rewardedVideoAd.show(); 216 | } 217 | } 218 | }); 219 | } 220 | 221 | 222 | /* Banner 223 | * ********************************************************************** */ 224 | 225 | /** 226 | * Load a banner 227 | * @param String id AdMod Banner ID 228 | * @param boolean isOnTop To made the banner top or bottom 229 | */ 230 | public void loadBanner(final String id, final boolean isOnTop) 231 | { 232 | activity.runOnUiThread(new Runnable() 233 | { 234 | @Override public void run() 235 | { 236 | layout = ((Godot) activity).layout; 237 | adParams = new FrameLayout.LayoutParams( 238 | FrameLayout.LayoutParams.MATCH_PARENT, 239 | FrameLayout.LayoutParams.WRAP_CONTENT 240 | ); 241 | if(isOnTop) adParams.gravity = Gravity.TOP; 242 | else adParams.gravity = Gravity.BOTTOM; 243 | 244 | if (adView != null) 245 | { 246 | layout.removeView(adView); // Remove the old view 247 | } 248 | 249 | adView = new AdView(activity); 250 | adView.setAdUnitId(id); 251 | 252 | adView.setBackgroundColor(Color.TRANSPARENT); 253 | 254 | adView.setAdSize(AdSize.SMART_BANNER); 255 | adView.setAdListener(new AdListener() 256 | { 257 | @Override 258 | public void onAdLoaded() { 259 | Log.w("godot", "AdMob: onAdLoaded"); 260 | GodotLib.calldeferred(instance_id, "_on_admob_ad_loaded", new Object[]{ }); 261 | } 262 | 263 | @Override 264 | public void onAdFailedToLoad(int errorCode) 265 | { 266 | String str; 267 | String callbackFunctionName = "_on_admob_banner_failed_to_load"; 268 | switch(errorCode) { 269 | case AdRequest.ERROR_CODE_INTERNAL_ERROR: 270 | str = "ERROR_CODE_INTERNAL_ERROR"; 271 | break; 272 | case AdRequest.ERROR_CODE_INVALID_REQUEST: 273 | str = "ERROR_CODE_INVALID_REQUEST"; 274 | break; 275 | case AdRequest.ERROR_CODE_NETWORK_ERROR: 276 | str = "ERROR_CODE_NETWORK_ERROR"; 277 | callbackFunctionName = "_on_admob_network_error"; 278 | break; 279 | case AdRequest.ERROR_CODE_NO_FILL: 280 | str = "ERROR_CODE_NO_FILL"; 281 | break; 282 | default: 283 | str = "Code: " + errorCode; 284 | break; 285 | } 286 | Log.w("godot", "AdMob: onAdFailedToLoad -> " + str); 287 | Log.w("godot", "AdMob: callbackfunction -> " + callbackFunctionName); 288 | 289 | GodotLib.calldeferred(instance_id, callbackFunctionName, new Object[]{ }); 290 | } 291 | }); 292 | layout.addView(adView, adParams); 293 | 294 | // Request 295 | adView.loadAd(getAdRequest()); 296 | } 297 | }); 298 | } 299 | 300 | /** 301 | * Show the banner 302 | */ 303 | public void showBanner() 304 | { 305 | activity.runOnUiThread(new Runnable() 306 | { 307 | @Override public void run() 308 | { 309 | if (adView.getVisibility() == View.VISIBLE) return; 310 | adView.setVisibility(View.VISIBLE); 311 | adView.resume(); 312 | Log.d("godot", "AdMob: Show Banner"); 313 | } 314 | }); 315 | } 316 | 317 | /** 318 | * Resize the banner 319 | * 320 | */ 321 | public void resize() 322 | { 323 | activity.runOnUiThread(new Runnable() 324 | { 325 | @Override public void run() 326 | { 327 | if (layout == null || adView == null || adParams == null) 328 | { 329 | return; 330 | } 331 | 332 | layout.removeView(adView); // Remove the old view 333 | 334 | // Extract params 335 | 336 | int gravity = adParams.gravity; 337 | FrameLayout layout = ((Godot)activity).layout; 338 | adParams = new FrameLayout.LayoutParams( 339 | FrameLayout.LayoutParams.MATCH_PARENT, 340 | FrameLayout.LayoutParams.WRAP_CONTENT 341 | ); 342 | adParams.gravity = gravity; 343 | AdListener adListener = adView.getAdListener(); 344 | String id = adView.getAdUnitId(); 345 | 346 | // Create new view & set old params 347 | adView = new AdView(activity); 348 | adView.setAdUnitId(id); 349 | adView.setBackgroundColor(Color.TRANSPARENT); 350 | adView.setAdSize(AdSize.SMART_BANNER); 351 | adView.setAdListener(adListener); 352 | 353 | // Add to layout and load ad 354 | layout.addView(adView, adParams); 355 | 356 | // Request 357 | adView.loadAd(getAdRequest()); 358 | 359 | Log.d("godot", "AdMob: Banner Resized"); 360 | } 361 | }); 362 | } 363 | 364 | 365 | 366 | 367 | /** 368 | * Hide the banner 369 | */ 370 | public void hideBanner() 371 | { 372 | activity.runOnUiThread(new Runnable() 373 | { 374 | @Override public void run() 375 | { 376 | if (adView.getVisibility() == View.GONE) return; 377 | adView.setVisibility(View.GONE); 378 | adView.pause(); 379 | Log.d("godot", "AdMob: Hide Banner"); 380 | } 381 | }); 382 | } 383 | 384 | /** 385 | * Get the banner width 386 | * @return int Banner width 387 | */ 388 | public int getBannerWidth() 389 | { 390 | return AdSize.SMART_BANNER.getWidthInPixels(activity); 391 | } 392 | 393 | /** 394 | * Get the banner height 395 | * @return int Banner height 396 | */ 397 | public int getBannerHeight() 398 | { 399 | return AdSize.SMART_BANNER.getHeightInPixels(activity); 400 | } 401 | 402 | /* Interstitial 403 | * ********************************************************************** */ 404 | 405 | /** 406 | * Load a interstitial 407 | * @param String id AdMod Interstitial ID 408 | */ 409 | public void loadInterstitial(final String id) 410 | { 411 | activity.runOnUiThread(new Runnable() 412 | { 413 | @Override public void run() 414 | { 415 | interstitialAd = new InterstitialAd(activity); 416 | interstitialAd.setAdUnitId(id); 417 | interstitialAd.setAdListener(new AdListener() 418 | { 419 | @Override 420 | public void onAdLoaded() { 421 | Log.w("godot", "AdMob: onAdLoaded"); 422 | GodotLib.calldeferred(instance_id, "_on_interstitial_loaded", new Object[] { }); 423 | } 424 | 425 | @Override 426 | public void onAdFailedToLoad(int errorCode) { 427 | Log.w("godot", "AdMob: onAdFailedToLoad(int errorCode) - error code: " + Integer.toString(errorCode)); 428 | Log.w("godot", "AdMob: _on_interstitial_not_loaded"); 429 | GodotLib.calldeferred(instance_id, "_on_interstitial_not_loaded", new Object[] { }); 430 | } 431 | 432 | @Override 433 | public void onAdOpened() { 434 | Log.w("godot", "AdMob: onAdOpened()"); 435 | } 436 | 437 | @Override 438 | public void onAdLeftApplication() { 439 | Log.w("godot", "AdMob: onAdLeftApplication()"); 440 | } 441 | 442 | @Override 443 | public void onAdClosed() { 444 | GodotLib.calldeferred(instance_id, "_on_interstitial_close", new Object[] { }); 445 | Log.w("godot", "AdMob: onAdClosed"); 446 | } 447 | }); 448 | 449 | 450 | 451 | interstitialAd.loadAd(getAdRequest()); 452 | } 453 | }); 454 | } 455 | 456 | /** 457 | * Show the interstitial 458 | */ 459 | public void showInterstitial() 460 | { 461 | activity.runOnUiThread(new Runnable() 462 | { 463 | @Override public void run() 464 | { 465 | if (interstitialAd.isLoaded()) { 466 | interstitialAd.show(); 467 | } else { 468 | Log.w("w", "AdMob: showInterstitial - interstitial not loaded"); 469 | } 470 | } 471 | }); 472 | } 473 | 474 | /* Utils 475 | * ********************************************************************** */ 476 | 477 | /** 478 | * Generate MD5 for the deviceID 479 | * @param String s The string to generate de MD5 480 | * @return String The MD5 generated 481 | */ 482 | private String md5(final String s) 483 | { 484 | try { 485 | // Create MD5 Hash 486 | MessageDigest digest = MessageDigest.getInstance("MD5"); 487 | digest.update(s.getBytes()); 488 | byte messageDigest[] = digest.digest(); 489 | 490 | // Create Hex String 491 | StringBuffer hexString = new StringBuffer(); 492 | for (int i=0; i 2 | #import "app_delegate.h" 3 | 4 | #define BANNER_ENABLE_DELAY 5 5 | 6 | @interface AdmobBanner: NSObject { 7 | GADBannerView *bannerView; 8 | bool initialized; 9 | bool isReal; 10 | bool isOnTop; 11 | int instanceId; 12 | NSString *adUnitId; 13 | ViewController *rootController; 14 | } 15 | 16 | - (void)initialize:(BOOL)is_real: (int)instance_id; 17 | - (void)loadBanner:(NSString*)bannerId :(BOOL)is_on_top; 18 | - (void)showBanner; 19 | - (void)hideBanner; 20 | - (void)disableBanner; 21 | - (void)enableBanner; 22 | - (void)resize; 23 | - (int)getBannerWidth; 24 | - (int)getBannerHeight; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /admob/ios/src/AdmobBanner.mm: -------------------------------------------------------------------------------- 1 | #import "AdmobBanner.h" 2 | #include "reference.h" 3 | 4 | @implementation AdmobBanner 5 | 6 | - (void)dealloc { 7 | bannerView.delegate = nil; 8 | [bannerView release]; 9 | [super dealloc]; 10 | } 11 | 12 | - (void)initialize:(BOOL)is_real: (int)instance_id { 13 | isReal = is_real; 14 | initialized = true; 15 | instanceId = instance_id; 16 | rootController = [AppDelegate getViewController]; 17 | } 18 | 19 | 20 | - (void) loadBanner:(NSString*)bannerId: (BOOL)is_on_top { 21 | NSLog(@"Calling loadBanner"); 22 | 23 | isOnTop = is_on_top; 24 | 25 | if (!initialized || (!bannerId.length)) { 26 | return; 27 | } 28 | else{ 29 | NSLog(@"banner will load with the banner id"); 30 | NSLog(bannerId); 31 | } 32 | 33 | 34 | UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; 35 | 36 | if (bannerView == nil) { 37 | if (orientation == 0 || orientation == UIInterfaceOrientationPortrait) { //portrait 38 | bannerView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeSmartBannerPortrait]; 39 | } 40 | else { //landscape 41 | bannerView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeSmartBannerLandscape]; 42 | } 43 | 44 | if(!isReal) { 45 | bannerView.adUnitID = @"ca-app-pub-3940256099942544/2934735716"; 46 | } 47 | else { 48 | bannerView.adUnitID = bannerId; 49 | } 50 | 51 | bannerView.delegate = self; 52 | bannerView.rootViewController = rootController; 53 | 54 | 55 | [self addBannerViewToView:bannerView:is_on_top]; 56 | } 57 | 58 | GADRequest *request = [GADRequest request]; 59 | [bannerView loadRequest:request]; 60 | 61 | } 62 | 63 | 64 | - (void)addBannerViewToView:(UIView *_Nonnull)bannerView: (BOOL)is_on_top{ 65 | bannerView.translatesAutoresizingMaskIntoConstraints = NO; 66 | [rootController.view addSubview:bannerView]; 67 | if (@available(ios 11.0, *)) { 68 | [self positionBannerViewFullWidthAtSafeArea:bannerView:is_on_top]; 69 | } else { 70 | [self positionBannerViewFullWidthAtView:bannerView:is_on_top]; 71 | } 72 | } 73 | 74 | 75 | 76 | - (void)positionBannerViewFullWidthAtSafeArea:(UIView *_Nonnull)bannerView: (BOOL)is_on_top NS_AVAILABLE_IOS(11.0) { 77 | UILayoutGuide *guide = rootController.view.safeAreaLayoutGuide; 78 | 79 | if (is_on_top) { 80 | [NSLayoutConstraint activateConstraints:@[ 81 | [guide.leftAnchor constraintEqualToAnchor:bannerView.leftAnchor], 82 | [guide.rightAnchor constraintEqualToAnchor:bannerView.rightAnchor], 83 | [guide.topAnchor constraintEqualToAnchor:bannerView.topAnchor] 84 | ]]; 85 | } else { 86 | [NSLayoutConstraint activateConstraints:@[ 87 | [guide.leftAnchor constraintEqualToAnchor:bannerView.leftAnchor], 88 | [guide.rightAnchor constraintEqualToAnchor:bannerView.rightAnchor], 89 | [guide.bottomAnchor constraintEqualToAnchor:bannerView.bottomAnchor] 90 | ]]; 91 | } 92 | } 93 | 94 | 95 | - (void)positionBannerViewFullWidthAtView:(UIView *_Nonnull)bannerView: (BOOL)is_on_top { 96 | 97 | [rootController.view addConstraint:[NSLayoutConstraint constraintWithItem:bannerView 98 | attribute:NSLayoutAttributeLeading 99 | relatedBy:NSLayoutRelationEqual 100 | toItem:rootController.view 101 | attribute:NSLayoutAttributeLeading 102 | multiplier:1 103 | constant:0]]; 104 | [rootController.view addConstraint:[NSLayoutConstraint constraintWithItem:bannerView 105 | attribute:NSLayoutAttributeTrailing 106 | relatedBy:NSLayoutRelationEqual 107 | toItem:rootController.view 108 | attribute:NSLayoutAttributeTrailing 109 | multiplier:1 110 | constant:0]]; 111 | 112 | if (is_on_top) { 113 | [rootController.view addConstraint:[NSLayoutConstraint constraintWithItem:bannerView 114 | attribute:NSLayoutAttributeTop 115 | relatedBy:NSLayoutRelationEqual 116 | toItem:rootController.topLayoutGuide 117 | attribute:NSLayoutAttributeTop 118 | multiplier:1 119 | constant:0]]; 120 | 121 | } else { 122 | [rootController.view addConstraint:[NSLayoutConstraint constraintWithItem:bannerView 123 | attribute:NSLayoutAttributeBottom 124 | relatedBy:NSLayoutRelationEqual 125 | toItem:rootController.bottomLayoutGuide 126 | attribute:NSLayoutAttributeTop 127 | multiplier:1 128 | constant:0]]; 129 | } 130 | } 131 | 132 | - (void)showBanner { 133 | NSLog(@"Calling showBanner"); 134 | 135 | if (bannerView == nil || !initialized) { 136 | return; 137 | } 138 | 139 | [bannerView setHidden:NO]; 140 | } 141 | 142 | - (void) hideBanner { 143 | NSLog(@"Calling hideBanner"); 144 | if (bannerView == nil || !initialized) { 145 | return; 146 | } 147 | [bannerView setHidden:YES]; 148 | } 149 | - (void) disableBanner { 150 | NSLog(@"Calling disableBanner"); 151 | if (bannerView == nil || !initialized) { 152 | return; 153 | } 154 | [bannerView setHidden:YES]; 155 | [bannerView removeFromSuperview]; 156 | adUnitId = bannerView.adUnitID; 157 | bannerView = nil; 158 | } 159 | 160 | - (void) enableBanner { 161 | NSLog(@"Calling enableBanner"); 162 | if (!initialized) { 163 | return; 164 | } 165 | 166 | if (bannerView == nil) { 167 | [self loadBanner:adUnitId:isOnTop]; 168 | } 169 | if (bannerView != nil){ 170 | [bannerView setHidden:NO]; 171 | } 172 | } 173 | 174 | - (void) resize { 175 | NSLog(@"Calling resize banner"); 176 | if (bannerView != nil){ 177 | NSString* currentAdUnitId = bannerView.adUnitID; 178 | [self hideBanner]; 179 | [bannerView removeFromSuperview]; 180 | bannerView = nil; 181 | [self loadBanner:currentAdUnitId:isOnTop]; 182 | NSLog(@"Resize called sucessful"); 183 | } 184 | else{ 185 | NSLog(@"Resize banner doesnt happen, because was not loaded"); 186 | } 187 | } 188 | 189 | - (int) getBannerWidth { 190 | return bannerView.bounds.size.width * [UIScreen mainScreen].scale; 191 | } 192 | 193 | - (int) getBannerHeight { 194 | return bannerView.bounds.size.height * [UIScreen mainScreen].scale; 195 | } 196 | 197 | 198 | 199 | /// Tells the delegate an ad request loaded an ad. 200 | - (void)adViewDidReceiveAd:(GADBannerView *)adView { 201 | NSLog(@"adViewDidReceiveAd"); 202 | Object *obj = ObjectDB::get_instance(instanceId); 203 | obj->call_deferred("_on_admob_ad_loaded"); 204 | } 205 | 206 | /// Tells the delegate an ad request failed. 207 | - (void)adView:(GADBannerView *)adView 208 | didFailToReceiveAdWithError:(GADRequestError *)error { 209 | NSLog(@"adView:didFailToReceiveAdWithError: %@", [error localizedDescription]); 210 | Object *obj = ObjectDB::get_instance(instanceId); 211 | obj->call_deferred("_on_admob_network_error"); 212 | } 213 | 214 | /// Tells the delegate that a full screen view will be presented in response 215 | /// to the user clicking on an ad. 216 | - (void)adViewWillPresentScreen:(GADBannerView *)adView { 217 | NSLog(@"adViewWillPresentScreen"); 218 | } 219 | 220 | /// Tells the delegate that the full screen view will be dismissed. 221 | - (void)adViewWillDismissScreen:(GADBannerView *)adView { 222 | NSLog(@"adViewWillDismissScreen"); 223 | } 224 | 225 | /// Tells the delegate that the full screen view has been dismissed. 226 | - (void)adViewDidDismissScreen:(GADBannerView *)adView { 227 | NSLog(@"adViewDidDismissScreen"); 228 | } 229 | 230 | /// Tells the delegate that a user click will open another app (such as 231 | /// the App Store), backgrounding the current app. 232 | - (void)adViewWillLeaveApplication:(GADBannerView *)adView { 233 | NSLog(@"adViewWillLeaveApplication"); 234 | } 235 | 236 | 237 | @end -------------------------------------------------------------------------------- /admob/ios/src/AdmobInterstitial.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "app_delegate.h" 3 | #import "AdmobBanner.h" 4 | 5 | @interface AdmobInterstitial: NSObject { 6 | AdmobBanner *admobBanner; 7 | GADInterstitial *interstitial; 8 | bool initialized; 9 | bool isReal; 10 | int instanceId; 11 | ViewController *rootController; 12 | } 13 | 14 | - (void)initialize:(BOOL)is_real: (int)instance_id: (AdmobBanner *)banner; 15 | - (void)loadInterstitial:(NSString*)interstitialId; 16 | - (void)showInterstitial; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /admob/ios/src/AdmobInterstitial.mm: -------------------------------------------------------------------------------- 1 | #import "AdmobInterstitial.h" 2 | #include "reference.h" 3 | 4 | 5 | @implementation AdmobInterstitial 6 | 7 | - (void)dealloc { 8 | interstitial.delegate = nil; 9 | [interstitial release]; 10 | [super dealloc]; 11 | } 12 | 13 | - (void)initialize:(BOOL)is_real: (int)instance_id: (AdmobBanner *)admob_banner { 14 | isReal = is_real; 15 | initialized = true; 16 | instanceId = instance_id; 17 | admobBanner = admob_banner; 18 | rootController = [AppDelegate getViewController]; 19 | } 20 | 21 | - (void) loadInterstitial:(NSString*)interstitialId { 22 | 23 | NSLog(@"Calling loadInterstitial"); 24 | //init 25 | if (!initialized) { 26 | return; 27 | } 28 | 29 | interstitial = nil; 30 | if(!isReal) { 31 | interstitial = [[GADInterstitial alloc] 32 | initWithAdUnitID:@"ca-app-pub-3940256099942544/4411468910"]; 33 | } 34 | else { 35 | interstitial = [[GADInterstitial alloc] initWithAdUnitID:interstitialId]; 36 | } 37 | 38 | interstitial.delegate = self; 39 | 40 | 41 | //load 42 | GADRequest *request = [GADRequest request]; 43 | [interstitial loadRequest:request]; 44 | } 45 | 46 | - (void) showInterstitial { 47 | NSLog(@"Calling showInterstitial"); 48 | //show 49 | 50 | if (interstitial == nil || !initialized) { 51 | return; 52 | } 53 | 54 | if (interstitial.isReady) { 55 | [admobBanner disableBanner]; 56 | [interstitial presentFromRootViewController:rootController]; 57 | } else { 58 | NSLog(@"Interstitial Ad wasn't ready"); 59 | } 60 | 61 | 62 | } 63 | 64 | 65 | 66 | /// Tells the delegate an ad request succeeded. 67 | - (void)interstitialDidReceiveAd:(GADInterstitial *)ad { 68 | NSLog(@"interstitialDidReceiveAd"); 69 | Object *obj = ObjectDB::get_instance(instanceId); 70 | obj->call_deferred("_on_interstitial_loaded"); 71 | } 72 | 73 | /// Tells the delegate an ad request failed. 74 | - (void)interstitial:(GADInterstitial *)ad 75 | didFailToReceiveAdWithError:(GADRequestError *)error { 76 | NSLog(@"interstitial:didFailToReceiveAdWithError: %@", [error localizedDescription]); 77 | Object *obj = ObjectDB::get_instance(instanceId); 78 | obj->call_deferred("_on_interstitial_not_loaded"); 79 | } 80 | 81 | /// Tells the delegate that an interstitial will be presented. 82 | - (void)interstitialWillPresentScreen:(GADInterstitial *)ad { 83 | NSLog(@"interstitialWillPresentScreen"); 84 | } 85 | 86 | /// Tells the delegate the interstitial is to be animated off the screen. 87 | - (void)interstitialWillDismissScreen:(GADInterstitial *)ad { 88 | NSLog(@"interstitialWillDismissScreen"); 89 | [self performSelector:@selector(bannerEnable) withObject:nil afterDelay:BANNER_ENABLE_DELAY]; 90 | } 91 | - (void)bannerEnable{ 92 | NSLog(@"banner enable call"); 93 | [admobBanner enableBanner]; 94 | } 95 | 96 | /// Tells the delegate the interstitial had been animated off the screen. 97 | - (void)interstitialDidDismissScreen:(GADInterstitial *)ad { 98 | NSLog(@"interstitialDidDismissScreen"); 99 | Object *obj = ObjectDB::get_instance(instanceId); 100 | obj->call_deferred("_on_interstitial_close"); 101 | 102 | } 103 | 104 | /// Tells the delegate that a user click will open another app 105 | /// (such as the App Store), backgrounding the current app. 106 | - (void)interstitialWillLeaveApplication:(GADInterstitial *)ad { 107 | NSLog(@"interstitialWillLeaveApplication"); 108 | } 109 | 110 | 111 | @end 112 | -------------------------------------------------------------------------------- /admob/ios/src/AdmobRewarded.h: -------------------------------------------------------------------------------- 1 | #import "app_delegate.h" 2 | #import 3 | #import "AdmobBanner.h" 4 | 5 | @interface AdmobRewarded: NSObject { 6 | AdmobBanner *admobBanner; 7 | bool initialized; 8 | bool isReal; 9 | int instanceId; 10 | ViewController *rootController; 11 | } 12 | 13 | - (void)initialize:(BOOL)is_real: (int)instance_id: (AdmobBanner *)banner; 14 | - (void)loadRewardedVideo:(NSString*)rewardedId; 15 | - (void)showRewardedVideo; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /admob/ios/src/AdmobRewarded.mm: -------------------------------------------------------------------------------- 1 | #import "AdmobRewarded.h" 2 | #import 3 | #import 4 | #include "reference.h" 5 | 6 | 7 | @implementation AdmobRewarded 8 | 9 | 10 | - (void)initialize:(BOOL)is_real: (int)instance_id: (AdmobBanner *)admob_banner { 11 | isReal = is_real; 12 | initialized = true; 13 | instanceId = instance_id; 14 | admobBanner = admob_banner; 15 | rootController = [AppDelegate getViewController]; 16 | } 17 | 18 | - (void) loadRewardedVideo:(NSString*) rewardedId { 19 | NSLog(@"Calling loadRewardedVideo"); 20 | //init 21 | if (!initialized) { 22 | return; 23 | } 24 | 25 | if(!isReal) { 26 | [[GADRewardBasedVideoAd sharedInstance] loadRequest:[GADRequest request] 27 | withAdUnitID:@"ca-app-pub-3940256099942544/1712485313"]; 28 | } 29 | else { 30 | [[GADRewardBasedVideoAd sharedInstance] loadRequest:[GADRequest request] withAdUnitID:rewardedId]; 31 | } 32 | 33 | 34 | [GADRewardBasedVideoAd sharedInstance].delegate = self; 35 | 36 | } 37 | 38 | - (void) showRewardedVideo { 39 | NSLog(@"Calling showRewardedVideo"); 40 | //init 41 | if (!initialized) { 42 | return; 43 | } 44 | 45 | if ([[GADRewardBasedVideoAd sharedInstance] isReady]) { 46 | [admobBanner disableBanner]; 47 | [[GADRewardBasedVideoAd sharedInstance] presentFromRootViewController:rootController]; 48 | } 49 | 50 | } 51 | 52 | 53 | - (void)rewardBasedVideoAd:(GADRewardBasedVideoAd *)rewardBasedVideoAd didRewardUserWithReward:(GADAdReward *)reward { 54 | NSString *rewardMessage = [NSString stringWithFormat:@"Reward received with currency %@ , amount %lf", 55 | reward.type, [reward.amount doubleValue]]; 56 | NSLog(rewardMessage); 57 | 58 | Object *obj = ObjectDB::get_instance(instanceId); 59 | obj->call_deferred("_on_rewarded", [reward.type UTF8String], reward.amount.doubleValue); 60 | 61 | } 62 | 63 | - (void)rewardBasedVideoAdDidReceiveAd:(GADRewardBasedVideoAd *)rewardBasedVideoAd { 64 | NSLog(@"Reward based video ad is received."); 65 | Object *obj = ObjectDB::get_instance(instanceId); 66 | obj->call_deferred("_on_rewarded_video_ad_loaded"); 67 | } 68 | 69 | - (void)rewardBasedVideoAdDidOpen:(GADRewardBasedVideoAd *)rewardBasedVideoAd { 70 | NSLog(@"Opened reward based video ad."); 71 | Object *obj = ObjectDB::get_instance(instanceId); 72 | obj->call_deferred("_on_rewarded_video_ad_opened"); 73 | } 74 | 75 | - (void)rewardBasedVideoAdDidStartPlaying:(GADRewardBasedVideoAd *)rewardBasedVideoAd { 76 | NSLog(@"Reward based video ad started playing."); 77 | Object *obj = ObjectDB::get_instance(instanceId); 78 | obj->call_deferred("_on_rewarded_video_started"); 79 | } 80 | 81 | - (void)rewardBasedVideoAdDidClose:(GADRewardBasedVideoAd *)rewardBasedVideoAd { 82 | NSLog(@"Reward based video ad is closed."); 83 | NSLog(@"Enable Banner with delay:%d",BANNER_ENABLE_DELAY); 84 | [self performSelector:@selector(bannerEnable) withObject:nil afterDelay:BANNER_ENABLE_DELAY]; 85 | Object *obj = ObjectDB::get_instance(instanceId); 86 | obj->call_deferred("_on_rewarded_video_ad_closed"); 87 | } 88 | - (void)bannerEnable{ 89 | NSLog(@"banner enable call"); 90 | [admobBanner enableBanner]; 91 | } 92 | 93 | - (void)rewardBasedVideoAdWillLeaveApplication:(GADRewardBasedVideoAd *)rewardBasedVideoAd { 94 | NSLog(@"Reward based video ad will leave application."); 95 | Object *obj = ObjectDB::get_instance(instanceId); 96 | obj->call_deferred("_on_rewarded_video_ad_left_application"); 97 | } 98 | 99 | - (void)rewardBasedVideoAd:(GADRewardBasedVideoAd *)rewardBasedVideoAd didFailToLoadWithError:(NSError *)error { 100 | NSLog(@"Reward based video ad failed to load: %@ ", error.localizedDescription); 101 | Object *obj = ObjectDB::get_instance(instanceId); 102 | obj->call_deferred("_on_rewarded_video_ad_failed_to_load", (int)error.code); 103 | } 104 | 105 | - (void)rewardBasedVideoAdDidCompletePlaying:(GADRewardBasedVideoAd *)rewardBasedVideoAd { 106 | NSLog(@"Reward based video ad has completed."); 107 | Object *obj = ObjectDB::get_instance(instanceId); 108 | obj->call_deferred("_on_rewarded_video_completed"); 109 | } 110 | 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /admob/ios/src/godotAdmob.h: -------------------------------------------------------------------------------- 1 | #ifndef GODOT_ADMOB_H 2 | #define GODOT_ADMOB_H 3 | 4 | #include 5 | 6 | #include "reference.h" 7 | 8 | 9 | #ifdef __OBJC__ 10 | @class AdmobBanner; 11 | typedef AdmobBanner *bannerPtr; 12 | @class AdmobInterstitial; 13 | typedef AdmobInterstitial *interstitialPtr; 14 | @class AdmobRewarded; 15 | typedef AdmobRewarded *rewardedPtr; 16 | #else 17 | typedef void *bannerPtr; 18 | typedef void *interstitialPtr; 19 | typedef void *rewardedPtr; 20 | #endif 21 | 22 | 23 | 24 | class GodotAdmob : public Reference { 25 | 26 | #if VERSION_MAJOR == 3 27 | GDCLASS(GodotAdmob, Reference); 28 | #else 29 | OBJ_TYPE(GodotAdmob, Reference); 30 | #endif 31 | 32 | bool initialized; 33 | static GodotAdmob *instance; //fix 34 | 35 | bannerPtr banner; 36 | interstitialPtr interstitial; 37 | rewardedPtr rewarded; 38 | 39 | 40 | protected: 41 | static void _bind_methods(); 42 | 43 | public: 44 | 45 | void init(bool isReal, int instanceId); 46 | void initWithContentRating(bool isReal, int instanceId, bool child_directed, bool is_personalized, const String &max_ad_content_rate); 47 | void loadBanner(const String &bannerId, bool isOnTop); 48 | void showBanner(); 49 | void hideBanner(); 50 | void resize(); 51 | int getBannerWidth(); 52 | int getBannerHeight(); 53 | void loadInterstitial(const String &interstitialId); 54 | void showInterstitial(); 55 | void loadRewardedVideo(const String &rewardedId); 56 | void showRewardedVideo(); 57 | 58 | GodotAdmob(); 59 | ~GodotAdmob(); 60 | }; 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /admob/ios/src/godotAdmob.mm: -------------------------------------------------------------------------------- 1 | #include "godotAdmob.h" 2 | #import "app_delegate.h" 3 | 4 | #if VERSION_MAJOR == 3 5 | #define CLASS_DB ClassDB 6 | #else 7 | #define CLASS_DB ObjectTypeDB 8 | #endif 9 | 10 | GodotAdmob *GodotAdmob::instance = NULL; //<< INIT NULL VAR ON COMPILE TIME! 11 | 12 | GodotAdmob::GodotAdmob() { 13 | initialized = false; 14 | banner = NULL; 15 | interstitial = NULL; 16 | rewarded = NULL; 17 | // 18 | ERR_FAIL_COND(instance != NULL); //<< SUCCESS!!! FIRST 19 | 20 | instance = this; 21 | } 22 | 23 | GodotAdmob::~GodotAdmob() { 24 | if (initialized) { 25 | [banner release]; //free banner 26 | [interstitial release]; //free 27 | [rewarded release]; //free 28 | } 29 | 30 | if (instance == this) { 31 | instance = NULL; 32 | } 33 | } 34 | 35 | void GodotAdmob::init(bool isReal, int instanceId) { 36 | if (instance != this) { 37 | NSLog(@"GodotAdmob Module dublicate singleton"); 38 | return; 39 | } 40 | if (initialized) { 41 | NSLog(@"GodotAdmob Module already initialized"); 42 | return; 43 | } 44 | 45 | initialized = true; 46 | 47 | banner = [[AdmobBanner alloc] init]; 48 | [banner initialize :isReal :instanceId]; 49 | 50 | interstitial = [[AdmobInterstitial alloc] init]; 51 | [interstitial initialize :isReal :instanceId :banner]; 52 | 53 | rewarded = [[AdmobRewarded alloc] init]; 54 | [rewarded initialize :isReal :instanceId :banner]; 55 | } 56 | 57 | void GodotAdmob::initWithContentRating(bool isReal, int instanceId, bool child_directed, bool is_personalized, const String &max_ad_content_rate) { 58 | if (instance != this) { 59 | NSLog(@"GodotAdmob Module dublicate singleton"); 60 | return; 61 | } 62 | if (initialized) { 63 | NSLog(@"GodotAdmob Module already initialized"); 64 | return; 65 | } 66 | 67 | initialized = true; 68 | 69 | banner = [[AdmobBanner alloc] init]; 70 | [banner initialize :isReal :instanceId]; 71 | 72 | interstitial = [[AdmobInterstitial alloc] init]; 73 | [interstitial initialize :isReal :instanceId :banner]; 74 | 75 | rewarded = [[AdmobRewarded alloc] init]; 76 | [rewarded initialize :isReal :instanceId :banner]; 77 | } 78 | 79 | void GodotAdmob::loadBanner(const String &bannerId, bool isOnTop) { 80 | if (!initialized) { 81 | NSLog(@"GodotAdmob Module not initialized"); 82 | return; 83 | } 84 | 85 | NSString *idStr = [NSString stringWithCString:bannerId.utf8().get_data() encoding: NSUTF8StringEncoding]; 86 | [banner loadBanner:idStr :isOnTop]; 87 | 88 | } 89 | 90 | void GodotAdmob::showBanner() { 91 | if (!initialized) { 92 | NSLog(@"GodotAdmob Module not initialized"); 93 | return; 94 | } 95 | 96 | [banner showBanner]; 97 | } 98 | 99 | void GodotAdmob::hideBanner() { 100 | if (!initialized) { 101 | NSLog(@"GodotAdmob Module not initialized"); 102 | return; 103 | } 104 | [banner hideBanner]; 105 | } 106 | 107 | 108 | void GodotAdmob::resize() { 109 | if (!initialized) { 110 | NSLog(@"GodotAdmob Module not initialized"); 111 | return; 112 | } 113 | [banner resize]; 114 | } 115 | 116 | int GodotAdmob::getBannerWidth() { 117 | if (!initialized) { 118 | NSLog(@"GodotAdmob Module not initialized"); 119 | return 0; 120 | } 121 | return (uintptr_t)[banner getBannerWidth]; 122 | } 123 | 124 | int GodotAdmob::getBannerHeight() { 125 | if (!initialized) { 126 | NSLog(@"GodotAdmob Module not initialized"); 127 | return 0; 128 | } 129 | return (uintptr_t)[banner getBannerHeight]; 130 | } 131 | 132 | void GodotAdmob::loadInterstitial(const String &interstitialId) { 133 | if (!initialized) { 134 | NSLog(@"GodotAdmob Module not initialized"); 135 | return; 136 | } 137 | 138 | NSString *idStr = [NSString stringWithCString:interstitialId.utf8().get_data() encoding: NSUTF8StringEncoding]; 139 | [interstitial loadInterstitial:idStr]; 140 | 141 | } 142 | 143 | void GodotAdmob::showInterstitial() { 144 | if (!initialized) { 145 | NSLog(@"GodotAdmob Module not initialized"); 146 | return; 147 | } 148 | 149 | [interstitial showInterstitial]; 150 | 151 | } 152 | 153 | void GodotAdmob::loadRewardedVideo(const String &rewardedId) { 154 | //init 155 | if (!initialized) { 156 | NSLog(@"GodotAdmob Module not initialized"); 157 | return; 158 | } 159 | 160 | NSString *idStr = [NSString stringWithCString:rewardedId.utf8().get_data() encoding: NSUTF8StringEncoding]; 161 | [rewarded loadRewardedVideo: idStr]; 162 | 163 | } 164 | 165 | void GodotAdmob::showRewardedVideo() { 166 | //show 167 | if (!initialized) { 168 | NSLog(@"GodotAdmob Module not initialized"); 169 | return; 170 | } 171 | 172 | [rewarded showRewardedVideo]; 173 | } 174 | 175 | 176 | 177 | void GodotAdmob::_bind_methods() { 178 | CLASS_DB::bind_method("init",&GodotAdmob::init); 179 | CLASS_DB::bind_method("initWithContentRating",&GodotAdmob::initWithContentRating); 180 | CLASS_DB::bind_method("loadBanner",&GodotAdmob::loadBanner); 181 | CLASS_DB::bind_method("showBanner",&GodotAdmob::showBanner); 182 | CLASS_DB::bind_method("hideBanner",&GodotAdmob::hideBanner); 183 | CLASS_DB::bind_method("loadInterstitial",&GodotAdmob::loadInterstitial); 184 | CLASS_DB::bind_method("showInterstitial",&GodotAdmob::showInterstitial); 185 | CLASS_DB::bind_method("loadRewardedVideo",&GodotAdmob::loadRewardedVideo); 186 | CLASS_DB::bind_method("showRewardedVideo",&GodotAdmob::showRewardedVideo); 187 | CLASS_DB::bind_method("resize",&GodotAdmob::resize); 188 | CLASS_DB::bind_method("getBannerWidth",&GodotAdmob::getBannerWidth); 189 | CLASS_DB::bind_method("getBannerHeight",&GodotAdmob::getBannerHeight); 190 | } 191 | -------------------------------------------------------------------------------- /admob/register_types.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #if VERSION_MAJOR == 3 4 | #include 5 | #include 6 | #else 7 | #include "object_type_db.h" 8 | #include "core/globals.h" 9 | #endif 10 | 11 | #include "register_types.h" 12 | #include "ios/src/godotAdmob.h" 13 | 14 | void register_admob_types() { 15 | #if VERSION_MAJOR == 3 16 | Engine::get_singleton()->add_singleton(Engine::Singleton("AdMob", memnew(GodotAdmob))); 17 | #else 18 | Globals::get_singleton()->add_singleton(Globals::Singleton("AdMob", memnew(GodotAdmob))); 19 | #endif 20 | } 21 | 22 | void unregister_admob_types() { 23 | } 24 | -------------------------------------------------------------------------------- /admob/register_types.h: -------------------------------------------------------------------------------- 1 | void register_admob_types(); 2 | void unregister_admob_types(); 3 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples of use for AdMob Module 2 | 3 | These examples show how to interact with the module. 4 | 5 | ## Usage 6 | 7 | For use these examples you must create an account on AdMob and create an app (or link with Google Play one). 8 | 9 | After that create a new Ad Unit ID and use in the example code. 10 | 11 | -------------------------------------------------------------------------------- /examples/godot-2/engine.cfg: -------------------------------------------------------------------------------- 1 | [android] 2 | 3 | modules="org/godotengine/godot/GodotAdMob" 4 | 5 | [application] 6 | 7 | name="testAdmob" 8 | main_scene="res://main.tscn" 9 | icon="icon.png" 10 | 11 | [display] 12 | 13 | width=1024 14 | height=600 15 | stretch_mode="viewport" 16 | stretch_aspect="keep_height" 17 | orientation="sensor" 18 | -------------------------------------------------------------------------------- /examples/godot-2/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kloder-games/godot-admob/f5996ed22dfab457d611bc1f4f32d6305de3dcd2/examples/godot-2/icon.png -------------------------------------------------------------------------------- /examples/godot-2/main.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | var admob = null 4 | var isReal = false 5 | var isTop = true 6 | var adBannerId = "ca-app-pub-XXXXXXXXXXXXXXXX/XXXXXXXXXX" # [Replace with your Ad Unit ID and delete this message.] 7 | var adInterstitialId = "ca-app-pub-XXXXXXXXXXXXXXXX/XXXXXXXXXX" # [Replace with your Ad Unit ID and delete this message.] 8 | var adRewardedId = "ca-app-pub-3940256099942544/5224354917" # [There is no testing option for rewarded videos, so you can use this id for testing] 9 | 10 | func _ready(): 11 | if(Globals.has_singleton("AdMob")): 12 | admob = Globals.get_singleton("AdMob") 13 | admob.init(isReal, get_instance_ID()) 14 | loadBanner() 15 | loadInterstitial() 16 | loadRewardedVideo() 17 | 18 | get_tree().connect("screen_resized", self, "onResize") 19 | 20 | # Loaders 21 | 22 | func loadBanner(): 23 | if admob != null: 24 | admob.loadBanner(adBannerId, isTop) 25 | 26 | func loadInterstitial(): 27 | if admob != null: 28 | admob.loadInterstitial(adInterstitialId) 29 | 30 | func loadRewardedVideo(): 31 | if admob != null: 32 | admob.loadRewardedVideo(adRewardedId) 33 | 34 | # Events 35 | 36 | func _on_BtnBanner_toggled(pressed): 37 | if admob != null: 38 | if pressed: admob.showBanner() 39 | else: admob.hideBanner() 40 | 41 | func _on_BtnInterstitial_pressed(): 42 | if admob != null: 43 | admob.showInterstitial() 44 | 45 | func _on_BtnRewardedVideo_pressed(): 46 | if admob != null: 47 | admob.showRewardedVideo() 48 | 49 | func _on_admob_network_error(): 50 | print("Network Error") 51 | 52 | func _on_admob_ad_loaded(): 53 | print("Ad loaded success") 54 | get_node("CanvasLayer/BtnBanner").set_disabled(false) 55 | 56 | func _on_interstitial_not_loaded(): 57 | print("Error: Interstitial not loaded") 58 | 59 | func _on_interstitial_loaded(): 60 | print("Interstitial loaded") 61 | get_node("CanvasLayer/BtnInterstitial").set_disabled(false) 62 | 63 | func _on_interstitial_close(): 64 | print("Interstitial closed") 65 | get_node("CanvasLayer/BtnInterstitial").set_disabled(true) 66 | 67 | func _on_rewarded_video_ad_loaded(): 68 | print("Rewarded loaded success") 69 | get_node("CanvasLayer/BtnRewardedVideo").set_disabled(false) 70 | 71 | func _on_rewarded_video_ad_closed(): 72 | print("Rewarded closed") 73 | get_node("CanvasLayer/BtnRewardedVideo").set_disabled(true) 74 | loadRewardedVideo() 75 | 76 | func _on_rewarded(currency, amount): 77 | print("Reward: " + currency + ", " + str(amount)) 78 | get_node("CanvasLayer/LblRewarded").set_text("Reward: " + currency + ", " + str(amount)) 79 | 80 | # Resize 81 | 82 | func onResize(): 83 | if admob != null: 84 | admob.resize() 85 | 86 | -------------------------------------------------------------------------------- /examples/godot-2/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=1] 2 | 3 | [ext_resource path="res://main.gd" type="Script" id=1] 4 | 5 | [node name="Node2D" type="Node2D"] 6 | 7 | script/script = ExtResource( 1 ) 8 | __meta__ = { 9 | "__editor_plugin_screen__": "3D" 10 | } 11 | 12 | [node name="CanvasLayer" type="CanvasLayer" parent="."] 13 | 14 | layer = 1 15 | offset = Vector2( 0, 0 ) 16 | rotation = 0.0 17 | scale = Vector2( 1, 1 ) 18 | 19 | [node name="BtnBanner" type="Button" parent="CanvasLayer"] 20 | 21 | anchor/left = 3 22 | anchor/top = 3 23 | anchor/right = 3 24 | anchor/bottom = 3 25 | focus/ignore_mouse = false 26 | focus/stop_mouse = true 27 | size_flags/horizontal = 2 28 | size_flags/vertical = 2 29 | margin/left = 75.0 30 | margin/top = 80.0 31 | margin/right = -75.0 32 | margin/bottom = 5.0 33 | disabled = true 34 | toggle_mode = true 35 | is_pressed = true 36 | enabled_focus_mode = 2 37 | shortcut = null 38 | text = "Show/Hide Banner" 39 | flat = false 40 | 41 | [node name="BtnInterstitial" type="Button" parent="CanvasLayer"] 42 | 43 | anchor/left = 3 44 | anchor/top = 3 45 | anchor/right = 3 46 | anchor/bottom = 3 47 | focus/ignore_mouse = false 48 | focus/stop_mouse = true 49 | size_flags/horizontal = 2 50 | size_flags/vertical = 2 51 | margin/left = 75.0 52 | margin/top = -5.0 53 | margin/right = -75.0 54 | margin/bottom = -80.0 55 | disabled = true 56 | toggle_mode = false 57 | enabled_focus_mode = 2 58 | shortcut = null 59 | text = "Show Interstitial" 60 | flat = false 61 | 62 | [node name="BtnRewardedVideo" type="Button" parent="CanvasLayer"] 63 | 64 | anchor/left = 3 65 | anchor/top = 3 66 | anchor/right = 3 67 | anchor/bottom = 3 68 | focus/ignore_mouse = false 69 | focus/stop_mouse = true 70 | size_flags/horizontal = 2 71 | size_flags/vertical = 2 72 | margin/left = 75.0 73 | margin/top = -94.0 74 | margin/right = -75.0 75 | margin/bottom = -169.0 76 | disabled = true 77 | toggle_mode = false 78 | enabled_focus_mode = 2 79 | shortcut = null 80 | text = "Show Rewarded Video" 81 | flat = false 82 | 83 | [node name="LblRewarded" type="Label" parent="CanvasLayer"] 84 | 85 | focus/ignore_mouse = true 86 | focus/stop_mouse = true 87 | size_flags/horizontal = 2 88 | size_flags/vertical = 0 89 | margin/left = 0.0 90 | margin/top = 0.0 91 | margin/right = 1026.0 92 | margin/bottom = 32.0 93 | text = "REWARDED VIDEO RETURN" 94 | align = 1 95 | valign = 1 96 | percent_visible = 1.0 97 | lines_skipped = 0 98 | max_lines_visible = -1 99 | 100 | [connection signal="toggled" from="CanvasLayer/BtnBanner" to="." method="_on_BtnBanner_toggled"] 101 | 102 | [connection signal="pressed" from="CanvasLayer/BtnInterstitial" to="." method="_on_BtnInterstitial_pressed"] 103 | 104 | [connection signal="pressed" from="CanvasLayer/BtnRewardedVideo" to="." method="_on_BtnRewardedVideo_pressed"] 105 | 106 | 107 | -------------------------------------------------------------------------------- /examples/godot-3/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kloder-games/godot-admob/f5996ed22dfab457d611bc1f4f32d6305de3dcd2/examples/godot-3/icon.png -------------------------------------------------------------------------------- /examples/godot-3/main.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | var admob = null 4 | var instance_id = get_instance_id() # The instance id from Godot 5 | 6 | var is_init_with_content_rating = true #Init AdMob with additional Content Rating parameters (Android and iOS) 7 | 8 | var is_for_child_directed_treatment = false # If true, maxAdContetRating will be ignored (your maxAdContentRating would can not be other than "G") 9 | var is_personalized = true # Ads are personalized by default, GDPR compliance within the European Economic Area may require you to disable personalization. 10 | var max_ad_content_rating = "G" #It's value must be "G", "PG", "T" or "MA". 11 | #If the rating of your app in Play Console and your config of maxAdContentRating in AdMob are not matched, your app can be banned by Google. 12 | 13 | 14 | var is_real = false # Show real ad or test ad 15 | var is_top = true # Show the banner on top or bottom 16 | 17 | const AD_BANNER_ID = { 18 | "Android": "ca-app-pub-3940256099942544/6300978111", 19 | "iOS" : "ca-app-pub-3940256099942544/2934735716" 20 | } 21 | #[Replace with your Ad Unit ID and delete this message] 22 | 23 | const AD_INTERSTITIAL_ID = { 24 | "Android": "ca-app-pub-3940256099942544/1033173712", 25 | "iOS" : "ca-app-pub-3940256099942544/4411468910" 26 | } 27 | #[Replace with your Ad Unit ID and delete this message] 28 | 29 | const AD_REWARDED_ID = { 30 | "Android": "ca-app-pub-3940256099942544/5224354917", 31 | "iOS" : "ca-app-pub-3940256099942544/1712485313" 32 | } 33 | #[Replace with your Ad Unit ID and delete this message] 34 | 35 | var platform_os = OS.get_name() 36 | 37 | func _ready(): 38 | if(Engine.has_singleton("AdMob")): 39 | admob = Engine.get_singleton("AdMob") 40 | if is_init_with_content_rating: 41 | admob.initWithContentRating(is_real, instance_id, is_for_child_directed_treatment, is_personalized, max_ad_content_rating) 42 | else: 43 | admob.init(is_real, instance_id) 44 | print("OS: " + platform_os) 45 | loadBanner() 46 | loadInterstitial() 47 | loadRewardedVideo() 48 | 49 | print_debug(get_tree().connect("screen_resized", self, "_on_screen_resized")) 50 | 51 | # Loaders 52 | func loadBanner(): 53 | if admob != null: 54 | admob.loadBanner(AD_BANNER_ID[platform_os], is_top) 55 | 56 | func loadInterstitial(): 57 | if admob != null: 58 | admob.loadInterstitial(AD_INTERSTITIAL_ID[platform_os]) 59 | 60 | func loadRewardedVideo(): 61 | if admob != null: 62 | admob.loadRewardedVideo(AD_REWARDED_ID[platform_os]) 63 | 64 | # Events 65 | func _on_BtnBanner_toggled(pressed): 66 | if admob != null: 67 | if pressed: admob.showBanner() 68 | else: admob.hideBanner() 69 | 70 | func _on_BtnInterstitial_pressed(): 71 | if admob != null: 72 | admob.showInterstitial() 73 | 74 | func _on_BtnRewardedVideo_pressed(): 75 | if admob != null: 76 | admob.showRewardedVideo() 77 | 78 | func _on_admob_network_error(): 79 | print("Network Error") 80 | 81 | func _on_admob_ad_loaded(): 82 | print("Ad loaded success") 83 | if admob != null: 84 | prints("BannerWidth: " + str(admob.getBannerWidth()), "BannerHeight: " + str(admob.getBannerHeight())) 85 | get_node("CanvasLayer/BtnBanner").set_disabled(false) 86 | 87 | func _on_interstitial_not_loaded(): 88 | print("Error: Interstitial not loaded") 89 | 90 | func _on_interstitial_loaded(): 91 | print("Interstitial loaded") 92 | get_node("CanvasLayer/BtnInterstitial").set_disabled(false) 93 | 94 | func _on_interstitial_close(): 95 | print("Interstitial closed") 96 | get_node("CanvasLayer/BtnInterstitial").set_disabled(true) 97 | loadInterstitial() 98 | 99 | func _on_rewarded_video_ad_loaded(): 100 | print("Rewarded loaded success") 101 | get_node("CanvasLayer/BtnRewardedVideo").set_disabled(false) 102 | 103 | func _on_rewarded_video_ad_closed(): 104 | print("Rewarded closed") 105 | get_node("CanvasLayer/BtnRewardedVideo").set_disabled(true) 106 | loadRewardedVideo() 107 | 108 | func _on_rewarded(currency, amount): 109 | print("Reward: " + currency + ", " + str(amount)) 110 | get_node("CanvasLayer/LblRewarded").set_text("Reward: " + currency + ", " + str(amount)) 111 | 112 | 113 | # Resize the banner 114 | func _on_screen_resized(): 115 | if admob != null: 116 | admob.resize() # this function makes the banner load and show again, but with different size 117 | -------------------------------------------------------------------------------- /examples/godot-3/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://main.gd" type="Script" id=1] 4 | 5 | [node name="Node2D" type="Node2D" index="0"] 6 | 7 | script = ExtResource( 1 ) 8 | __meta__ = { 9 | "__editor_plugin_screen__": "3D" 10 | } 11 | 12 | [node name="CanvasLayer" type="CanvasLayer" parent="." index="0"] 13 | 14 | layer = 1 15 | offset = Vector2( 0, 0 ) 16 | rotation = 0.0 17 | scale = Vector2( 1, 1 ) 18 | transform = Transform2D( 1, 0, 0, 1, 0, 0 ) 19 | 20 | [node name="BtnBanner" type="Button" parent="CanvasLayer" index="0"] 21 | 22 | anchor_left = 0.0 23 | anchor_top = 0.0 24 | anchor_right = 0.0 25 | anchor_bottom = 0.0 26 | margin_left = 437.0 27 | margin_top = 220.0 28 | margin_right = 587.0 29 | margin_bottom = 295.0 30 | rect_pivot_offset = Vector2( 0, 0 ) 31 | rect_clip_content = false 32 | focus_mode = 2 33 | mouse_filter = 0 34 | mouse_default_cursor_shape = 0 35 | size_flags_horizontal = 1 36 | size_flags_vertical = 1 37 | disabled = true 38 | toggle_mode = true 39 | enabled_focus_mode = 2 40 | shortcut = null 41 | group = null 42 | text = "Show/Hide Banner" 43 | flat = false 44 | align = 1 45 | _sections_unfolded = [ "Rect" ] 46 | 47 | [node name="BtnInterstitial" type="Button" parent="CanvasLayer" index="1"] 48 | 49 | anchor_left = 0.0 50 | anchor_top = 0.0 51 | anchor_right = 0.0 52 | anchor_bottom = 0.0 53 | margin_left = 437.0 54 | margin_top = 305.0 55 | margin_right = 587.0 56 | margin_bottom = 380.0 57 | rect_pivot_offset = Vector2( 0, 0 ) 58 | rect_clip_content = false 59 | focus_mode = 2 60 | mouse_filter = 0 61 | mouse_default_cursor_shape = 0 62 | size_flags_horizontal = 1 63 | size_flags_vertical = 1 64 | disabled = true 65 | toggle_mode = false 66 | enabled_focus_mode = 2 67 | shortcut = null 68 | group = null 69 | text = "Show Interstitial" 70 | flat = false 71 | align = 1 72 | _sections_unfolded = [ "Rect" ] 73 | 74 | [node name="BtnRewardedVideo" type="Button" parent="CanvasLayer" index="2"] 75 | 76 | anchor_left = 0.0 77 | anchor_top = 0.0 78 | anchor_right = 0.0 79 | anchor_bottom = 0.0 80 | margin_left = 437.0 81 | margin_top = 394.0 82 | margin_right = 588.0 83 | margin_bottom = 469.0 84 | rect_pivot_offset = Vector2( 0, 0 ) 85 | rect_clip_content = false 86 | focus_mode = 2 87 | mouse_filter = 0 88 | mouse_default_cursor_shape = 0 89 | size_flags_horizontal = 1 90 | size_flags_vertical = 1 91 | disabled = true 92 | toggle_mode = false 93 | enabled_focus_mode = 2 94 | shortcut = null 95 | group = null 96 | text = "Show Rewarded Video" 97 | flat = false 98 | align = 1 99 | _sections_unfolded = [ "Rect" ] 100 | 101 | [node name="LblRewarded" type="Label" parent="CanvasLayer" index="3"] 102 | 103 | anchor_left = 0.0 104 | anchor_top = 0.0 105 | anchor_right = 0.0 106 | anchor_bottom = 0.0 107 | margin_right = 1026.0 108 | margin_bottom = 32.0 109 | rect_pivot_offset = Vector2( 0, 0 ) 110 | rect_clip_content = false 111 | mouse_filter = 2 112 | mouse_default_cursor_shape = 0 113 | size_flags_horizontal = 1 114 | size_flags_vertical = 4 115 | text = "REWARDED VIDEO RETURN" 116 | align = 1 117 | valign = 1 118 | percent_visible = 1.0 119 | lines_skipped = 0 120 | max_lines_visible = -1 121 | _sections_unfolded = [ "Rect" ] 122 | 123 | [connection signal="toggled" from="CanvasLayer/BtnBanner" to="." method="_on_BtnBanner_toggled"] 124 | 125 | [connection signal="pressed" from="CanvasLayer/BtnInterstitial" to="." method="_on_BtnInterstitial_pressed"] 126 | 127 | [connection signal="pressed" from="CanvasLayer/BtnRewardedVideo" to="." method="_on_BtnRewardedVideo_pressed"] 128 | 129 | 130 | -------------------------------------------------------------------------------- /examples/godot-3/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=3 10 | 11 | [android] 12 | 13 | modules="org/godotengine/godot/GodotAdMob" 14 | 15 | [application] 16 | 17 | config/name="testAdmob" 18 | run/main_scene="res://main.tscn" 19 | config/icon="res://icon.png" 20 | 21 | [display] 22 | 23 | window/handheld/orientation="sensor" 24 | window/stretch/mode="viewport" 25 | window/stretch/aspect="keep_height" 26 | -------------------------------------------------------------------------------- /issue_template.md: -------------------------------------------------------------------------------- 1 | **OS target (Android/iOS):** 2 | 3 | 4 | **Godot version:** 5 | 6 | 7 | **Issue description:** 8 | 9 | 10 | -------------------------------------------------------------------------------- /templates/README.md: -------------------------------------------------------------------------------- 1 | # Templates generated with Godot Engine 2.1 and Admob Module (Not Firebase) 2 | 3 | This templates are compiled using Godot 2.1 (Stable) and this module (Admob). 4 | 5 | For the compilation I change the minSDKVersion to 9 for reach more devices. 6 | 7 | For use this templates you can use the [Godot Documentation](http://docs.godotengine.org/en/stable/reference/compiling_for_android.html#installing-the-templates) for use the custom templates. 8 | 9 | :) 10 | -------------------------------------------------------------------------------- /templates/android_debug.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kloder-games/godot-admob/f5996ed22dfab457d611bc1f4f32d6305de3dcd2/templates/android_debug.apk -------------------------------------------------------------------------------- /templates/android_release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kloder-games/godot-admob/f5996ed22dfab457d611bc1f4f32d6305de3dcd2/templates/android_release.apk --------------------------------------------------------------------------------