Skip to content

Commit

Permalink
[Feature/admob_reward_video]: 리워드 비디오 광고 작업 (#311)
Browse files Browse the repository at this point in the history
* [feature/reward_admob]: Add Two Button Dialog

* [feature/reward_admob]: Add Admob App Id

* [feature/reward_admob]: Add Ad Constant API

* [feature/reward_admob]: Add Ad Dialog

* [feature/reward_admob]: Fix Code Review

* [feature/reward_admob]: Fix Code Review
  • Loading branch information
kez-lab authored Oct 17, 2023
1 parent 6304279 commit 83d92fb
Show file tree
Hide file tree
Showing 34 changed files with 633 additions and 31 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/develop_PR_builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@ jobs:
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
KAKAO_API_KEY: ${{ secrets.KAKAO_API_KEY }}
POPHORY_BASE_URL: ${{ secrets.POPHORY_BASE_URL }}
ADMOB_APP_ID: ${{ secrets.ADMOB_APP_ID }}
KEY_ALIAS: ${{ secrets.SENTRY_DSN }}
KEY_PASSWORD: ${{ secrets.SENTRY_DSN }}
STORE_PASSWORD: ${{ secrets.SENTRY_DSN }}
run: |
echo sentryDsn=\"$SENTRY_DSN\" >> ./local.properties
echo kakaoApiKey=$KAKAO_API_KEY >> ./local.properties
echo pophoryBaseUrl=$POPHORY_BASE_URL >> ./local.properties
echo admobAppId=$ADMOB_APP_ID >> ./local.properties
echo keyAlias=$KEY_ALIAS >> ./local.properties
echo keyPassword=KEY_PASSWORD >> ./local.properties
echo storePassword=$STORE_PASSWORD >> ./local.properties
Expand Down
2 changes: 2 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,12 @@ dependencies {
// domain
implementation(projects.domain.auth)
implementation(projects.domain.share)
implementation(projects.domain.ad)

// data
implementation(projects.data.auth)
implementation(projects.data.share)
implementation(projects.data.ad)

// core
implementation(projects.core.common)
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
android:value="true" />
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713" />
android:value="${admobAppId}" />

<provider
android:name="androidx.startup.InitializationProvider"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,14 @@ class AdmobRewardedAdService @AssistedInject constructor(
}

interface AdmobRewardEvents {
fun onAdLoaded()
fun onAdFailedToLoad(error: LoadAdError)
fun onAdClicked()
fun onAdDismissed()
fun onAdFailedToShow(error: AdError)
fun onAdImpression()
fun onAdShowed()
fun onUserEarnedReward(rewardItem: RewardItem)
fun onAdLoaded() {}
fun onAdFailedToLoad(error: LoadAdError) {}
fun onAdClicked() {}
fun onAdDismissed() {}
fun onAdFailedToShow(error: AdError) {}
fun onAdImpression() {}
fun onAdShowed() {}
fun onUserEarnedReward(rewardItem: RewardItem) {}
}
}

Expand Down
31 changes: 31 additions & 0 deletions app/src/main/java/com/teampophory/pophory/config/di/AdModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.teampophory.pophory.config.di

import com.teampophory.pophory.ad.repository.AdRepository
import com.teampophory.pophory.ad.repository.DefaultAdRepository
import com.teampophory.pophory.ad.service.AdService
import com.teampophory.pophory.common.qualifier.Secured
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import retrofit2.Retrofit
import retrofit2.create
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object AdModule {

@Provides
@Singleton
fun provideAdService(@Secured retrofit: Retrofit): AdService = retrofit.create()

@Module
@InstallIn(SingletonComponent::class)
interface Binder {
@Binds
@Singleton
fun bindAdRepository(defaultAdRepository: DefaultAdRepository): AdRepository
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.teampophory.pophory.domain
package com.teampophory.pophory.domain.usecase

import com.teampophory.pophory.data.network.model.mypage.MyPageResponse
import com.teampophory.pophory.data.repository.my.MyPageRepository
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,32 @@ import androidx.core.view.isVisible
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.viewpager2.widget.ViewPager2
import com.google.android.gms.ads.AdError
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.rewarded.RewardItem
import com.teampophory.pophory.R
import com.teampophory.pophory.common.activity.hideLoading
import com.teampophory.pophory.common.activity.showError
import com.teampophory.pophory.common.activity.showLoading
import com.teampophory.pophory.common.ad.AdName
import com.teampophory.pophory.common.context.stringOf
import com.teampophory.pophory.common.intent.intExtra
import com.teampophory.pophory.common.intent.longExtra
import com.teampophory.pophory.common.view.dp
import com.teampophory.pophory.common.view.showAllowingStateLoss
import com.teampophory.pophory.common.view.viewBinding
import com.teampophory.pophory.config.ad.AdmobRewardedAdFactory
import com.teampophory.pophory.config.ad.AdmobRewardedAdService
import com.teampophory.pophory.databinding.ActivityAlbumCoverEditBinding
import com.teampophory.pophory.feature.album.cover.adapter.AlbumCoverEditAdapter
import com.teampophory.pophory.feature.album.cover.model.AlbumCoverItem
import com.teampophory.pophory.util.HorizontalMarginItemDecoration
import com.teampophory.pophory.util.dialog.TwoButtonCommonDialog
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import javax.inject.Inject

@AndroidEntryPoint
class AlbumCoverEditActivity : AppCompatActivity() {
Expand All @@ -33,6 +45,9 @@ class AlbumCoverEditActivity : AppCompatActivity() {
private val currentAlbumCoverId by intExtra(1)
private val albumId by longExtra(0)

@Inject
lateinit var admobRewardedAdFactory: AdmobRewardedAdFactory

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
Expand Down Expand Up @@ -73,7 +88,7 @@ class AlbumCoverEditActivity : AppCompatActivity() {

private fun initButton() {
binding.tvEditButton.setOnClickListener {
viewModel.patchAlbumCover(albumId)
showAdCheckDialog()
}

binding.ivBack.setOnClickListener {
Expand Down Expand Up @@ -176,6 +191,56 @@ class AlbumCoverEditActivity : AppCompatActivity() {
}
}

private fun showAdCheckDialog() {
TwoButtonCommonDialog.newInstance(
title = stringOf(R.string.edit_album_ad_title),
description = stringOf(R.string.edit_album_ad_description),
imageResId = R.drawable.ic_album_cover,
confirmButtonText = stringOf(R.string.s_continue),
dismissButtonText = stringOf(R.string.s_return),
).apply {
setConfirmButtonClickListener {
loadRewardAd()
}
setDismissButtonClickListener {
finish()
}
}.showAllowingStateLoss(supportFragmentManager, "TwoButtonCommonDialog")
}

private fun loadRewardAd() {
lifecycleScope.launch {
val adConstant = viewModel.fetchAdConstant(AdName.ALBUM_EDIT_COVER_REWARD_01.adName)
if (adConstant != null) {
getRewardService(adConstant.name).loadAd()
} else {
viewModel.patchAlbumCover(albumId)
}
}
}

private fun getRewardService(adName: String): AdmobRewardedAdService {
return admobRewardedAdFactory.create(adUnitId = adName).apply {
setAdmobRewardEvents(object : AdmobRewardedAdService.AdmobRewardEvents {
override fun onAdFailedToLoad(error: LoadAdError) {
viewModel.patchAlbumCover(albumId)
}

override fun onAdFailedToShow(error: AdError) {
viewModel.patchAlbumCover(albumId)
}

override fun onAdShowed() {
viewModel.patchAlbumCover(albumId)
}

override fun onUserEarnedReward(rewardItem: RewardItem) {
viewModel.patchAlbumCover(albumId)
}
})
}
}

companion object {
fun newIntent(
context: Context,
Expand All @@ -188,4 +253,4 @@ class AlbumCoverEditActivity : AppCompatActivity() {
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package com.teampophory.pophory.feature.album.cover
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.teampophory.pophory.R
import com.teampophory.pophory.ad.entity.AdIdentifier
import com.teampophory.pophory.ad.usecase.FetchAdConstantUseCase
import com.teampophory.pophory.data.network.model.album.AlbumCoverChangeRequest
import com.teampophory.pophory.domain.repository.photo.PhotoRepository
import com.teampophory.pophory.feature.album.cover.model.AlbumCoverItem
Expand All @@ -14,8 +16,10 @@ import javax.inject.Inject

@HiltViewModel
class AlbumCoverEditViewModel @Inject constructor(
private val photoRepository: PhotoRepository
) : ViewModel() {
private val photoRepository: PhotoRepository,
private val fetchAdConstantUseCase: FetchAdConstantUseCase,

) : ViewModel() {

private val _albumEditState = MutableStateFlow<AlbumEditState>(AlbumEditState.Uninitialized)
val albumEditState = _albumEditState.asStateFlow()
Expand Down Expand Up @@ -50,4 +54,8 @@ class AlbumCoverEditViewModel @Inject constructor(
fun updateCurrentPosition(currentDesignId: Long) {
this.currentDesignId = currentDesignId + 1
}
}

suspend fun fetchAdConstant(adName: String): AdIdentifier? {
return fetchAdConstantUseCase(adName)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package com.teampophory.pophory.feature.home

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.teampophory.pophory.domain.ConfigureMeUseCase
import com.teampophory.pophory.BuildConfig
import com.teampophory.pophory.ad.usecase.GetAdConstantUseCase
import com.teampophory.pophory.ad.usecase.SetAdConstantUseCase
import com.teampophory.pophory.domain.usecase.ConfigureMeUseCase
import com.teampophory.pophory.feature.home.store.model.AlbumItem
import dagger.hilt.android.lifecycle.HiltViewModel
import io.sentry.Sentry
Expand All @@ -14,11 +17,14 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject

@HiltViewModel
class HomeViewModel @Inject constructor(
private val configureMeUseCase: ConfigureMeUseCase
private val configureMeUseCase: ConfigureMeUseCase,
private val getAdConstantUseCase: GetAdConstantUseCase,
private val setAdConstantUseCase: SetAdConstantUseCase
) : ViewModel() {

private val _homeState = MutableStateFlow(HomeViewState())
Expand All @@ -38,6 +44,14 @@ class HomeViewModel @Inject constructor(
}
Sentry.setUser(user)
}
getAdConstantUseCase("android", BuildConfig.VERSION_NAME).onSuccess {
it.forEach { adConstant ->
Timber.d("adConstant: $adConstant")
setAdConstantUseCase(adConstant.name, adConstant.id)
}
}.onFailure {
Timber.e(it)
}
}
}

Expand All @@ -54,4 +68,4 @@ class HomeViewModel @Inject constructor(
_albumCountUpdateEvent.emit(Unit)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,21 +104,26 @@ class StoreFragment : Fragment() {

private fun intiViews() {
binding.ivEditButton.setOnClickListener {
if (viewModel.albums.value is StoreState.SuccessAlbums) {
val currentAlbumPosition = homeViewModel.homeState.value.currentAlbumPosition
val albumItem = viewModel.getCurrentAlbumItem(currentAlbumPosition)
val currentAlbumCoverId = albumItem?.albumCover ?: 1
val intent = AlbumCoverEditActivity.newIntent(
context = requireContext(),
albumCoverId = currentAlbumCoverId,
albumId = albumItem?.id ?: 0
)
albumCoverChangeLauncher.launch(intent)
}
moveToAlbumCoverEditActivity()
}
binding.seekBarStore.setOnTouchListener { _, _ -> true }
}

private fun moveToAlbumCoverEditActivity() {
if (viewModel.albums.value !is StoreState.SuccessAlbums) {
return
}
val currentAlbumPosition = homeViewModel.homeState.value.currentAlbumPosition
val albumItem = viewModel.getCurrentAlbumItem(currentAlbumPosition)
val currentAlbumCoverId = albumItem?.albumCover ?: 1
val intent = AlbumCoverEditActivity.newIntent(
context = requireContext(),
albumCoverId = currentAlbumCoverId,
albumId = albumItem?.id ?: 0
)
albumCoverChangeLauncher.launch(intent)
}

private fun initHomeObserver() {
homeViewModel.albumCountUpdateEvent.flowWithLifecycle(viewLifeCycle).onEach {
viewModel.getAlbums()
Expand Down
Loading

0 comments on commit 83d92fb

Please sign in to comment.