Browse Source

【GroMore】优化原生广告AdView加载使用

liuxiaolong 1 year ago
parent
commit
80d4977bf7
50 changed files with 1098 additions and 620 deletions
  1. 1 1
      app/build.gradle
  2. 4 0
      app/src/main/AndroidManifest.xml
  3. 54 1
      app/src/main/java/com/convenient/android/lib/LibApplication.kt
  4. 2 11
      app/src/main/java/com/convenient/android/lib/ui/sample/ad/AdMainActivity.kt
  5. 7 15
      app/src/main/java/com/convenient/android/lib/ui/sample/ad/activity/AdBannerActivity.kt
  6. 112 0
      app/src/main/java/com/convenient/android/lib/ui/sample/ad/activity/AdFeedActivity.kt
  7. 18 7
      app/src/main/java/com/convenient/android/lib/ui/sample/ad/adapter/NativeAdSampleListAdapter.kt
  8. 14 10
      app/src/main/java/com/convenient/android/lib/ui/sample/ad/model/Datas.kt
  9. 128 44
      app/src/main/java/com/convenient/android/lib/ui/sample/ad/page/AdHomePage.kt
  10. 14 0
      app/src/main/java/com/convenient/android/lib/ui/sample/ad/viewmodel/AdConfigViewModel.kt
  11. 14 14
      app/src/main/res/layout/activity_ad_banner.xml
  12. 78 0
      app/src/main/res/layout/activity_ad_feed.xml
  13. 5 3
      app/src/main/res/layout/activity_ad_native.xml
  14. 5 9
      app/src/main/res/layout/activity_ad_native_template.xml
  15. 4 3
      app/src/main/res/layout/view_rv_ad_native_item.xml
  16. 4 13
      app/src/main/res/layout/view_rv_ad_native_template_item.xml
  17. 0 18
      lib_ad_admob/src/main/java/com/composition/android/ad/admob/impl/AdmobAdSize.kt
  18. 19 4
      lib_ad_admob/src/main/java/com/composition/android/ad/admob/load/AdmobAdLoader.kt
  19. 21 7
      lib_ad_admob/src/main/java/com/composition/android/ad/admob/load/request/AdmobBannerRequestImpl.kt
  20. 35 22
      lib_ad_admob/src/main/java/com/composition/android/ad/admob/load/view/AdmobBannerView.kt
  21. 1 1
      lib_ad_admob/src/main/java/com/composition/android/ad/admob/load/view/AdmobNativeAdView.kt
  22. 0 12
      lib_ad_admob/src/main/java/com/composition/android/ad/admob/util/AdmobAdExpan.kt
  23. 1 1
      lib_ad_applovinmax/build.gradle
  24. 10 0
      lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/AppLovinMaxLoader.kt
  25. 47 37
      lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/view/AppLovinMaxBannerView.kt
  26. 1 4
      lib_ad_core/src/main/java/com/composition/android/lib/ad/AdManager.kt
  27. 5 0
      lib_ad_core/src/main/java/com/composition/android/lib/ad/basic/AdType.kt
  28. 0 5
      lib_ad_core/src/main/java/com/composition/android/lib/ad/basic/Advertisers.kt
  29. 2 3
      lib_ad_core/src/main/java/com/composition/android/lib/ad/bean/AdUnitBean.kt
  30. 20 21
      lib_ad_core/src/main/java/com/composition/android/lib/ad/interfaces/IAdSize.kt
  31. 8 0
      lib_ad_core/src/main/java/com/composition/android/lib/ad/util/AdCoreExtenstions.kt
  32. 126 94
      lib_ad_core/src/main/java/com/composition/android/lib/ad/widget/NativeAdView.kt
  33. 0 111
      lib_ad_core/src/main/java/com/composition/android/lib/ad/widget/BannerAdView.kt
  34. 27 7
      lib_ad_core/src/main/res/values/attr.xml
  35. 0 17
      lib_ad_csj/src/main/java/com/composition/android/ad/csj/impl/CSJBannerAdSize.kt
  36. 0 17
      lib_ad_csj/src/main/java/com/composition/android/ad/csj/impl/CSJNativeAdImageSize.kt
  37. 5 6
      lib_ad_csj/src/main/java/com/composition/android/ad/csj/load/request/CSJBannerRequestImpl.kt
  38. 4 6
      lib_ad_csj/src/main/java/com/composition/android/ad/csj/load/request/CSJNativeRequestImpl.kt
  39. 12 13
      lib_ad_csj/src/main/java/com/composition/android/ad/csj/load/request/CSJNativeTemplateRequestImpl.kt
  40. 0 19
      lib_ad_csj/src/main/java/com/composition/android/ad/csj/util/CSJAdExpan.kt
  41. 0 16
      lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/impl/GMAdImageSize.kt
  42. 25 19
      lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/load/GroMoreAdLoader.kt
  43. 7 2
      lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/load/request/GMBannerRequestImpl.kt
  44. 55 0
      lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/load/request/GMFeedRequestImpl.kt
  45. 6 7
      lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/load/request/GMNativeRequestImpl.kt
  46. 5 7
      lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/load/request/GMNativeTemplateRequestImpl.kt
  47. 190 0
      lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/load/view/GMTTFeedAdView.kt
  48. 1 1
      lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/load/view/CSJNativeAdView.kt
  49. 0 11
      lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/util/GMAdExpan.kt
  50. 1 1
      settings.gradle

+ 1 - 1
app/build.gradle

@@ -139,7 +139,7 @@ dependencies {
     //广告
     implementation project(':lib_ad_core')
     implementation project(':lib_ad_admob')
-    implementation project(':lib_ad_csj')
+//    implementation project(':lib_ad_csj')
     implementation project(':lib_ad_applovinmax')
     implementation project(':lib_ad_gromore')
     implementation project(':lib_ad_gromore_beizis')

+ 4 - 0
app/src/main/AndroidManifest.xml

@@ -65,6 +65,10 @@
         <activity
             android:name=".ui.sample.ad.activity.AdNativeActivity"
             android:exported="false" />
+
+        <activity
+            android:name=".ui.sample.ad.activity.AdFeedActivity"
+            android:exported="false" />
         <activity
             android:name=".ui.sample.ad.activity.AdBannerActivity"
             android:exported="false" />

+ 54 - 1
app/src/main/java/com/convenient/android/lib/LibApplication.kt

@@ -1,12 +1,22 @@
 package com.convenient.android.lib
 
+import android.app.Activity
 import android.app.Application
+import android.content.Context
 import android.content.Intent
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
 import androidx.lifecycle.*
 import com.composition.android.lib.ad.AdLoad
+import com.composition.android.lib.ad.AdUnitConfigManager
+import com.convenient.android.common.base.ActivitysUtils
 import com.convenient.android.common.extension.readyGo
 import com.convenient.android.lib.ui.sample.ad.activity.AppWelcomeActivity
 import com.convenient.android.lib.ui.sample.ad.model.Datas
+import com.google.android.gms.analytics.GoogleAnalytics
+import com.gyf.immersionbar.ImmersionBar
+import com.orhanobut.logger.Logger
+import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
 
 /**
@@ -17,8 +27,16 @@ import kotlinx.coroutines.launch
  */
 class LibApplication : Application(), LifecycleEventObserver {
 
+    companion object{
+
+        lateinit var context: Context
+
+    }
+
     override fun onCreate() {
         super<Application>.onCreate()
+        context = applicationContext
+        registerActivityLifecycleCallbacks()
         ProcessLifecycleOwner.get().lifecycle.addObserver(this)
     }
 
@@ -37,7 +55,9 @@ class LibApplication : Application(), LifecycleEventObserver {
             Lifecycle.Event.ON_PAUSE->{
                 if (Datas.bgShowAppOpen){
                     ProcessLifecycleOwner.get().lifecycleScope.launch {
-                        AdLoad.preloadAd(this@LibApplication, Datas.APP_OPEN)
+                        ActivitysUtils.current()?.let {
+                            AdLoad.preloadAd(it, Datas.APP_OPEN)
+                        }
                     }
                 }
             }
@@ -48,4 +68,37 @@ class LibApplication : Application(), LifecycleEventObserver {
         }
     }
 
+
+    private fun registerActivityLifecycleCallbacks() {
+
+        registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
+
+            override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
+
+            override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
+                ActivitysUtils.add(activity = activity)
+            }
+
+
+            override fun onActivityStarted(activity: Activity) {
+
+            }
+
+            override fun onActivityResumed(activity: Activity) {}
+
+            override fun onActivityPaused(activity: Activity) {}
+
+            override fun onActivityStopped(activity: Activity) {
+
+            }
+
+            override fun onActivityDestroyed(activity: Activity) {
+                ActivitysUtils.remove(activity = activity)
+
+            }
+
+        })
+    }
+
+
 }

+ 2 - 11
app/src/main/java/com/convenient/android/lib/ui/sample/ad/AdMainActivity.kt

@@ -5,7 +5,7 @@ import android.util.Log
 import androidx.activity.compose.setContent
 import androidx.appcompat.app.AppCompatActivity
 import com.composition.android.ad.admob.impl.AdmobInitialize
-import com.composition.android.ad.csj.impl.CSJInitialize
+import com.composition.android.ad.applovinmax.impl.AppLovinMaxInitialize
 import com.composition.android.ad.gromore.impl.GroMoreInitialize
 import com.composition.android.lib.ad.AdManager
 import com.composition.android.lib.ad.AdUnitConfigManager
@@ -28,18 +28,9 @@ class AdMainActivity : AppCompatActivity() {
 
     private fun initAd() {
         AdManager.instance.init(applicationContext, true)
-        AdManager.instance.initAdvertisersSDK(applicationContext, AdmobInitialize(), GroMoreInitialize("5089223"))
-        val list = mutableListOf<AdUnitBean>()
-//        list.addAll(Datas.AdmobAdUnitList)
-//        list.addAll(Datas.CSJAdUnitList)
-        list.addAll(Datas.GroMoreAdUnitList)
-//        list.addAll(Datas.AppLovinMaxAdUnitList)
-        AdUnitConfigManager.instance.setAdUnits(list)
-
+        AdManager.instance.initAdvertisersSDK(applicationContext, AdmobInitialize(), GroMoreInitialize("5089223"), AppLovinMaxInitialize())
         AdManager.instance.addGlobalAdShowListener {
             Log.e("广告全局展示监听", "广告位名称:${it.adSlotName}\n广告商:${it.advertisersName}\n广告id:${it.adUnitId}\n广告类型:${it.adType}")
         }
     }
-
-
 }

+ 7 - 15
app/src/main/java/com/convenient/android/lib/ui/sample/ad/activity/AdBannerActivity.kt

@@ -10,6 +10,7 @@ import com.composition.android.lib.ad.basic.buildBannerAdViewHolder
 import com.composition.android.lib.ad.impl.NormalAdListener
 import com.composition.android.lib.ad.util.adLogE
 import com.convenient.android.common.base.viewbinding.BaseBindingActivity
+import com.convenient.android.common.extension.readyGo
 import com.convenient.android.common.extension.setViewsClick
 import com.convenient.android.common.utils.ToastUtil
 import com.convenient.android.lib.R
@@ -32,6 +33,11 @@ class AdBannerActivity : BaseBindingActivity<ActivityAdBannerBinding>(ActivityAd
         super.onCreate(savedInstanceState)
         setViewsClick({
             when (it.id) {
+                R.id.btn_load_native_in_recyclerview->{
+                    readyGo(AdNativeListActivity::class.java){
+                        it.putExtra("ad_slot_name", Datas.BANNER)
+                    }
+                }
                 R.id.btn_load_banner -> {
                     loadBanner()
                 }
@@ -41,23 +47,9 @@ class AdBannerActivity : BaseBindingActivity<ActivityAdBannerBinding>(ActivityAd
                         showBanner()
                     }
                 }
-                R.id.btn_load_and_show -> {
-                    lifecycleScope.launch {
-                        binding.llAdContent.removeAllViews()
-                        delay(1000)
-                        loadBanner(true)
-
-                        //第二种方法, 直接添加BannerAdView, 指定广告位后自动加载并展示
-//                        val bannerAdView = BannerAdView(context = this@AdBannerActivity)
-//                        bannerAdView.setAdSlotName(Datas.BANNER)
-//                        binding.llAdContent.addView(bannerAdView)
-//                        binding.llAdContent.isVisible = true
-
-                    }
-                }
             }
 
-        }, binding.btnLoadBanner, binding.btnShowBanner, binding.btnLoadAndShow)
+        }, binding.btnLoadBanner, binding.btnShowBanner, binding.btnLoadNativeInRecyclerview)
     }
 
     private fun loadBanner(show: Boolean = false) {

+ 112 - 0
app/src/main/java/com/convenient/android/lib/ui/sample/ad/activity/AdFeedActivity.kt

@@ -0,0 +1,112 @@
+package com.convenient.android.lib.ui.sample.ad.activity
+
+import android.os.Bundle
+import androidx.core.view.isVisible
+import androidx.lifecycle.lifecycleScope
+import com.composition.android.lib.ad.AdLoad
+import com.composition.android.lib.ad.AdManager
+import com.composition.android.lib.ad.basic.AdResult
+import com.composition.android.lib.ad.basic.buildAdNativeViewHolder
+import com.composition.android.lib.ad.impl.NormalAdListener
+import com.composition.android.lib.ad.util.adLogE
+import com.convenient.android.common.base.viewbinding.BaseBindingActivity
+import com.convenient.android.common.extension.readyGo
+import com.convenient.android.common.extension.setViewsClick
+import com.convenient.android.common.utils.ToastUtil
+import com.convenient.android.lib.R
+import com.convenient.android.lib.databinding.ActivityAdFeedBinding
+import com.convenient.android.lib.databinding.ViewAdNativeBinding
+import com.convenient.android.lib.ui.sample.ad.model.Datas
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+/**
+ * @classname:
+ * @author: LiuXiaoLong
+ * @date: 2022/9/6
+ * description: 横幅广告示例
+ */
+class AdFeedActivity : BaseBindingActivity<ActivityAdFeedBinding>(ActivityAdFeedBinding::inflate) {
+
+    private var adResult: AdResult.Success? = null
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setViewsClick({
+            when (it.id) {
+                R.id.btn_load_native_in_recyclerview->{
+                    readyGo(AdNativeListActivity::class.java){
+                        it.putExtra("ad_slot_name", Datas.FEED)
+                    }
+                }
+                R.id.btn_load_native -> {
+                    loadFeedAd { success ->
+                        adResult = success
+                    }
+                }
+                R.id.btn_show_native -> {
+                    lifecycleScope.launch {
+                        delay(1000)
+                        showFeedAd()
+                    }
+                }
+                R.id.btn_load_and_show -> {
+                    lifecycleScope.launch {
+                        binding.llAdContent.removeAllViews()
+                        delay(1000)
+                        loadFeedAd {
+                            adResult = it
+                            showFeedAd()
+                        }
+                    }
+                }
+            }
+        }, binding.btnLoadNative, binding.btnShowNative, binding.btnLoadAndShow,binding.btnLoadNativeInRecyclerview)
+    }
+
+    private fun loadFeedAd(success: (AdResult.Success) -> Unit) {
+        lifecycleScope.launch {
+            AdLoad.loadAd(this@AdFeedActivity, Datas.FEED)
+                .collect {
+                    if (it is AdResult.Success) {
+                        ToastUtil.showLongToast(this@AdFeedActivity, "加载原生广告成功")
+                        success.invoke(it)
+                    } else {
+                        adLogE(AdManager.TAG, it.msg)
+                    }
+                }
+        }
+    }
+
+    private fun showFeedAd() {
+        adResult?.let {
+            val nativeViewBinding = ViewAdNativeBinding.inflate(layoutInflater)
+            val viewHolder = buildAdNativeViewHolder {
+                this.customLayoutRootView = nativeViewBinding.root
+                this.titleView = nativeViewBinding.tvAdTitle
+                this.titleDescView = nativeViewBinding.tvAdTitleDesc
+                this.iconView = nativeViewBinding.ivAdIcon
+                this.contentMediaViewGroup = nativeViewBinding.flAdMediaContent
+                this.callActionButtonView = nativeViewBinding.btnCallToAction
+                this.dislikeView
+                this.activity= this@AdFeedActivity
+                this.adListener = object : NormalAdListener(){
+                    override fun onAdDisLike() {
+                        super.onAdDisLike()
+                        binding.llAdContent.isVisible = false
+                        binding.llAdContent.removeAllViews()
+                    }
+                }
+            }
+
+            AdLoad.getNativeAdView(this, it, viewHolder)?.let {
+                binding.llAdContent.removeAllViews()
+                binding.llAdContent.addView(it)
+                binding.llAdContent.isVisible = true
+            }
+
+        } ?: ToastUtil.showLongToast(this, "请先加载广告")
+    }
+
+
+}

+ 18 - 7
app/src/main/java/com/convenient/android/lib/ui/sample/ad/adapter/NativeAdSampleListAdapter.kt

@@ -61,12 +61,26 @@ class NativeAdSampleListAdapter() : RecyclerView.Adapter<RecyclerView.ViewHolder
                 }
             }
             ITEM_NATIVE_AD->{
-                (holder as BindingViewHolder<ViewRvAdNativeItemBinding>)
-                    .binding.nativeAdView.populateNativeAd(lists[position].success!!)
+                (holder as BindingViewHolder<ViewRvAdNativeItemBinding>).apply {
+                    binding.nativeAdView.populateAd(lists[position].success!!)
+                    binding.nativeAdView.setAdListener {
+                        onAdDisLike {
+                            lists.removeAt(holder.bindingAdapterPosition)
+                            notifyItemRemoved(holder.bindingAdapterPosition)
+                        }
+                    }
+                }
             }
             else->{
-                (holder as BindingViewHolder<ViewRvAdNativeTemplateItemBinding>)
-                    .binding.nativeAdView.populateNativeAd(lists[position].success!!)
+                (holder as BindingViewHolder<ViewRvAdNativeTemplateItemBinding>).apply {
+                    binding.nativeAdView.populateAd(lists[position].success!!)
+                    binding.nativeAdView.setAdListener {
+                        onAdDisLike {
+                            lists.removeAt(holder.bindingAdapterPosition)
+                            notifyItemRemoved(holder.bindingAdapterPosition)
+                        }
+                    }
+                }
             }
         }
     }
@@ -74,7 +88,4 @@ class NativeAdSampleListAdapter() : RecyclerView.Adapter<RecyclerView.ViewHolder
     override fun getItemCount(): Int {
         return lists.size
     }
-
-
-
 }

+ 14 - 10
app/src/main/java/com/convenient/android/lib/ui/sample/ad/model/Datas.kt

@@ -1,8 +1,6 @@
 package com.convenient.android.lib.ui.sample.ad.model
 
 import android.content.Context
-import com.composition.android.ad.csj.util.buildCSJBannerAdSize
-import com.composition.android.ad.gromore.util.buildGroMoreAdImageSize
 import com.composition.android.lib.ad.AdLoad
 import com.composition.android.lib.ad.basic.AdResult
 import com.composition.android.lib.ad.basic.AdType
@@ -10,7 +8,9 @@ import com.composition.android.lib.ad.basic.Advertisers
 import com.composition.android.lib.ad.bean.AdUnitBean
 import com.composition.android.lib.ad.bean.AdUnitLoadConfig
 import com.composition.android.lib.ad.interfaces.AdSize
+import com.convenient.android.common.extension.getScreenWidth
 import com.convenient.android.common.media.MediaBean
+import com.convenient.android.lib.LibApplication
 import com.convenient.android.lib.ui.sample.ad.adapter.NativeAdSampleListAdapter
 import kotlinx.coroutines.flow.firstOrNull
 import kotlin.random.Random
@@ -38,6 +38,7 @@ object Datas {
     val BANNER = "banner"
     val NATIVE = "native"
     val NATIVE_TEMPLATE = "NativeTemplate"
+    val FEED = "feed"
     val INTERSTITIAL = "interstitial"
     val REWARDED_VIDEO = "rewarded_video"
     val REWARDED_INTERSTITIAL = "rewarded_interstitial"
@@ -57,21 +58,22 @@ object Datas {
 
     val CSJAdUnitList: List<AdUnitBean> =
         listOf(
-            AdUnitBean(BANNER, Advertisers.CSJ.name, AdType.BANNER.name, "946203930", adSize = AdSize.Builder.create().buildCSJBannerAdSize(600F, 90F)),
-            AdUnitBean(NATIVE, Advertisers.CSJ.name, AdType.NATIVE.name, "946203930", adSize = AdSize.Builder.create().buildCSJBannerAdSize(600F, 90F)),
-            AdUnitBean(NATIVE_TEMPLATE, Advertisers.CSJ.name, AdType.NATIVE_TEMPLATE.name, "945777279"),
-            AdUnitBean(INTERSTITIAL, Advertisers.CSJ.name, AdType.INTERSTITIAL.name, "946096767"),
-            AdUnitBean(REWARDED_VIDEO, Advertisers.CSJ.name, AdType.REWARDED_VIDEO.name, "949726565"),
-            AdUnitBean(APP_OPEN, Advertisers.CSJ.name, AdType.APP_OPEN.name, "887352035", requestAdConfig = AdUnitLoadConfig(adLoadRetryCount = 1, adLoadTimeOut = 5000))
+            AdUnitBean(BANNER, Advertisers.GroMore.name, AdType.BANNER.name, "946203930", adSize = AdSize(600, 90)),
+            AdUnitBean(NATIVE, Advertisers.GroMore.name, AdType.NATIVE.name, "946061659", adSize = AdSize(600, 90)),
+            AdUnitBean(NATIVE_TEMPLATE, Advertisers.GroMore.name, AdType.NATIVE_TEMPLATE.name, "945777279"),
+            AdUnitBean(INTERSTITIAL, Advertisers.GroMore.name, AdType.INTERSTITIAL.name, "946096767"),
+            AdUnitBean(REWARDED_VIDEO, Advertisers.GroMore.name, AdType.REWARDED_VIDEO.name, "949726565"),
+            AdUnitBean(APP_OPEN, Advertisers.GroMore.name, AdType.APP_OPEN.name, "887352035", requestAdConfig = AdUnitLoadConfig(adLoadRetryCount = 1, adLoadTimeOut = 5000))
         )
 
     val GroMoreAdUnitList: List<AdUnitBean> =
         listOf(
-            AdUnitBean(BANNER, Advertisers.GroMore.name, AdType.BANNER.name, "102217403", adSize = AdSize.Builder.create().buildGroMoreAdImageSize(600, 90)),
+            AdUnitBean(BANNER, Advertisers.GroMore.name, AdType.BANNER.name, "102217403", adSize = AdSize(LibApplication.context.getScreenWidth(), 600)),
             AdUnitBean(INTERSTITIAL, Advertisers.GroMore.name, AdType.INTERSTITIAL.name, "948013677"),
             AdUnitBean(APP_OPEN, Advertisers.GroMore.name, AdType.APP_OPEN.name, "887622184"),
             AdUnitBean(REWARDED_VIDEO, Advertisers.GroMore.name, AdType.REWARDED_VIDEO.name, "102137844"),
-            AdUnitBean(NATIVE_TEMPLATE, Advertisers.GroMore.name, AdType.NATIVE_TEMPLATE.name, "948013677"),
+            AdUnitBean(FEED, Advertisers.GroMore.name, AdType.FEED.name, "102217511", adSize =
+            AdSize(LibApplication.context.getScreenWidth(), 120)),
         )
 
     val AppLovinMaxAdUnitList: List<AdUnitBean> =
@@ -80,6 +82,8 @@ object Datas {
             AdUnitBean(NATIVE_TEMPLATE, Advertisers.AppLovinMax.name, AdType.NATIVE_TEMPLATE.name, "653e223426fd9778"),
             AdUnitBean(INTERSTITIAL, Advertisers.AppLovinMax.name, AdType.INTERSTITIAL.name, "209850248dc00c9d", requestAdConfig = AdUnitLoadConfig(2, 200000)),
             AdUnitBean(REWARDED_VIDEO, Advertisers.AppLovinMax.name, AdType.REWARDED_VIDEO.name, "cffda14986a7bf4b"),
+            AdUnitBean(REWARDED_VIDEO, Advertisers.AppLovinMax.name, AdType.REWARDED_VIDEO.name, "cffda14986a7bf4b"),
+            AdUnitBean(APP_OPEN, Advertisers.AppLovinMax.name, AdType.APP_OPEN.name, "57b22faaea8bdca7"),
         )
 
     suspend fun getNativeADSampleLists(context: Context, adSlotName: String): List<NativeListBean> {

+ 128 - 44
app/src/main/java/com/convenient/android/lib/ui/sample/ad/page/AdHomePage.kt

@@ -1,5 +1,6 @@
 package com.convenient.android.lib.ui.sample.ad.page
 
+import android.content.Context
 import androidx.compose.foundation.layout.*
 import androidx.compose.material.DropdownMenu
 import androidx.compose.material.DropdownMenuItem
@@ -56,12 +57,13 @@ fun AdHomePage(viewModel: AdConfigViewModel, navHostController: NavHostControlle
 
         Box {
             Button(
-                shape = RectangleShape,
                 onClick = {
                     expanded.value = true
-                }, modifier = Modifier.padding(bottom = 4.dp)
+                }, modifier = Modifier
+                    .padding(bottom = 4.dp)
+                    .fillMaxWidth()
             ) {
-                Text(text = "启用的广告商${if (registerAdvertisers.value == Advertisers.UNKNOWN) "" else ":${registerAdvertisers.value.name}"}")
+                Text(text = "选择广告商${if (registerAdvertisers.value == Advertisers.UNKNOWN) "" else ":${registerAdvertisers.value.name}"}")
             }
 
             DropdownMenu(expanded = expanded.value, offset = DpOffset(0.dp, 0.dp), onDismissRequest = { expanded.value = false }) {
@@ -80,54 +82,136 @@ fun AdHomePage(viewModel: AdConfigViewModel, navHostController: NavHostControlle
         }
 
         if (registerAdvertisers.value != Advertisers.UNKNOWN) {
+            when (registerAdvertisers.value) {
+                Advertisers.Admob -> admobItems(context = context)
+                Advertisers.AppLovin,
+                Advertisers.AppLovinMax -> appLovinMaxItems(context = context)
+                Advertisers.CSJ -> csjItems(context = context)
+                Advertisers.GroMore -> groMoreItems(context = context)
+                else->{
 
-            val modifier = Modifier.fillMaxWidth()
-            Item(modifier = modifier, title = "横幅广告") {
-                context.readyGo(AdBannerActivity::class.java)
-            }
-            Item(modifier = modifier, title = "原生广告") {
-                context.readyGo(AdNativeActivity::class.java)
-            }
-            Item(modifier = modifier, title = "原生模板广告") {
-                context.readyGo(AdNativeTemplateActivity::class.java)
-            }
-            Item(modifier = modifier, title = "插屏广告") {
-                context.readyGo(AdFullScreenAdActivity::class.java) {
-                    it.putExtra("ad_slot_name", Datas.INTERSTITIAL)
-                }
-            }
-            Item(modifier = modifier, title = "激励视频广告") {
-                context.readyGo(AdFullScreenAdActivity::class.java) {
-                    it.putExtra("ad_slot_name", Datas.REWARDED_VIDEO)
-                }
-            }
-            Item(modifier = modifier, title = "激励插屏广告") {
-                context.readyGo(AdFullScreenAdActivity::class.java) {
-                    it.putExtra("ad_slot_name", Datas.REWARDED_INTERSTITIAL)
-                }
-            }
-            Item(modifier = modifier, title = "开屏广告") {
-                context.readyGo(AdAppOpenActivity::class.java) {
                 }
             }
+        }
+    }
+}
 
-            if (registerAdvertisers.value == Advertisers.AppLovinMax) {
-                Item(modifier = modifier, title = "AppLovinMax 中介测试套件") {
-                    AppLovinSdk.getInstance(context).showMediationDebugger()
-                }
-            }
+@Composable
+private fun admobItems(context: Context) {
+    val modifier = Modifier.fillMaxWidth()
+    Item(modifier = modifier, title = "横幅广告") {
+        context.readyGo(AdBannerActivity::class.java)
+    }
+    Item(modifier = modifier, title = "原生广告") {
+        context.readyGo(AdNativeActivity::class.java)
+    }
+    Item(modifier = modifier, title = "插屏广告") {
+        context.readyGo(AdFullScreenAdActivity::class.java) {
+            it.putExtra("ad_slot_name", Datas.INTERSTITIAL)
+        }
+    }
+    Item(modifier = modifier, title = "激励视频广告") {
+        context.readyGo(AdFullScreenAdActivity::class.java) {
+            it.putExtra("ad_slot_name", Datas.REWARDED_VIDEO)
+        }
+    }
+    Item(modifier = modifier, title = "激励插屏广告") {
+        context.readyGo(AdFullScreenAdActivity::class.java) {
+            it.putExtra("ad_slot_name", Datas.REWARDED_INTERSTITIAL)
+        }
+    }
+    Item(modifier = modifier, title = "开屏广告") {
+        context.readyGo(AdAppOpenActivity::class.java) {
+        }
+    }
+}
 
-            if (registerAdvertisers.value == Advertisers.GroMore || registerAdvertisers.value == Advertisers.CSJ) {
-                Item(modifier = modifier, title = "GroMore 中介测试套件") {
-                    TTMediationTestTool.launchTestTools(context) { imageView, s ->
-                        Glide.with(context)
-                            .load(s)
-                            .into(imageView)
-                    }
-                }
-            }
+@Composable
+private fun csjItems(context: Context) {
+    val modifier = Modifier.fillMaxWidth()
+    Item(modifier = modifier, title = "横幅广告") {
+        context.readyGo(AdBannerActivity::class.java)
+    }
+    Item(modifier = modifier, title = "原生广告") {
+        context.readyGo(AdNativeActivity::class.java)
+    }
+    Item(modifier = modifier, title = "原生模板") {
+        context.readyGo(AdNativeTemplateActivity::class.java)
+    }
+    Item(modifier = modifier, title = "插屏广告") {
+        context.readyGo(AdFullScreenAdActivity::class.java) {
+            it.putExtra("ad_slot_name", Datas.INTERSTITIAL)
+        }
+    }
+    Item(modifier = modifier, title = "激励视频广告") {
+        context.readyGo(AdFullScreenAdActivity::class.java) {
+            it.putExtra("ad_slot_name", Datas.REWARDED_VIDEO)
+        }
+    }
+    Item(modifier = modifier, title = "开屏广告") {
+        context.readyGo(AdAppOpenActivity::class.java) {
+        }
+    }
+}
+
+@Composable
+private fun groMoreItems(context: Context) {
+    val modifier = Modifier.fillMaxWidth()
+    Item(modifier = modifier, title = "横幅广告") {
+        context.readyGo(AdBannerActivity::class.java)
+    }
+    Item(modifier = modifier, title = "Feed信息流") {
+        context.readyGo(AdFeedActivity::class.java)
+    }
+    Item(modifier = modifier, title = "新插全屏广告") {
+        context.readyGo(AdFullScreenAdActivity::class.java) {
+            it.putExtra("ad_slot_name", Datas.INTERSTITIAL)
+        }
+    }
+    Item(modifier = modifier, title = "激励视频广告") {
+        context.readyGo(AdFullScreenAdActivity::class.java) {
+            it.putExtra("ad_slot_name", Datas.REWARDED_VIDEO)
         }
     }
+    Item(modifier = modifier, title = "开屏广告") {
+        context.readyGo(AdAppOpenActivity::class.java) {
+        }
+    }
+    Item(modifier = modifier, title = "GroMore 中介测试套件") {
+        TTMediationTestTool.launchTestTools(context) { imageView, s ->
+            Glide.with(context)
+                .load(s)
+                .into(imageView)
+        }
+    }
+}
+
+@Composable
+private fun appLovinMaxItems(context: Context) {
+    val modifier = Modifier.fillMaxWidth()
+    Item(modifier = modifier, title = "横幅广告") {
+        context.readyGo(AdBannerActivity::class.java)
+    }
+    Item(modifier = modifier, title = "原生模板") {
+        context.readyGo(AdNativeTemplateActivity::class.java)
+    }
+    Item(modifier = modifier, title = "插屏广告") {
+        context.readyGo(AdFullScreenAdActivity::class.java) {
+            it.putExtra("ad_slot_name", Datas.INTERSTITIAL)
+        }
+    }
+    Item(modifier = modifier, title = "激励视频广告") {
+        context.readyGo(AdFullScreenAdActivity::class.java) {
+            it.putExtra("ad_slot_name", Datas.REWARDED_VIDEO)
+        }
+    }
+    Item(modifier = modifier, title = "开屏广告") {
+        context.readyGo(AdAppOpenActivity::class.java) {
+        }
+    }
+    Item(modifier = modifier, title = "中介测试套件") {
+        AppLovinSdk.getInstance(context).showMediationDebugger()
+    }
 }
 
 @Composable

+ 14 - 0
app/src/main/java/com/convenient/android/lib/ui/sample/ad/viewmodel/AdConfigViewModel.kt

@@ -6,9 +6,12 @@ import com.composition.android.ad.admob.load.AdmobAdLoader
 import com.composition.android.ad.applovinmax.load.AppLovinMaxLoader
 import com.composition.android.ad.gromore.load.GroMoreAdLoader
 import com.composition.android.lib.ad.AdManager
+import com.composition.android.lib.ad.AdUnitConfigManager
 import com.composition.android.lib.ad.basic.Advertisers
+import com.composition.android.lib.ad.bean.AdUnitBean
 import com.composition.android.lib.ad.impl.UnknownAdLoader
 import com.composition.android.lib.ad.interfaces.AdLoader
+import com.convenient.android.lib.ui.sample.ad.model.Datas
 
 /**
  * @classname:
@@ -27,6 +30,7 @@ class AdConfigViewModel : ViewModel() {
             this.advertisers.value = advertisers
         }
         AdManager.instance.registerAdLoader(getAdLoader(advertisers = this.advertisers.value))
+        AdUnitConfigManager.instance.setAdUnits(getAdUnits(this.advertisers.value))
     }
 
     fun getAdLoader(advertisers: Advertisers): AdLoader {
@@ -38,4 +42,14 @@ class AdConfigViewModel : ViewModel() {
             else -> UnknownAdLoader()
         }
     }
+
+    fun getAdUnits(advertisers: Advertisers) : List<AdUnitBean> {
+        return when (advertisers) {
+            Advertisers.Admob -> Datas.AdmobAdUnitList
+            Advertisers.CSJ -> Datas.CSJAdUnitList
+            Advertisers.GroMore -> Datas.GroMoreAdUnitList
+            Advertisers.AppLovinMax -> Datas.AppLovinMaxAdUnitList
+            else -> emptyList()
+        }
+    }
 }

+ 14 - 14
app/src/main/res/layout/activity_ad_banner.xml

@@ -6,28 +6,29 @@
     android:layout_height="match_parent">
 
     <androidx.appcompat.widget.AppCompatButton
-        android:id="@+id/btn_load_banner"
+        android:id="@+id/btn_load_native_in_recyclerview"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:text="加载广告"
-        app:layout_constraintTop_toTopOf="parent"
+        android:text="原生广告在RecyclerView中运用"
+        app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"/>
+        app:layout_constraintTop_toTopOf="parent" />
+
 
     <androidx.appcompat.widget.AppCompatButton
-        android:id="@+id/btn_show_banner"
+        android:id="@+id/btn_load_banner"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:text="显示广告"
+        android:text="加载广告"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent"/>
 
     <androidx.appcompat.widget.AppCompatButton
-        android:id="@+id/btn_load_and_show"
+        android:id="@+id/btn_show_banner"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:text="加载并显示广告"
+        android:text="显示广告"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent"/>
@@ -50,17 +51,16 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="8dp"
-        android:text="以下为自动加载广告View,先配置好AdUnitBean,这里只需要指定ad_slot_name(广告位名称)即可\n
-com.composition.android.lib.ad.widget.BannerAdView"
+        android:text="XML自动加载广告"
         />
 
-    <com.composition.android.lib.ad.widget.BannerAdView
+    <com.composition.android.lib.ad.widget.AdView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         app:ad_slot_name="banner"
+        app:ad_auto_load="true"
         />
 
-
-
-
+    
+    
 </LinearLayout>

+ 78 - 0
app/src/main/res/layout/activity_ad_feed.xml

@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <androidx.appcompat.widget.AppCompatButton
+            android:id="@+id/btn_load_native_in_recyclerview"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="原生广告在RecyclerView中运用"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <androidx.appcompat.widget.AppCompatButton
+            android:id="@+id/btn_load_native"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="加载广告"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <androidx.appcompat.widget.AppCompatButton
+            android:id="@+id/btn_show_native"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="显示广告"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <androidx.appcompat.widget.AppCompatButton
+            android:id="@+id/btn_load_and_show"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="加载并显示广告"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+
+        <LinearLayout
+            android:id="@+id/ll_ad_content"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical" />
+
+
+        <androidx.appcompat.widget.AppCompatTextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:text="layout自动加载广告"
+            android:textSize="18sp"
+            />
+
+        <com.composition.android.lib.ad.widget.AdView
+            android:layout_width="match_parent"
+            android:layout_height="200dp"
+            app:ad_slot_name="feed"
+            app:ad_auto_populate="true"
+            app:ad_auto_size="true"
+            >
+
+        </com.composition.android.lib.ad.widget.AdView>
+
+    </LinearLayout>
+
+</ScrollView>

+ 5 - 3
app/src/main/res/layout/activity_ad_native.xml

@@ -63,13 +63,15 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_marginTop="16dp"
-            android:text="原生广告自行加载填充模式,在Xml NativeAdView中设置好配置, View中自动完成加载"
+            android:text="AdView自动填充"
             />
 
-        <com.composition.android.lib.ad.widget.NativeAdView
+        <com.composition.android.lib.ad.widget.AdView
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             app:ad_slot_name="native"
+            app:ad_auto_load="true"
+            app:ad_auto_size="true"
             app:ad_admob_native_ad_view_layout="@layout/layout_admob_native_ad_view_root"
             app:ad_view_title_id="@id/tv_ad_title_1"
             app:ad_view_title_desc_id="@id/tv_ad_title_desc_1"
@@ -131,7 +133,7 @@
 
             </androidx.constraintlayout.widget.ConstraintLayout>
 
-        </com.composition.android.lib.ad.widget.NativeAdView>
+        </com.composition.android.lib.ad.widget.AdView>
 
     </LinearLayout>
 

+ 5 - 9
app/src/main/res/layout/activity_ad_native_template.xml

@@ -45,10 +45,6 @@
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toTopOf="parent" />
 
-        <androidx.appcompat.widget.AppCompatTextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="此处为getNativeAdView, 自定义布局不用写在此界面,通过addView添加到界面中" />
 
         <LinearLayout
             android:id="@+id/ll_ad_content"
@@ -60,14 +56,14 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_marginTop="16dp"
-            android:text="原生模板广告自行加载填充模式,在Xml NativeAdView中设置好配置, View中自动完成加载" />
+            android:text="XML" />
 
-        <com.composition.android.lib.ad.widget.NativeAdView
+        <com.composition.android.lib.ad.widget.AdView
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            app:ad_admob_native_ad_view_layout="@layout/layout_admob_native_ad_view_root"
-            app:ad_auto_populate="true"
-            app:ad_gro_more_tt_native_ad_view_layout="@layout/layout_admob_native_ad_view_root"
+            app:ad_auto_load="true"
+            app:ad_auto_size="true"
             app:ad_slot_name="NativeTemplate" />
+
     </LinearLayout>
 </ScrollView>

+ 4 - 3
app/src/main/res/layout/view_rv_ad_native_item.xml

@@ -6,11 +6,12 @@
     android:layout_height="wrap_content">
 
 
-    <com.composition.android.lib.ad.widget.NativeAdView
+    <com.composition.android.lib.ad.widget.AdView
         android:id="@+id/native_ad_view"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        app:ad_auto_populate="false"
+        app:ad_auto_load="false"
+        app:ad_auto_size="true"
         app:ad_view_call_to_action_id="@id/btn_call_to_action_1"
         app:ad_view_icon_id="@id/iv_ad_icon_1"
         app:ad_view_media_content_group_id="@id/fl_ad_media_content_1"
@@ -77,7 +78,7 @@
 
         </androidx.constraintlayout.widget.ConstraintLayout>
 
-    </com.composition.android.lib.ad.widget.NativeAdView>
+    </com.composition.android.lib.ad.widget.AdView>
 
 
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 4 - 13
app/src/main/res/layout/view_rv_ad_native_template_item.xml

@@ -5,28 +5,19 @@
     android:layout_height="wrap_content">
 
 
-    <com.composition.android.lib.ad.widget.NativeAdView
+    <com.composition.android.lib.ad.widget.AdView
         android:id="@+id/native_ad_view"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        app:ad_auto_populate="false"
+        app:ad_auto_load="false"
+        app:ad_auto_size="false"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
-        app:ad_slot_name="NativeTemplate"
-        app:ad_admob_native_ad_view_layout="@layout/layout_admob_native_ad_view_root"
-        app:ad_gro_more_tt_native_ad_view_layout="@layout/layout_gro_more_native_template_ad_view_root"
         >
 
-        <androidx.constraintlayout.widget.ConstraintLayout
-            android:id="@+id/cl_ad_root_1"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-
-        </androidx.constraintlayout.widget.ConstraintLayout>
-
-    </com.composition.android.lib.ad.widget.NativeAdView>
+    </com.composition.android.lib.ad.widget.AdView>
 
 
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 0 - 18
lib_ad_admob/src/main/java/com/composition/android/ad/admob/impl/AdmobAdSize.kt

@@ -1,18 +0,0 @@
-package com.composition.android.ad.admob.impl
-
-import com.composition.android.lib.ad.interfaces.IAdSize
-import com.google.android.gms.ads.AdSize
-
-/**
- * @classname:
- * @author: LiuXiaoLong
- * @date: 2022/9/13
- * description: AdMob横幅广告尺寸
- */
-class AdmobAdSize(var size: AdSize) : IAdSize<AdSize> {
-
-    override fun getAdSize(): AdSize {
-        return size
-    }
-
-}

+ 19 - 4
lib_ad_admob/src/main/java/com/composition/android/ad/admob/load/AdmobAdLoader.kt

@@ -13,6 +13,7 @@ import com.composition.android.lib.ad.bean.AdUnitBean
 import com.composition.android.lib.ad.interfaces.AdListener
 import com.composition.android.lib.ad.interfaces.AdLoader
 import com.composition.android.lib.ad.util.adLog
+import com.composition.android.lib.ad.util.parentRemove
 import com.google.android.gms.ads.AdError
 import com.google.android.gms.ads.AdView
 import com.google.android.gms.ads.FullScreenContentCallback
@@ -79,10 +80,24 @@ class AdmobAdLoader : AdLoader {
 
     override fun populateNativeAdView(context: Context, adResult: AdResult.Success, viewHolder: NativeAdViewHolder, advertisersContainerView: ViewGroup) {
         AdManager.instance.globalListener?.invoke(adResult.adBean)
-        if (advertisersContainerView is NativeAdView) {
-            AdmobNativeAdView.populateNativeAdView(context, adResult, viewHolder, advertisersContainerView)
-        } else {
-            adLog(msg = "Admob广告-填充原生-advertisersContainerView类型错误, 应该为NativeAdView")
+        when (adResult.adBean.getAdType()) {
+            AdType.BANNER->{
+                val adView = adResult?.adObject as? AdView
+                AdmobBannerView.populateBannerView(context, adResult, buildBannerAdViewHolder {
+                    this.activity = viewHolder.activity
+                    this.adListener = viewHolder.adListener
+                })
+                advertisersContainerView.removeAllViews()
+                adView?.parentRemove()
+                advertisersContainerView.addView(adView)
+            }
+            AdType.NATIVE->{
+                AdmobNativeAdView.populateNativeAdView(context, adResult, viewHolder, advertisersContainerView as NativeAdView)
+            }
+            else ->{
+                adLog(msg = "Admob广告-填充View广告,未命中广告类型:${adResult.adBean.getAdType()}")
+
+            }
         }
     }
 

+ 21 - 7
lib_ad_admob/src/main/java/com/composition/android/ad/admob/load/request/AdmobBannerRequestImpl.kt

@@ -1,16 +1,14 @@
 package com.composition.android.ad.admob.load.request
 
 import android.content.Context
-import com.composition.android.ad.admob.impl.AdmobAdSize
 import com.composition.android.ad.admob.util.getAdSize
 import com.composition.android.lib.ad.basic.AdLoadCode
 import com.composition.android.lib.ad.basic.AdResult
 import com.composition.android.lib.ad.bean.AdUnitBean
 import com.composition.android.lib.ad.interfaces.IAdFormatRequest
-import com.composition.android.lib.ad.util.isActiveResult
-import com.composition.android.lib.ad.util.printAdFailInfo
-import com.composition.android.lib.ad.util.printAdInfo
+import com.composition.android.lib.ad.util.*
 import com.google.android.gms.ads.AdListener
+import com.google.android.gms.ads.AdSize
 import com.google.android.gms.ads.AdView
 import com.google.android.gms.ads.LoadAdError
 import kotlinx.coroutines.suspendCancellableCoroutine
@@ -29,9 +27,25 @@ class AdmobBannerRequestImpl : IAdFormatRequest {
             val adView = AdView(context).apply {
                 adUnitId = adUnitBean.adUnitId
                 setAdSize(
-                    if (adUnitBean.adSize is AdmobAdSize) {
-                        (adUnitBean.adSize as AdmobAdSize).size
-                    } else {
+                    if (adUnitBean.adSize != null){
+                        var adSize = adUnitBean.adSize!!
+                        if (adSize.autoSize){
+                            adLogWithFrame(msg = "Admob广告-横幅-使用自适应尺寸")
+                            getAdSize(context)
+                        }else{
+                            if (adSize.widthPx > 0 && adSize.heightPx > 0){
+                                val density: Float = getDensity(context)
+                                val adWidth = (adSize.widthPx / density).toInt()
+                                val adHeight = (adSize.heightPx / density).toInt()
+                                adLogWithFrame(msg = "Admob广告-横幅-使用自定义尺寸(${adWidth}dp*${adHeight}dp)")
+                                AdSize(adWidth, adHeight)
+                            }else{
+                                adLogWithFrame(msg = "Admob广告-横幅-自定义尺寸为0,使用自适应尺寸")
+                                getAdSize(context)
+                            }
+                        }
+                    }else{
+                        adLogWithFrame(msg = "Admob广告-横幅-自定义AdSize=null,使用自适应尺寸")
                         getAdSize(context)
                     }
                 )

+ 35 - 22
lib_ad_admob/src/main/java/com/composition/android/ad/admob/load/view/AdmobBannerView.kt

@@ -2,11 +2,15 @@ package com.composition.android.ad.admob.load.view
 
 import android.annotation.SuppressLint
 import android.content.Context
+import android.view.ViewGroup
+import com.composition.android.lib.ad.basic.AdResult
 import com.composition.android.lib.ad.basic.BannerAdViewHolder
 import com.composition.android.lib.ad.basic.BasicAdView
+import com.composition.android.lib.ad.basic.NativeAdViewHolder
 import com.composition.android.lib.ad.util.adLog
 import com.google.android.gms.ads.AdListener
 import com.google.android.gms.ads.AdView
+import com.google.android.gms.ads.nativead.NativeAdView
 
 /**
  * @classname:
@@ -17,34 +21,15 @@ import com.google.android.gms.ads.AdView
 @SuppressLint("ViewConstructor")
 class AdmobBannerView(context: Context?) : BasicAdView<AdView>(context) {
 
-    private var viewHolder : BannerAdViewHolder? = null
+    private var viewHolder: BannerAdViewHolder? = null
 
-    fun setBannerAdViewHolder(bannerAdViewHolder: BannerAdViewHolder){
+    fun setBannerAdViewHolder(bannerAdViewHolder: BannerAdViewHolder) {
         this.viewHolder = bannerAdViewHolder
     }
 
     override fun adContentView(): AdView? {
         val adView = adResult?.adObject as? AdView
-        adView?.adListener = object : AdListener(){
-            override fun onAdClicked() {
-                super.onAdClicked()
-                adLog(msg = "Admob广告-横幅-点击")
-                viewHolder?.adListener?.onAdClick()
-            }
-
-            override fun onAdClosed() {
-                super.onAdClosed()
-                adLog(msg = "Admob广告-横幅-关闭")
-                viewHolder?.adListener?.onAdClose()
-            }
-
-            override fun onAdOpened() {
-                super.onAdOpened()
-                adLog(msg = "Admob广告-横幅-打开")
-                adResult?.adBean?.let { viewHolder?.adListener?.onAdShow(it) }
-            }
-        }
-
+        populateBannerView(context, adResult, viewHolder)
         return adView
     }
 
@@ -62,4 +47,32 @@ class AdmobBannerView(context: Context?) : BasicAdView<AdView>(context) {
         adResult?.adObject = null
     }
 
+    companion object {
+
+
+        fun populateBannerView(context: Context, success: AdResult.Success?, viewHolder: BannerAdViewHolder?) {
+            val adView = success?.adObject as? AdView
+            adView?.adListener = object : AdListener() {
+                override fun onAdClicked() {
+                    super.onAdClicked()
+                    adLog(msg = "Admob广告-横幅-点击")
+                    viewHolder?.adListener?.onAdClick()
+                }
+
+                override fun onAdClosed() {
+                    super.onAdClosed()
+                    adLog(msg = "Admob广告-横幅-关闭")
+                    viewHolder?.adListener?.onAdClose()
+                }
+
+                override fun onAdOpened() {
+                    super.onAdOpened()
+                    adLog(msg = "Admob广告-横幅-打开")
+                    success?.adBean?.let { viewHolder?.adListener?.onAdShow(it) }
+                }
+            }
+
+        }
+    }
+
 }

+ 1 - 1
lib_ad_admob/src/main/java/com/composition/android/ad/admob/load/view/AdmobNativeAdView.kt

@@ -108,7 +108,7 @@ class AdmobNativeAdView(context: Context?) : BasicAdView<NativeAdView>(context)
                 nativeAdViewHolder.advertiserLogoImageView?.isVisible = false
                 nativeAdView.setNativeAd(nativeAd)
             } catch (e: Exception) {
-
+            e.printStackTrace()
             }
         }
     }

+ 0 - 12
lib_ad_admob/src/main/java/com/composition/android/ad/admob/util/AdmobAdExpan.kt

@@ -1,8 +1,6 @@
 package com.composition.android.ad.admob.util
 
 import android.content.Context
-import com.composition.android.ad.admob.impl.AdmobAdSize
-import com.composition.android.lib.ad.interfaces.IAdSize
 import com.composition.android.lib.ad.util.getDensity
 import com.composition.android.lib.ad.util.getScreenWidth
 import com.google.android.gms.ads.AdRequest
@@ -32,12 +30,10 @@ internal fun getFailedCodeInfo(code: Int): String {
  * 横幅广告尺寸
  */
 internal fun getAdSize(context: Context): AdSize {
-
     // Step 2 - Determine the screen width (less decorations) to use for the ad width.
     val widthPixels: Int = getScreenWidth(context)
     val density: Float = getDensity(context)
     val adWidth = (widthPixels / density).toInt()
-
     // Step 3 - Get adaptive ad size and return for setting on the ad view.
     return AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(context, adWidth)
 }
@@ -49,11 +45,3 @@ internal fun getAdSize(context: Context): AdSize {
 fun AdSize.autoSize(context: Context) : AdSize{
     return getAdSize(context)
 }
-
-
-/**
- * 构建Admob横幅广告尺寸
- */
-fun com.composition.android.lib.ad.interfaces.AdSize.Builder.buildAdmobBannerAdSize(adSize : AdSize) : IAdSize<AdSize>{
-    return AdmobAdSize(adSize)
-}

+ 1 - 1
lib_ad_applovinmax/build.gradle

@@ -48,6 +48,6 @@ android {
 dependencies {
     implementation project(':lib_ad_core')
 
-    api 'com.applovin:applovin-sdk:11.7.1'
+    api 'com.applovin:applovin-sdk:11.9.0'
     api "com.google.android.gms:play-services-ads-identifier:18.0.1"
 }

+ 10 - 0
lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/AppLovinMaxLoader.kt

@@ -162,6 +162,16 @@ class AppLovinMaxLoader : AdLoader {
                 advertisersContainerView.removeAllViews()
                 advertisersContainerView.addView(triple?.second)
             }
+            AdType.BANNER ->{
+                val maxAdView = adResult?.adObject as? MaxAdView
+                advertisersContainerView.removeAllViews()
+                AppLovinMaxBannerView.populateBannerAdView(context,adResult, buildBannerAdViewHolder {
+                    this.adListener = viewHolder.adListener
+                    this.activity = viewHolder.activity
+                })
+                maxAdView?.parentRemove()
+                advertisersContainerView.addView(maxAdView)
+            }
             else->{
                 adLogE(tag = AdManager.TAG, "AppLovinMax组件暂未接入原生广告,不支持填充")
             }

+ 47 - 37
lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/view/AppLovinMaxBannerView.kt

@@ -5,9 +5,14 @@ import com.applovin.mediation.MaxAd
 import com.applovin.mediation.MaxAdViewAdListener
 import com.applovin.mediation.MaxError
 import com.applovin.mediation.ads.MaxAdView
+import com.applovin.mediation.nativeAds.MaxNativeAdListener
+import com.applovin.mediation.nativeAds.MaxNativeAdLoader
+import com.applovin.mediation.nativeAds.MaxNativeAdView
 import com.composition.android.lib.ad.AdManager
+import com.composition.android.lib.ad.basic.AdResult
 import com.composition.android.lib.ad.basic.BannerAdViewHolder
 import com.composition.android.lib.ad.basic.BasicAdView
+import com.composition.android.lib.ad.basic.NativeAdViewHolder
 import com.composition.android.lib.ad.util.adLog
 import com.composition.android.lib.ad.util.adLogE
 import com.composition.android.lib.ad.util.adLogWithFrame
@@ -28,43 +33,7 @@ class AppLovinMaxBannerView(context: Context?) : BasicAdView<MaxAdView>(context)
 
     override fun adContentView(): MaxAdView? {
         val maxAdView = adResult?.adObject as? MaxAdView
-        maxAdView?.setListener(object : MaxAdViewAdListener {
-            override fun onAdLoaded(ad: MaxAd?) {
-
-
-                adLogWithFrame(msg = "AppLovinMax广告-横幅-onAdLoaded")
-            }
-
-            override fun onAdDisplayed(ad: MaxAd?) {
-                adResult?.adBean?.let { bannerAdViewHolder?.adListener?.onAdShow(it) }
-            }
-
-            override fun onAdHidden(ad: MaxAd?) {
-                bannerAdViewHolder?.adListener?.onAdClose()
-            }
-
-            override fun onAdClicked(ad: MaxAd?) {
-                bannerAdViewHolder?.adListener?.onAdClick()
-            }
-
-            override fun onAdLoadFailed(adUnitId: String?, error: MaxError?) {
-
-            }
-
-            override fun onAdDisplayFailed(ad: MaxAd?, error: MaxError?) {
-                adLogWithFrame(AdManager.TAG, "AppLovinMax广告-横幅-显示失败\ncode:${error?.code}\nmessage:${error?.message}")
-                bannerAdViewHolder?.adListener?.onAdShowFail("AppLovinMax广告-横幅-显示失败")
-            }
-
-            override fun onAdExpanded(ad: MaxAd?) {
-
-            }
-
-            override fun onAdCollapsed(ad: MaxAd?) {
-            }
-
-        })
-
+        populateBannerAdView(context, adResult, bannerAdViewHolder)
         return maxAdView
     }
 
@@ -83,4 +52,45 @@ class AppLovinMaxBannerView(context: Context?) : BasicAdView<MaxAdView>(context)
         }
         adResult?.adObject = null
     }
+
+    companion object{
+
+        fun populateBannerAdView(context: Context, adResult: AdResult.Success?, viewHolder: BannerAdViewHolder?) {
+            val maxAdView = adResult?.adObject as? MaxAdView
+            maxAdView?.setListener(object : MaxAdViewAdListener {
+                override fun onAdLoaded(ad: MaxAd?) {
+                    adLogWithFrame(msg = "AppLovinMax广告-横幅-onAdLoaded")
+                }
+
+                override fun onAdDisplayed(ad: MaxAd?) {
+                    adResult?.adBean?.let { viewHolder?.adListener?.onAdShow(it) }
+                }
+
+                override fun onAdHidden(ad: MaxAd?) {
+                    viewHolder?.adListener?.onAdClose()
+                }
+
+                override fun onAdClicked(ad: MaxAd?) {
+                    viewHolder?.adListener?.onAdClick()
+                }
+
+                override fun onAdLoadFailed(adUnitId: String?, error: MaxError?) {
+
+                }
+
+                override fun onAdDisplayFailed(ad: MaxAd?, error: MaxError?) {
+                    adLogWithFrame(AdManager.TAG, "AppLovinMax广告-横幅-显示失败\ncode:${error?.code}\nmessage:${error?.message}")
+                    viewHolder?.adListener?.onAdShowFail("AppLovinMax广告-横幅-显示失败")
+                }
+
+                override fun onAdExpanded(ad: MaxAd?) {
+
+                }
+
+                override fun onAdCollapsed(ad: MaxAd?) {
+                }
+
+            })
+        }
+    }
 }

+ 1 - 4
lib_ad_core/src/main/java/com/composition/android/lib/ad/AdManager.kt

@@ -79,12 +79,10 @@ class AdManager {
                 }]")
     }
 
-
     fun addGlobalAdShowListener(adListener: OnAdShow) {
         globalListener = adListener
     }
 
-
     /**
      * 初始化广告商SDK
      */
@@ -94,6 +92,5 @@ class AdManager {
         }
     }
 
-
-
+    fun getAdUnitManager() = AdUnitConfigManager.instance
 }

+ 5 - 0
lib_ad_core/src/main/java/com/composition/android/lib/ad/basic/AdType.kt

@@ -28,6 +28,11 @@ enum class AdType {
      */
     NATIVE_TEMPLATE,
 
+    /**
+     * 信息流广告
+     */
+    FEED,
+
     /**
      * 插屏广告
      */

+ 0 - 5
lib_ad_core/src/main/java/com/composition/android/lib/ad/basic/Advertisers.kt

@@ -30,11 +30,6 @@ enum class Advertisers {
 
     GroMore,
 
-    /**
-     * AdScope广告
-     */
-    AdScope,
-
     /**
      * 自定义广告
      */

+ 2 - 3
lib_ad_core/src/main/java/com/composition/android/lib/ad/bean/AdUnitBean.kt

@@ -4,7 +4,7 @@ import com.composition.android.lib.ad.basic.AdType
 import com.composition.android.lib.ad.basic.Advertisers
 import com.composition.android.lib.ad.basic.strategy.IStrategy
 import com.composition.android.lib.ad.impl.NormalStrategy
-import com.composition.android.lib.ad.interfaces.IAdSize
+import com.composition.android.lib.ad.interfaces.AdSize
 
 
 /**
@@ -19,7 +19,7 @@ open class AdUnitBean(
     var advertisersName: String,
     var adType: String,
     var adUnitId: String,
-    var adSize: IAdSize<*>? = null,
+    var adSize: AdSize? = null,
     var loadStrategy: IStrategy = NormalStrategy(),
     var requestAdConfig: AdUnitLoadConfig = AdUnitLoadConfig(),
 ) : java.io.Serializable {
@@ -64,7 +64,6 @@ open class AdUnitBean(
     fun isAvailable(): Boolean {
         return adUnitId.isNotEmpty() && advertisersName.isNotEmpty() && adType.isNotEmpty() && adSlotName.isNotEmpty()
     }
-
 }
 
 

+ 20 - 21
lib_ad_core/src/main/java/com/composition/android/lib/ad/interfaces/IAdSize.kt

@@ -1,34 +1,33 @@
 package com.composition.android.lib.ad.interfaces
 
-/**
- * @classname:
- * @author: LiuXiaoLong
- * @date: 2022/9/13
- * description:
- */
-interface IAdSize<T> {
-
-    fun getAdSize() : T
-
-}
+import android.content.Context
+import com.composition.android.lib.ad.util.px2dip
 
 
 /**
  * @classname:
  * @author: LiuXiaoLong
  * @date: 2022/10/25
- * description:
+ * description: 广告尺寸
+ * @param widthPx 广告view宽度
+ * @param heightPx 广告view 高度
+ * @param autoSize 自适应尺寸,仅admob可用
  */
-class AdSize {
-
-
-    class Builder{
-
-        companion object{
-
-            fun create() : Builder = Builder()
-        }
+data class AdSize(
+    var widthPx: Int,
+    var heightPx: Int,
+    var autoSize: Boolean = false
+) {
+
+    fun isAvailable(): Boolean {
+        return (widthPx > 0 && heightPx > 0) || autoSize
+    }
 
+    fun getWidthDp(context: Context) : Int{
+        return px2dip(context, widthPx.toFloat())
     }
 
+    fun getHeightDp(context: Context) : Int{
+        return px2dip(context, heightPx.toFloat())
+    }
 }

+ 8 - 0
lib_ad_core/src/main/java/com/composition/android/lib/ad/util/AdCoreExtenstions.kt

@@ -122,4 +122,12 @@ fun <T> CancellableContinuation<T>.isActiveResult(value : T){
     if (isActive){
         resume(value)
     }
+}
+
+fun Context.getLayoutResId(layoutName : String) : Int{
+    try {
+        return resources.getIdentifier(layoutName, "layout", packageName)
+    }catch (e : java.lang.Exception){
+        return -1
+    }
 }

+ 126 - 94
lib_ad_core/src/main/java/com/composition/android/lib/ad/widget/NativeAdView.kt

@@ -7,21 +7,22 @@ import android.util.Log
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import android.view.ViewTreeObserver
 import android.widget.LinearLayout
 import androidx.core.view.isVisible
 import androidx.lifecycle.findViewTreeLifecycleOwner
 import androidx.lifecycle.lifecycleScope
 import com.composition.android.lib.ad.AdLoad
-import com.composition.android.lib.ad.AdManager
 import com.composition.android.lib.ad.AdUnitConfigManager
 import com.composition.android.lib.ad.R
-import com.composition.android.lib.ad.basic.AdResult
-import com.composition.android.lib.ad.basic.Advertisers
-import com.composition.android.lib.ad.basic.NativeAdViewHolder
-import com.composition.android.lib.ad.basic.buildAdNativeViewHolder
+import com.composition.android.lib.ad.basic.*
+import com.composition.android.lib.ad.bean.AdUnitBean
 import com.composition.android.lib.ad.impl.NormalAdListener
+import com.composition.android.lib.ad.interfaces.AdSize
 import com.composition.android.lib.ad.util.adLogE
+import com.composition.android.lib.ad.util.adLogWithFrame
 import com.composition.android.lib.ad.util.getActivityFromView
+import com.composition.android.lib.ad.util.getLayoutResId
 import kotlinx.coroutines.flow.firstOrNull
 import kotlinx.coroutines.launch
 
@@ -29,34 +30,9 @@ import kotlinx.coroutines.launch
  * @classname:
  * @author: LiuXiaoLong
  * @date: 2022/9/7
- * description: 自定义的原生广告View, 通过在xml中的配置,view中进行加载广告并展示
- *
- * <NativeAdView
- *  //对应的NativeAdViewHolder view配置,设置view的id..还有其他的,具体查看attr.xml/NativeAdView
- *  app:ad_view_title="@id/tv_ad_title"
- *  app:ad_view_title_desc="..."
- *
- *  //不同广告厂商的原生广告根布局,在每个库中都会默认定义一个,或者自行添加
- *  admob : layout_admob_native_ad_view_root.xml   gms.NativeAdView
- *
- *  app:native_admob_advertisers_root_view="@layout/layout_admob_native_ad_view_root"
- *  app:native_csj_advertisers_root_view="xxx"
- *  app:native_app_lovin_advertisers_root_view="xxx"
- *  app:native_custom_advertisers_root_view="xxx"
- *
- * >
- *
- *     //具体的原生广告view布局
- *     <TextView
- *      android:id="@+id/tv_ad_title"
- *     />
- *
- * </NativeAdView>
- *
- *
- *
+ * description: 广告View
  */
-class NativeAdView : LinearLayout {
+class AdView : LinearLayout {
 
     /**
      * 广告位名称
@@ -86,69 +62,64 @@ class NativeAdView : LinearLayout {
 
     private var advertisersContainerView: ViewGroup? = null
 
-    /**
-     * <-----------
-     */
+    private var autoLoad = true
 
-    private var autoPopulate = true
+    private var autoSize = false
 
-    constructor(context: Context?) : super(context)
-    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
-    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
+    private var adLoading = false
+
+    constructor(context: Context?) : this(context, null)
+    constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
+    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
         init(attrs)
     }
 
+
     private fun init(attrs: AttributeSet?) {
-        val typedArray: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.NativeAdView)
+        val typedArray: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.AdView)
         //获取到配置的广告名称
-        adSlotName = typedArray.getString(R.styleable.NativeAdView_ad_slot_name) ?: ""
-
-        val adUnitBean = AdUnitConfigManager.instance.getAdUnitBySlotName(adSlotNames = listOf(adSlotName)).getOrNull(0)
-        if (adUnitBean == null) {
-            adLogE(AdManager.TAG, "配置的广告位数据不存在, 当前广告位:${adSlotName}")
-        }
-        when (adUnitBean?.getAdvertisers()) {
-            Advertisers.Admob -> attachedAdvertisersNativeAdViewToRoot(typedArray, R.styleable.NativeAdView_ad_admob_native_ad_view_layout)
-            Advertisers.CSJ, Advertisers.AppLovinMax -> advertisersContainerView = this
-            Advertisers.GroMore -> attachedAdvertisersNativeAdViewToRoot(typedArray, R.styleable.NativeAdView_ad_gro_more_tt_native_ad_view_layout)
-            Advertisers.CUSTOM -> advertisersContainerView = this
-            else -> {}
+        adSlotName = typedArray.getString(R.styleable.AdView_ad_slot_name) ?: ""
+        var adUnitBean = AdUnitConfigManager.instance.getAdUnitBySlotName(listOf(adSlotName))
+        if (adUnitBean.isNullOrEmpty().not()) {
+            initAdContainerView(adUnitBean[0])
         }
 
-        adTitleViewId = typedArray.getResourceId(R.styleable.NativeAdView_ad_view_title_id, 0)
-        adTitleDescViewId = typedArray.getResourceId(R.styleable.NativeAdView_ad_view_title_desc_id, 0)
-        adIconViewId = typedArray.getResourceId(R.styleable.NativeAdView_ad_view_icon_id, 0)
-        adMediaContentViewId = typedArray.getResourceId(R.styleable.NativeAdView_ad_view_media_content_group_id, 0)
-        adCallToActionViewId = typedArray.getResourceId(R.styleable.NativeAdView_ad_view_call_to_action_id, 0)
-        adAdvertisersLogoViewId = typedArray.getResourceId(R.styleable.NativeAdView_ad_view_advertisers_logo_id, 0)
-        adCloseIconViewId = typedArray.getResourceId(R.styleable.NativeAdView_ad_view_close_ad_icon_id, 0)
-        autoPopulate = typedArray.getBoolean(R.styleable.NativeAdView_ad_auto_populate, true)
+        autoLoad = typedArray.getBoolean(R.styleable.AdView_ad_auto_load, true)
+        autoSize = typedArray.getBoolean(R.styleable.AdView_ad_auto_size, false)
+        adTitleViewId = typedArray.getResourceId(R.styleable.AdView_ad_view_title_id, 0)
+        adTitleDescViewId = typedArray.getResourceId(R.styleable.AdView_ad_view_title_desc_id, 0)
+        adIconViewId = typedArray.getResourceId(R.styleable.AdView_ad_view_icon_id, 0)
+        adMediaContentViewId = typedArray.getResourceId(R.styleable.AdView_ad_view_media_content_group_id, 0)
+        adCallToActionViewId = typedArray.getResourceId(R.styleable.AdView_ad_view_call_to_action_id, 0)
+        adAdvertisersLogoViewId = typedArray.getResourceId(R.styleable.AdView_ad_view_advertisers_logo_id, 0)
+        adCloseIconViewId = typedArray.getResourceId(R.styleable.AdView_ad_view_close_ad_icon_id, 0)
 
         typedArray.recycle()
     }
 
+    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
 
-    override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) {
 
-        val root = getChildAt(0)
-        if (childCount != 0 && root is ViewGroup) {
-            //这里会把xml 中写的自定义布局加入进来
-            (getChildAt(0) as ViewGroup).addView(child, index, params)
-            Log.e("测试", "if true, child:${child?.javaClass?.simpleName}")
-        } else {
-            //把广告商的View先加进来
-            super.addView(child, index, params)
-            Log.e("测试", "if else, child:${child?.javaClass?.simpleName}")
-        }
     }
 
+    override fun onFinishInflate() {
+        super.onFinishInflate()
+        viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener{
+            override fun onGlobalLayout() {
+                adLogWithFrame(msg = "AdView size :${measuredWidth},${measuredHeight}")
+                viewTreeObserver.removeOnGlobalLayoutListener(this)
+                if (autoLoad && !adLoading) {
+                    loadAd()
+                }
+            }
+        })
+    }
 
     override fun onAttachedToWindow() {
         super.onAttachedToWindow()
         initViewHolder()
-        if (autoPopulate) {
-            loadAd()
-        }
+
     }
 
     override fun onDetachedFromWindow() {
@@ -168,67 +139,128 @@ class NativeAdView : LinearLayout {
                 this.advertiserLogoImageView = findViewById(adAdvertisersLogoViewId)
                 this.dislikeView = findViewById(adCloseIconViewId)
                 this.activity = getActivityFromView()
-                this.adListener = object : NormalAdListener() {
-                    override fun onAdDisLike() {
-                        super.onAdDisLike()
-                        isVisible = false
-                        advertisersContainerView?.removeAllViews()
+                this.adListener = this@AdView.adListener
+            }
+        }else{
+            viewHolder?.adListener = this@AdView.adListener
+        }
+    }
+
+    private fun initAdContainerView(adUnitBean: AdUnitBean?) {
+        if (advertisersContainerView != null) {
+            return
+        }
+        when (adUnitBean?.getAdvertisers()) {
+            Advertisers.Admob -> {
+                when (adUnitBean.getAdType()) {
+                    AdType.NATIVE -> {
+                        parseAdRootView("layout_admob_native_ad_view_root")
+                    }
+                    else -> {
+                        advertisersContainerView = this
                     }
                 }
             }
+            Advertisers.CSJ, Advertisers.AppLovinMax -> advertisersContainerView = this
+            Advertisers.GroMore -> {
+                advertisersContainerView = this
+            }
+            else -> {
+                advertisersContainerView = this
+            }
+        }
+    }
+
+    override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) {
+        val root = getChildAt(0)
+        if (childCount != 0 && root is ViewGroup) {
+            //这里会把xml 中写的自定义布局加入进来
+            (getChildAt(0) as ViewGroup).addView(child, index, params)
+            Log.e("测试", "if true, child:${child?.javaClass?.simpleName}")
+        } else {
+            //把广告商的View先加进来
+            super.addView(child, index, params)
+            Log.e("测试", "if else, child:${child?.javaClass?.simpleName}")
         }
     }
 
-    private fun attachedAdvertisersNativeAdViewToRoot(typedArray: TypedArray, id: Int) {
-        typedArray.getResourceId(id, -1).let {
-            if (it != -1) {
-                Log.e("测试", "开始解析厂商布局")
-                LayoutInflater.from(context).inflate(it, this, true) as ViewGroup
+
+    private fun parseAdRootView(layoutName: String) {
+        try {
+            adLogWithFrame(msg = "AdView 开始获取:${layoutName}.xml")
+            val layoutResId = context.getLayoutResId(layoutName)
+            if (layoutResId != -1) {
+                adLogWithFrame(msg = "AdView ${layoutName}.xml 解析成功")
+                LayoutInflater.from(context).inflate(layoutResId, this, true) as ViewGroup
                 val root = getChildAt(0) as ViewGroup
                 advertisersContainerView = root
-                Log.e("测试", "厂商布局解析完成: root${root.javaClass.simpleName}")
+                adLogWithFrame(msg = "AdView 获取成功 root: ${root.javaClass.simpleName}")
+            } else {
+                adLogWithFrame(msg = "AdView ${layoutName}.xml 解析失败,请确认该layout是否存在")
             }
+
+        } catch (e: Exception) {
+            adLogWithFrame(msg = "AdView ${layoutName}.xml 解析失败")
+            e.printStackTrace()
         }
     }
 
     fun loadAd() {
         findViewTreeLifecycleOwner()?.lifecycleScope?.launch {
             destroyAd()
-            adResult = AdLoad.loadAd(context, adSlotName).firstOrNull()
+            var adUnits = AdUnitConfigManager.instance.getAdUnitBySlotName(listOf(adSlotName))
+            if (autoSize) {
+                if (measuredWidth > 0 && measuredHeight > 0) {
+                    adLogWithFrame(msg = "AdView 使用AutoSize : (${measuredWidth} * ${measuredHeight})")
+                    for (adUnit in adUnits) {
+                        adUnit.adSize = AdSize(measuredWidth, measuredHeight)
+                    }
+                }
+            }
+            adLoading = true
+            adResult = AdLoad.loadAd(context, adUnits).firstOrNull()
+            adLoading = false
             initViewHolder()
             if (adResult != null && adResult is AdResult.Success && viewHolder != null && advertisersContainerView != null) {
                 AdLoad.populateNativeAdView(context, adResult as AdResult.Success, viewHolder!!, advertisersContainerView!!)
                 isVisible = true
             }
-            if (advertisersContainerView == null){
-                adLogE(tag = "原生广告NativeAdView", msg = "厂商的原生广告容器为null, 请指定 ad_admob_native_ad_view_layout 或 其他属性")
+            if (advertisersContainerView == null) {
+                adLogE(tag = "原生广告NativeAdView", msg = "厂商的原生广告容器为null")
             }
         }
     }
 
-
     private fun destroyAd() {
         AdLoad.destroyAd(adResult)
     }
 
-
     /**
      * 可以不使用View中的自动加载,在这里进行自行填充,非常适用于在RecyclerView中使用
      */
-    fun populateNativeAd(adResult: AdResult.Success) {
+    fun populateAd(adResult: AdResult.Success) {
+        initAdContainerView(adResult.adBean)
         initViewHolder()
         if (viewHolder != null && advertisersContainerView != null) {
             AdLoad.populateNativeAdView(context, adResult, viewHolder!!, advertisersContainerView!!)
         }
     }
 
+    private var adListener : NormalAdListener? = object : NormalAdListener(){
+        override fun onAdDisLike() {
+            removeAd()
+        }
+    }
+
+    public fun setAdListener(adListener: NormalAdListener.()->Unit){
+        this.adListener = NormalAdListener().also(adListener)
+    }
 
-    fun setAdSlotNameAndLoadAd(adSlotName: String) {
+    fun loadAd(adSlotName: String) {
         this.adSlotName = adSlotName
         loadAd()
     }
 
-
     /**
      * 刷新广告
      */
@@ -238,6 +270,6 @@ class NativeAdView : LinearLayout {
 
     fun removeAd() {
         isVisible = false
+        destroyAd()
     }
-
 }

+ 0 - 111
lib_ad_core/src/main/java/com/composition/android/lib/ad/widget/BannerAdView.kt

@@ -1,111 +0,0 @@
-package com.composition.android.lib.ad.widget
-
-import android.content.Context
-import android.content.res.TypedArray
-import android.util.AttributeSet
-import android.widget.LinearLayout
-import androidx.core.view.isVisible
-import androidx.lifecycle.findViewTreeLifecycleOwner
-import androidx.lifecycle.lifecycleScope
-import com.composition.android.lib.ad.AdLoad
-import com.composition.android.lib.ad.R
-import com.composition.android.lib.ad.basic.AdResult
-import com.composition.android.lib.ad.basic.buildBannerAdViewHolder
-import com.composition.android.lib.ad.impl.NormalAdListener
-import com.composition.android.lib.ad.util.getActivityFromView
-import kotlinx.coroutines.flow.firstOrNull
-import kotlinx.coroutines.launch
-
-/**
- * @classname:
- * @author: LiuXiaoLong
- * @date: 2022/9/7
- * description: 横幅广告View
- * 可以直接写入在布局中,设置ad_slot_name(广告位名称)后,自动进行加载展示横幅广告
- * 广告跟随生命周期自动销毁
- */
-class BannerAdView : LinearLayout{
-
-    /**
-     * 广告位名称
-     */
-    private var adSlotName : String = ""
-
-    private var adResult : AdResult? = null
-
-    init {
-        orientation = VERTICAL
-    }
-
-    constructor(context: Context?) : super(context)
-
-    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs){
-        init(attrs)
-    }
-    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
-
-    private fun init(attrs: AttributeSet?){
-        val typedArray: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.BannerAdView)
-        //获取到配置的广告名称
-        adSlotName = typedArray.getString(R.styleable.BannerAdView_ad_slot_name)?:""
-        typedArray.recycle()
-    }
-
-    override fun onAttachedToWindow() {
-        super.onAttachedToWindow()
-        loadAd()
-    }
-
-    override fun onDetachedFromWindow() {
-        super.onDetachedFromWindow()
-        destroyAd()
-    }
-
-
-    private fun loadAd(){
-        findViewTreeLifecycleOwner()?.lifecycleScope?.launch {
-            destroyAd()
-            adResult = AdLoad.loadAd(context, adSlotName)
-                .firstOrNull()
-            if (adResult is AdResult.Success){
-                AdLoad.getBannerAdView(context, adResult as AdResult.Success, buildBannerAdViewHolder {
-                    this.activity = getActivityFromView()
-                    this.adListener = object : NormalAdListener(){
-                        override fun onAdDisLike() {
-                            super.onAdDisLike()
-                            isVisible = false
-                            removeAllViews()
-                            destroyAd()
-                        }
-                    }
-                })?.let {
-                    removeAllViews()
-                    addView(it)
-                    isVisible = true
-                }
-            }
-        }
-    }
-
-    private fun destroyAd(){
-        AdLoad.destroyAd(adResult)
-    }
-
-    /**
-     * 更新广告
-     */
-    fun setAdSlotName(adSlotName : String){
-        this.adSlotName = adSlotName
-        loadAd()
-    }
-
-    /**
-     * 移除广告
-     */
-    fun removeAd(){
-        removeAllViews()
-        isVisible = false
-    }
-
-
-}

+ 27 - 7
lib_ad_core/src/main/res/values/attr.xml

@@ -2,6 +2,13 @@
 <resources>
 
     <attr name="ad_slot_name" format="string"/>
+    <attr name="ad_view_title_id" format="reference"/>
+    <attr name="ad_view_title_desc_id" format="reference"/>
+    <attr name="ad_view_icon_id" format="reference"/>
+    <attr name="ad_view_media_content_group_id" format="reference"/>
+    <attr name="ad_view_call_to_action_id" format="reference"/>
+    <attr name="ad_view_advertisers_logo_id" format="reference"/>
+    <attr name="ad_view_close_ad_icon_id" format="reference"/>
     <declare-styleable name="BannerAdView">
 
         <attr name="ad_slot_name" />
@@ -14,13 +21,13 @@
         <attr name="ad_slot_name" />
         <attr name="ad_auto_populate" format="boolean"/>
 
-        <attr name="ad_view_title_id" format="reference"/>
-        <attr name="ad_view_title_desc_id" format="reference"/>
-        <attr name="ad_view_icon_id" format="reference"/>
-        <attr name="ad_view_media_content_group_id" format="reference"/>
-        <attr name="ad_view_call_to_action_id" format="reference"/>
-        <attr name="ad_view_advertisers_logo_id" format="reference"/>
-        <attr name="ad_view_close_ad_icon_id" format="reference"/>
+        <attr name="ad_view_title_id"/>
+        <attr name="ad_view_title_desc_id"/>
+        <attr name="ad_view_icon_id" />
+        <attr name="ad_view_media_content_group_id" />
+        <attr name="ad_view_call_to_action_id"/>
+        <attr name="ad_view_advertisers_logo_id" />
+        <attr name="ad_view_close_ad_icon_id" />
 
         <!-- 这里指定广告商提供的原生广告根节点view, 各个广告库中已经写了默认的-->
         <!-- lib_ad_admob/res/layout/layout_admob_native_ad_view_root -->
@@ -35,4 +42,17 @@
 
     </declare-styleable>
 
+    <declare-styleable name="AdView">
+        <attr name="ad_slot_name" />
+        <attr name="ad_auto_load" format="boolean"/>
+        <attr name="ad_auto_size" format="boolean"/>
+        <attr name="ad_view_title_id"/>
+        <attr name="ad_view_title_desc_id"/>
+        <attr name="ad_view_icon_id" />
+        <attr name="ad_view_media_content_group_id" />
+        <attr name="ad_view_call_to_action_id"/>
+        <attr name="ad_view_advertisers_logo_id" />
+        <attr name="ad_view_close_ad_icon_id" />
+    </declare-styleable>
+
 </resources>

+ 0 - 17
lib_ad_csj/src/main/java/com/composition/android/ad/csj/impl/CSJBannerAdSize.kt

@@ -1,17 +0,0 @@
-package com.composition.android.ad.csj.impl
-
-import com.composition.android.lib.ad.interfaces.IAdSize
-
-/**
- * @classname:
- * @author: LiuXiaoLong
- * @date: 2022/9/13
- * description:穿山甲横幅广告尺寸
- */
-class CSJBannerAdSize(var widthDp : Float, var heightDp : Float) : IAdSize<Pair<Float, Float>> {
-
-    override fun getAdSize(): Pair<Float, Float> {
-        return widthDp to heightDp
-    }
-
-}

+ 0 - 17
lib_ad_csj/src/main/java/com/composition/android/ad/csj/impl/CSJNativeAdImageSize.kt

@@ -1,17 +0,0 @@
-package com.composition.android.ad.csj.impl
-
-import com.composition.android.lib.ad.interfaces.IAdSize
-
-/**
- * @classname:
- * @author: LiuXiaoLong
- * @date: 2022/9/13
- * description:穿山甲原生广告图片尺寸
- */
-class CSJNativeAdImageSize(var width : Int, var height : Int) : IAdSize<Pair<Int, Int>> {
-
-    override fun getAdSize(): Pair<Int, Int> {
-        return width to width
-    }
-
-}

+ 5 - 6
lib_ad_csj/src/main/java/com/composition/android/ad/csj/load/request/CSJBannerRequestImpl.kt

@@ -2,11 +2,9 @@ package com.composition.android.ad.csj.load.request
 
 import android.content.Context
 import com.bytedance.sdk.openadsdk.*
-import com.composition.android.ad.csj.impl.CSJBannerAdSize
 import com.composition.android.lib.ad.basic.AdResult
 import com.composition.android.lib.ad.bean.AdUnitBean
 import com.composition.android.lib.ad.interfaces.IAdFormatRequest
-import com.composition.android.lib.ad.util.adLog
 import com.composition.android.lib.ad.util.isActiveResult
 import com.composition.android.lib.ad.util.printAdFailInfo
 import com.composition.android.lib.ad.util.printAdInfo
@@ -21,15 +19,16 @@ import kotlinx.coroutines.suspendCancellableCoroutine
 class CSJBannerRequestImpl : IAdFormatRequest {
     override suspend fun load(context: Context, adUnitBean: AdUnitBean): AdResult {
         return suspendCancellableCoroutine {
-            val size = if (adUnitBean.adSize is CSJBannerAdSize) {
-                (adUnitBean.adSize as CSJBannerAdSize).getAdSize()
+            val size = if (adUnitBean.adSize != null && adUnitBean.adSize!!.isAvailable()) {
+                adUnitBean.adSize!!.getWidthDp(context) to adUnitBean.adSize!!.getHeightDp(context)
             } else {
-                600F to 90F
+                360 to 120
             }
+
             val adSlot = AdSlot.Builder()
                 .setCodeId(adUnitBean.adUnitId)
                 .setAdCount(1)
-                .setExpressViewAcceptedSize(size.first / 2F, size.second / 2F)
+                .setExpressViewAcceptedSize(size.first.toFloat(), size.second.toFloat())
                 .setAdLoadType(TTAdLoadType.PRELOAD)
                 .build()
 

+ 4 - 6
lib_ad_csj/src/main/java/com/composition/android/ad/csj/load/request/CSJNativeRequestImpl.kt

@@ -2,7 +2,6 @@ package com.composition.android.ad.csj.load.request
 
 import android.content.Context
 import com.bytedance.sdk.openadsdk.*
-import com.composition.android.ad.csj.impl.CSJNativeAdImageSize
 import com.composition.android.lib.ad.basic.AdResult
 import com.composition.android.lib.ad.bean.AdUnitBean
 import com.composition.android.lib.ad.interfaces.IAdFormatRequest
@@ -23,18 +22,17 @@ class CSJNativeRequestImpl : IAdFormatRequest {
 
         return suspendCancellableCoroutine {
 
-            val adSize = if (adUnitBean.adSize != null && adUnitBean.adSize is CSJNativeAdImageSize) {
-                val size = adUnitBean.adSize as CSJNativeAdImageSize
-                size.width to size.height
+            val size = if (adUnitBean.adSize != null && adUnitBean.adSize!!.isAvailable()) {
+                adUnitBean.adSize!!.widthPx to adUnitBean.adSize!!.heightPx
             } else {
                 640 to 320
             }
+
             val adSlot = AdSlot.Builder()
                 .setCodeId(adUnitBean.adUnitId)
                 .setSupportDeepLink(true)
                 .setAdCount(1)
-                .setImageAcceptedSize(adSize.first, adSize.second)
-                .setNativeAdType(AdSlot.TYPE_BANNER)
+                .setImageAcceptedSize(size.first, size.second)
                 .setAdLoadType(TTAdLoadType.PRELOAD)
                 .build()
 

+ 12 - 13
lib_ad_csj/src/main/java/com/composition/android/ad/csj/load/request/CSJNativeTemplateRequestImpl.kt

@@ -2,7 +2,6 @@ package com.composition.android.ad.csj.load.request
 
 import android.content.Context
 import com.bytedance.sdk.openadsdk.*
-import com.composition.android.ad.csj.impl.CSJNativeAdImageSize
 import com.composition.android.lib.ad.AdManager
 import com.composition.android.lib.ad.basic.AdResult
 import com.composition.android.lib.ad.bean.AdUnitBean
@@ -24,17 +23,17 @@ class CSJNativeTemplateRequestImpl : IAdFormatRequest {
     override suspend fun load(context: Context, adUnitBean: AdUnitBean): AdResult {
         return suspendCancellableCoroutine {
 
-            val imageAcceptedSize = if (adUnitBean.adSize is CSJNativeAdImageSize){
-                val adSize = adUnitBean.adSize as CSJNativeAdImageSize
-                adSize.width to adSize.height
-            }else{
+            val size = if (adUnitBean.adSize != null && adUnitBean.adSize!!.isAvailable()) {
+                adUnitBean.adSize!!.widthPx to adUnitBean.adSize!!.heightPx
+            } else {
                 640 to 320
             }
+
             adLogE(tag = AdManager.TAG, msg = "CSJNativeTemplateRequestImpl load")
             val adSlot = AdSlot.Builder()
                 .setCodeId(adUnitBean.adUnitId)
                 .setAdCount(1)
-                .setImageAcceptedSize(imageAcceptedSize.first, imageAcceptedSize.second)
+                .setImageAcceptedSize(size.first, size.second)
                 .setAdLoadType(TTAdLoadType.PRELOAD)
                 .build()
 
@@ -46,13 +45,13 @@ class CSJNativeTemplateRequestImpl : IAdFormatRequest {
                     }
 
                     override fun onNativeExpressAdLoad(p0: MutableList<TTNativeExpressAd>?) {
-                            if (p0.isNullOrEmpty().not()) {
-                                printAdInfo(adUnitBean)
-                                it.isActiveResult(AdResult.Success(adBean = adUnitBean, adObject = p0?.get(0), msg = "穿山甲广告-原生模板-加载成功"))
-                            } else {
-                                printAdFailInfo(adUnitBean, 0, "SDK返回的广告实例为空")
-                                it.isActiveResult(AdResult.Fail(adUnitBean, msg = "穿山甲广告原生模板-加载失败, SDK返回的广告实例为空"))
-                            }
+                        if (p0.isNullOrEmpty().not()) {
+                            printAdInfo(adUnitBean)
+                            it.isActiveResult(AdResult.Success(adBean = adUnitBean, adObject = p0?.get(0), msg = "穿山甲广告-原生模板-加载成功"))
+                        } else {
+                            printAdFailInfo(adUnitBean, 0, "SDK返回的广告实例为空")
+                            it.isActiveResult(AdResult.Fail(adUnitBean, msg = "穿山甲广告原生模板-加载失败, SDK返回的广告实例为空"))
+                        }
                     }
                 })
         }

+ 0 - 19
lib_ad_csj/src/main/java/com/composition/android/ad/csj/util/CSJAdExpan.kt

@@ -1,19 +0,0 @@
-package com.composition.android.ad.csj.util
-
-import com.composition.android.ad.csj.impl.CSJBannerAdSize
-import com.composition.android.ad.csj.impl.CSJNativeAdImageSize
-import com.composition.android.lib.ad.interfaces.AdSize
-
-
-/**
- * 构建穿山甲横幅广告 尺寸
- */
-fun AdSize.Builder.buildCSJBannerAdSize(widthDp : Float, heightDp : Float) :CSJBannerAdSize{
-    return CSJBannerAdSize(widthDp, heightDp)
-}
-
-fun AdSize.Builder.buildCSJNativeImageAdSize(width : Int, height : Int) : CSJNativeAdImageSize{
-    return CSJNativeAdImageSize(width, height)
-}
-
-

+ 0 - 16
lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/impl/GMAdImageSize.kt

@@ -1,16 +0,0 @@
-package com.composition.android.ad.gromore.impl
-
-import com.composition.android.lib.ad.interfaces.IAdSize
-
-/**
- * @classname:
- * @author: LiuXiaoLong
- * @date: 2022/9/15
- * description: GroMore Banner 广告高度
- */
-class GMAdImageSize(var gmAdSize : Pair<Int, Int>) : IAdSize<Pair<Int, Int>> {
-
-    override fun getAdSize(): Pair<Int, Int> {
-        return gmAdSize
-    }
-}

+ 25 - 19
lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/load/GroMoreAdLoader.kt

@@ -11,15 +11,11 @@ import com.bytedance.sdk.openadsdk.TTNativeAd
 import com.bytedance.sdk.openadsdk.TTNativeExpressAd
 import com.bytedance.sdk.openadsdk.TTRewardVideoAd
 import com.bytedance.sdk.openadsdk.TTSplashAd
-import com.composition.android.ad.gromore.load.request.GMAppOpenRequestImpl
-import com.composition.android.ad.gromore.load.request.GMBannerRequestImpl
-import com.composition.android.ad.gromore.load.request.GMInterstitialRequestImpl
-import com.composition.android.ad.gromore.load.request.GMNativeRequestImpl
-import com.composition.android.ad.gromore.load.request.GMNativeTemplateRequestImpl
-import com.composition.android.ad.gromore.load.request.GMRewardRequestImpl
-import com.composition.android.ad.gromore.load.view.CSJNativeAdView
+import com.composition.android.ad.gromore.load.request.*
+import com.composition.android.ad.gromore.load.view.GmNativeAdView
 import com.composition.android.ad.gromore.load.view.GMBannerView
 import com.composition.android.ad.gromore.load.view.GMNativeTemplateAdView
+import com.composition.android.ad.gromore.load.view.GMTTFeedAdView
 import com.composition.android.lib.ad.AdManager
 import com.composition.android.lib.ad.basic.AdResult
 import com.composition.android.lib.ad.basic.AdType
@@ -53,6 +49,7 @@ class GroMoreAdLoader : AdLoader {
         val adRequest = when (adUnitBean.getAdType()) {
             AdType.BANNER -> GMBannerRequestImpl()
             AdType.NATIVE -> GMNativeRequestImpl()
+            AdType.FEED -> GMFeedRequestImpl()
             AdType.NATIVE_TEMPLATE -> GMNativeTemplateRequestImpl()
             AdType.INTERSTITIAL, AdType.REWARDED_INTERSTITIAL -> GMInterstitialRequestImpl()
             AdType.REWARDED_VIDEO -> GMRewardRequestImpl()
@@ -82,7 +79,7 @@ class GroMoreAdLoader : AdLoader {
             AdManager.instance.globalListener?.invoke(adResult.adBean)
             when (adResult.adBean.getAdType()) {
                 AdType.NATIVE -> {
-                    CSJNativeAdView(context).apply {
+                    GmNativeAdView(context).apply {
                         setViewHolder(viewHolder)
                         render(adResult)
                     }
@@ -94,7 +91,12 @@ class GroMoreAdLoader : AdLoader {
                         render(adResult)
                     }
                 }
-
+                AdType.FEED -> {
+                    GMTTFeedAdView(context).apply {
+                        setViewHolder(viewHolder)
+                        render(adResult)
+                    }
+                }
                 else -> {
                     null
                 }
@@ -108,18 +110,22 @@ class GroMoreAdLoader : AdLoader {
         AdManager.instance.globalListener?.invoke(adResult.adBean)
         when (adResult.adBean.getAdType()) {
             AdType.NATIVE -> {
-                CSJNativeAdView.populateNativeAdView(context = context, adResult, viewHolder, advertisersContainerView)
+                GmNativeAdView.populateNativeAdView(context = context, adResult, viewHolder, advertisersContainerView)
             }
-
-            AdType.NATIVE_TEMPLATE -> {
-                val ttNativeExpressAd = adResult.adObject as TTNativeExpressAd
-                advertisersContainerView.removeAllViews()
-                val expressAdView = ttNativeExpressAd.expressAdView
-                expressAdView.parentRemove()
-                advertisersContainerView.addView(expressAdView)
-                GMNativeTemplateAdView.populateNativeTemplateAdView(context, adResult, viewHolder)
+            AdType.NATIVE_TEMPLATE,
+            AdType.BANNER -> {
+                if (adResult.adObject != null) {
+                    val ttNativeExpressAd = adResult.adObject as TTNativeExpressAd
+                    advertisersContainerView.removeAllViews()
+                    val expressAdView = ttNativeExpressAd.expressAdView
+                    expressAdView.parentRemove()
+                    advertisersContainerView.addView(expressAdView)
+                    GMNativeTemplateAdView.populateNativeTemplateAdView(context, adResult, viewHolder)
+                }
+            }
+            AdType.FEED -> {
+                GMTTFeedAdView.populateFeedAdView(context = context, adResult, viewHolder, advertisersContainerView)
             }
-
             else -> {
                 adLogE(tag = AdManager.TAG, msg = "GroMore-填充原生,adType类型错误,不支持")
             }

+ 7 - 2
lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/load/request/GMBannerRequestImpl.kt

@@ -2,10 +2,10 @@ package com.composition.android.ad.gromore.load.request
 
 import android.content.Context
 import com.bytedance.sdk.openadsdk.*
-import com.composition.android.ad.gromore.impl.GMAdImageSize
 import com.composition.android.lib.ad.basic.AdResult
 import com.composition.android.lib.ad.bean.AdUnitBean
 import com.composition.android.lib.ad.interfaces.IAdFormatRequest
+import com.composition.android.lib.ad.util.getScreenWidth
 import com.composition.android.lib.ad.util.isActiveResult
 import com.composition.android.lib.ad.util.printAdFailInfo
 import com.composition.android.lib.ad.util.printAdInfo
@@ -20,7 +20,12 @@ import kotlinx.coroutines.suspendCancellableCoroutine
 class GMBannerRequestImpl : IAdFormatRequest {
     override suspend fun load(context: Context, adUnitBean: AdUnitBean): AdResult {
         return suspendCancellableCoroutine {
-            val size = if (adUnitBean.adSize is GMAdImageSize) (adUnitBean.adSize as GMAdImageSize).gmAdSize else 600 to 90
+            val size = if (adUnitBean.adSize != null && adUnitBean.adSize!!.isAvailable()) {
+                adUnitBean.adSize!!.getWidthDp(context) to adUnitBean.adSize!!.getHeightDp(context)
+            } else {
+                getScreenWidth(context) to 320
+            }
+
             val adSlot = AdSlot.Builder()
                 .setCodeId(adUnitBean.adUnitId)
                 .setAdCount(1)

+ 55 - 0
lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/load/request/GMFeedRequestImpl.kt

@@ -0,0 +1,55 @@
+package com.composition.android.ad.gromore.load.request
+
+import android.content.Context
+import com.bytedance.sdk.openadsdk.AdSlot
+import com.bytedance.sdk.openadsdk.TTAdLoadType
+import com.bytedance.sdk.openadsdk.TTAdNative
+import com.bytedance.sdk.openadsdk.TTAdSdk
+import com.bytedance.sdk.openadsdk.TTFeedAd
+import com.composition.android.lib.ad.AdManager
+import com.composition.android.lib.ad.basic.AdResult
+import com.composition.android.lib.ad.bean.AdUnitBean
+import com.composition.android.lib.ad.interfaces.IAdFormatRequest
+import com.composition.android.lib.ad.util.*
+import kotlinx.coroutines.suspendCancellableCoroutine
+
+class GMFeedRequestImpl : IAdFormatRequest {
+
+    override suspend fun load(context: Context, adUnitBean: AdUnitBean): AdResult {
+
+        return suspendCancellableCoroutine {
+            val size = if (adUnitBean.adSize != null && adUnitBean.adSize!!.isAvailable()) {
+                adUnitBean.adSize!!.widthPx to adUnitBean.adSize!!.heightPx
+            } else {
+                getScreenWidth(context) to 320
+            }
+
+            val adSlot = AdSlot.Builder()
+                .setCodeId(adUnitBean.adUnitId)
+                .setSupportDeepLink(true)
+                .setAdCount(1)
+                .setImageAcceptedSize(size.first, size.second)
+                .setExpressViewAcceptedSize(px2dip(context, size.first.toFloat()).toFloat(), px2dip(context, size.second.toFloat()).toFloat())
+                .setAdLoadType(TTAdLoadType.PRELOAD)
+                .build()
+            adLogE(tag = AdManager.TAG, msg = "GroMore-信息流广告-开始加载")
+            TTAdSdk.getAdManager().createAdNative(context)
+                .loadFeedAd(adSlot, object : TTAdNative.FeedAdListener {
+                    override fun onError(p0: Int, p1: String?) {
+                        printAdFailInfo(adUnitBean, p0, p1)
+                        it.isActiveResult(AdResult.Fail(adUnitBean, msg = p1 ?: "GroMore广告-信息流广告-加载失败"))
+                    }
+
+                    override fun onFeedAdLoad(p0: MutableList<TTFeedAd>?) {
+                        if (p0.isNullOrEmpty().not()) {
+                            printAdInfo(adUnitBean)
+                            it.isActiveResult(AdResult.Success(adBean = adUnitBean, adObject = p0?.get(0), msg = "GroMore-信息流广告-加载成功"))
+                        } else {
+                            printAdFailInfo(adUnitBean, 0, "SDK返回的广告实例为空")
+                            it.isActiveResult(AdResult.Fail(adUnitBean, msg = "GroMore信息流广告-加载失败, SDK返回的广告实例为空"))
+                        }
+                    }
+                })
+        }
+    }
+}

+ 6 - 7
lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/load/request/GMNativeRequestImpl.kt

@@ -6,10 +6,10 @@ import com.bytedance.sdk.openadsdk.TTAdLoadType
 import com.bytedance.sdk.openadsdk.TTAdNative
 import com.bytedance.sdk.openadsdk.TTAdSdk
 import com.bytedance.sdk.openadsdk.TTNativeAd
-import com.composition.android.ad.gromore.impl.GMAdImageSize
 import com.composition.android.lib.ad.basic.AdResult
 import com.composition.android.lib.ad.bean.AdUnitBean
 import com.composition.android.lib.ad.interfaces.IAdFormatRequest
+import com.composition.android.lib.ad.util.getScreenWidth
 import com.composition.android.lib.ad.util.isActiveResult
 import com.composition.android.lib.ad.util.printAdFailInfo
 import com.composition.android.lib.ad.util.printAdInfo
@@ -21,18 +21,17 @@ class GMNativeRequestImpl : IAdFormatRequest {
 
         return suspendCancellableCoroutine {
 
-            val adSize = if (adUnitBean.adSize != null && adUnitBean.adSize is GMAdImageSize) {
-                val size = adUnitBean.adSize as  GMAdImageSize
-                size.gmAdSize
+            val size = if (adUnitBean.adSize != null && adUnitBean.adSize!!.isAvailable()) {
+                adUnitBean.adSize!!.widthPx to adUnitBean.adSize!!.heightPx
             } else {
-                640 to 320
+                getScreenWidth(context) to 320
             }
+
             val adSlot = AdSlot.Builder()
                 .setCodeId(adUnitBean.adUnitId)
                 .setSupportDeepLink(true)
                 .setAdCount(1)
-                .setImageAcceptedSize(adSize.first, adSize.second)
-                .setNativeAdType(AdSlot.TYPE_BANNER)
+                .setImageAcceptedSize(size.first, size.second)
                 .setAdLoadType(TTAdLoadType.PRELOAD)
                 .build()
 

+ 5 - 7
lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/load/request/GMNativeTemplateRequestImpl.kt

@@ -2,7 +2,6 @@ package com.composition.android.ad.gromore.load.request
 
 import android.content.Context
 import com.bytedance.sdk.openadsdk.*
-import com.composition.android.ad.gromore.impl.GMAdImageSize
 import com.composition.android.lib.ad.AdManager
 import com.composition.android.lib.ad.basic.AdResult
 import com.composition.android.lib.ad.bean.AdUnitBean
@@ -19,17 +18,16 @@ import kotlinx.coroutines.suspendCancellableCoroutine
 class GMNativeTemplateRequestImpl : IAdFormatRequest {
     override suspend fun load(context: Context, adUnitBean: AdUnitBean): AdResult {
         return suspendCancellableCoroutine {
-            val adImageSize = if (adUnitBean.adSize != null && adUnitBean.adSize is GMAdImageSize) {
-                val size = adUnitBean.adSize as GMAdImageSize
-                size.gmAdSize
+            val size = if (adUnitBean.adSize != null && adUnitBean.adSize!!.isAvailable()) {
+                adUnitBean.adSize!!.widthPx to adUnitBean.adSize!!.heightPx
             } else {
-                getScreenWidthDp(context).toInt() to 340
+                getScreenWidth(context) to 320
             }
-            adLogE(tag = AdManager.TAG, msg = "CSJNativeTemplateRequestImpl load")
+            adLogE(tag = AdManager.TAG, msg = "GroMore-原生模板-开始加载")
             val adSlot = AdSlot.Builder()
                 .setCodeId(adUnitBean.adUnitId)
                 .setAdCount(1)
-                .setImageAcceptedSize(adImageSize.first, adImageSize.second)
+                .setImageAcceptedSize(size.first, size.second)
                 .setAdLoadType(TTAdLoadType.PRELOAD)
                 .build()
 

+ 190 - 0
lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/load/view/GMTTFeedAdView.kt

@@ -0,0 +1,190 @@
+package com.composition.android.ad.gromore.load.view
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.appcompat.widget.AppCompatImageView
+import androidx.appcompat.widget.AppCompatTextView
+import androidx.core.view.isVisible
+import com.bytedance.sdk.openadsdk.TTAdConstant
+import com.bytedance.sdk.openadsdk.TTAdDislike
+import com.bytedance.sdk.openadsdk.TTFeedAd
+import com.bytedance.sdk.openadsdk.TTNativeAd
+import com.composition.android.ad.gromore.R
+import com.composition.android.ad.gromore.impl.GMAppDownloadListener
+import com.composition.android.lib.ad.AdManager
+import com.composition.android.lib.ad.basic.AdResult
+import com.composition.android.lib.ad.basic.BasicAdView
+import com.composition.android.lib.ad.basic.NativeAdViewHolder
+import com.composition.android.lib.ad.util.adLog
+import com.composition.android.lib.ad.util.adLogE
+import com.composition.android.lib.ad.util.parentRemove
+
+/**
+ * @classname:
+ * @author: LiuXiaoLong
+ * @date: 2022/9/13
+ * description: GroMore 信息流广告View
+ */
+class GMTTFeedAdView(context: Context?) : BasicAdView<View>(context) {
+
+    private var viewHolder: NativeAdViewHolder? = null
+
+    fun setViewHolder(viewHolder: NativeAdViewHolder) {
+        this.viewHolder = viewHolder
+    }
+
+    override fun adContentView(): View? {
+        if (adResult == null || viewHolder == null) {
+            return null
+        }
+        val ttFeedAd = adResult?.adObject as? TTFeedAd
+        ttFeedAd?.render()
+        if (ttFeedAd?.mediationManager?.isExpress == true){
+            return ttFeedAd.adView ?: null
+        } else{
+            return null
+        }
+    }
+
+    override fun onResume() {
+
+    }
+
+    override fun onPause() {
+
+    }
+
+    override fun onDestroy() {
+        val ttFeedAd = adResult?.adObject as? TTFeedAd
+        ttFeedAd?.destroy()
+        adResult?.adObject = null
+    }
+
+    companion object {
+
+        fun populateFeedAdView(context: Context, adResult: AdResult.Success, viewHolder: NativeAdViewHolder, advertisersContainerView: ViewGroup?) {
+
+            val ttFeedAd = adResult.adObject as TTFeedAd
+            viewHolder.activity?.apply {
+                ttFeedAd.setDislikeCallback(this, object : TTAdDislike.DislikeInteractionCallback {
+                    override fun onShow() {
+
+                    }
+
+                    override fun onSelected(p0: Int, p1: String?, p2: Boolean) {
+                        adLog(msg = "穿山甲广告-原生-点击不喜欢按钮")
+                        viewHolder.adListener?.onAdDisLike()
+                    }
+
+                    override fun onCancel() {
+                    }
+                })
+            }
+            if (ttFeedAd.mediationManager.isExpress) {
+                ttFeedAd.setExpressRenderListener { view, fl, fl2, b ->
+                    advertisersContainerView?.removeAllViews()
+                    view?.parentRemove()
+                    advertisersContainerView?.addView(ttFeedAd.adView)
+                }
+                ttFeedAd.render()
+            } else {
+                viewHolder.titleView?.text = ttFeedAd.title
+                (viewHolder.titleDescView as? AppCompatTextView)?.text = ttFeedAd.description
+
+                val mediaImageViews = LayoutInflater.from(context).inflate(R.layout.csj_native_ad_media_image_views, null)
+
+                val imageViewList = mutableListOf<View>()
+                imageViewList.add(mediaImageViews.findViewById(R.id.id_ad_media_iv_1))
+                imageViewList.add(mediaImageViews.findViewById(R.id.id_ad_media_iv_2))
+                imageViewList.add(mediaImageViews.findViewById(R.id.id_ad_media_iv_3))
+
+                viewHolder.contentMediaViewGroup?.apply {
+                    removeAllViews()
+                    addView(mediaImageViews)
+                }
+                if (ttFeedAd.imageList.isNullOrEmpty().not()) {
+
+                    for (i in 0..2) {
+                        val imageItem = ttFeedAd.imageList.getOrNull(i)
+                        if (imageItem != null) {
+                            if (imageItem.isValid) {
+                                viewHolder.mediaImageLoader?.displayImage(context, imageItem.imageUrl, imageViewList[i] as AppCompatImageView)
+                            }
+                        } else {
+                            imageViewList.getOrNull(i)?.isVisible = false
+                        }
+                    }
+                }
+                if (ttFeedAd.icon != null && ttFeedAd.icon.isValid && viewHolder.iconView != null) {
+                    viewHolder.iconImageLoader?.displayImage(context, ttFeedAd.icon.imageUrl, viewHolder.iconView as AppCompatImageView)
+                }
+                when (ttFeedAd.interactionType) {
+                    TTAdConstant.INTERACTION_TYPE_DOWNLOAD -> {
+                        ttFeedAd.setActivityForDownloadApp(viewHolder.activity)
+                        viewHolder.callActionButtonView?.isVisible = true
+                        ttFeedAd.setDownloadListener(GMAppDownloadListener(context, viewHolder))
+                    }
+                    TTAdConstant.INTERACTION_TYPE_DIAL -> {
+                        viewHolder.callActionButtonView?.also {
+                            it.isVisible = true
+                            it.text = context.getString(R.string.call_now)
+                        }
+                    }
+                    TTAdConstant.INTERACTION_TYPE_LANDING_PAGE -> {
+                        viewHolder.callActionButtonView?.also {
+                            it.isVisible = true
+                            it.text = context.getString(R.string.check_the_details)
+                        }
+                    }
+                    else -> {
+                        viewHolder.callActionButtonView?.isVisible = false
+                    }
+                }
+
+                (viewHolder.advertiserLogoImageView as? AppCompatImageView)?.setImageBitmap(ttFeedAd.adLogo)
+
+                val clickViewList = mutableListOf<View>()
+                viewHolder.customLayoutRootView?.let { clickViewList.add(it) }
+
+                val creativeViewList = mutableListOf<View>()
+                viewHolder.callActionButtonView?.let {
+                    creativeViewList.add(it)
+                }
+                adLogE(tag = AdManager.TAG, msg = "GroMore-Feed广告-isExpress:${ttFeedAd.mediationManager.isExpress}")
+                ttFeedAd.registerViewForInteraction(
+                    viewHolder.customLayoutRootView as ViewGroup,
+                    imageViewList,
+                    clickViewList,
+                    creativeViewList,
+                    viewHolder.dislikeView,
+                    object : TTNativeAd.AdInteractionListener {
+                        override fun onAdClicked(p0: View?, p1: TTNativeAd?) {
+                            adLog(msg = "穿山甲广告-原生-点击广告")
+                            viewHolder.adListener?.onAdClick()
+                        }
+
+                        override fun onAdCreativeClick(p0: View?, p1: TTNativeAd?) {
+                        }
+
+                        override fun onAdShow(p0: TTNativeAd?) {
+                            adLog(msg = "穿山甲广告-原生-广告展示")
+                        }
+
+                    })
+
+                ttFeedAd.setExpressRenderListener { view, width, height, isExpress ->
+                    adLog(AdManager.TAG, "穿山甲广告-原生-渲染成功 width:${width},height:${height}")
+                    viewHolder.adListener?.onAdShow(adResult.adBean)
+                }
+                ttFeedAd.render()
+            }
+        }
+    }
+
+    override fun onDetachedFromWindow() {
+        super.onDetachedFromWindow()
+        adResult?.adObject = null
+    }
+}

+ 1 - 1
lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/load/view/CSJNativeAdView.kt

@@ -24,7 +24,7 @@ import com.composition.android.lib.ad.util.adLog
  * @date: 2022/9/13
  * description: 穿山甲原生模板广告View
  */
-class CSJNativeAdView(context: Context?) : BasicAdView<View>(context) {
+class GmNativeAdView(context: Context?) : BasicAdView<View>(context) {
 
     private var viewHolder: NativeAdViewHolder? = null
 

+ 0 - 11
lib_ad_gromore/src/main/java/com/composition/android/ad/gromore/util/GMAdExpan.kt

@@ -1,17 +1,6 @@
 package com.composition.android.ad.gromore.util
 
-import com.composition.android.ad.gromore.impl.GMAdImageSize
 import com.composition.android.lib.ad.interfaces.AdSize
-import com.composition.android.lib.ad.interfaces.IAdSize
 
 
-/**
- * 构建GroMore横幅广告尺寸
- * @param adImageWidthPx 横幅广告 图片宽度
- * @param adImageHeightPx 横幅广告 图片高度
- * 尺寸最好与后台配置的广告尺寸一致
- */
-fun AdSize.Builder.buildGroMoreAdImageSize(adImageWidthPx : Int, adImageHeightPx : Int) : IAdSize<Pair<Int, Int>>{
-    return GMAdImageSize(adImageWidthPx to adImageHeightPx)
-}
 

+ 1 - 1
settings.gradle

@@ -33,7 +33,7 @@ include ':app'
 include ':lib_common'
 include ':lib_ad_core'
 include ':lib_ad_admob'
-include ':lib_ad_csj'
+//include ':lib_ad_csj'
 include ':lib_ad_gromore'
 include ':lib_pdf_base'
 include ':lib_ad_applovinmax'