Skip to content

Commit

Permalink
Add Adfox slider screen in sample app (#274)
Browse files Browse the repository at this point in the history
* Add Adfox slider screen in sample app
  • Loading branch information
mobile-ads-github authored Jul 17, 2024
1 parent 9d3a5ee commit f1d0b52
Show file tree
Hide file tree
Showing 27 changed files with 685 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ internal class HomeScreen(
NavigationItem.Rewarded::class.java -> 3
NavigationItem.NativeTemplate::class.java -> 4
NavigationItem.CustomNative::class.java -> 5
NavigationItem.InstreamBinder::class.java -> 7
NavigationItem.InstreamInRoll::class.java -> 8
NavigationItem.Policies::class.java -> 9
NavigationItem.AppOpenAd::class.java -> 10
NavigationItem.AdfoxSlider::class.java -> 6
NavigationItem.InstreamBinder::class.java -> 8
NavigationItem.InstreamInRoll::class.java -> 9
NavigationItem.Policies::class.java -> 10
NavigationItem.AppOpenAd::class.java -> 11
else -> error("unsupported type")
}
}
Expand All @@ -43,6 +44,7 @@ internal class HomeScreen(
{
itemType { NavigationItem.NativeTemplate(it) }
itemType { NavigationItem.CustomNative(it) }
itemType { NavigationItem.AdfoxSlider(it) }
itemType { NavigationItem.Policies(it) }
itemType { NavigationItem.AppOpenAd(it) }
itemType { NavigationItem.Rewarded(it) }
Expand Down Expand Up @@ -85,6 +87,8 @@ internal class HomeScreen(

class CustomNative(matcher: Matcher<View>) : NavigationItem<CustomNative>(matcher)

class AdfoxSlider(matcher: Matcher<View>) : NavigationItem<AdfoxSlider>(matcher)

class Policies(matcher: Matcher<View>) : NavigationItem<Policies>(matcher)

class AppOpenAd(matcher: Matcher<View>) : NavigationItem<AppOpenAd>(matcher)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ internal class GoToSection<ScenarioData>(
enum class NavigationItem {
NATIVE_TEMPLATE,
CUSTOM_NATIVE,
ADFOX_SLIDER,
POLICIES,
APP_OPEN_AD,
REWARDED,
Expand All @@ -39,6 +40,7 @@ internal class GoToSection<ScenarioData>(
get() = when (this) {
NavigationItem.NATIVE_TEMPLATE -> R.string.native_template_title
NavigationItem.CUSTOM_NATIVE -> R.string.native_custom_title
NavigationItem.ADFOX_SLIDER -> R.string.adfox_slider_title
NavigationItem.POLICIES -> R.string.policies
NavigationItem.APP_OPEN_AD -> R.string.appopenad_title
NavigationItem.REWARDED -> R.string.rewarded_title
Expand All @@ -53,6 +55,7 @@ internal class GoToSection<ScenarioData>(
get() = when (this) {
NavigationItem.NATIVE_TEMPLATE -> HomeScreen.NavigationItem.NativeTemplate::class.java
NavigationItem.CUSTOM_NATIVE -> HomeScreen.NavigationItem.CustomNative::class.java
NavigationItem.ADFOX_SLIDER -> HomeScreen.NavigationItem.AdfoxSlider::class.java
NavigationItem.POLICIES -> HomeScreen.NavigationItem.Policies::class.java
NavigationItem.APP_OPEN_AD -> HomeScreen.NavigationItem.AppOpenAd::class.java
NavigationItem.REWARDED -> HomeScreen.NavigationItem.Rewarded::class.java
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ internal class InterstitialLoadTest : BaseUITest() {

step("Нажать на кнопку \"Show ad\"") {
onScreen<InterstitialScreen> {
clickShowAd()
flakySafely(10_000) {
clickShowAd()
}
}

step("Успешно отобразилась реклама") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ internal class RewardedLoadTest : BaseUITest() {

step("Нажать на кнопку \"Show ad\"") {
onScreen<RewardedScreen> {
clickShowAd()
flakySafely(10_000) {
clickShowAd()
}
}

step("Успешно отобразилась реклама") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ internal class InterstitialLoadTest(

step("Нажать на кнопку \"Show ad\"") {
onScreen<InterstitialScreen> {
clickShowAd()
flakySafely(10_000) {
clickShowAd()
}
}

step("Реклама загрузилась. В случае подбора рекламы отобразилась на полный экран.") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ internal class RewardedLoadTest(

step("Нажать на кнопку \"Show ad\"") {
onScreen<RewardedScreen> {
clickShowAd()
flakySafely(10_000) {
clickShowAd()
}
}

step("Реклама загрузилась. В случае подбора рекламы отобразилась на полный экран.") {
Expand All @@ -68,7 +70,6 @@ internal class RewardedLoadTest(
}

companion object {

private const val NO_ADS_AVAILABLE_MESSAGE =
"Ad request completed successfully, but there are no ads available."

Expand Down
3 changes: 3 additions & 0 deletions YandexMobileAdsExample/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
<activity
android:name="com.yandex.ads.sample.adunits.CustomNativeAdActivity"
android:exported="false" />
<activity
android:name="com.yandex.ads.sample.adunits.AdfoxSliderAdActivity"
android:exported="false" />
<activity
android:name="com.yandex.ads.sample.adunits.NativeTemplateAdActivity"
android:exported="false" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.yandex.ads.sample.adunits.AdfoxSliderAdActivity
import com.yandex.ads.sample.adunits.AppOpenAdActivity
import com.yandex.ads.sample.adunits.CustomNativeAdActivity
import com.yandex.ads.sample.adunits.FeedActivity
Expand Down Expand Up @@ -97,6 +98,11 @@ class HomeActivity : AppCompatActivity(R.layout.activity_home) {
R.string.native_custom_title,
ActivityNavigation(CustomNativeAdActivity::class.java),
),
NavigationItem(
R.drawable.ic_outline_carousel_24,
R.string.adfox_slider_title,
ActivityNavigation(AdfoxSliderAdActivity::class.java),
),
NavigationItem(
R.drawable.ic_outline_movie_24,
R.string.instream_simple_title,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* This file is a part of the Yandex Advertising Network
*
* Version for Android (C) 2022 YANDEX
*
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at https://legal.yandex.com/partner_ch/
*/

package com.yandex.ads.sample.adfoxslider

import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.yandex.ads.sample.databinding.AdfoxSliderItemBinding
import com.yandex.mobile.ads.nativeads.NativeAd
import com.yandex.mobile.ads.nativeads.NativeAdException
import com.yandex.mobile.ads.nativeads.NativeAdViewBinder

class AdfoxSliderAdapter : RecyclerView.Adapter<NativeAdViewBinderHolder>() {

private var nativeAds: List<NativeAd> = listOf()

fun setData(nativeAds: List<NativeAd>) {
this.nativeAds = nativeAds
notifyDataSetChanged()
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NativeAdViewBinderHolder {
val binding = AdfoxSliderItemBinding.inflate(
LayoutInflater.from(parent.context), parent, false
)
return NativeAdViewBinderHolder(binding)
}

override fun onBindViewHolder(holder: NativeAdViewBinderHolder, position: Int) {
val nativeAd = nativeAds[position]
bindNativeAd(nativeAd, holder.nativeAdViewBinder)
}

override fun getItemCount(): Int {
return nativeAds.size
}

private fun bindNativeAd(nativeAd: NativeAd, viewBinder: NativeAdViewBinder) {
try {
nativeAd.bindNativeAd(viewBinder)
} catch (exception: NativeAdException) {
Log.d(VIEW_PAGER_TAG, "${exception.message}")
}
}

companion object {

private const val VIEW_PAGER_TAG = "ViewPagerAdapter"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* This file is a part of the Yandex Advertising Network
*
* Version for Android (C) 2022 YANDEX
*
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at https://legal.yandex.com/partner_ch/
*/

package com.yandex.ads.sample.adfoxslider

import androidx.recyclerview.widget.RecyclerView
import com.yandex.ads.sample.databinding.AdfoxSliderItemBinding
import com.yandex.mobile.ads.nativeads.NativeAdViewBinder

class NativeAdViewBinderHolder(binding: AdfoxSliderItemBinding) : RecyclerView.ViewHolder(binding.root) {

val nativeAdViewBinder: NativeAdViewBinder = createNativeAdViewBinder(binding)

private fun createNativeAdViewBinder(binding: AdfoxSliderItemBinding): NativeAdViewBinder {
return binding.nativeAd.run {
NativeAdViewBinder.Builder(root)
.setAgeView(age)
.setBodyView(body)
.setCallToActionView(callToAction)
.setDomainView(domain)
.setFaviconView(favicon)
.setFeedbackView(feedback)
.setIconView(icon)
.setMediaView(media)
.setPriceView(price)
.setRatingView(rating)
.setReviewCountView(reviewCount)
.setSponsoredView(sponsored)
.setTitleView(title)
.setWarningView(warning)
.build()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* This file is a part of the Yandex Advertising Network
*
* Version for Android (C) 2022 YANDEX
*
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at https://legal.yandex.com/partner_ch/
*/

package com.yandex.ads.sample.adfoxslider

import androidx.viewpager2.widget.ViewPager2
import kotlinx.coroutines.Job
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class SliderAutoscroller(private val viewPager2: ViewPager2) {

private val itemCount get() = viewPager2.adapter!!.itemCount
private val currentItem get() = viewPager2.currentItem

private val scope = MainScope()
private var job: Job? = null
private var lastScroll = 0L

fun startScrolling() {
stopScrolling()
updateLastScroll()
job = scope.launch {
while (true) {
delay(CHECK_INTERVAL_MILLIS)
if (System.currentTimeMillis() - lastScroll > SCROLL_INTERVAL_MILLIS) {
scroll()
}
}
}
}

fun updateLastScroll() {
lastScroll = System.currentTimeMillis()
}

fun stopScrolling() {
job?.cancel()
job = null
}

private fun scroll() {
openNextPage()
updateLastScroll()
}

private fun openNextPage() {
val nextItem = (currentItem + 1) % itemCount
viewPager2.setCurrentItem(nextItem, true)
}

companion object {

private const val SCROLL_INTERVAL_MILLIS = 5000L
private const val CHECK_INTERVAL_MILLIS = 1000L
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* This file is a part of the Yandex Advertising Network
*
* Version for Android (C) 2022 YANDEX
*
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at https://legal.yandex.com/partner_ch/
*/

package com.yandex.ads.sample.adfoxslider

import android.widget.ImageView
import android.widget.LinearLayout
import androidx.annotation.DimenRes
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.core.view.setMargins
import com.yandex.ads.sample.R
import kotlin.math.absoluteValue

class SliderIndicatorController(private val indicatorLayout: LinearLayout) {
private val dotsImageViews = arrayListOf<ImageView>()

fun setupIndicator(pagesCount: Int, selectedPage: Int) {
indicatorLayout.removeAllViews()
dotsImageViews.clear()

for (i in 0 until pagesCount) {
val dotView = ImageView(indicatorLayout.context).apply {
setImageDrawable(ContextCompat.getDrawable(indicatorLayout.context, R.drawable.shape_adfox_slider_indicator_dot))
}
dotsImageViews.add(dotView)
indicatorLayout.addView(dotsImageViews[i])
}
changeSelectedPage(selectedPage)
}

fun changeSelectedPage(selectedPage: Int) {
dotsImageViews.forEachIndexed { page, view ->
val distance = (selectedPage - page).absoluteValue
val size = when {
dotsImageViews.size <= 4 || distance < 2 -> R.dimen.adfox_slider_indicator_dot_size_large
distance == 2 -> R.dimen.adfox_slider_indicator_dot_size_medium
else -> R.dimen.adfox_slider_indicator_dot_size_small
}
view.layoutParams = getLayoutParams(getResource(size))
view.isVisible = dotsImageViews.size <= 4 || distance <= 3
view.alpha = if (page == selectedPage) DOT_ALPHA_SELECTED
else DOT_ALPHA_NOT_SELECTED
}
}

private fun getLayoutParams(dotSize: Int): LinearLayout.LayoutParams {
val layoutParams = LinearLayout.LayoutParams(dotSize, dotSize)
layoutParams.setMargins(getResource(R.dimen.adfox_slider_indicator_dot_margin))
return layoutParams
}

private fun getResource(@DimenRes id: Int): Int {
return indicatorLayout.resources.getDimension(id).toInt()
}

companion object {

private const val DOT_ALPHA_SELECTED = 1f
private const val DOT_ALPHA_NOT_SELECTED = 0.6f
}
}
Loading

0 comments on commit f1d0b52

Please sign in to comment.