From 86c0480788e994c675b92866233d7a763f9a8065 Mon Sep 17 00:00:00 2001 From: Nicholas Ventimiglia Date: Tue, 6 Aug 2024 14:25:51 -0700 Subject: [PATCH] Fixed Kotlin APIDemo custom playback controls issue. PiperOrigin-RevId: 660096496 --- .../AdManagerCustomControlsFragment.kt | 43 +++++------ .../gms/example/apidemo/CustomControlsView.kt | 55 ++++++------- .../app/src/main/res/drawable/video_mute.png | Bin 0 -> 542 bytes .../app/src/main/res/drawable/video_pause.png | Bin 0 -> 120 bytes .../app/src/main/res/drawable/video_play.png | Bin 0 -> 294 bytes .../src/main/res/drawable/video_unmute.png | Bin 0 -> 489 bytes .../res/layout/ad_simple_custom_template.xml | 73 ++++++++++++------ .../main/res/layout/custom_video_controls.xml | 44 ++++------- .../layout/fragment_gam_customcontrols.xml | 9 +-- .../app/src/main/res/layout/native_ad.xml | 34 +++++--- .../app/src/main/res/values/strings.xml | 2 +- 11 files changed, 136 insertions(+), 124 deletions(-) create mode 100644 kotlin/advanced/APIDemo/app/src/main/res/drawable/video_mute.png create mode 100644 kotlin/advanced/APIDemo/app/src/main/res/drawable/video_pause.png create mode 100644 kotlin/advanced/APIDemo/app/src/main/res/drawable/video_play.png create mode 100644 kotlin/advanced/APIDemo/app/src/main/res/drawable/video_unmute.png diff --git a/kotlin/advanced/APIDemo/app/src/main/java/com/google/android/gms/example/apidemo/AdManagerCustomControlsFragment.kt b/kotlin/advanced/APIDemo/app/src/main/java/com/google/android/gms/example/apidemo/AdManagerCustomControlsFragment.kt index 69ff66784..540d5d7b6 100644 --- a/kotlin/advanced/APIDemo/app/src/main/java/com/google/android/gms/example/apidemo/AdManagerCustomControlsFragment.kt +++ b/kotlin/advanced/APIDemo/app/src/main/java/com/google/android/gms/example/apidemo/AdManagerCustomControlsFragment.kt @@ -19,12 +19,14 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.* +import android.widget.FrameLayout +import android.widget.ImageView +import android.widget.TextView +import android.widget.Toast import androidx.fragment.app.Fragment import com.google.android.gms.ads.AdListener import com.google.android.gms.ads.AdLoader import com.google.android.gms.ads.LoadAdError -import com.google.android.gms.ads.MediaContent import com.google.android.gms.ads.VideoOptions import com.google.android.gms.ads.admanager.AdManagerAdRequest import com.google.android.gms.ads.nativead.MediaView @@ -95,8 +97,6 @@ class AdManagerCustomControlsFragment : Fragment() { nativeAdBinding.adCallToAction.text = nativeAd.callToAction nativeAdBinding.adAppIcon.setImageDrawable(nativeAd.icon?.drawable) - nativeAd.mediaContent?.let { nativeAdBinding.adMedia.setMediaContent(it) } - // These assets aren't guaranteed to be in every NativeAd, so it's important to // check before trying to display them. if (nativeAd.price == null) { @@ -120,12 +120,12 @@ class AdManagerCustomControlsFragment : Fragment() { nativeAdBinding.adStars.visibility = View.VISIBLE } + nativeAdBinding.adMedia.mediaContent = nativeAd.mediaContent + nativeAdBinding.customVideoControls.setMediaContent(nativeAd.mediaContent) + // Assign native ad object to the native view. nativeAdView.setNativeAd(nativeAd) - val mediaContent: MediaContent? = nativeAd.mediaContent - mediaContent?.let { fragmentBinding.customControls.setMediaContent(it) } - fragmentBinding.btnRefresh.isEnabled = true } @@ -140,33 +140,34 @@ class AdManagerCustomControlsFragment : Fragment() { nativeCustomFormatAd: NativeCustomFormatAd, adView: View, ) { - val headline = adView.findViewById(R.id.simplecustom_headline) - val caption = adView.findViewById(R.id.simplecustom_caption) + val headline = adView.findViewById(R.id.headline) + val caption = adView.findViewById(R.id.caption) + val customControls = adView.findViewById(R.id.custom_video_controls) + val mediaView = adView.findViewById(R.id.ad_media) + val imageView = adView.findViewById(R.id.ad_image) headline.text = nativeCustomFormatAd.getText("Headline") caption.text = nativeCustomFormatAd.getText("Caption") - headline.setOnClickListener { nativeCustomFormatAd.performClick("Headline") } - val mediaPlaceholder = adView.findViewById(R.id.simplecustom_media_placeholder) - // Get the media content for the ad. val mediaContent = nativeCustomFormatAd.mediaContent // Apps can check the MediaContent's hasVideoContent property to // determine if the NativeCustomFormatAd has a video asset. if (mediaContent != null && mediaContent.hasVideoContent()) { - val mediaView = MediaView(mediaPlaceholder.getContext()) + customControls.visibility = View.VISIBLE + mediaView.visibility = View.VISIBLE + imageView.visibility = View.GONE mediaView.mediaContent = mediaContent + customControls.setMediaContent(mediaContent) } else { - val mainImage = ImageView(activity) - mainImage.adjustViewBounds = true - mainImage.setImageDrawable(nativeCustomFormatAd.getImage("MainImage")?.drawable) - - mainImage.setOnClickListener { nativeCustomFormatAd.performClick("MainImage") } - mediaPlaceholder.addView(mainImage) + customControls.visibility = View.GONE + mediaView.visibility = View.GONE + imageView.visibility = View.VISIBLE + imageView.setImageDrawable(nativeCustomFormatAd.getImage("MainImage")?.drawable) + imageView.setOnClickListener { nativeCustomFormatAd.performClick("MainImage") } } - mediaContent?.let { fragmentBinding.customControls.setMediaContent(it) } fragmentBinding.btnRefresh.isEnabled = true } @@ -257,7 +258,5 @@ class AdManagerCustomControlsFragment : Fragment() { .build() adLoader.loadAd(AdManagerAdRequest.Builder().build()) - - fragmentBinding.customControls.reset() } } diff --git a/kotlin/advanced/APIDemo/app/src/main/java/com/google/android/gms/example/apidemo/CustomControlsView.kt b/kotlin/advanced/APIDemo/app/src/main/java/com/google/android/gms/example/apidemo/CustomControlsView.kt index 7ccb88f91..4649913d5 100644 --- a/kotlin/advanced/APIDemo/app/src/main/java/com/google/android/gms/example/apidemo/CustomControlsView.kt +++ b/kotlin/advanced/APIDemo/app/src/main/java/com/google/android/gms/example/apidemo/CustomControlsView.kt @@ -4,9 +4,8 @@ import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater import android.view.View -import android.widget.Button +import android.widget.ImageButton import android.widget.LinearLayout -import android.widget.TextView import com.google.android.gms.ads.MediaContent import com.google.android.gms.ads.VideoController @@ -18,10 +17,9 @@ class CustomControlsView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : LinearLayout(context, attrs, defStyle) { - private val playButton: Button - private val muteButton: Button + private val playButton: ImageButton + private val muteButton: ImageButton private val controlsView: View - private val videoStatusText: TextView private var isVideoPlaying: Boolean = false init { @@ -31,37 +29,30 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : playButton = findViewById(R.id.btn_play) muteButton = findViewById(R.id.btn_mute) controlsView = findViewById(R.id.video_controls) - videoStatusText = findViewById(R.id.tv_video_status) controlsView.visibility = View.GONE } - /* - * Reset the custom controls view. - */ - fun reset() { - controlsView.visibility = View.GONE - videoStatusText.text = "" - } - /* * Sets up the custom controls view with the provided VideoController. */ - fun setMediaContent(mediaContent: MediaContent) { + fun setMediaContent(mediaContent: MediaContent?) { controlsView.visibility = View.GONE - if (mediaContent.hasVideoContent()) { + if (mediaContent != null && mediaContent.hasVideoContent()) { configureVideoContent(mediaContent.videoController) - } else { - videoStatusText.text = "Video status: Ad does not contain a video asset." } } private fun configureVideoContent(videoController: VideoController) { if (videoController.isCustomControlsEnabled) { - muteButton.text = if (videoController.isMuted) "Unmute" else "Mute" + val muteResource = + if (videoController.isMuted) { + R.drawable.video_mute + } else { + R.drawable.video_unmute + } + muteButton.setImageResource(muteResource) controlsView.visibility = View.VISIBLE - muteButton.setOnClickListener { videoController.mute(!videoController.isMuted) } - playButton.setOnClickListener { if (isVideoPlaying) { videoController.pause() @@ -78,36 +69,36 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : object : VideoController.VideoLifecycleCallbacks() { override fun onVideoMute(muted: Boolean) { - videoStatusText.text = - "Video status: " + if (muted) "Video did mute" else "Video did un-mute" - muteButton.text = if (muted) "Unmute" else "Mute" + val muteResource = + if (muted) { + R.drawable.video_unmute + } else { + R.drawable.video_mute + } + muteButton.setImageResource(muteResource) super.onVideoMute(muted) } override fun onVideoPause() { - videoStatusText.text = "Video status: Video did pause." - playButton.text = "Play" + playButton.setImageResource(R.drawable.video_play) isVideoPlaying = false super.onVideoPause() } override fun onVideoPlay() { - videoStatusText.text = "Video status: Video did play." - playButton.text = "Pause" + playButton.setImageResource(R.drawable.video_pause) isVideoPlaying = true super.onVideoPlay() } override fun onVideoStart() { - videoStatusText.text = "Video status: Video did start." - playButton.text = "Pause" + playButton.setImageResource(R.drawable.video_pause) isVideoPlaying = true super.onVideoStart() } override fun onVideoEnd() { - videoStatusText.text = "Video status: Video playback has ended." - playButton.text = "Play" + playButton.setImageResource(R.drawable.video_play) isVideoPlaying = false super.onVideoEnd() } diff --git a/kotlin/advanced/APIDemo/app/src/main/res/drawable/video_mute.png b/kotlin/advanced/APIDemo/app/src/main/res/drawable/video_mute.png new file mode 100644 index 0000000000000000000000000000000000000000..53726693f1bba7ec9131ae5ddcf008540cc8cc0b GIT binary patch literal 542 zcmV+(0^$9MP)+9#~?da<5=<4p^9zaC^000GaQchCocbaGY%;n$YLkpeFR0)}aY~yx#** zJ{NjQZz;T6Z7lTB+m?_70OxCPU9elBOcBn2qd^vo2&M@LsJPyw&;$TKqi_kL@E+(_ zo8+SK4piGD@(qZ~aExKN~@0bCFOCTPI?jPo(T1^q?F+(`)h!GT_dxr3kq zSbaW$q+11qJP8^AA-OO)54w<4hzZbzqyi=e0EA>hC_onezk>k4c%cWvcl$}e;7Dji zpR&R8m z(BcJw{j9kn09XGAr*|t42^*Y{{R2aF0jnb11!eG8XSNWn^mCf3ST3eHRdOglsv7B=w6Ibh0+2?&s_4=jrWk;UnPy000GaQchC<|Gz+h&#iSx0004mNklI*o1)%5SqQ;lt6{P_+J_H24dJE!%i2!(d3%Cp|6)?LR|3E;?1&HL= z@mxS#1uHE+7SOH*Naoe20+h>&X_X0dALdw4r#0LUfb1zVp`DFsG zV|oSndI864@X!CE`itf@0eCAY&PCu}KwAXfI$evVL!BQS+FF9vPo}R=h(jNJhn#K8 zmPnT^eG4yUSI54kW28fUWbvyCuxt4q7keC^-hj+(p&Xi9tA;(F)7x0LvY~OCoEvuM zIMECVDBj=B@h-j$xmNtLA-#I>>xQd0JciqvKHHd$>DKaWb3A;sy&qvS5q?gWc}sKAj{B00000NkvXXu0mjfQHj$| literal 0 HcmV?d00001 diff --git a/kotlin/advanced/APIDemo/app/src/main/res/layout/ad_simple_custom_template.xml b/kotlin/advanced/APIDemo/app/src/main/res/layout/ad_simple_custom_template.xml index bcaaf1bc1..30b9a346e 100644 --- a/kotlin/advanced/APIDemo/app/src/main/res/layout/ad_simple_custom_template.xml +++ b/kotlin/advanced/APIDemo/app/src/main/res/layout/ad_simple_custom_template.xml @@ -1,35 +1,58 @@ - + android:orientation="vertical"> + + - + + - + android:adjustViewBounds="true" + android:layout_marginTop="5dp"/> - - + android:layout_marginBottom="5dp" /> + + diff --git a/kotlin/advanced/APIDemo/app/src/main/res/layout/custom_video_controls.xml b/kotlin/advanced/APIDemo/app/src/main/res/layout/custom_video_controls.xml index 27d0a6393..f78b21f77 100644 --- a/kotlin/advanced/APIDemo/app/src/main/res/layout/custom_video_controls.xml +++ b/kotlin/advanced/APIDemo/app/src/main/res/layout/custom_video_controls.xml @@ -1,38 +1,26 @@ -