Android 앱(Kotlin)에 Huawei Ads Kit의 롤 광고 기능 통합

22820 단어 androidxmladskotlin


소개

이 기사에서는 Huawei Ads Kit의 Roll Ads 기능을 Android 앱에 통합하는 방법을 알아볼 수 있습니다. 따라서 롤 광고는 동영상 콘텐츠가 재생되기 전, 도중 또는 후에 짧은 동영상이나 이미지로 표시됩니다.

광고 키트

Huawei Ads는 개발자에게 양질의 광고 콘텐츠를 사용자에게 제공할 수 있는 광범위한 기능을 제공합니다. 이는 대상 고객에게 쉽게 도달하고 사용자 생산성을 측정할 수 있는 가장 좋은 방법입니다. 무료 앱을 게시하고 그것으로 돈을 벌고 싶을 때 매우 유용합니다.

HMS 광고 키트에는 7가지 유형의 광고 키트가 있습니다. 이제 이 애플리케이션에서 롤 광고를 구현할 수 있습니다.

요구 사항
  • 모든 운영 체제(MacOS, Linux 및 Windows).
  • HMS 4.0.0.300 이상이 설치된 Huawei 휴대폰이 있어야 합니다.
  • Android Studio, Jdk 1.8, SDK 플랫폼 26 및 Gradle 4.6 이상이 설치된 노트북 또는 데스크톱이 있어야 합니다.
  • 최소 API 레벨 24가 필요합니다.
  • EMUI 9.0.0 이상 버전 장치가 필요합니다.

  • HMS 종속성을 통합하는 방법
  • 먼저 Huawei 개발자로 등록하고 Huawei 개발자 웹 사이트에서 신원 확인을 완료합니다. 등록 aHuawei ID를 참조하십시오.
  • android studio에서 프로젝트를 생성합니다. Creating an Android Studio Project을 참조하십시오.
  • SHA-256 인증서 지문을 생성합니다.
  • SHA-256 인증서 지문을 생성합니다. Android 프로젝트의 오른쪽 상단에서 Gradle을 클릭하고 Project Name > Tasks > android를 선택한 후 다음과 같이 SigningReport를 클릭합니다.



  • 참고: 프로젝트 이름은 사용자가 만든 이름에 따라 다릅니다.
  • Create an App in AppGallery Connect .
  • 다음과 같이 앱 정보에서 agconnect-services.json 파일을 다운로드하고 앱 디렉토리 아래의 android Project에 복사하여 붙여넣습니다.


  • 다음과 같이 SHA-256 인증서 지문을 입력하고 저장 버튼을 클릭합니다.
  • buildscript, dependencies 및 allprojects의 리포지토리 아래 build.gradle(Project) 파일에 아래 maven URL을 추가합니다. Add Configuration을 참조하십시오.

  • maven { url 'http://developer.huawei.com/repo/' }
    classpath 'com.huawei.agconnect:agcp:1.6.0.300'
    


  • build.gradle(Module) 파일에 아래 플러그인 및 종속 항목을 추가합니다.

  • 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'
    


  • 이제 Gradle을 동기화합니다.
  • AndroidManifest.xml 파일에 필요한 권한을 추가합니다.

  • // 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 개발자로 등록되어 있는지 확인하십시오.
  • minSDK 버전을 24 이상으로 설정하십시오. 그렇지 않으면 AndriodManifest 병합 문제가 발생합니다.
  • 앱 폴더에 agconnect-services.json 파일을 추가했는지 확인하십시오.
  • 반드시 SHA-256 지문을 추가했는지 확인하십시오.
  • 모든 종속성이 제대로 추가되었는지 확인하십시오.

  • 결론

    이 기사에서는 Huawei Ads Kit의 Roll Ads 기능을 Android 앱에 통합하는 방법을 배웠습니다. 따라서 롤 광고는 동영상 콘텐츠가 재생되기 전, 도중 또는 후에 짧은 동영상이나 이미지로 표시됩니다.

    이 기사를 읽으셨기를 바랍니다. 도움이 되셨다면 좋아요와 댓글 부탁드립니다.

    참조

    광고 키트 - Roll Ads

    광고 키트 – Training Video

    좋은 웹페이지 즐겨찾기