Googleのガイドが間違っている。
背景
Google AdMob のリワード広告を公式のガイドを参考にして実装しようとしたらできなかった。
問題点
2021/03/23現在、下のサイトの広告を表示する
セクションのコードを実行してもonUserEarnedReward
が実行されない。
if (mRewardedAd != null){ mRewardedAd?.show(this, OnUserEarnedRewardListener() { fun onUserEarnedReward(rewardItem: RewardItem) { var rewardAmount = rewardItem.getReward() var rewardType = rewardItem.getType() Log.d("TAG", "User earned the reward.") } }) } else { Log.d("TAG", "The rewarded ad wasn't ready yet.") }
環境
- Android Studio 4.1.1
- Kotlin 1.3.72
- com.google.android.gms:play-services-ads:19.8.0
解決法
基本的に変更点はshowRewardedAd()
の中です。
1. 具象クラスを作ってインスタンスを入れる
package ..... ....... class MainActivity : AppCompatActivity() { // Admob private var mRewardedAd: RewardedAd? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) //Rewarded Ad loadRewardedAd() button.setOnClickListener { showRewardedAd() } } private fun loadRewardedAd() { val adRequest = AdRequest.Builder().build() RewardedAd.load(this, "ca-app-pub-3940256099942544/5224354917", adRequest, object : RewardedAdLoadCallback() { override fun onAdFailedToLoad(adError: LoadAdError) { Log.d("rewarded ads", adError.message) mRewardedAd = null } override fun onAdLoaded(rewardedAd: RewardedAd) { Log.d("rewarded ads", "Ad was loaded.") mRewardedAd = rewardedAd } }) mRewardedAd?.fullScreenContentCallback = object : FullScreenContentCallback() { override fun onAdDismissedFullScreenContent() { Log.d("rewarded ads", "Ad was dismissed.") } override fun onAdFailedToShowFullScreenContent(adError: AdError?) { Log.d("rewarded ads", "Ad failed to show.") } override fun onAdShowedFullScreenContent() { Log.d("rewarded ads", "Ad showed fullscreen content.") // Called when ad is dismissed. // Don't set the ad reference to null to avoid showing the ad a second time. mRewardedAd = null } } } private fun showRewardedAd() { if (mRewardedAd != null) { mRewardedAd?.show(this, OnUserEarnedRewardListenerImpl()) } else { Log.d("TAG", "The rewarded ad wasn't ready yet.") } } } class OnUserEarnedRewardListenerImpl() : OnUserEarnedRewardListener { override fun onUserEarnedReward(rewardItem: RewardItem) { var rewardAmount = rewardItem.amount var rewardType = rewardItem.type Log.d("TAG", "User earned the reward.") } }
2. object
を使ってOnUserEarnedRewardListener
を継承する無名クラスのインスタンスを作る
package ..... ....... class MainActivity : AppCompatActivity() { // Admob private var mRewardedAd: RewardedAd? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) //Rewarded Ad loadRewardedAd() button.setOnClickListener { showRewardedAd() } } private fun loadRewardedAd() { val adRequest = AdRequest.Builder().build() RewardedAd.load(this, "ca-app-pub-3940256099942544/5224354917", adRequest, object : RewardedAdLoadCallback() { override fun onAdFailedToLoad(adError: LoadAdError) { Log.d("rewarded ads", adError.message) mRewardedAd = null } override fun onAdLoaded(rewardedAd: RewardedAd) { Log.d("rewarded ads", "Ad was loaded.") mRewardedAd = rewardedAd } }) mRewardedAd?.fullScreenContentCallback = object : FullScreenContentCallback() { override fun onAdDismissedFullScreenContent() { Log.d("rewarded ads", "Ad was dismissed.") } override fun onAdFailedToShowFullScreenContent(adError: AdError?) { Log.d("rewarded ads", "Ad failed to show.") } override fun onAdShowedFullScreenContent() { Log.d("rewarded ads", "Ad showed fullscreen content.") // Called when ad is dismissed. // Don't set the ad reference to null to avoid showing the ad a second time. mRewardedAd = null } } } private fun showRewardAd() { if (mRewardedAd != null) { mRewardedAd?.show(this, object:OnUserEarnedRewardListener { override fun onUserEarnedReward(rewardItem: RewardItem) { var rewardAmount = rewardItem.amount var rewardType = rewardItem.type Log.d("TAG", rewardItem.toString()) Log.d("TAG", "User earned the reward.") } }) } else { Log.d("TAG", "The rewarded ad wasn't ready yet.") } } }
3. ラムダ式を用いて記述する
package ..... ....... class MainActivity : AppCompatActivity() { // Admob private var mRewardedAd: RewardedAd? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) //Rewarded Ad loadRewardedAd() button.setOnClickListener { showRewardedAd() } } private fun loadRewardedAd() { val adRequest = AdRequest.Builder().build() RewardedAd.load(this, "ca-app-pub-3940256099942544/5224354917", adRequest, object : RewardedAdLoadCallback() { override fun onAdFailedToLoad(adError: LoadAdError) { Log.d("rewarded ads", adError.message) mRewardedAd = null } override fun onAdLoaded(rewardedAd: RewardedAd) { Log.d("rewarded ads", "Ad was loaded.") mRewardedAd = rewardedAd } }) mRewardedAd?.fullScreenContentCallback = object : FullScreenContentCallback() { override fun onAdDismissedFullScreenContent() { Log.d("rewarded ads", "Ad was dismissed.") } override fun onAdFailedToShowFullScreenContent(adError: AdError?) { Log.d("rewarded ads", "Ad failed to show.") } override fun onAdShowedFullScreenContent() { Log.d("rewarded ads", "Ad showed fullscreen content.") // Called when ad is dismissed. // Don't set the ad reference to null to avoid showing the ad a second time. mRewardedAd = null } } } private fun showRewardAd() { if (mRewardedAd != null) { mRewardedAd?.show(this) { rewardItem -> var rewardAmount = rewardItem.amount var rewardType = rewardItem.type Log.d("TAG", rewardItem.toString()) Log.d("TAG", "User earned the reward.") } } else { Log.d("TAG", "The rewarded ad wasn't ready yet.") } } }
詳細
OnUserEarnedRewardListener
を見るとJavaで記述されたinterfaceになっている。よって、具象クラスを作り、onUserEarnedReward
メソッドをoverrideすることで任意のメソッドを作成することができる。
他にもKotlinではobject
を用いるとOnUserEarnedRewardListener
を継承する無名クラスのインスタンスを作ることができる。
また、KotlinにSAM変換があることにより、ラムダ式で記述することができる。
Kotlin 1.3系ではJavaで記述されたsingle methodしか変換できないがKotlin 1.4系ではKotlinで記述されたsingle methodも変換できるらしい。
ガイドに記述されていたJavaのコードをAndroid StudioにコピペしてKotlinへ自動変換すると同一のKotlinコードに変換された。 よって、今回のGoogleのガイドが間違っていたのは、JavaからKotlinへ自動変換し、そのコードを確認せずにガイドとして表記していることが原因として考えられる。(あくまで個人的な一説です。)