广告封装
EasyAdv 封装了 穿山甲融合 sdk ,旨在使用广告时可以更加 Easy。
- 统一 API,一句话调用。
- 与业务分离,不需要关注广告实现,让你可以只关心业务开发
- 全局监听各种广告回调,可以统一处理一些埋点之类的操作,不需要写得到处都是。
- 总之,感觉还行。。
dependencies {
implementation 'com.github.EspoirX:EasyAdvApp:vX.X.x'
}
先导下基本的广告sdk,因为框架里面用的是 compileOnly
implementation "com.pangle.cn:mediation-sdk:5.7.0.5"
EasyAdv.init(this)
.sdkConfig {
context = this@MyApp
appId = "KFC_V_WO_50"
appName = "EasyAdvApp"
userId = "123456"
timeOutMillis = 3000
}
.setGlobalAdvConfig {
enableHotSplashAdv = true
hotSplashAdvStrategy = TTHotSplashAdvStrategy()
}
.setPlatform(TTAdSdkPlatform())
.setSplashAdvEngine(TTSplashAdvEngine())
.apply()
如示例代码,通过 init 方法初始化,初始化后可配置各种配置,下面一一说明:
穿山甲 sdk 初始化时需要的参数,应该都知道吧.
其中 userId 是自己用户系统的 userId,因为初始化或者一些广告加载的时候需要传,当然看情况,不是必要参数。
timeOutMillis 是sdk初始化超时时间,影响的是冷启动开屏广告,因为如果网络问题或者其他问题导致sdk初始化太久的话,不可能一直卡在开屏页,
所以加个超时逻辑,不设置就是没有这逻辑。
配置一些全局的广告配置:
class GlobalAdvConfig {
var splashAdvListener: SplashAdvListener? = null
var fullScreenVideoAdvListener: FullScreenVideoAdvListener? = null
var bannerAdvListener: BannerAdvListener? = null
var feedAdvListener: FeedAdvListener? = null
var rewardVideoAdvListener: RewardVideoAdvListener? = null
var userId: String = ""
var enableHotSplashAdv = false
var hotSplashAdvStrategy: IHotSplashAdvStrategy? = null
}
- splashAdvListener 全局的开屏页广告回调监听
- fullScreenVideoAdvListener 全局的插屏广告回调监听
- bannerAdvListener 全局的Banner广告回调监听
- feedAdvListener 全局的信息流广告回调监听
- rewardVideoAdvListener 全局的激励广告回调监听
- userId 跟 sdkConfig 那说的一个意思
- enableHotSplashAdv 是否运行热启动开屏广告
- hotSplashAdvStrategy 热启动开屏广告实现方案,要结合 enableHotSplashAdv 为 true 才会生效
interface ISdkPlatform {
fun initAdvSdk(
builder: AdvSDKBuilder,
callback: AdvSdkInitCallback
)
}
setSplashAdvEngine(engine: ISplashAdvEngine)
setFullScreenVideoAdvEngine(engine: IFullScreenVideoAdvEngine)
setBannerAdvEngine(engine: IBannerAdvEngine)
setFeedAdvEngine(engine: IFeedAdvEngine)
setRewardVideoEngine(engine: IRewardVideoAdvEngine)
对应各种广告的实现,实现对应的接口即可。最后调用 apply() 完成初始化.
以 开屏广告 为例,其他类型差不多。
- 首先实现 ISplashAdvEngine 接口,完成开屏广告具体的实现,主要是实现 showSplashAdv 方法(完整示例可以查看代码中的 TTSplashAdvEngine)
class TTSplashAdvEngine : ISplashAdvEngine {
override fun showSplashAdv(config: SplashAdvConfig) {
val adNativeLoader = TTAdSdk.getAdManager().createAdNative(act)
val adSlot = AdSlot.Builder()
.setCodeId(config.codeId)
.setImageAcceptedSize(config.width, config.height)
.build()
adNativeLoader.loadSplashAd(adSlot, object : TTAdNative.SplashAdListener {
//...
}
}
}
然后在开屏页直接调用展示即可:
EasyAdv.splashConfig()
.setCodeId("KFC_V_WO_50")
.setActivity(this)
.setWidth(getScreenWidth())
.setHeight(getScreenHeight())
.lifecycle(this)
.scope(lifecycleScope)
.setContainer(findViewById<FrameLayout>(R.id.adLayout))
.setSplashAdvListener(onError = { _, _ ->
toMain()
}, onAdClicked = { _, _ ->
toMain()
}, onAdSkip = {
toMain()
}, onAdTimeOver = {
toMain()
})
.showSplashAdv()
如上,设置广告的 codeId,当前act(如果不是 act 的上下文,广告会显示不出来),常规宽高,广告 ViewGroup,各种回调等,最后调用 showSplashAdv 即可。
在调用开屏广告的时候如果 sdk 还没初始化完成,showSplashAdv 会一直等待 sdk 初始化完成才会执行,所以不用担心时序问题。
当 sdk 初始化失败或者超时的时候,会回调 onError。回调方法除了常规的以外,还提供了 DSL 的方式(如上示例),要哪个再写哪个,提高代码的简洁度。
** 热启动开屏广告 **
先在初始化的时候将 enableHotSplashAdv 设为 true,然后实现 IHotSplashAdvStrategy 接口。
interface IHotSplashAdvStrategy {
fun getCodeId(): String
fun showRequirement(activity: Activity): Boolean
fun showHotSplashAdv(activity: Activity, codeId: String)
}
- getCodeId 就是热启动广告的 codeId
- showRequirement 展示条件,比如说隔10分钟展示一次,哪些页面展示哪些不需要等,要是没条件直接返回 true 就行
- showHotSplashAdv 显示具体实现
举例(演示了每隔10分钟显示一次热启动广告):
class TTHotSplashAdvStrategy : IHotSplashAdvStrategy {
private var lastShowTime = 0L
private var ttHotSplashAdvDialog: TTHotSplashAdvDialog? = null
override fun getCodeId(): String = "KFC_V_WO_50"
override fun showRequirement(activity: Activity): Boolean {
return activity !is SplashActivity
&& System.currentTimeMillis() - lastShowTime > 60 * 60 * 1000
}
override fun showHotSplashAdv(activity: Activity, codeId: String) {
lastShowTime = System.currentTimeMillis()
ttHotSplashAdvDialog = TTHotSplashAdvDialog(activity, onShow = { container ->
EasyAdv.splashConfig()
.setCodeId(codeId)
.setActivity(activity)
.setWidth(activity.getScreenWidth())
.setHeight(activity.getScreenHeight())
.setContainer(container)
.setSplashAdvListener(onError = { _, _ ->
ttHotSplashAdvDialog?.dismiss()
}, onAdClicked = { _, _ ->
ttHotSplashAdvDialog?.dismiss()
}, onAdSkip = {
ttHotSplashAdvDialog?.dismiss()
}, onAdTimeOver = {
ttHotSplashAdvDialog?.dismiss()
})
.showSplashAdv()
}, onDismiss = {})
ttHotSplashAdvDialog?.show()
}
}
广告流程大体就跟上面说的差不多,其他广告也一样,激励广告在显示时可能需要先获取接口返回的一些参数 id,在调用的时候传给 广告sdk 。所以激励广告多了一个拦截器逻辑用来处理这类情况。
EasyAdv.rewardVideoConfig()
.setCodeId("KFC_V_WO_50")
.setXXX()
...
.addInterceptor(object : AdvInterceptor() {
override fun getTag(): String = "RewardInterceptor"
override fun process(map: HashMap<String, String>?, callback: AdvInterceptCallback) {
super.process(map, callback)
//比如一顿操作后获取到各种参数,然后把他设置到 map 里面即可
map?.put(MediationConstant.CUSTOM_DATA_KEY_GROMORE_EXTRA, "KFC_V_WO_50")
map?.put(MediationConstant.ADN_PANGLE, "KFC_V_WO_50")
map?.put(MediationConstant.ADN_KS, "KFC_V_WO_50")
map?.put(MediationConstant.ADN_GDT, "KFC_V_WO_50")
callback.onNext(map)
}
})
喜欢的可以点个星,有负责的场景可以提出意见,我会进行完善。