Browse Source

【APPLovinMax】广告商接入,未测试

liuxiaolong 2 years ago
parent
commit
3eda52bd0d
52 changed files with 5116 additions and 10 deletions
  1. 1 0
      app/build.gradle
  2. 2 0
      app/src/main/java/com/convenient/android/lib/ui/sample/ad/AdMainActivity.kt
  3. 1 0
      app/src/main/java/com/convenient/android/lib/ui/sample/ad/activity/AdNativeActivity.kt
  4. 2 0
      app/src/main/res/values/strings.xml
  5. 1 0
      build.gradle
  6. 4 0
      lib_ad_applovinmax/build.gradle
  7. 48 0
      lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/AdExt.kt
  8. 26 0
      lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/impl/AppLovinMaxInitialize.kt
  9. 333 0
      lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/AppLovinMaxLoader.kt
  10. 65 0
      lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/request/AppLovinMaxAppOpenRequestImpl.kt
  11. 107 0
      lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/request/AppLovinMaxBannerRequestImpl.kt
  12. 66 0
      lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/request/AppLovinMaxInterstitialRequestImpl.kt
  13. 101 0
      lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/request/AppLovinMaxNativeRequestImpl.kt
  14. 73 0
      lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/request/AppLovinMaxNativeTemplateRequestImpl.kt
  15. 75 0
      lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/request/AppLovinMaxRewardRequestImpl.kt
  16. 83 0
      lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/view/AppLovinMaxBannerView.kt
  17. 80 0
      lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/view/AppLovinMaxNativeTemplateView.kt
  18. 5 0
      lib_ad_applovinmax/src/main/res/values-sw600dp/dimens.xml
  19. 5 0
      lib_ad_applovinmax/src/main/res/values/dimens.xml
  20. 19 0
      lib_ad_core/src/main/java/com/composition/android/lib/ad/util/AdCoreExtenstions.kt
  21. 21 10
      lib_ad_csj/src/main/java/com/composition/android/ad/csj/load/CSJAdLoader.kt
  22. 1 0
      lib_material_design_tokens/.gitignore
  23. 50 0
      lib_material_design_tokens/build.gradle
  24. BIN
      lib_material_design_tokens/libs/json-20220924.jar
  25. 21 0
      lib_material_design_tokens/proguard-rules.pro
  26. 24 0
      lib_material_design_tokens/src/androidTest/java/com/convenient/android/material/design/tokens/ExampleInstrumentedTest.kt
  27. 12 0
      lib_material_design_tokens/src/main/AndroidManifest.xml
  28. 25 0
      lib_material_design_tokens/src/main/java/com/convenient/android/material/design/tokens/MdTokenUtil.kt
  29. 69 0
      lib_material_design_tokens/src/main/java/com/convenient/android/material/design/tokens/category/MdParseGlobalUtil.kt
  30. 30 0
      lib_material_design_tokens/src/main/res/drawable-v24/ic_launcher_foreground.xml
  31. 170 0
      lib_material_design_tokens/src/main/res/drawable/ic_launcher_background.xml
  32. 5 0
      lib_material_design_tokens/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
  33. 5 0
      lib_material_design_tokens/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
  34. BIN
      lib_material_design_tokens/src/main/res/mipmap-hdpi/ic_launcher.webp
  35. BIN
      lib_material_design_tokens/src/main/res/mipmap-hdpi/ic_launcher_round.webp
  36. BIN
      lib_material_design_tokens/src/main/res/mipmap-mdpi/ic_launcher.webp
  37. BIN
      lib_material_design_tokens/src/main/res/mipmap-mdpi/ic_launcher_round.webp
  38. BIN
      lib_material_design_tokens/src/main/res/mipmap-xhdpi/ic_launcher.webp
  39. BIN
      lib_material_design_tokens/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
  40. BIN
      lib_material_design_tokens/src/main/res/mipmap-xxhdpi/ic_launcher.webp
  41. BIN
      lib_material_design_tokens/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
  42. BIN
      lib_material_design_tokens/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
  43. BIN
      lib_material_design_tokens/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
  44. 16 0
      lib_material_design_tokens/src/main/res/values-night/themes.xml
  45. 10 0
      lib_material_design_tokens/src/main/res/values/colors.xml
  46. 3 0
      lib_material_design_tokens/src/main/res/values/strings.xml
  47. 16 0
      lib_material_design_tokens/src/main/res/values/themes.xml
  48. 17 0
      lib_material_design_tokens/src/test/java/com/convenient/android/material/design/tokens/ExampleUnitTest.kt
  49. 330 0
      lib_material_design_tokens/tokens/alias.json
  50. 2506 0
      lib_material_design_tokens/tokens/composition.json
  51. 687 0
      lib_material_design_tokens/tokens/global.json
  52. 1 0
      settings.gradle

+ 1 - 0
app/build.gradle

@@ -81,6 +81,7 @@ dependencies {
     implementation project(':lib_ad_core')
     implementation project(':lib_ad_admob')
     implementation project(':lib_ad_csj')
+    implementation project(':lib_ad_applovinmax')
     implementation project(':lib_ad_gromore')
     implementation project(':lib_pdf_base')
 

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

@@ -4,6 +4,7 @@ import android.os.Bundle
 import android.util.Log
 import androidx.activity.compose.setContent
 import androidx.appcompat.app.AppCompatActivity
+import androidx.lifecycle.lifecycleScope
 import com.composition.android.ad.admob.impl.AdmobInitialize
 import com.composition.android.ad.csj.impl.CSJInitialize
 import com.composition.android.ad.gromore.impl.GroMoreInitialize
@@ -13,6 +14,7 @@ import com.composition.android.lib.ad.bean.AdUnitBean
 import com.convenient.android.lib.ui.sample.ad.model.Datas
 import com.convenient.android.lib.ui.sample.ad.page.AdMainPage
 import com.convenient.android.lib.ui.theme.SampleTheme
+import kotlinx.coroutines.launch
 
 class AdMainActivity : AppCompatActivity() {
 

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

@@ -3,6 +3,7 @@ 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.ad.applovinmax.loadAppLovinNativeAd
 import com.composition.android.lib.ad.AdLoad
 import com.composition.android.lib.ad.AdManager
 import com.composition.android.lib.ad.basic.AdResult

+ 2 - 0
app/src/main/res/values/strings.xml

@@ -4,4 +4,6 @@
     <string name="app_open_1">后台进入前台展示开屏(目前状态:%s)</string>
     <string name="close">关闭</string>
     <string name="open">开启</string>
+
+
 </resources>

+ 1 - 0
build.gradle

@@ -10,6 +10,7 @@ plugins {
     id 'com.android.application' version '7.2.0' apply false
     id 'com.android.library' version '7.2.0' apply false
     id 'org.jetbrains.kotlin.android' version '1.7.0' apply false
+    id 'org.jetbrains.kotlin.jvm' version '1.7.0' apply false
 }
 
 project.ext {

+ 4 - 0
lib_ad_applovinmax/build.gradle

@@ -38,4 +38,8 @@ dependencies {
     testImplementation 'junit:junit:4.13.2'
     androidTestImplementation 'androidx.test.ext:junit:1.1.3'
     androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+    implementation 'com.applovin:applovin-sdk:11.5.5'
+    implementation "com.google.android.gms:play-services-ads-identifier:18.0.1"
+
+
 }

+ 48 - 0
lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/AdExt.kt

@@ -0,0 +1,48 @@
+package com.composition.android.ad.applovinmax
+
+import android.content.Context
+import com.composition.android.ad.applovinmax.load.AppLovinMaxLoader
+import com.composition.android.lib.ad.AdLoad
+import com.composition.android.lib.ad.AdUnitConfigManager
+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.bean.AdUnitBean
+import com.composition.android.lib.ad.factory.AdLoaderFactory
+import com.composition.android.lib.ad.util.adLog
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flow
+
+/**
+ * @classname:
+ * @author: LiuXiaoLong
+ * @date: 2022/11/18
+ * description:
+ */
+
+
+/**
+ * 加载原生广告扩展类, APPLovin原生广告需要先传入创建的自定义布局内容进行加载
+ * @param context 上下文,要是activity类型
+ * @param adSlotNames 广告位名称
+ * @param 原生广告自定义布局内容配置
+ */
+suspend fun AdLoad.loadAppLovinNativeAd(context: Context, vararg adSlotNames: String, nativeAdViewHolder: NativeAdViewHolder): Flow<AdResult> {
+    return flow<AdResult> {
+        val adUnitBeans = AdUnitConfigManager.instance.getAdUnitBySlotName(adSlotNames.toList())
+        if (adUnitBeans.isNullOrEmpty()) {
+            adLog(msg = "广告单元配置为空")
+            emit(AdResult.Fail(adBean = AdUnitBean.emptyAdUnitBean(), msg = "AdUnitBeans 为空"))
+            return@flow
+        }
+        for (bean in adUnitBeans) {
+            if (bean.getAdvertisers() == Advertisers.AppLovinMax) {
+                (AdLoaderFactory.getAdLoader(bean) as? AppLovinMaxLoader)?.loadNativeAd(context, bean, nativeAdViewHolder)?.let {
+                    emit(it)
+                } ?: emit(AdResult.Fail(bean, msg = "AppLovinMax广告-原生-加载失败"))
+            } else {
+                emit(AdLoaderFactory.getAdLoader(bean).load(context, bean))
+            }
+        }
+    }
+}

+ 26 - 0
lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/impl/AppLovinMaxInitialize.kt

@@ -0,0 +1,26 @@
+package com.composition.android.ad.applovinmax.impl
+
+import android.content.Context
+import com.applovin.sdk.AppLovinSdk
+import com.composition.android.lib.ad.AdManager
+import com.composition.android.lib.ad.interfaces.Initialize
+import com.composition.android.lib.ad.util.adLogE
+
+/**
+ * @classname:AppLovinMaxInitialize
+ * @author: LiuXiaoLong
+ * @date: 2022/11/11
+ * description: AppLovinMax SDK 初始化默认实现
+ */
+class AppLovinMaxInitialize : Initialize {
+
+    override fun init(context: Context) {
+
+        AppLovinSdk.getInstance(context).mediationProvider = "max"
+        AppLovinSdk.initializeSdk(context){
+            adLogE(AdManager.TAG, "AppLovinMax广告初始化完成")
+        }
+
+    }
+
+}

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

@@ -0,0 +1,333 @@
+package com.composition.android.ad.applovinmax.load
+
+import android.app.Activity
+import android.content.Context
+import android.view.View
+import android.view.ViewGroup
+import com.applovin.mediation.*
+import com.applovin.mediation.ads.MaxAdView
+import com.applovin.mediation.ads.MaxAppOpenAd
+import com.applovin.mediation.ads.MaxInterstitialAd
+import com.applovin.mediation.ads.MaxRewardedAd
+import com.applovin.mediation.nativeAds.MaxNativeAdLoader
+import com.applovin.mediation.nativeAds.MaxNativeAdView
+import com.applovin.sdk.AppLovinSdk
+import com.composition.android.ad.applovinmax.load.request.*
+import com.composition.android.ad.applovinmax.load.view.AppLovinMaxBannerView
+import com.composition.android.ad.applovinmax.load.view.AppLovinMaxNativeTemplateView
+import com.composition.android.lib.ad.AdManager
+import com.composition.android.lib.ad.basic.*
+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.adLogE
+import com.composition.android.lib.ad.util.parentRemove
+
+/**
+ * @classname:
+ * @author: LiuXiaoLong
+ * @date: 2022/11/11
+ * description:AppLovinMax广告加载器
+ */
+class AppLovinMaxLoader : AdLoader {
+    override val advertisers: Advertisers
+        get() = Advertisers.AppLovinMax
+
+
+    suspend fun loadNativeAd(context: Context, adUnitBean: AdUnitBean, nativeAdViewHolder: NativeAdViewHolder): AdResult{
+        return loadByStrategy(context, adUnitBean, AppLovinMaxNativeRequestImpl(nativeAdViewHolder))
+    }
+
+    override suspend fun load(context: Context, adUnitBean: AdUnitBean): AdResult {
+
+        val requestImpl = when (adUnitBean.getAdType()) {
+            AdType.APP_OPEN -> AppLovinMaxAppOpenRequestImpl()
+            AdType.INTERSTITIAL -> AppLovinMaxInterstitialRequestImpl()
+            AdType.BANNER -> AppLovinMaxBannerRequestImpl()
+            AdType.NATIVE_TEMPLATE -> AppLovinMaxNativeTemplateRequestImpl()
+            AdType.REWARDED_VIDEO -> AppLovinMaxRewardRequestImpl()
+            else -> null
+        }
+        return loadByStrategy(context, adUnitBean, requestImpl)
+    }
+
+
+    /**
+     * 获取横幅Banner广告View
+     * @param context 上下文
+     * @param adResult 请求成功的结果
+     * @param viewHolder 横幅广告需要的配置:activity、adListener
+     */
+    override fun getBannerView(context: Context, adResult: AdResult.Success, viewHolder: BannerAdViewHolder): BasicAdView<*>? {
+        return if (adResult.adObject is MaxAdView) {
+            AdManager.instance.globalListener?.invoke(adResult.adBean)
+            AppLovinMaxBannerView(context).apply {
+                setBannerAdViewHolder(viewHolder)
+                render(adResult)
+            }
+        } else {
+            null
+        }
+    }
+
+    /**
+     * 获取原生、原生模板广告View
+     * @param context 上下文
+     * @param adResult 请求成功的结果
+     * @param viewHolder 原生广告需要的配置
+     * @return View?
+     */
+    override fun getNativeAdView(context: Context, adResult: AdResult.Success, viewHolder: NativeAdViewHolder): View? {
+        return if (adResult.adObject != null) {
+            AdManager.instance.globalListener?.invoke(adResult.adBean)
+            when (adResult.adBean.getAdType()) {
+                AdType.NATIVE_TEMPLATE -> {
+                    AppLovinMaxNativeTemplateView(context).apply {
+                        setViewHolder(viewHolder)
+                        render(adResult)
+                    }
+                }
+                else -> {
+                    null
+                }
+            }
+        } else {
+            null
+        }
+    }
+
+
+    /**
+     * 根据广告adResult.adObject类型,销毁广告
+     * @param 广告实例
+     *
+     */
+    override fun destroyAd(adResult: AdResult) {
+
+        try {
+            if (adResult is AdResult.Success) {
+                when(val ad = adResult.adObject) {
+                    is Triple<*, *, *>-> {
+                        val triple = adResult.adObject as? Triple<MaxNativeAdLoader, MaxNativeAdView?, MaxAd?>
+                        triple?.first?.destroy(triple.third)
+                    }
+                    is MaxAdView -> ad.destroy()
+                    is MaxInterstitialAd -> ad.destroy()
+                    is MaxRewardedAd -> ad.destroy()
+                    is MaxAppOpenAd -> ad.destroy()
+                    else -> {}
+                }
+                adResult.adObject = null
+            }
+            adLog(msg = "APPLovin广告-${adResult.adBean.getAdType().name}-销毁广告对象完成")
+        }catch (e : Exception){
+            adLog(msg = "APPLovin广告-销毁广告出现了问题\n${e.message}")
+
+        }
+
+    }
+
+    /**
+     * 填充原生广告
+     *
+     */
+    override fun populateNativeAdView(context: Context, adResult: AdResult.Success, viewHolder: NativeAdViewHolder, advertisersContainerView: ViewGroup) {
+        when(adResult.adBean.getAdType()){
+            AdType.NATIVE_TEMPLATE ->{
+                val triple = adResult.adObject as? Triple<MaxNativeAdLoader, MaxNativeAdView?, MaxAd?>
+                //这里主要是对广告View设置监听
+                AppLovinMaxNativeTemplateView.populateNativeTemplateAdView(context, adResult, viewHolder)
+                //父布局先移除
+                triple?.second?.parentRemove()
+                //移除View
+                advertisersContainerView.removeAllViews()
+                advertisersContainerView.addView(triple?.second)
+            }
+            else->{
+                adLogE(tag = AdManager.TAG, "AppLovinMax组件暂未接入原生广告,不支持填充")
+            }
+        }
+    }
+
+    override fun showInterstitialAd(activity: Activity, adResult: AdResult.Success, adListener: AdListener) {
+        if (adResult.adObject is MaxInterstitialAd) {
+            val maxInterstitialAd = adResult.adObject as? MaxInterstitialAd
+            if (maxInterstitialAd?.isReady == true) {
+                maxInterstitialAd.setListener(object : MaxAdListener{
+                    override fun onAdLoaded(ad: MaxAd?) {
+
+                    }
+
+                    override fun onAdDisplayed(ad: MaxAd?) {
+                        AdManager.instance.globalListener?.invoke(adResult.adBean)
+                        adListener.onAdShow(adResult.adBean)
+                        adLog(msg = "AppLovinMax广告-插屏-显示")
+                    }
+
+                    override fun onAdHidden(ad: MaxAd?) {
+                        adListener.onAdClose()
+                        adLog(msg = "AppLovinMax广告-插屏-关闭")
+                        destroyAd(adResult)
+                    }
+
+                    override fun onAdClicked(ad: MaxAd?) {
+                        adListener.onAdClick()
+                        adLog(msg = "AppLovinMax广告-插屏-点击")
+                    }
+
+                    override fun onAdLoadFailed(adUnitId: String?, error: MaxError?) {
+                    }
+
+                    override fun onAdDisplayFailed(ad: MaxAd?, error: MaxError?) {
+                        adListener.onAdShowFail("AppLovinMax广告-插屏-显示失败-${error?.message}")
+                        adLog(msg = "AppLovinMax广告-插屏-显示失败")
+                    }
+                })
+                maxInterstitialAd.showAd()
+            }else{
+                adLog(msg = "AppLovinMax广告-插屏-显示失败-isReady:false")
+                adListener.onAdShowFail("AppLovinMax广告-插屏-显示失败-isReady:false")
+            }
+        }else{
+            adLog(
+                msg = "AppLovinMax广告-插屏-错误\n" +
+                        "类型错误,当前为:${adResult.adObject?.javaClass?.simpleName}, 应该为:MaxInterstitialAd"
+            )
+            adListener.onAdShowFail("类型错误,当前为:${adResult.adObject?.javaClass?.simpleName}, 应该为:MaxInterstitialAd")
+        }
+    }
+
+    override fun showRewardedAd(activity: Activity, adResult: AdResult.Success, adListener: AdListener) {
+        if (adResult.adObject is MaxRewardedAd) {
+            val maxRewardedAd = adResult.adObject as? MaxRewardedAd
+            if (maxRewardedAd?.isReady == true) {
+                maxRewardedAd.setListener(object : MaxRewardedAdListener{
+                    override fun onAdLoaded(ad: MaxAd?) {
+
+                    }
+
+                    override fun onAdDisplayed(ad: MaxAd?) {
+                        AdManager.instance.globalListener?.invoke(adResult.adBean)
+                        adListener.onAdShow(adResult.adBean)
+                        adLog(msg = "AppLovinMax广告-激励-显示")
+                    }
+
+                    override fun onAdHidden(ad: MaxAd?) {
+                        adListener.onAdClose()
+                        adLog(msg = "AppLovinMax广告-激励-关闭")
+                        destroyAd(adResult)
+                    }
+
+                    override fun onAdClicked(ad: MaxAd?) {
+                        adListener.onAdClick()
+                        adLog(msg = "AppLovinMax广告-激励-点击")
+                    }
+
+                    override fun onAdLoadFailed(adUnitId: String?, error: MaxError?) {
+                    }
+
+                    override fun onAdDisplayFailed(ad: MaxAd?, error: MaxError?) {
+                        adListener.onAdShowFail("AppLovinMax广告-激励-显示失败-${error?.message}")
+                        adLog(msg = "AppLovinMax广告-激励-显示失败")
+                    }
+
+                    override fun onUserRewarded(ad: MaxAd?, reward: MaxReward?) {
+
+                    }
+
+                    override fun onRewardedVideoStarted(ad: MaxAd?) {
+                    }
+
+                    override fun onRewardedVideoCompleted(ad: MaxAd?) {
+                    }
+                })
+                maxRewardedAd.showAd()
+            }else{
+                adLog(msg = "AppLovinMax广告-激励-显示失败-isReady:false")
+                adListener.onAdShowFail("AppLovinMax广告-激励-显示失败-isReady:false")
+            }
+        }else{
+            adLog(
+                msg = "AppLovinMax广告-激励-错误\n" +
+                        "类型错误,当前为:${adResult.adObject?.javaClass?.simpleName}, 应该为:MaxRewardedAd"
+            )
+            adListener.onAdShowFail("类型错误,当前为:${adResult.adObject?.javaClass?.simpleName}, 应该为:MaxRewardedAd")
+        }
+    }
+
+    override fun showRewardedInterstitialAd(activity: Activity, adResult: AdResult.Success, adListener: AdListener) {
+        adLogE(tag = AdManager.TAG, msg = "AppLovinMax广告-插屏激励-不支持此广告格式")
+        adListener.onAdShowFail("AppLovinMax广告-插屏激励-不支持此广告格式")
+    }
+
+    override fun showSplashAd(activity: Activity, splashViewGroup: ViewGroup?, adResult: AdResult.Success, adListener: AdListener) {
+        if (adResult.adObject is MaxAppOpenAd) {
+
+            val maxAppOpenAd = adResult.adObject as MaxAppOpenAd
+
+            if (maxAppOpenAd.isReady && AppLovinSdk.getInstance(activity).isInitialized) {
+                maxAppOpenAd.setListener(object : MaxAdListener {
+                    override fun onAdLoaded(ad: MaxAd?) {
+
+                    }
+
+                    override fun onAdDisplayed(ad: MaxAd?) {
+                        adListener.onAdShow(adResult.adBean)
+                        AdManager.instance.globalListener?.invoke(adResult.adBean)
+                    }
+
+                    override fun onAdHidden(ad: MaxAd?) {
+                        adLog(msg = "穿山甲广告-开屏-关闭")
+                        adListener.onAdClose()
+                        destroyAd(adResult)
+                    }
+
+                    override fun onAdClicked(ad: MaxAd?) {
+                        adLog(msg = "AppLovinMax广告-开屏-点击")
+                        adListener.onAdClick()
+                    }
+
+                    override fun onAdLoadFailed(adUnitId: String?, error: MaxError?) {
+                        adLog(msg = "AppLovinMax广告-开屏-点击")
+
+                    }
+
+                    override fun onAdDisplayFailed(ad: MaxAd?, error: MaxError?) {
+                        adLog(msg = "AppLovinMax广告-开屏-显示失败")
+                        adListener.onAdShowFail("AppLovinMax广告-开屏-显示失败")
+                    }
+
+                })
+            }
+            maxAppOpenAd.showAd()
+
+
+        } else {
+            adLog(
+                msg = "AppLovinMax广告-开屏-异常\n" +
+                        "类型错误,当前类型为:${adResult.adObject?.javaClass?.simpleName}, 应为:MaxAppOpenAd"
+            )
+            adListener.onAdShowFail("类型错误,当前类型为:${adResult.adObject?.javaClass?.simpleName}, 应为:MaxAppOpenAd")
+        }
+    }
+
+    /**
+     * 显示全屏类型广告
+     * @param activity 用于展示广告的上下文
+     * @param adResult 请求成功的广告实例
+     * @param adListener 广告监听
+     */
+    override fun showFullScreenAd(activity: Activity, adResult: AdResult.Success, adListener: AdListener) {
+        when(adResult.adBean.getAdType()){
+            AdType.INTERSTITIAL -> showInterstitialAd(activity, adResult, adListener)
+            AdType.REWARDED_INTERSTITIAL -> showRewardedInterstitialAd(activity, adResult, adListener)
+            AdType.REWARDED_VIDEO -> showRewardedAd(activity, adResult, adListener)
+            else -> {
+                adListener.onAdShowFail("AppLovinMax, 传入的AdType为:${adResult.adBean.getAdType()},  非全屏类型广告")
+            }
+        }
+    }
+
+
+}

+ 65 - 0
lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/request/AppLovinMaxAppOpenRequestImpl.kt

@@ -0,0 +1,65 @@
+package com.composition.android.ad.applovinmax.load.request
+
+import android.app.Activity
+import android.content.Context
+import com.applovin.mediation.MaxAd
+import com.applovin.mediation.MaxAdListener
+import com.applovin.mediation.MaxError
+import com.applovin.mediation.ads.MaxAppOpenAd
+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 kotlinx.coroutines.suspendCancellableCoroutine
+import kotlin.coroutines.resume
+
+/**
+ * @classname:AppLovinMaxAppOpenRequestImpl
+ * @author: LiuXiaoLong
+ * @date: 2022/11/11
+ * description: AppLovinMax 开屏广告加载类
+ */
+class AppLovinMaxAppOpenRequestImpl : IAdFormatRequest {
+
+
+    override suspend fun load(context: Context, adUnitBean: AdUnitBean): AdResult {
+        return suspendCancellableCoroutine {
+
+            if (context !is Activity) {
+                printAdFailInfo(0, "AppLovinMax广告,context必须为Activity类型")
+                it.isActiveResult(AdResult.Fail(adUnitBean, msg = "AppLovinMax广告-开屏-加载失败,context必须为Activity"))
+                return@suspendCancellableCoroutine
+            }
+
+            val appOpenAd = MaxAppOpenAd(adUnitBean.adUnitId, context)
+            appOpenAd.setListener(object : MaxAdListener {
+                override fun onAdLoaded(ad: MaxAd?) {
+                    printAdInfo(adUnitBean)
+                    it.isActiveResult(AdResult.Success(appOpenAd, adUnitBean, msg = "AppLovinMax广告-开屏-加载成功"))
+                }
+
+                override fun onAdDisplayed(ad: MaxAd?) {
+                }
+
+                override fun onAdHidden(ad: MaxAd?) {
+                }
+
+                override fun onAdClicked(ad: MaxAd?) {
+
+                }
+
+                override fun onAdLoadFailed(adUnitId: String?, error: MaxError?) {
+                    printAdFailInfo(error?.code ?: 0, error?.message)
+                    it.isActiveResult(AdResult.Fail(adUnitBean, msg = "AppLovinMax广告-开屏-加载失败"))
+                }
+
+                override fun onAdDisplayFailed(ad: MaxAd?, error: MaxError?) {
+
+                }
+            })
+
+        }
+    }
+}

+ 107 - 0
lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/request/AppLovinMaxBannerRequestImpl.kt

@@ -0,0 +1,107 @@
+package com.composition.android.ad.applovinmax.load.request
+
+import android.app.Activity
+import android.content.Context
+import android.view.ViewGroup
+import android.widget.RelativeLayout
+import com.applovin.mediation.MaxAd
+import com.applovin.mediation.MaxAdViewAdListener
+import com.applovin.mediation.MaxError
+import com.applovin.mediation.ads.MaxAdView
+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 com.kdanmobile.android.ad.applovinmax.R
+import kotlinx.coroutines.suspendCancellableCoroutine
+import kotlin.coroutines.resume
+
+/**
+ * @classname:
+ * @author: LiuXiaoLong
+ * @date: 2022/11/11
+ * description: AppLovinMax 横幅广告加载类
+ */
+class AppLovinMaxBannerRequestImpl : IAdFormatRequest {
+
+    override suspend fun load(context: Context, adUnitBean: AdUnitBean): AdResult {
+
+        return suspendCancellableCoroutine {
+
+            if (context !is Activity) {
+                printAdFailInfo(0, "AppLovinMax广告,context必须为Activity类型")
+                it.isActiveResult(AdResult.Fail(adUnitBean, msg = "AppLovinMax广告-插屏-加载失败,context必须为Activity"))
+                return@suspendCancellableCoroutine
+            }
+
+            val maxAdView = MaxAdView(adUnitBean.adUnitId, context)
+            //先关闭自动刷新,当请求成功再开启自动刷新功能
+            //这样做是为了统一逻辑, BannerView中会有重试, app lovin会大概间隔10秒刷新一次广告, 每次都会调用onAdLoaded
+            maxAdView.setExtraParameter("allow_pause_auto_refresh_immediately", "true")
+            maxAdView.stopAutoRefresh()
+            val listener = object : MaxAdViewAdListener {
+                override fun onAdLoaded(ad: MaxAd?) {
+                    printAdInfo(adUnitBean)
+                    //更新view的高度
+                    val width = ViewGroup.LayoutParams.MATCH_PARENT
+                    val heightDp = if (ad != null) {
+                        ad.size?.height ?: 0
+                    } else {
+                        context.resources.getDimensionPixelSize(R.dimen.app_lovin_banner_height)
+                    }
+
+                    val heightPx = dp2px(context, heightDp.toFloat())
+                    maxAdView.layoutParams = RelativeLayout.LayoutParams(width, heightPx).also { layoutParams ->
+                        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT)
+                        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT)
+                        layoutParams.topMargin = (1.5f * 5).toInt()
+                    }
+
+                    //返回结果 返回一次之后 isActive为 false
+                    it.isActiveResult(AdResult.Success(adObject = maxAdView, adUnitBean, msg = "AppLovinMax广告-横幅-加载成功"))
+                }
+
+                override fun onAdDisplayed(ad: MaxAd?) {
+//                    adLog(TAG, "广告展示")
+                }
+
+                override fun onAdHidden(ad: MaxAd?) {
+
+                }
+
+                override fun onAdClicked(ad: MaxAd?) {
+                    //这里没有错,横幅广告点击才算广告打开
+
+                }
+
+                override fun onAdLoadFailed(adUnitId: String?, error: MaxError?) {
+                    printAdFailInfo(error?.code ?: 0, error?.message)
+
+                    error?.waterfall?.let {
+                        for (networkRespons in it.networkResponses) {
+                            adLog(AdManager.TAG, networkRespons.error.code.toString())
+                            adLog(AdManager.TAG, networkRespons.error.message)
+                        }
+                    }
+                    it.isActiveResult(AdResult.Fail(adUnitBean, msg = "AppLovinMax广告-横幅-加载失败"))
+                }
+
+                override fun onAdDisplayFailed(ad: MaxAd?, error: MaxError?) {
+                }
+
+                override fun onAdExpanded(ad: MaxAd?) {
+                }
+
+                override fun onAdCollapsed(ad: MaxAd?) {
+
+                }
+            }
+            maxAdView.setListener(listener)
+            //设置返回 适配器广告的尺寸
+            maxAdView.setExtraParameter("adaptive_banner", "true")
+            maxAdView.loadAd()
+        }
+    }
+
+}

+ 66 - 0
lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/request/AppLovinMaxInterstitialRequestImpl.kt

@@ -0,0 +1,66 @@
+package com.composition.android.ad.applovinmax.load.request
+
+import android.app.Activity
+import android.content.Context
+import com.applovin.mediation.MaxAd
+import com.applovin.mediation.MaxAdListener
+import com.applovin.mediation.MaxError
+import com.applovin.mediation.ads.MaxAppOpenAd
+import com.applovin.mediation.ads.MaxInterstitialAd
+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 kotlinx.coroutines.suspendCancellableCoroutine
+import kotlin.coroutines.resume
+
+/**
+ * @classname:AppLovinMaxAppOpenRequestImpl
+ * @author: LiuXiaoLong
+ * @date: 2022/11/11
+ * description: AppLovinMax 插屏广告加载类
+ */
+class AppLovinMaxInterstitialRequestImpl : IAdFormatRequest {
+
+
+    override suspend fun load(context: Context, adUnitBean: AdUnitBean): AdResult {
+
+        return suspendCancellableCoroutine {
+
+            if (context !is Activity) {
+                printAdFailInfo(0, "AppLovinMax广告,context必须为Activity类型")
+                it.isActiveResult(AdResult.Fail(adUnitBean, msg = "AppLovinMax广告-插屏-加载失败,context必须为Activity"))
+                return@suspendCancellableCoroutine
+            }
+
+            val interstitialAd = MaxInterstitialAd(adUnitBean.adUnitId, context)
+            interstitialAd.setListener(object : MaxAdListener{
+                override fun onAdLoaded(ad: MaxAd?) {
+                    printAdInfo(adUnitBean)
+                    it.isActiveResult(AdResult.Success(adObject = interstitialAd, adBean = adUnitBean, msg = "AppLovinMax广告-插屏-加载成功"))
+                }
+
+                override fun onAdDisplayed(ad: MaxAd?) {
+
+                }
+
+                override fun onAdHidden(ad: MaxAd?) {
+                }
+
+                override fun onAdClicked(ad: MaxAd?) {
+                }
+
+                override fun onAdLoadFailed(adUnitId: String?, error: MaxError?) {
+                    printAdFailInfo(error?.code?:0, error?.message)
+                    it.isActiveResult(AdResult.Fail(adUnitBean, msg = "AppLovinMax广告-插屏-加载失败"))
+                }
+
+                override fun onAdDisplayFailed(ad: MaxAd?, error: MaxError?) {
+                }
+            })
+
+        }
+    }
+}

+ 101 - 0
lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/request/AppLovinMaxNativeRequestImpl.kt

@@ -0,0 +1,101 @@
+package com.composition.android.ad.applovinmax.load.request
+
+import android.app.Activity
+import android.content.Context
+import android.view.ViewGroup
+import android.widget.RelativeLayout
+import androidx.appcompat.widget.AppCompatImageView
+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.applovin.mediation.nativeAds.MaxNativeAdViewBinder
+import com.composition.android.lib.ad.AdManager
+import com.composition.android.lib.ad.basic.AdResult
+import com.composition.android.lib.ad.basic.NativeAdViewHolder
+import com.composition.android.lib.ad.bean.AdUnitBean
+import com.composition.android.lib.ad.interfaces.IAdFormatRequest
+import com.composition.android.lib.ad.util.*
+import com.kdanmobile.android.ad.applovinmax.R
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.suspendCancellableCoroutine
+import kotlin.coroutines.resume
+
+/**
+ * @classname:
+ * @author: LiuXiaoLong
+ * @date: 2022/11/11
+ * description: AppLovinMax 原生广告加载类
+ */
+class AppLovinMaxNativeRequestImpl(var nativeAdViewHolder: NativeAdViewHolder) : IAdFormatRequest {
+
+    override suspend fun load(context: Context, adUnitBean: AdUnitBean): AdResult {
+
+        return suspendCancellableCoroutine {
+
+            if (context !is Activity) {
+                printAdFailInfo(0, "AppLovinMax广告,context必须为Activity类型")
+                it.isActiveResult(AdResult.Fail(adUnitBean, msg = "AppLovinMax广告-原生模板-加载失败,context必须为Activity"))
+                return@suspendCancellableCoroutine
+            }
+
+            val maxNativeAdLoader = MaxNativeAdLoader(adUnitBean.adUnitId, context)
+
+            val listener = object : MaxNativeAdListener() {
+                override fun onNativeAdLoaded(maxNativeAdView: MaxNativeAdView?, p1: MaxAd?) {
+                    super.onNativeAdLoaded(maxNativeAdView, p1)
+                    printAdInfo(adUnitBean)
+                    //这里会保存下三个值, 用于处理destroy
+                    it.isActiveResult(AdResult.Success(adBean = adUnitBean, adObject = Triple<MaxNativeAdLoader, MaxNativeAdView?, MaxAd?>(maxNativeAdLoader, maxNativeAdView, p1), msg = "AppLovinMax广告-原生模板-加载成功"))
+                }
+
+                override fun onNativeAdClicked(p0: MaxAd?) {
+                    super.onNativeAdClicked(p0)
+                }
+
+                override fun onNativeAdLoadFailed(p0: String?, p1: MaxError?) {
+                    super.onNativeAdLoadFailed(p0, p1)
+                    printAdFailInfo(p1?.code?:0, p1?.message)
+                    it.isActiveResult(AdResult.Fail(adUnitBean, msg = "AppLovinMax广告-原生模板-加载失败"))
+                }
+
+                override fun onNativeAdExpired(p0: MaxAd?) {
+                    super.onNativeAdExpired(p0)
+                }
+            }
+
+            maxNativeAdLoader.setNativeAdListener(listener)
+            maxNativeAdLoader.loadAd(MaxNativeAdView(createMaxNativeAdViewBinder(nativeAdViewHolder), context))
+
+        }
+    }
+
+    private fun createMaxNativeAdViewBinder(nativeAdViewHolder: NativeAdViewHolder) : MaxNativeAdViewBinder{
+        val binder = MaxNativeAdViewBinder.Builder(nativeAdViewHolder.customLayoutRootView)
+
+        nativeAdViewHolder.titleView?.let {
+            binder.setTitleTextViewId(it.id)
+        }
+        nativeAdViewHolder.titleDescView?.let {
+            binder.setBodyTextViewId(it.id)
+        }
+        (nativeAdViewHolder.iconView as? AppCompatImageView)?.let {
+            binder.setIconImageViewId(it.id)
+        }
+        nativeAdViewHolder.contentMediaViewGroup?.let {
+            binder.setMediaContentViewGroupId(it.id)
+        }
+        nativeAdViewHolder.callActionButtonView?.let {
+            binder.setCallToActionButtonId(it.id)
+        }
+        nativeAdViewHolder.dislikeView?.let {
+            binder.setOptionsContentViewGroupId(it.id)
+
+        }
+        return binder.build()
+    }
+
+}

+ 73 - 0
lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/request/AppLovinMaxNativeTemplateRequestImpl.kt

@@ -0,0 +1,73 @@
+package com.composition.android.ad.applovinmax.load.request
+
+import android.app.Activity
+import android.content.Context
+import android.view.ViewGroup
+import android.widget.RelativeLayout
+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.bean.AdUnitBean
+import com.composition.android.lib.ad.interfaces.IAdFormatRequest
+import com.composition.android.lib.ad.util.*
+import com.kdanmobile.android.ad.applovinmax.R
+import kotlinx.coroutines.suspendCancellableCoroutine
+import kotlin.coroutines.resume
+
+/**
+ * @classname:
+ * @author: LiuXiaoLong
+ * @date: 2022/11/11
+ * description: AppLovinMax 原生模板广告加载类
+ */
+class AppLovinMaxNativeTemplateRequestImpl : IAdFormatRequest {
+
+    override suspend fun load(context: Context, adUnitBean: AdUnitBean): AdResult {
+
+        return suspendCancellableCoroutine {
+
+            if (context !is Activity) {
+                printAdFailInfo(0, "AppLovinMax广告,context必须为Activity类型")
+                it.isActiveResult(AdResult.Fail(adUnitBean, msg = "AppLovinMax广告-原生模板-加载失败,context必须为Activity"))
+                return@suspendCancellableCoroutine
+            }
+
+            val maxNativeAdLoader = MaxNativeAdLoader(adUnitBean.adUnitId, context)
+
+            val listener = object : MaxNativeAdListener() {
+                override fun onNativeAdLoaded(maxNativeAdView: MaxNativeAdView?, p1: MaxAd?) {
+                    super.onNativeAdLoaded(maxNativeAdView, p1)
+                    printAdInfo(adUnitBean)
+                    //这里会保存下三个值, 用于处理destroy
+                    it.isActiveResult(AdResult.Success(adBean = adUnitBean, adObject = Triple<MaxNativeAdLoader, MaxNativeAdView?, MaxAd?>(maxNativeAdLoader, maxNativeAdView, p1), msg = "AppLovinMax广告-原生模板-加载成功"))
+                }
+
+                override fun onNativeAdClicked(p0: MaxAd?) {
+                    super.onNativeAdClicked(p0)
+                }
+
+                override fun onNativeAdLoadFailed(p0: String?, p1: MaxError?) {
+                    super.onNativeAdLoadFailed(p0, p1)
+                    printAdFailInfo(p1?.code?:0, p1?.message)
+                    it.isActiveResult(AdResult.Fail(adUnitBean, msg = "AppLovinMax广告-原生模板-加载失败"))
+                }
+
+                override fun onNativeAdExpired(p0: MaxAd?) {
+                    super.onNativeAdExpired(p0)
+                }
+            }
+
+            maxNativeAdLoader.setNativeAdListener(listener)
+            maxNativeAdLoader.loadAd()
+
+
+        }
+    }
+
+}

+ 75 - 0
lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/request/AppLovinMaxRewardRequestImpl.kt

@@ -0,0 +1,75 @@
+package com.composition.android.ad.applovinmax.load.request
+
+import android.app.Activity
+import android.content.Context
+import com.applovin.mediation.*
+import com.applovin.mediation.ads.MaxAppOpenAd
+import com.applovin.mediation.ads.MaxInterstitialAd
+import com.applovin.mediation.ads.MaxRewardedAd
+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 kotlinx.coroutines.suspendCancellableCoroutine
+import kotlin.coroutines.resume
+
+/**
+ * @classname:AppLovinMaxAppOpenRequestImpl
+ * @author: LiuXiaoLong
+ * @date: 2022/11/11
+ * description: AppLovinMax 激励广告加载类
+ */
+class AppLovinMaxRewardRequestImpl : IAdFormatRequest {
+
+
+    override suspend fun load(context: Context, adUnitBean: AdUnitBean): AdResult {
+
+        return suspendCancellableCoroutine {
+
+            if (context !is Activity) {
+                printAdFailInfo(0, "AppLovinMax广告,context必须为Activity类型")
+                it.isActiveResult(AdResult.Fail(adUnitBean, msg = "AppLovinMax广告-激励-加载失败,context必须为Activity"))
+                return@suspendCancellableCoroutine
+            }
+
+            val maxRewardedAd = MaxRewardedAd.getInstance(adUnitBean.adUnitId, context)
+
+            maxRewardedAd.setListener(object : MaxRewardedAdListener{
+                override fun onAdLoaded(ad: MaxAd?) {
+                    printAdInfo(adUnitBean)
+                    it.isActiveResult(AdResult.Success(adObject = maxRewardedAd, adBean = adUnitBean, msg = "AppLovinMax广告-激励-加载成功"))
+                }
+
+                override fun onAdDisplayed(ad: MaxAd?) {
+
+                }
+
+                override fun onAdHidden(ad: MaxAd?) {
+                }
+
+                override fun onAdClicked(ad: MaxAd?) {
+                }
+
+                override fun onAdLoadFailed(adUnitId: String?, error: MaxError?) {
+                    printAdFailInfo(error?.code?:0, error?.message)
+                    it.isActiveResult(AdResult.Fail(adUnitBean, msg = "AppLovinMax广告-激励-加载失败"))
+                }
+
+                override fun onAdDisplayFailed(ad: MaxAd?, error: MaxError?) {
+                }
+
+                override fun onUserRewarded(ad: MaxAd?, reward: MaxReward?) {
+                }
+
+                override fun onRewardedVideoStarted(ad: MaxAd?) {
+                }
+
+                override fun onRewardedVideoCompleted(ad: MaxAd?) {
+                }
+            })
+
+        }
+    }
+}

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

@@ -0,0 +1,83 @@
+package com.composition.android.ad.applovinmax.load.view
+
+import android.content.Context
+import com.applovin.mediation.MaxAd
+import com.applovin.mediation.MaxAdListener
+import com.applovin.mediation.MaxAdViewAdListener
+import com.applovin.mediation.MaxError
+import com.applovin.mediation.ads.MaxAdView
+import com.composition.android.lib.ad.AdManager
+import com.composition.android.lib.ad.basic.BannerAdViewHolder
+import com.composition.android.lib.ad.basic.BasicAdView
+import com.composition.android.lib.ad.util.adLogE
+
+/**
+ * @classname:
+ * @author: LiuXiaoLong
+ * @date: 2022/11/14
+ * description: AppLovinMax横幅广告View
+ */
+class AppLovinMaxBannerView(context: Context?) : BasicAdView<MaxAdView>(context) {
+
+    private var bannerAdViewHolder: BannerAdViewHolder? = null
+
+    fun setBannerAdViewHolder(adViewHolder: BannerAdViewHolder) {
+        this.bannerAdViewHolder = adViewHolder
+    }
+
+    override fun adContentView(): MaxAdView? {
+        val maxAdView = adResult?.adObject as? MaxAdView
+        maxAdView?.setListener(object : MaxAdViewAdListener {
+            override fun onAdLoaded(ad: MaxAd?) {
+
+            }
+
+            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?) {
+                adLogE(AdManager.TAG, "AppLovinMax广告-横幅-显示失败\ncode:${error?.code}\nmessage:${error?.message}")
+                bannerAdViewHolder?.adListener?.onAdShowFail("AppLovinMax广告-横幅-显示失败")
+            }
+
+            override fun onAdExpanded(ad: MaxAd?) {
+
+            }
+
+            override fun onAdCollapsed(ad: MaxAd?) {
+            }
+
+        })
+
+        return maxAdView
+    }
+
+    override fun onResume() {
+        (adResult?.adObject as? MaxAdView)?.startAutoRefresh()
+    }
+
+    override fun onPause() {
+        (adResult?.adObject as? MaxAdView)?.stopAutoRefresh()
+    }
+
+    override fun onDestroy() {
+        (adResult?.adObject as? MaxAdView)?.also {
+            it.stopAutoRefresh()
+            it.destroy()
+        }
+        adResult?.adObject = null
+    }
+}

+ 80 - 0
lib_ad_applovinmax/src/main/java/com/composition/android/ad/applovinmax/load/view/AppLovinMaxNativeTemplateView.kt

@@ -0,0 +1,80 @@
+package com.composition.android.ad.applovinmax.load.view
+
+import android.content.Context
+import com.applovin.mediation.MaxAd
+import com.applovin.mediation.nativeAds.MaxNativeAdListener
+import com.applovin.mediation.nativeAds.MaxNativeAdLoader
+import com.applovin.mediation.nativeAds.MaxNativeAdView
+import com.composition.android.lib.ad.basic.AdResult
+import com.composition.android.lib.ad.basic.BasicAdView
+import com.composition.android.lib.ad.basic.NativeAdViewHolder
+
+/**
+ * @classname:
+ * @author: LiuXiaoLong
+ * @date: 2022/11/16
+ * description:
+ */
+class AppLovinMaxNativeTemplateView(context: Context?) : BasicAdView<MaxNativeAdView>(context) {
+
+    private var nativeAdViewHolder: NativeAdViewHolder? = null
+
+    fun setViewHolder(viewHolder: NativeAdViewHolder) {
+        this.nativeAdViewHolder = viewHolder
+    }
+
+
+    override fun adContentView(): MaxNativeAdView? {
+
+        if (nativeAdViewHolder == null || adResult == null){
+            return null
+        }
+        val triple = getAdObj()
+        populateNativeTemplateAdView(context, adResult!!, nativeAdViewHolder!!)
+        return triple?.second
+    }
+
+
+    private fun getAdObj(): Triple<MaxNativeAdLoader, MaxNativeAdView?, MaxAd?>? {
+        return try {
+            adResult?.adObject as Triple<MaxNativeAdLoader, MaxNativeAdView?, MaxAd?>
+        } catch (e: Exception) {
+            null
+        }
+    }
+
+    override fun onResume() {
+
+    }
+
+    override fun onPause() {
+    }
+
+    override fun onDestroy() {
+        getAdObj()?.apply {
+            first.destroy(third)
+        }
+        adResult?.adObject = null
+    }
+
+
+    companion object {
+
+        fun populateNativeTemplateAdView(context: Context, adResult: AdResult.Success, viewHolder: NativeAdViewHolder) {
+
+            val triple = adResult.adObject as? Triple<MaxNativeAdLoader, MaxNativeAdView?, MaxAd?>
+
+            triple?.first?.setNativeAdListener(object : MaxNativeAdListener() {
+                override fun onNativeAdClicked(p0: MaxAd?) {
+                    super.onNativeAdClicked(p0)
+                    viewHolder.adListener?.onAdClick()
+                }
+            })
+
+            viewHolder.adListener?.onAdShow(adResult.adBean)
+
+        }
+    }
+
+
+}

+ 5 - 0
lib_ad_applovinmax/src/main/res/values-sw600dp/dimens.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <dimen name="app_lovin_banner_height">90dp</dimen>
+</resources>

+ 5 - 0
lib_ad_applovinmax/src/main/res/values/dimens.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <dimen name="app_lovin_banner_height">50dp</dimen>
+</resources>

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

@@ -9,6 +9,8 @@ import android.net.NetworkCapabilities
 import android.os.Build
 import android.view.View
 import android.view.ViewGroup
+import kotlinx.coroutines.CancellableContinuation
+import kotlin.coroutines.resume
 
 /**
  * @classname:
@@ -99,8 +101,25 @@ fun getScreenWidthDp(context: Context) : Float = getScreenWidth(context) / (if (
 
 fun getScreenHeightDp(context: Context) : Float = px2dip(context, getScreenHeight(context).toFloat()).toFloat()
 
+/**
+ * @param :[context, dpValue]
+ * @return : int
+ * @methodName :dip2px created by luozhipeng on 5/12/17 13:57.
+ * @description :根据手机的分辨率从 dp 的单位 转成为 px(像素)
+ */
+fun dp2px(context: Context, dpValue: Float): Int {
+    val scale = getDensity(context = context)
+    return (dpValue * scale + 0.5f).toInt()
+}
 
 fun px2dip(context: Context,pxValue: Float): Int {
     val scale = getDensity(context)
     return (pxValue / scale + 0.5f).toInt()
+}
+
+
+fun <T> CancellableContinuation<T>.isActiveResult(value : T){
+    if (isActive){
+        resume(value)
+    }
 }

+ 21 - 10
lib_ad_csj/src/main/java/com/composition/android/ad/csj/load/CSJAdLoader.kt

@@ -16,6 +16,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.adLogE
 import com.composition.android.lib.ad.util.parentRemove
 
 /**
@@ -87,16 +88,23 @@ class CSJAdLoader : AdLoader {
 
     override fun populateNativeAdView(context: Context, adResult: AdResult.Success, viewHolder: NativeAdViewHolder, advertisersContainerView: ViewGroup) {
         AdManager.instance.globalListener?.invoke(adResult.adBean)
-        if (adResult.adBean.getAdType() == AdType.NATIVE) {
-            CSJNativeAdView.populateNativeAdView(context = context, adResult, viewHolder, advertisersContainerView)
-        } else {
-            val ttNativeExpressAd = adResult.adObject as TTNativeExpressAd
-            advertisersContainerView.removeAllViews()
-            val expressAdView = ttNativeExpressAd.expressAdView
-            expressAdView.parentRemove()
-            advertisersContainerView.addView(expressAdView)
-            CSJNativeTemplateAdView.populateNativeTemplateAdView(context, adResult, viewHolder)
+        when (adResult.adBean.getAdType()) {
+            AdType.NATIVE -> {
+                CSJNativeAdView.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)
+                CSJNativeTemplateAdView.populateNativeTemplateAdView(context, adResult, viewHolder)
+            }
+            else->{
+                adLogE(tag = AdManager.TAG, msg = "穿山甲广告-填充原生,adType类型错误,不支持")
+            }
         }
+
     }
 
     override fun showInterstitialAd(activity: Activity, adResult: AdResult.Success, adListener: AdListener) {
@@ -117,7 +125,7 @@ class CSJAdLoader : AdLoader {
                 override fun onAdClose() {
                     adLog(msg = "穿山甲广告-插屏-关闭")
                     adListener.onAdClose()
-                    adResult.adObject = null
+                    destroyAd(adResult)
                 }
 
                 override fun onVideoComplete() {
@@ -161,6 +169,7 @@ class CSJAdLoader : AdLoader {
                 override fun onAdClose() {
                     adLog(msg = "穿山甲广告-激励视频-关闭")
                     adListener.onAdClose()
+                    destroyAd(adResult)
                 }
 
                 override fun onVideoComplete() {
@@ -224,6 +233,8 @@ class CSJAdLoader : AdLoader {
                 override fun onAdSkip() {
                     adLog(msg = "穿山甲广告-开屏-跳过")
                     adListener.onAdSkip()
+                    destroyAd(adResult)
+
                 }
 
                 override fun onAdTimeOver() {

+ 1 - 0
lib_material_design_tokens/.gitignore

@@ -0,0 +1 @@
+/build

+ 50 - 0
lib_material_design_tokens/build.gradle

@@ -0,0 +1,50 @@
+plugins {
+    id 'com.android.library'
+    id 'org.jetbrains.kotlin.android'
+}
+
+android {
+
+    namespace 'com.convenient.android.material.design.tokens'
+    compileSdk 32
+
+    defaultConfig {
+        minSdk 21
+        targetSdk 32
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+    kotlinOptions {
+        jvmTarget = '1.8'
+    }
+
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+    implementation 'androidx.core:core-ktx:1.7.0'
+    implementation 'androidx.appcompat:appcompat:1.5.1'
+    implementation 'com.google.android.material:material:1.7.0'
+    testImplementation 'junit:junit:4.13.2'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.4'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
+
+    api 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.3'
+    api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.3'
+    api 'com.google.code.gson:gson:2.8.9'
+
+}

BIN
lib_material_design_tokens/libs/json-20220924.jar


+ 21 - 0
lib_material_design_tokens/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 24 - 0
lib_material_design_tokens/src/androidTest/java/com/convenient/android/material/design/tokens/ExampleInstrumentedTest.kt

@@ -0,0 +1,24 @@
+package com.convenient.android.material.design.tokens
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+    @Test
+    fun useAppContext() {
+        // Context of the app under test.
+        val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+        assertEquals("com.convenient.android.material.design.tokens", appContext.packageName)
+    }
+}

+ 12 - 0
lib_material_design_tokens/src/main/AndroidManifest.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <application
+        android:allowBackup="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:supportsRtl="true"
+        android:theme="@style/Theme.Lib" />
+
+</manifest>

+ 25 - 0
lib_material_design_tokens/src/main/java/com/convenient/android/material/design/tokens/MdTokenUtil.kt

@@ -0,0 +1,25 @@
+package com.convenient.android.material.design.tokens
+
+import com.convenient.android.material.design.tokens.category.MdParseGlobalUtil
+
+/**
+ * @classname:
+ * @author: LiuXiaoLong
+ * @date: 2022/11/9
+ * description:
+ */
+class MdTokenUtil {
+
+
+}
+
+fun main() {
+
+    val globalTokenUtil = MdParseGlobalUtil("./lib_material_design_tokens/tokens/global.json")
+    globalTokenUtil.start()
+
+
+
+
+
+}

+ 69 - 0
lib_material_design_tokens/src/main/java/com/convenient/android/material/design/tokens/category/MdParseGlobalUtil.kt

@@ -0,0 +1,69 @@
+package com.convenient.android.material.design.tokens.category
+
+import org.json.JSONObject
+import java.io.File
+
+/**
+ * @classname:
+ * @author: LiuXiaoLong
+ * @date: 2022/11/9
+ * description:
+ */
+class MdParseGlobalUtil(var filePath: String) {
+
+
+    fun start() {
+
+        try {
+            var file = File(filePath)
+            var json = file.readText()
+            parseCategoryMap(json)
+
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+    }
+
+    private fun parseCategoryMap(json: String): HashMap<String, TokenBean> {
+        var jsonObj = JSONObject(json)
+        parseObj(jsonObj)
+
+        return hashMapOf()
+    }
+
+    private fun parseObj(obj: JSONObject) {
+
+        val iterator = obj.keys()
+        if (iterator.hasNext()) {
+            val key = iterator.next().toString()
+            val valueObj = obj.get(key)
+
+            if (valueObj is JSONObject) {
+                parseObj(valueObj)
+            } else {
+
+                println("key:${key}, value:${valueObj}")
+            }
+
+        }
+
+    }
+
+
+    /**
+     * 解析尺寸
+     */
+    private fun parseSizing(json: String): List<Pair<String, String>> {
+
+        return emptyList()
+    }
+
+
+}
+
+data class TokenBean(
+    var type: String,
+    var value: String,
+    var currentLevelTokenName: String,
+    var parentLevelTokenNames: List<String>
+)

File diff suppressed because it is too large
+ 30 - 0
lib_material_design_tokens/src/main/res/drawable-v24/ic_launcher_foreground.xml


+ 170 - 0
lib_material_design_tokens/src/main/res/drawable/ic_launcher_background.xml

@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+    <path
+        android:fillColor="#3DDC84"
+        android:pathData="M0,0h108v108h-108z" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M9,0L9,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,0L19,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,0L29,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,0L39,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,0L49,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,0L59,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,0L69,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,0L79,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M89,0L89,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M99,0L99,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,9L108,9"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,19L108,19"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,29L108,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,39L108,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,49L108,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,59L108,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,69L108,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,79L108,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,89L108,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,99L108,99"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,29L89,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,39L89,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,49L89,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,59L89,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,69L89,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,79L89,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,19L29,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,19L39,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,19L49,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,19L59,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,19L69,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,19L79,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+</vector>

+ 5 - 0
lib_material_design_tokens/src/main/res/mipmap-anydpi-v26/ic_launcher.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>

+ 5 - 0
lib_material_design_tokens/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>

BIN
lib_material_design_tokens/src/main/res/mipmap-hdpi/ic_launcher.webp


BIN
lib_material_design_tokens/src/main/res/mipmap-hdpi/ic_launcher_round.webp


BIN
lib_material_design_tokens/src/main/res/mipmap-mdpi/ic_launcher.webp


BIN
lib_material_design_tokens/src/main/res/mipmap-mdpi/ic_launcher_round.webp


BIN
lib_material_design_tokens/src/main/res/mipmap-xhdpi/ic_launcher.webp


BIN
lib_material_design_tokens/src/main/res/mipmap-xhdpi/ic_launcher_round.webp


BIN
lib_material_design_tokens/src/main/res/mipmap-xxhdpi/ic_launcher.webp


BIN
lib_material_design_tokens/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp


BIN
lib_material_design_tokens/src/main/res/mipmap-xxxhdpi/ic_launcher.webp


BIN
lib_material_design_tokens/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp


+ 16 - 0
lib_material_design_tokens/src/main/res/values-night/themes.xml

@@ -0,0 +1,16 @@
+<resources xmlns:tools="http://schemas.android.com/tools">
+    <!-- Base application theme. -->
+    <style name="Theme.Lib" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
+        <!-- Primary brand color. -->
+        <item name="colorPrimary">@color/purple_200</item>
+        <item name="colorPrimaryVariant">@color/purple_700</item>
+        <item name="colorOnPrimary">@color/black</item>
+        <!-- Secondary brand color. -->
+        <item name="colorSecondary">@color/teal_200</item>
+        <item name="colorSecondaryVariant">@color/teal_200</item>
+        <item name="colorOnSecondary">@color/black</item>
+        <!-- Status bar color. -->
+        <item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
+        <!-- Customize your theme here. -->
+    </style>
+</resources>

+ 10 - 0
lib_material_design_tokens/src/main/res/values/colors.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="purple_200">#FFBB86FC</color>
+    <color name="purple_500">#FF6200EE</color>
+    <color name="purple_700">#FF3700B3</color>
+    <color name="teal_200">#FF03DAC5</color>
+    <color name="teal_700">#FF018786</color>
+    <color name="black">#FF000000</color>
+    <color name="white">#FFFFFFFF</color>
+</resources>

+ 3 - 0
lib_material_design_tokens/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">lib_material_design_tokens</string>
+</resources>

+ 16 - 0
lib_material_design_tokens/src/main/res/values/themes.xml

@@ -0,0 +1,16 @@
+<resources xmlns:tools="http://schemas.android.com/tools">
+    <!-- Base application theme. -->
+    <style name="Theme.Lib" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
+        <!-- Primary brand color. -->
+        <item name="colorPrimary">@color/purple_500</item>
+        <item name="colorPrimaryVariant">@color/purple_700</item>
+        <item name="colorOnPrimary">@color/white</item>
+        <!-- Secondary brand color. -->
+        <item name="colorSecondary">@color/teal_200</item>
+        <item name="colorSecondaryVariant">@color/teal_700</item>
+        <item name="colorOnSecondary">@color/black</item>
+        <!-- Status bar color. -->
+        <item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
+        <!-- Customize your theme here. -->
+    </style>
+</resources>

+ 17 - 0
lib_material_design_tokens/src/test/java/com/convenient/android/material/design/tokens/ExampleUnitTest.kt

@@ -0,0 +1,17 @@
+package com.convenient.android.material.design.tokens
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+    @Test
+    fun addition_isCorrect() {
+        assertEquals(4, 2 + 2)
+    }
+}

+ 330 - 0
lib_material_design_tokens/tokens/alias.json

@@ -0,0 +1,330 @@
+{
+  "spacing": {
+    "btn": {
+      "large": {
+        "left": {
+          "value": "{spacing.24}",
+          "type": "spacing"
+        },
+        "right": {
+          "value": "{spacing.24}",
+          "type": "spacing"
+        }
+      },
+      "medium": {
+        "left": {
+          "value": "{spacing.16}",
+          "type": "spacing"
+        },
+        "right": {
+          "value": "{spacing.16}",
+          "type": "spacing"
+        }
+      },
+      "small": {
+        "left": {
+          "value": "{spacing.8}",
+          "type": "spacing"
+        },
+        "right": {
+          "value": "{spacing.8}",
+          "type": "spacing"
+        }
+      }
+    }
+  },
+  "color": {
+    "font": {
+      "primary": {
+        "value": "{color.neutral.gray11}",
+        "type": "color"
+      },
+      "secondary": {
+        "value": "{color.neutral.gray9}",
+        "type": "color"
+      },
+      "thirdry": {
+        "value": "{color.neutral.gray7}",
+        "type": "color"
+      },
+      "disabled": {
+        "value": "{color.neutral.gray6}",
+        "type": "color"
+      },
+      "anti": {
+        "value": "{color.neutral.gray1}",
+        "type": "color"
+      }
+    },
+    "btn_bg_accent": {
+      "default": {
+        "value": "{color.accent.blue6}",
+        "type": "color"
+      },
+      "hover": {
+        "value": "{color.accent.blue5}",
+        "type": "color"
+      },
+      "active": {
+        "value": "{color.accent.blue7}",
+        "type": "color"
+      },
+      "disabled": {
+        "value": "{color.accent.blue3}",
+        "type": "color"
+      }
+    },
+    "fill": {
+      "anti": {
+        "value": "{color.neutral.gray1}",
+        "type": "color"
+      },
+      "hover": {
+        "value": "{color.neutral.gray3}",
+        "type": "color"
+      },
+      "active": {
+        "value": "{color.neutral.gray4}",
+        "type": "color"
+      },
+      "disabled": {
+        "value": "{color.neutral.gray3}",
+        "type": "color"
+      }
+    },
+    "error": {
+      "default": {
+        "value": "{color.functional.error.red6}",
+        "type": "color"
+      },
+      "hover": {
+        "value": "{color.functional.error.red5}",
+        "type": "color"
+      },
+      "active": {
+        "value": "{color.functional.error.red7}",
+        "type": "color"
+      },
+      "disabled": {
+        "value": "{color.functional.error.red3}",
+        "type": "color"
+      }
+    },
+    "warning": {
+      "default": {
+        "value": "{color.functional.warnning.gold6}",
+        "type": "color"
+      },
+      "hover": {
+        "value": "{color.functional.warnning.gold5}",
+        "type": "color"
+      },
+      "active": {
+        "value": "{color.functional.warnning.gold7}",
+        "type": "color"
+      },
+      "disabled": {
+        "value": "{color.functional.warnning.gold3}",
+        "type": "color"
+      }
+    },
+    "success": {
+      "default": {
+        "value": "{color.functional.success.green6}",
+        "type": "color"
+      },
+      "hover": {
+        "value": "{color.other.cyan.cyan5}",
+        "type": "color"
+      },
+      "active": {
+        "value": "{color.functional.success.green7}",
+        "type": "color"
+      },
+      "disabled": {
+        "value": "{color.functional.success.green3}",
+        "type": "color"
+      }
+    },
+    "btn_bg_brand": {
+      "default": {
+        "value": "{color.brand.navyblue6}",
+        "type": "color"
+      },
+      "hover": {
+        "value": "{color.brand.navyblue5}",
+        "type": "color"
+      },
+      "active": {
+        "value": "{color.brand.navyblue7}",
+        "type": "color"
+      },
+      "disabled": {
+        "value": "{color.brand.navyblue3}",
+        "type": "color"
+      }
+    },
+    "component_border": {
+      "value": "{color.neutral.gray4}",
+      "type": "color"
+    },
+    "stroke": {
+      "value": "{color.neutral.gray3}",
+      "type": "color"
+    },
+    "btn_bg_normal": {
+      "default": {
+        "value": "{color.neutral.gray3}",
+        "type": "color"
+      },
+      "hover": {
+        "value": "{color.neutral.gray4}",
+        "type": "color"
+      },
+      "active": {
+        "value": "{color.neutral.gray5}",
+        "type": "color"
+      },
+      "disabled": {
+        "value": "{color.neutral.gray3}",
+        "type": "color"
+      }
+    }
+  },
+  "sizing": {
+    "icon": {
+      "xsmall": {
+        "value": "{sizing.12}",
+        "type": "sizing"
+      },
+      "small": {
+        "value": "{sizing.14}",
+        "type": "sizing"
+      },
+      "medium": {
+        "value": "{sizing.16}",
+        "type": "sizing"
+      },
+      "xlarge": {
+        "value": "{sizing.20}",
+        "type": "sizing"
+      }
+    },
+    "btn": {
+      "small": {
+        "value": "24",
+        "type": "sizing"
+      },
+      "medium": {
+        "value": "32",
+        "type": "sizing"
+      },
+      "large": {
+        "value": "40",
+        "type": "sizing"
+      }
+    }
+  },
+  "border_radius": {
+    "btn": {
+      "full": {
+        "large": {
+          "value": "{border_radius.20}",
+          "type": "borderRadius"
+        },
+        "medium": {
+          "value": "{border_radius.16}",
+          "type": "borderRadius"
+        },
+        "small": {
+          "value": "{border_radius.12}",
+          "type": "borderRadius"
+        }
+      },
+      "round": {
+        "normal": {
+          "value": "{border_radius.4}",
+          "type": "borderRadius"
+        }
+      }
+    },
+    "card": {
+      "small": {
+        "value": "{border_radius.4}",
+        "type": "borderRadius"
+      },
+      "medium": {
+        "value": "8",
+        "type": "borderRadius"
+      }
+    }
+  },
+  "font_size": {
+    "footnote": {
+      "value": "{font_size.10}",
+      "type": "fontSizes"
+    },
+    "sub_body": {
+      "value": "{font_size.12}",
+      "type": "fontSizes"
+    },
+    "body": {
+      "value": "{font_size.14}",
+      "type": "fontSizes"
+    },
+    "sub_title": {
+      "value": "{font_size.16}",
+      "type": "fontSizes"
+    },
+    "title": {
+      "value": "{font_size.20}",
+      "type": "fontSizes"
+    },
+    "headline": {
+      "value": "{font_size.24}",
+      "type": "fontSizes"
+    }
+  },
+  "border_width": {
+    "normal": {
+      "value": "{border_width.1}",
+      "type": "borderWidth"
+    }
+  },
+  "lint_height": {
+    "footnote": {
+      "value": "{line_height.18}",
+      "type": "lineHeights"
+    },
+    "sub_body": {
+      "value": "{line_height.20}",
+      "type": "lineHeights"
+    },
+    "body": {
+      "value": "{line_height.22}",
+      "type": "lineHeights"
+    },
+    "sub_title": {
+      "value": "{line_height.24}",
+      "type": "lineHeights"
+    },
+    "title": {
+      "value": "{line_height.28}",
+      "type": "lineHeights"
+    },
+    "headline": {
+      "value": "{line_height.40}",
+      "type": "lineHeights"
+    }
+  },
+  "font_weight": {
+    "regular": {
+      "value": "{font_weight.400}",
+      "type": "fontWeights"
+    },
+    "bold": {
+      "value": "{font_weight.600}",
+      "type": "fontWeights"
+    }
+  }
+}

File diff suppressed because it is too large
+ 2506 - 0
lib_material_design_tokens/tokens/composition.json


+ 687 - 0
lib_material_design_tokens/tokens/global.json

@@ -0,0 +1,687 @@
+{
+  "sizing": {
+    "12": {
+      "value": "12",
+      "type": "sizing"
+    },
+    "14": {
+      "value": "14",
+      "type": "sizing"
+    },
+    "16": {
+      "value": "16",
+      "type": "sizing"
+    },
+    "18": {
+      "value": "18",
+      "type": "sizing"
+    },
+    "20": {
+      "value": "20",
+      "type": "sizing"
+    },
+    "24": {
+      "value": "24",
+      "type": "sizing"
+    },
+    "28": {
+      "value": "28",
+      "type": "sizing"
+    },
+    "32": {
+      "value": "32",
+      "type": "sizing"
+    },
+    "34": {
+      "value": "34",
+      "type": "sizing"
+    },
+    "40": {
+      "value": "40",
+      "type": "sizing"
+    },
+    "48": {
+      "value": "48",
+      "type": "sizing"
+    },
+    "64": {
+      "value": "64",
+      "type": "sizing"
+    },
+    "110": {
+      "value": "110",
+      "type": "sizing"
+    },
+    "116": {
+      "value": "116",
+      "type": "sizing"
+    },
+    "228": {
+      "value": "228",
+      "type": "sizing"
+    }
+  },
+  "spacing": {
+    "2": {
+      "value": "2",
+      "type": "spacing"
+    },
+    "4": {
+      "value": "4",
+      "type": "spacing"
+    },
+    "5": {
+      "value": "5",
+      "type": "spacing"
+    },
+    "8": {
+      "value": "8",
+      "type": "spacing"
+    },
+    "10": {
+      "value": "10",
+      "type": "spacing"
+    },
+    "12": {
+      "value": "12",
+      "type": "spacing"
+    },
+    "16": {
+      "value": "16",
+      "type": "spacing"
+    },
+    "24": {
+      "value": "24",
+      "type": "spacing"
+    },
+    "32": {
+      "value": "32",
+      "type": "spacing"
+    }
+  },
+  "color": {
+    "accent": {
+      "blue1": {
+        "value": "#E8F5FF",
+        "type": "color"
+      },
+      "blue2": {
+        "value": "#BDDFFD",
+        "type": "color"
+      },
+      "blue3": {
+        "value": "#92C6FB",
+        "type": "color"
+      },
+      "blue4": {
+        "value": "#68acf8",
+        "type": "color"
+      },
+      "blue5": {
+        "value": "#3f8ff6",
+        "type": "color"
+      },
+      "blue6": {
+        "value": "#1770F4",
+        "type": "color"
+      },
+      "blue7": {
+        "value": "#0e53ca",
+        "type": "color"
+      },
+      "blue8": {
+        "value": "#083aa0",
+        "type": "color"
+      },
+      "blue9": {
+        "value": "#032576",
+        "type": "color"
+      },
+      "blue10": {
+        "value": "#00144d",
+        "type": "color"
+      }
+    },
+    "neutral": {
+      "gray1": {
+        "value": "#ffffff",
+        "type": "color"
+      },
+      "gray2": {
+        "value": "#F7F8FA",
+        "type": "color"
+      },
+      "gray3": {
+        "value": "#EDEEF0",
+        "type": "color"
+      },
+      "gray4": {
+        "value": "#DFE1E5",
+        "type": "color"
+      },
+      "gray5": {
+        "value": "#CED0D4",
+        "type": "color"
+      },
+      "gray6": {
+        "value": "#B1B3B8",
+        "type": "color"
+      },
+      "gray7": {
+        "value": "#94989C",
+        "type": "color"
+      },
+      "gray8": {
+        "value": "#7C8085",
+        "type": "color"
+      },
+      "gray9": {
+        "value": "#616469",
+        "type": "color"
+      },
+      "gray10": {
+        "value": "#36383B",
+        "type": "color"
+      },
+      "gray11": {
+        "value": "#252629",
+        "type": "color"
+      }
+    },
+    "brand": {
+      "navyblue1": {
+        "value": "#E8F4FF",
+        "type": "color"
+      },
+      "navyblue2": {
+        "value": "#B5C9E0",
+        "type": "color"
+      },
+      "navyblue3": {
+        "value": "#88A1C0",
+        "type": "color"
+      },
+      "navyblue4": {
+        "value": "#617CA1",
+        "type": "color"
+      },
+      "navyblue5": {
+        "value": "#415A81",
+        "type": "color"
+      },
+      "navyblue6": {
+        "value": "#273C62",
+        "type": "color"
+      },
+      "navyblue7": {
+        "value": "#1C305D",
+        "type": "color"
+      },
+      "navyblue8": {
+        "value": "#112557",
+        "type": "color"
+      },
+      "navyblue9": {
+        "value": "#081B52",
+        "type": "color"
+      },
+      "navyblue10": {
+        "value": "#00114D",
+        "type": "color"
+      }
+    },
+    "functional": {
+      "success": {
+        "green1": {
+          "value": "#E8FFF4",
+          "type": "color"
+        },
+        "green2": {
+          "value": "#BAF7DA",
+          "type": "color"
+        },
+        "green3": {
+          "value": "#8EEEC4",
+          "type": "color"
+        },
+        "green4": {
+          "value": "#64E6B2",
+          "type": "color"
+        },
+        "green5": {
+          "value": "#3EDDA3",
+          "type": "color"
+        },
+        "green6": {
+          "value": "#1AD598",
+          "type": "color"
+        },
+        "green7": {
+          "value": "#10B382",
+          "type": "color"
+        },
+        "green8": {
+          "value": "#09916D",
+          "type": "color"
+        },
+        "green9": {
+          "value": "#036F56",
+          "type": "color"
+        },
+        "green10": {
+          "value": "#004D3D",
+          "type": "color"
+        }
+      },
+      "warnning": {
+        "gold1": {
+          "value": "#FFFAE8",
+          "type": "color"
+        },
+        "gold2": {
+          "value": "#FFF1C1",
+          "type": "color"
+        },
+        "gold3": {
+          "value": "#FFE49A",
+          "type": "color"
+        },
+        "gold4": {
+          "value": "#FFD573",
+          "type": "color"
+        },
+        "gold5": {
+          "value": "#FFC34C",
+          "type": "color"
+        },
+        "gold6": {
+          "value": "#FFAF25",
+          "type": "color"
+        },
+        "gold7": {
+          "value": "#D28717",
+          "type": "color"
+        },
+        "gold8": {
+          "value": "#A6630C",
+          "type": "color"
+        },
+        "gold9": {
+          "value": "#794304",
+          "type": "color"
+        },
+        "gold10": {
+          "value": "#4D2600",
+          "type": "color"
+        }
+      },
+      "error": {
+        "red1": {
+          "value": "#FFE9E8",
+          "type": "color"
+        },
+        "red2": {
+          "value": "#FDC7C6",
+          "type": "color"
+        },
+        "red3": {
+          "value": "#FAA5A7",
+          "type": "color"
+        },
+        "red4": {
+          "value": "#F8858B",
+          "type": "color"
+        },
+        "red5": {
+          "value": "#F56571",
+          "type": "color"
+        },
+        "red6": {
+          "value": "#F3465B",
+          "type": "color"
+        },
+        "red7": {
+          "value": "#C92C43",
+          "type": "color"
+        },
+        "red8": {
+          "value": "#A01730",
+          "type": "color"
+        },
+        "red9": {
+          "value": "#760920",
+          "type": "color"
+        },
+        "red10": {
+          "value": "#4D0013",
+          "type": "color"
+        }
+      }
+    },
+    "other": {
+      "orange": {
+        "orange1": {
+          "value": "#FFF5E8",
+          "type": "color"
+        },
+        "orange2": {
+          "value": "#FFE4C3",
+          "type": "color"
+        },
+        "orange3": {
+          "value": "#FFD09E",
+          "type": "color"
+        },
+        "orange4": {
+          "value": "#FFB978",
+          "type": "color"
+        },
+        "orange5": {
+          "value": "#FFA153",
+          "type": "color"
+        },
+        "orange6": {
+          "value": "#FF852E",
+          "type": "color"
+        },
+        "orange7": {
+          "value": "#D2621C",
+          "type": "color"
+        },
+        "orange8": {
+          "value": "#A6440F",
+          "type": "color"
+        },
+        "orange9": {
+          "value": "#792A05",
+          "type": "color"
+        },
+        "orange10": {
+          "value": "#4D1600",
+          "type": "color"
+        }
+      },
+      "cyan": {
+        "cyan1": {
+          "value": "#E8FFFB",
+          "type": "color"
+        },
+        "cyan2": {
+          "value": "#B7F4EC",
+          "type": "color"
+        },
+        "cyan3": {
+          "value": "#89E9E0",
+          "type": "color"
+        },
+        "cyan4": {
+          "value": "#5EDFD6",
+          "type": "color"
+        },
+        "cyan5": {
+          "value": "#37D4CF",
+          "type": "color"
+        },
+        "cyan6": {
+          "value": "#14C9C9",
+          "type": "color"
+        },
+        "cyan7": {
+          "value": "#0DA5AA",
+          "type": "color"
+        },
+        "cyan8": {
+          "value": "#07828B",
+          "type": "color"
+        },
+        "cyan9": {
+          "value": "#03616C",
+          "type": "color"
+        },
+        "cyan10": {
+          "value": "#03616C",
+          "type": "color"
+        }
+      },
+      "purple": {
+        "purple1": {
+          "value": "#F2E8FF",
+          "type": "color"
+        },
+        "purple2": {
+          "value": "#DBC3FE",
+          "type": "color"
+        },
+        "purple3": {
+          "value": "#C29EFC",
+          "type": "color"
+        },
+        "purple4": {
+          "value": "#A77AFB",
+          "type": "color"
+        },
+        "purple5": {
+          "value": "#8A56F9",
+          "type": "color"
+        },
+        "purple6": {
+          "value": "#6C33F8",
+          "type": "color"
+        },
+        "purple7": {
+          "value": "#4B20CD",
+          "type": "color"
+        },
+        "purple8": {
+          "value": "#3011A2",
+          "type": "color"
+        },
+        "purple9": {
+          "value": "#1B0677",
+          "type": "color"
+        },
+        "purple10": {
+          "value": "#0B004D",
+          "type": "color"
+        }
+      },
+      "pink": {
+        "pink1": {
+          "value": "#FFE8F5",
+          "type": "color"
+        },
+        "pink2": {
+          "value": "#FDC4E6",
+          "type": "color"
+        },
+        "pink3": {
+          "value": "#FBA0DA",
+          "type": "color"
+        },
+        "pink4": {
+          "value": "#FA7CD0",
+          "type": "color"
+        },
+        "pink5": {
+          "value": "#F859C8",
+          "type": "color"
+        },
+        "pink6": {
+          "value": "#F637C4",
+          "type": "color"
+        },
+        "pink7": {
+          "value": "#CC22A4",
+          "type": "color"
+        },
+        "pink8": {
+          "value": "#A11285",
+          "type": "color"
+        },
+        "pink9": {
+          "value": "#770764",
+          "type": "color"
+        },
+        "pink10": {
+          "value": "#4D0042",
+          "type": "color"
+        }
+      }
+    }
+  },
+  "border_radius": {
+    "2": {
+      "value": "2",
+      "type": "borderRadius"
+    },
+    "4": {
+      "value": "4",
+      "type": "borderRadius"
+    },
+    "6": {
+      "value": "6",
+      "type": "borderRadius"
+    },
+    "8": {
+      "value": "8",
+      "type": "borderRadius"
+    },
+    "12": {
+      "value": "12",
+      "type": "borderRadius"
+    },
+    "16": {
+      "value": "16",
+      "type": "borderRadius"
+    },
+    "20": {
+      "value": "20",
+      "type": "borderRadius"
+    }
+  },
+  "font_size": {
+    "10": {
+      "value": "10",
+      "type": "fontSizes"
+    },
+    "12": {
+      "value": "12",
+      "type": "fontSizes"
+    },
+    "14": {
+      "value": "14",
+      "type": "fontSizes"
+    },
+    "16": {
+      "value": "16",
+      "type": "fontSizes"
+    },
+    "20": {
+      "value": "20",
+      "type": "fontSizes"
+    },
+    "24": {
+      "value": "24",
+      "type": "fontSizes"
+    }
+  },
+  "border_width": {
+    "1": {
+      "value": "1",
+      "type": "borderWidth"
+    }
+  },
+  "font_weight": {
+    "400": {
+      "value": "400",
+      "type": "fontWeights"
+    },
+    "600": {
+      "value": "600",
+      "type": "fontWeights"
+    }
+  },
+  "line_height": {
+    "18": {
+      "value": "18",
+      "type": "lineHeights"
+    },
+    "20": {
+      "value": "20",
+      "type": "lineHeights"
+    },
+    "22": {
+      "value": "22",
+      "type": "lineHeights"
+    },
+    "24": {
+      "value": "24",
+      "type": "lineHeights"
+    },
+    "28": {
+      "value": "28",
+      "type": "lineHeights"
+    },
+    "32": {
+      "value": "32",
+      "type": "lineHeights"
+    },
+    "40": {
+      "value": "40",
+      "type": "lineHeights"
+    }
+  },
+  "shadow": {
+    "normal_2": {
+      "value": {
+        "x": "0",
+        "y": "2",
+        "blur": "2",
+        "spread": "0",
+        "color": "#000000",
+        "type": "dropShadow"
+      },
+      "type": "boxShadow"
+    },
+    "accent_2": {
+      "value": {
+        "x": "0",
+        "y": "0",
+        "blur": "4",
+        "spread": "0",
+        "color": "{color.accent.blue3}",
+        "type": "dropShadow"
+      },
+      "type": "boxShadow"
+    },
+    "error_4": {
+      "value": {
+        "x": "0",
+        "y": "0",
+        "blur": "4",
+        "spread": "0",
+        "color": "{color.functional.error.red3}",
+        "type": "dropShadow"
+      },
+      "type": "boxShadow"
+    }
+  },
+  "opacity": {
+    "10%": {
+      "value": "10%",
+      "type": "opacity"
+    },
+    "20%": {
+      "value": "20%",
+      "type": "opacity"
+    },
+    "40%": {
+      "value": "40%",
+      "type": "opacity"
+    },
+    "60%": {
+      "value": "60%",
+      "type": "opacity"
+    }
+  }
+}

+ 1 - 0
settings.gradle

@@ -35,3 +35,4 @@ include ':lib_ad_csj'
 include ':lib_ad_gromore'
 include ':lib_pdf_base'
 include ':lib_ad_applovinmax'
+include ':lib_material_design_tokens'