as you know by using the Delphi Android JNI you can access to Native features provided by Android SDK. The RAD Studio installation includes also Google Mobile ADS library (Androidapi.JNI.AdMob unit), as built-in java library for Android.
So by using this unit we can use the new Interstitials Ads provided by AdMob.
First of all rember to set to true the AdMob Service ( Project -> Entitlement List -> AdMob Service )
Let's start with the code.
Create an instance of TJInterstitialAd, wich is present in Androidapi.JNI.AdMob.
FInterstitial := TJInterstitialAd.JavaClass.init(MainActivity); FInterstitial.setAdUnitId(StringToJString('Your-Publisher-ID'));
For example you can put the previous code in the FormCreate event. Then you have to use this code to display an Interstitial Ad (on button-click event in my demo):
var LADRequestBuilder: JAdRequest_Builder; LadRequest: JAdRequest; begin LADRequestBuilder := TJAdRequest_Builder.Create; LADRequestBuilder.addTestDevice(MainActivity.getDeviceID); LadRequest := LADRequestBuilder.build(); LAdViewListener := TMyAdViewListener.Create(FInterStitial); CallInUIThread( procedure begin FInterStitial.setAdListener(TJAdListenerAdapter.JavaClass.init (LAdViewListener)); FInterStitial.loadAd(LadRequest); end); end;
I used the TJAdRequest_Builder to create a request and set my device like a test device (see AdMob guidelines).
I also created a custom AdViewListener to intercept the interstitial events:
- onAdClosed;
- onAdFailedToLoad(errorCode: Integer);
- onAdLeftApplication;
- onAdOpened;
- onAdLoaded;
TJAdListenerAdapter adapts my Listener class to Interstitial AdListener, this because I created a custom class to support interstitial events and show effectively the Ad when it was loaded.
TMyAdViewListener = class(TJavaLocal, JIAdListener) private FAD: JInterstitialAd; public constructor Create(AAD: JInterstitialAd); procedure onAdClosed; cdecl; procedure onAdFailedToLoad(errorCode: Integer); cdecl; procedure onAdLeftApplication; cdecl; procedure onAdOpened; cdecl; procedure onAdLoaded; cdecl; end; procedure TMyAdViewListener.onAdLoaded; begin FAD.show; end;
Here the screenshot of interstitial on my phone:
This code should works also on AppMethod.
You can find the demo in my GitHub repository.
C++ ?
ReplyDeleteFor this tutorial I've used only the existing bridge files available for Delphi. You can find the same units in include\android\rtl (path for C++) and use them in the same way I did.
DeleteGreat tutorial, is there a link to download the demo project? (Delphi XE8)
ReplyDeleteI have added the demo in my GitHub repository https://github.com/spinettaro/DelphiDemos
DeleteHow to use without test mode.
ReplyDeleteI could not do it. Thanks
admob dont run on delphi 10 seatlle
ReplyDeleteI've been following this tutorial: Brilliant! Thanks!
ReplyDeleteBut I have one problem: Ads are shown in test mode... How to set test mode OFF?
Hi! Try to remove this line
DeleteLADRequestBuilder.addTestDevice(MainActivity.getDeviceID);
Hi!
ReplyDeleteGreat!!!! It works!
(I feel I should have found this myself in your code... :-S)
Really THANKS!!!
THANKS! THANKS!
You're welcome! I really like your enthusiasm!! :)
DeleteHi there I am done with a game for android and need to add admob advertising.
ReplyDeleteI am using c++, I having trouble with it. Banners and interstital doesnt seem to work.
Simple banner is not even working and i marked allow internet and admob to yes.
Please help.
Thanks.
Hi! What about Access Network State permission? It should be checked if I remember correctly...
DeleteThis comment has been removed by the author.
DeleteHi daniele, also my app crashes whenever it returns from opening an external link like email, go to url or interstial ad. i disabled timer and stopped mediaplayer too, but still have the problem
DeleteAlso have you done rewarded videos?
DeleteThanks, this was solved by editing the android manifest file and adding this :
DeleteThis comment has been removed by the author.
ReplyDeleteHi, I want to award the user for watching a video with gems in my game, do I use Interstitial or rewarded video in admob? If It is rewarded video, how do i implement so
ReplyDeleteHi! Yes you have to use Rewarded Video... I need to understand how it works and convert it to Delphi. I'll work on it, stay tuned!
DeleteThanks Daniele, I really apprecite it. As that will help me alot as this is the last main thing that is delaying my launch. Don't mean to sound like a nag, but do you have an approximation on how long this will take as you seem to be the only one worldwide that is clued up on how to do this.
ReplyDeleteHi Danielle Spinetti,
ReplyDeleteI found this to work with on ffg link. Would this help?
https://github.com/googleads/googleads-mobile-android-mediation/blob/e665019b3077f5456676677841531f45a6cae377/Example/adapter/src/main/java/com/google/ads/mediation/sample/adapter/SampleMediationRewardedVideoEventForwarder.java
Hi Daniele Spinetti,
ReplyDeleteI think this link should help more. I hope 1 of us can come with a solution on this. Thanks again
https://github.com/googleads/googleads-mobile-android-examples/blob/master/admob/RewardedVideoExample/app/src/main/java/com/google/ads/rewardedvideoexample/MainActivity.java
I also noticed on admob for example, you set the reward amount eg 5, and what the reward is ("Text) eg gems. and on the implementation the function gets this from admob. Last link i posted is the ultimate help on this
ReplyDeletehave this so far :
ReplyDeleteclass MainActivity : public Activity, public RewardedVideoAdListener
{
private:
//JAVA TO C++ CONVERTER TODO TASK: Native C++ does not allow initialization of static non-const/integral fields in their declarations:
static const std::wstring AD_UNIT_ID = L"ca-app-pub-3940256099942544/5224354917";
//JAVA TO C++ CONVERTER TODO TASK: Native C++ does not allow initialization of static non-const/integral fields in their declarations:
static const std::wstring APP_ID = L"ca-app-pub-3940256099942544~3347511713";
int mCoinCount = 0;
TextView *mCoinCountText; //change to edit1
RewardedVideoAd *mRewardedVideoAd;
// Button *mShowVideoButton; //change to button
public:
virtual ~MainActivity()
{
delete mCoinCountText;
delete mRewardedVideoAd;
delete mShowVideoButton;
}
// };
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
protected:
void onCreate(Bundle *savedInstanceState) override
{
__super::onCreate(savedInstanceState);
setContentView(R::layout::activity_main);
// Initialize the Mobile Ads SDK.
MobileAds::initialize(this, APP_ID);
mRewardedVideoAd = MobileAds::getRewardedVideoAdInstance(this);
mRewardedVideoAd::setRewardedVideoAdListener(this);
loadRewardedVideoAd();
}
private:
void loadRewardedVideoAd()
{
if (!mRewardedVideoAd::isLoaded())
{
AdRequest::Builder tempVar();
mRewardedVideoAd::loadAd(AD_UNIT_ID, (&tempVar)->build());
}
}
void addCoins(int coins)
{ //here we implement the adding of gems
mCoinCount = mCoinCount + coins; //change
//mCoinCountText::setText(L"Coins: " + mCoinCount); //change
mCoinCountText->Text=(L"Coins: " + mCoinCount);
}
void showRewardedVideo()
{
mShowVideoButton::setVisibility(View::INVISIBLE);
if (mRewardedVideoAd::isLoaded())
{
mRewardedVideoAd::show();
}
}
public:
void onRewardedVideoAdLeftApplication() override
{
Toast::makeText(this, L"onRewardedVideoAdLeftApplication", Toast::LENGTH_SHORT).show();
}
void onRewardedVideoAdClosed() override
{
Toast::makeText(this, L"onRewardedVideoAdClosed", Toast::LENGTH_SHORT).show();
// Preload the next video ad.
loadRewardedVideoAd();
}
void onRewardedVideoAdFailedToLoad(int errorCode) override
{
Toast::makeText(this, L"onRewardedVideoAdFailedToLoad", Toast::LENGTH_SHORT).show();
}
void onRewardedVideoAdLoaded() override
{
Toast::makeText(this, L"onRewardedVideoAdLoaded", Toast::LENGTH_SHORT).show();
}
void onRewardedVideoAdOpened() override
{
Toast::makeText(this, L"onRewardedVideoAdOpened", Toast::LENGTH_SHORT).show();
}
void onRewarded(RewardItem *reward) override
{
Toast::makeText(this, std::wstring::format(L" onRewarded! currency: %s amount: %d", reward->getType(), reward->getAmount()), Toast::LENGTH_SHORT).show();
addCoins(reward->getAmount());
}
void onRewardedVideoStarted() override
{
Toast::makeText(this, L"onRewardedVideoStarted", Toast::LENGTH_SHORT).show();
}
};
Hi Daniele,
ReplyDeleteAny luck with the rewarded video, can it be done on embarcadero?
Also My interstitial app crashes on some phones when closes. is there a way to restart app upon crash?
hi This code works very well. Thank you for sharing.
ReplyDeleteBut the device can be canceled with the back button. Do you have a solution to this already thank you very much.
Hi Daniele This code works very well. Thank you for sharing.
ReplyDeleteBut the device can be canceled with the back button. Do you have a solution to this already thank you very much.
Hi Daniele This code works very well. Thank you for sharing.
ReplyDeleteBut the device can be canceled with the back button. Do you have a solution to this already thank you very much.
How can I prevent the display from shutting down for 5-6 seconds? Does not this have knowledge?
ReplyDeletehi, i have rewarded video, interstitial and banner ads done thru aerserv integration. It fairs much better than admob. and you can add ad network mediations to it like admob etc. The event handling is much easier too. Basically you install a plugin. and it adds the component to the tools.
ReplyDeleteIs it possible to cancel the device back key on the right hand side?
DeleteI have done interstitial ads, videos, banner and rewarded video with aerserv. It works much better
ReplyDeleteMerhaba, ben uygulamayı çalıştırdım fakat sizin gibi geri tuş özelliğini kapatamadım. Videolar 15, 20, 30, 33 saniye gibi değişen sürelerde sonlanıyor. Bu arada siz bir çözüm bulabildiniz mi?
ReplyDeleteteşekkürler
Only English here, please...
Delete