InterstitialAd возвращает null даже после загрузки

Я загрузил межстраничное объявление в начале действия, но когда я его показываю, оно возвращает нулевое значение. Журнал.

2022-11-18 09:53:45.102 18604-18604/com.blogspot.bunnylists.maate D/ADAD: Ad was loaded.
2022-11-18 09:54:17.358 18604-18604/com.blogspot.bunnylists.maate D/ADAD: The interstitial wasn't loaded yet.

Приложение представляет собой приложение с одним действием. Я следовал официальной документации по внедрению межстраничной рекламы. Весь код, связанный с рекламой, находится в MainActivity. После нажатия кнопки я показываю полноэкранный фрагмент в MainActivityLayout. Я реализовал ReyclerView в этом фрагменте. Когда recyclerView загрузил некоторое количество просмотров на экране, я хочу показать объявление. Я вызываю метод showAd() класса MainActivity внутри метода onBindViewHolder.

class MainActivity : AppCompatActivity() {
    private lateinit var bind : ActivityMainBinding
    private lateinit var viewModel: MainActivityViewModel
    private var mInterstitialAd: InterstitialAd? = null
    val TAG = "ADAD"
    val adRequest = AdRequest.Builder().build()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        bind = DataBindingUtil.setContentView(this, com.blogspot.bunnylists.maate.R.layout.activity_main)
        val repository = (application as MyApplication).repository
        viewModel = ViewModelProvider(this, MyViewModelFactory(repository, "MainActivity"))[MainActivity2ViewModel::class.java]

        //Here I am loading the Ad at the creation of the MainActivity
        loadAd()

        mInterstitialAd?.fullScreenContentCallback = object: FullScreenContentCallback() {
            override fun onAdClicked() {
                // Called when a click is recorded for an ad.
                Log.d(TAG, "Ad was clicked.")
            }

            override fun onAdDismissedFullScreenContent() {
                // Called when ad is dismissed.
                Log.d(TAG, "Ad dismissed fullscreen content.")
                mInterstitialAd = null
            }

            override fun onAdFailedToShowFullScreenContent(p0: AdError) {
                // Called when ad fails to show.
                Log.e(TAG, "Ad failed to show fullscreen content.")
                mInterstitialAd = null
            }

            override fun onAdImpression() {
                // Called when an impression is recorded for an ad.
                Log.d(TAG, "Ad recorded an impression.")
            }

            override fun onAdShowedFullScreenContent() {
                // Called when ad is shown.
                Log.d(TAG, "Ad showed fullscreen content.")
            }
        }

    }

   // The method which is called from the onBindViewHolder
    fun showAd() {
        if (mInterstitialAd != null) {
            Log.d(TAG, "showing Ad")
            mInterstitialAd?.show(this)
            loadAd()
        } else {
            Log.d(TAG, "The interstitial wasn't loaded yet.")
        }
    }

    private fun loadAd(){
        InterstitialAd.load(this,
            "ca-app-pub-3940256099942544/1033173712",
            adRequest,
            object : InterstitialAdLoadCallback() {
                override fun onAdFailedToLoad(adError: LoadAdError) {
                    Log.d(TAG, adError.toString())
                    mInterstitialAd = null
                }

                override fun onAdLoaded(interstitialAd: InterstitialAd) {
                    Log.d(TAG, "Ad was loaded.")
                    mInterstitialAd = interstitialAd
                }
            })
    }
}

onBindViewHolder:

override fun onBindViewHolder(holder: MyViewHolder, position: Int){
    if (position%20==0){
       MainActivity().showAd()
    }
}

Вы создаете новую активность, вызывая ее конструктор, что вы никогда не должны делать и не будет работать (и может вызвать сбои). Вместо этого вам нужно открыть свойство слушателя из вашего адаптера. Activity может передать ему прослушиватель, который вызывает showAd(). Вы можете найти примеры шаблона прослушивателя кликов с помощью адаптеров, но просто измените его на прослушиватель, когда показывать рекламу.

Tenfour04 18.11.2022 06:53

Также вам нужно добавить свой полноэкранный обратный вызов внутри вашего AdLoadedCallback. В настоящее время вы вообще не добавляете его, потому что вы добавляете его с нулевым безопасным вызовом в то время, когда объявление является нулевым.

Tenfour04 18.11.2022 06:56

Не могли бы вы поделиться некоторыми ресурсами, я не понял, что вы пытаетесь сказать.

ApunichGULSHER 18.11.2022 07:18
0
3
73
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Никогда не делайте этого:

MainActivity()

Вышеупомянутое создает экземпляр Activity, вызывая его конструктор. Это имеет две проблемы:

  1. Это не тот экземпляр, с которым вы работали, поэтому он не был настроен для ваших объявлений.
  2. Если он не создан ОС, значит, он настроен неправильно. Он полон нулевых объектов, которые не должны быть нулевыми, поэтому он очень подвержен сбоям. Это также просто бессмысленно, потому что вы не используете его как Activity — нет никакого способа получить созданный вами экземпляр Activity на экране.

Вам нужно открыть обратный вызов, показывающий рекламу, от вашего адаптера и вызвать его вместо этого:

class MyAdapter: RecyclerView.Adapter<SomeType, SomeViewHolder>() {

    var onRequestAd: (()->Unit)? = null

    override fun onBindViewHolder(holder: MyViewHolder, position: Int){
        if (position%20==0){
           onRequestAd?.invoke()
        }
        //...
    }
}

Затем в своей деятельности, сразу после создания экземпляра адаптера, вы должны настроить прослушиватель на вызов showAd():

val adapter = MyAdapter()
adapter.onRequestAd = ::showAd // or { showAd() }
bind.adapter = adapter

Отдельную проблему я упомянул в ваших комментариях. В этой строке:

mInterstitialAd?.fullScreenContentCallback = object: FullScreenContentCallback() {

вы звоните в тот момент, когда mInterstitialAd все еще имеет значение null, поэтому он ничего не делает, и ваш обратный вызов никогда не используется. Вам нужно переместить этот код внутрь функции обратного вызова onAdLoaded, чтобы он добавлялся к объявлению после его создания и добавлялся каждый раз, когда вы загружаете новое объявление.


Кстати, вам может понадобиться более сложный способ определения времени показа рекламы. Как бы то ни было, я думаю, что если 20-й элемент находится за пределами экрана, а пользователь покачивает его вверх и вниз, он будет запрашивать рекламу снова и снова. Вы можете добавить таймер, например:

private var lastAdTime = 0L

override fun onBindViewHolder(holder: MyViewHolder, position: Int){
    if (position%20==0 && lastAdTime + 3000 < System.currentTimeMillis()){
       onRequestAd()
       lastAdTime = System.currentTimeMillis()
    }
}

Большое спасибо за то, что уделили свое драгоценное время.

ApunichGULSHER 19.11.2022 05:44

Не могли бы вы также взглянуть и дать несколько советов по этому вопросу: stackoverflow.com/q/74485942/16350333

ApunichGULSHER 19.11.2022 09:56

Другие вопросы по теме