Android 앱(Kotlin)에 Huawei Ads Kit의 롤 광고 기능 통합
소개
이 기사에서는 Huawei Ads Kit의 Roll Ads 기능을 Android 앱에 통합하는 방법을 알아볼 수 있습니다. 따라서 롤 광고는 동영상 콘텐츠가 재생되기 전, 도중 또는 후에 짧은 동영상이나 이미지로 표시됩니다.
광고 키트
Huawei Ads는 개발자에게 양질의 광고 콘텐츠를 사용자에게 제공할 수 있는 광범위한 기능을 제공합니다. 이는 대상 고객에게 쉽게 도달하고 사용자 생산성을 측정할 수 있는 가장 좋은 방법입니다. 무료 앱을 게시하고 그것으로 돈을 벌고 싶을 때 매우 유용합니다.
HMS 광고 키트에는 7가지 유형의 광고 키트가 있습니다. 이제 이 애플리케이션에서 롤 광고를 구현할 수 있습니다.
요구 사항
HMS 종속성을 통합하는 방법
참고: 프로젝트 이름은 사용자가 만든 이름에 따라 다릅니다.
maven { url 'http://developer.huawei.com/repo/' }
classpath 'com.huawei.agconnect:agcp:1.6.0.300'
apply plugin: id 'com.huawei.agconnect'
// Huawei AGC
implementation 'com.huawei.agconnect:agconnect-core:1.6.0.300'
// Huawei Ads Kit
implementation 'com.huawei.hms:ads-lite:13.4.51.300'
// Ads Kit
<uses-permission android:name="android.permission.INTERNET" />
개발로 이동하자
빈 활동으로 Android 스튜디오에서 프로젝트를 생성하여 코딩을 시작하겠습니다.
MainActivity.kt에서 광고에 대한 비즈니스 로직을 찾을 수 있습니다.
class MainActivity : AppCompatActivity() {
private var videoContent: TextView? = null
private var skipAd: TextView? = null
private var countDown: TextView? = null
private var callToAction: TextView? = null
private var loadButton: Button? = null
private var registerButton: Button? = null
private var muteButton: Button? = null
private var pauseButton: Button? = null
private var instreamContainer: RelativeLayout? = null
private var instreamView: InstreamView? = null
private var whyThisAd: ImageView? = null
private var context: Context? = null
private var maxAdDuration = 0
private var whyThisAdUrl: String? = null
private var isMuted = false
private var adLoader: InstreamAdLoader? = null
private var instreamAds: List<InstreamAd>? = ArrayList()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
context = applicationContext
setTitle(R.string.instream_ad)
initInstreamAdView()
initButtons()
configAdLoader()
}
private val mediaChangeListener = InstreamMediaChangeListener { instreamAd ->
whyThisAdUrl = null
whyThisAdUrl = instreamAd.whyThisAd
Log.i(TAG, "onSegmentMediaChange, whyThisAd: $whyThisAdUrl")
if (!TextUtils.isEmpty(whyThisAdUrl)) {
whyThisAd!!.visibility = View.VISIBLE
whyThisAd!!.setOnClickListener { startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(whyThisAdUrl))) }
} else {
whyThisAd!!.visibility = View.GONE
}
val cta = instreamAd.callToAction
if (!TextUtils.isEmpty(cta)) {
callToAction!!.visibility = View.VISIBLE
callToAction!!.text = cta
instreamView!!.callToActionView = callToAction
}
}
private val mediaStateListener: InstreamMediaStateListener = object : InstreamMediaStateListener {
override fun onMediaProgress(per: Int, playTime: Int) {
updateCountDown(playTime.toLong())
}
override fun onMediaStart(playTime: Int) {
updateCountDown(playTime.toLong())
}
override fun onMediaPause(playTime: Int) {
updateCountDown(playTime.toLong())
}
override fun onMediaStop(playTime: Int) {
updateCountDown(playTime.toLong())
}
override fun onMediaCompletion(playTime: Int) {
updateCountDown(playTime.toLong())
playVideo()
}
override fun onMediaError(playTime: Int, errorCode: Int, extra: Int) {
updateCountDown(playTime.toLong())
}
}
private val mediaMuteListener: MediaMuteListener = object : MediaMuteListener {
override fun onMute() {
isMuted = true
Toast.makeText(context, "Ad muted", Toast.LENGTH_SHORT).show()
}
override fun onUnmute() {
isMuted = false
Toast.makeText(context, "Ad unmuted", Toast.LENGTH_SHORT).show()
}
}
private fun initInstreamAdView() {
instreamContainer = findViewById(R.id.instream_ad_container)
videoContent = findViewById(R.id.instream_video_content)
skipAd = findViewById(R.id.instream_skip)
skipAd!!.setOnClickListener(View.OnClickListener {
if (null != instreamView) {
instreamView!!.onClose()
instreamView!!.destroy()
instreamContainer!!.visibility = View.GONE
}
})
countDown = findViewById(R.id.instream_count_down)
callToAction = findViewById(R.id.instream_call_to_action)
whyThisAd = findViewById(R.id.instream_why_this_ad)
instreamView = findViewById(R.id.instream_view)
instreamView!!.setInstreamMediaChangeListener(mediaChangeListener)
instreamView!!.setInstreamMediaStateListener(mediaStateListener)
instreamView!!.setMediaMuteListener(mediaMuteListener)
instreamView!!.setOnInstreamAdClickListener(InstreamView.OnInstreamAdClickListener {
Toast.makeText(context,"instream clicked.", Toast.LENGTH_SHORT).show()
})
}
private val clickListener = View.OnClickListener { view ->
when (view.id) {
R.id.instream_load -> if (null != adLoader) {
loadButton!!.text = getString(R.string.instream_loading)
adLoader!!.loadAd(AdParam.Builder().build())
}
R.id.instream_register -> if (null == instreamAds || instreamAds!!.isEmpty()) {
playVideo()
} else {
playInstreamAds(instreamAds!!)
}
R.id.instream_mute -> if (isMuted) {
instreamView!!.unmute()
muteButton!!.text = getString(R.string.instream_mute)
} else {
instreamView!!.mute()
muteButton!!.text = getString(R.string.instream_unmute)
}
R.id.instream_pause_play -> if (instreamView!!.isPlaying) {
instreamView!!.pause()
pauseButton!!.text = getString(R.string.instream_play)
} else {
instreamView!!.play()
pauseButton!!.text = getString(R.string.instream_pause)
}
else -> {
}
}
}
private fun initButtons() {
loadButton = findViewById(R.id.instream_load)
registerButton = findViewById(R.id.instream_register)
muteButton = findViewById(R.id.instream_mute)
pauseButton = findViewById(R.id.instream_pause_play)
loadButton!!.setOnClickListener(clickListener)
registerButton!!.setOnClickListener(clickListener)
muteButton!!.setOnClickListener(clickListener)
pauseButton!!.setOnClickListener(clickListener)
}
private val instreamAdLoadListener: InstreamAdLoadListener = object : InstreamAdLoadListener {
override fun onAdLoaded(ads: MutableList<InstreamAd>) {
if (null == ads || ads.size == 0) {
playVideo()
return
}
val it = ads.iterator()
while (it.hasNext()) {
val ad = it.next()
if (ad.isExpired) {
it.remove()
}
}
if (ads.size == 0) {
playVideo()
return
}
loadButton!!.text = getString(R.string.instream_loaded)
instreamAds = ads
Toast.makeText(context, "onAdLoaded, ad size: " + ads.size + ", click REGISTER to play.", Toast.LENGTH_SHORT).show()
}
override fun onAdFailed(errorCode: Int) {
Log.w(TAG, "onAdFailed: $errorCode")
loadButton!!.text = getString(R.string.instream_load)
Toast.makeText(context, "onAdFailed: $errorCode", Toast.LENGTH_SHORT).show()
playVideo()
}
}
private fun configAdLoader() {
// if the maximum total duration is 60 seconds and the maximum number of roll ads is eight,
// at most four 15-second roll ads or two 30-second roll ads will be returned.
// If the maximum total duration is 120 seconds and the maximum number of roll ads is four,
// no more roll ads will be returned after whichever is reached.
val totalDuration = 60
val maxCount = 4
val builder = InstreamAdLoader.Builder(context, getString(R.string.instream_ad_id))
adLoader = builder.setTotalDuration(totalDuration)
.setMaxCount(maxCount)
.setInstreamAdLoadListener(instreamAdLoadListener)
.build()
}
// play your normal video content.
private fun playVideo() {
hideAdViews()
videoContent!!.setText(R.string.instream_normal_video_playing)
}
private fun hideAdViews() {
instreamContainer!!.visibility = View.GONE
}
private fun playInstreamAds(ads: List<InstreamAd>) {
maxAdDuration = getMaxInstreamDuration(ads)
instreamContainer!!.visibility = View.VISIBLE
loadButton!!.text = getString(R.string.instream_load)
instreamView!!.setInstreamAds(ads)
}
private fun updateCountDown(playTime: Long) {
val time = Math.round((maxAdDuration - playTime) / 1000.toFloat()).toString()
runOnUiThread { countDown!!.text = time + "s" }
}
private fun getMaxInstreamDuration(ads: List<InstreamAd>): Int {
var duration = 0
for (ad in ads) {
duration += ad.duration.toInt()
}
return duration
}
override fun onPause() {
super.onPause()
if (null != instreamView && instreamView!!.isPlaying) {
instreamView!!.pause()
pauseButton!!.text = getText(R.string.instream_play)
}
}
override fun onResume() {
super.onResume()
if (null != instreamView && !instreamView!!.isPlaying) {
instreamView!!.play()
pauseButton!!.text = getText(R.string.instream_pause)
}
}
override fun onDestroy() {
super.onDestroy()
if (null != instreamView) {
instreamView!!.removeInstreamMediaStateListener()
instreamView!!.removeInstreamMediaChangeListener()
instreamView!!.removeMediaMuteListener()
instreamView!!.destroy()
}
}
companion object {
private val TAG = MainActivity::class.java.simpleName
}
}
activity_main.xml에서 UI 화면을 만들 수 있습니다.
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="@+id/your_video_content"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@android:color/black">
<TextView
android:id="@+id/instream_video_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
android:layout_centerInParent="true"
android:text="Your video content"
android:textColor="@android:color/white"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/instream_ad_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<com.huawei.hms.ads.instreamad.InstreamView
android:id="@+id/instream_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/instream_skip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingVertical="3dp"
android:paddingHorizontal="5dp"
android:layout_alignStart="@id/instream_view"
android:layout_alignLeft="@id/instream_view"
android:layout_alignTop="@id/instream_view"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="8dp"
android:text="Skip"
android:textColor="@android:color/white"
android:textSize="16sp"
android:background="@drawable/emui_button_select"/>
<TextView
android:id="@+id/instream_count_down"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingVertical="3dp"
android:paddingHorizontal="5dp"
android:layout_alignEnd="@id/instream_view"
android:layout_alignRight="@id/instream_view"
android:layout_alignTop="@id/instream_view"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:textColor="@android:color/white"
android:textSize="16sp"
android:background="@drawable/emui_button_select"/>
<TextView
android:id="@+id/instream_ad_flag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@id/instream_view"
android:layout_alignLeft="@id/instream_view"
android:layout_alignBottom="@id/instream_view"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginBottom="8dp"
android:background="@drawable/emui_button_select"
android:gravity="center"
android:text="Ad"
android:textColor="@android:color/white"
android:textSize="8sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/instream_why_this_ad"
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_toEndOf="@id/instream_ad_flag"
android:layout_toRightOf="@id/instream_ad_flag"
android:layout_alignBottom="@id/instream_view"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_marginBottom="8dp"
android:src="@drawable/app_whythisad_info"/>
<TextView
android:id="@+id/instream_call_to_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingVertical="3dp"
android:paddingHorizontal="5dp"
android:layout_alignEnd="@id/instream_view"
android:layout_alignRight="@id/instream_view"
android:layout_alignBottom="@id/instream_view"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="8dp"
android:text="Learn more"
android:textColor="@android:color/white"
android:textSize="16sp"
android:background="@drawable/emui_button_select"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/instream_ctrl_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingVertical="16dp"
android:layout_below="@id/your_video_content">
<LinearLayout
android:id="@+id/load_and_register"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_centerHorizontal="true">
<Button
android:id="@+id/instream_load"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:text="Load Ad"/>
<Button
android:id="@+id/instream_register"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:text="Register"/>
</LinearLayout>
<LinearLayout
android:id="@+id/play_ctrl"
android:layout_below="@id/load_and_register"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_centerHorizontal="true">
<Button
android:id="@+id/instream_mute"
android:layout_width="100dp"
android:layout_marginRight="10dp"
android:layout_height="wrap_content"
android:text="Mute"/>
<Button
android:id="@+id/instream_pause_play"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="Pause"/>
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
</ScrollView>
데모
팁과 요령
결론
이 기사에서는 Huawei Ads Kit의 Roll Ads 기능을 Android 앱에 통합하는 방법을 배웠습니다. 따라서 롤 광고는 동영상 콘텐츠가 재생되기 전, 도중 또는 후에 짧은 동영상이나 이미지로 표시됩니다.
이 기사를 읽으셨기를 바랍니다. 도움이 되셨다면 좋아요와 댓글 부탁드립니다.
참조
광고 키트 - Roll Ads
광고 키트 – Training Video
Reference
이 문제에 관하여(Android 앱(Kotlin)에 Huawei Ads Kit의 롤 광고 기능 통합), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/hmscommunity/integration-of-the-roll-ads-feature-of-huawei-ads-kit-in-android-app-kotlin-j2b텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)