Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ android {
buildConfigField "String", "REMOTE_KEY_APP_VERSION", properties["REMOTE_KEY_APP_VERSION"]
buildConfigField "String", "REMOTE_KEY_FORCE_UPDATE", properties["REMOTE_KEY_FORCE_UPDATE"]
buildConfigField "String", "KAKAO_CHANNEL_ID", properties["KAKAO_CHANNEL_ID"]
buildConfigField "String", "ADMOB_REWARDED_AD_UNIT_ID", properties["ADMOB_REWARDED_AD_UNIT_ID"]
}

signingConfigs {
Expand Down Expand Up @@ -184,6 +185,7 @@ dependencies {

// Google
implementation libs.play.services.auth
implementation libs.play.services.ads

// Logging
implementation libs.timber
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@
android:name="com.naver.maps.map.NCP_KEY_ID"
android:value="${NAVER_CLIENT_ID}" />

<!-- 개발용 Google 공식 테스트 App ID. 실제 배포 전 본인 AdMob 계정의 App ID로 교체 필요 -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="${ADMOB_APP_ID}" />

<activity
android:name=".presentation.MainActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.runnect.runnect.application
import android.app.Application
import android.content.Context
import androidx.appcompat.app.AppCompatDelegate
import com.google.android.gms.ads.MobileAds
import com.kakao.sdk.common.KakaoSdk
import com.runnect.runnect.BuildConfig
import com.runnect.runnect.R
Expand All @@ -24,6 +25,7 @@ class ApplicationClass : Application() {
KakaoSdk.init(this, getString(R.string.kakao_native_app_key))
initApiMode()
initAnalytics()
MobileAds.initialize(this)
}

private fun initApiMode() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.runnect.runnect.data.dto.request

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class RequestConsumeMarkerQuota(
@SerialName("amount")
val amount: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.runnect.runnect.data.dto.request

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class RequestGrantMarkerReward(
@SerialName("amount")
val amount: Int,
@SerialName("rewardTransactionId")
val rewardTransactionId: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.runnect.runnect.data.dto.response

import com.runnect.runnect.domain.entity.MarkerRewardResult
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class ResponseGrantMarkerReward(
@SerialName("granted")
val granted: Boolean,
@SerialName("balance")
val balance: Int
) {
fun toMarkerRewardResult(): MarkerRewardResult {
return MarkerRewardResult(granted = granted, balance = balance)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.runnect.runnect.data.dto.response

import com.runnect.runnect.domain.entity.MarkerQuota
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class ResponseMarkerQuota(
@SerialName("balance")
val balance: Int
) {
fun toMarkerQuota(): MarkerQuota {
return MarkerQuota(balance = balance)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.runnect.runnect.data.repository

import com.runnect.runnect.data.network.mapToFlowResult
import com.runnect.runnect.data.source.remote.RemoteMarkerQuotaDataSource
import com.runnect.runnect.domain.entity.MarkerQuota
import com.runnect.runnect.domain.entity.MarkerRewardResult
import com.runnect.runnect.domain.repository.MarkerQuotaRepository
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

class MarkerQuotaRepositoryImpl @Inject constructor(
private val remoteMarkerQuotaDataSource: RemoteMarkerQuotaDataSource
) : MarkerQuotaRepository {

override suspend fun getMarkerQuota(): Flow<Result<MarkerQuota>> =
remoteMarkerQuotaDataSource.getMarkerQuota().mapToFlowResult {
it.toMarkerQuota()
}

override suspend fun consumeMarkerQuota(amount: Int): Flow<Result<MarkerQuota>> =
remoteMarkerQuotaDataSource.consumeMarkerQuota(amount = amount).mapToFlowResult {
it.toMarkerQuota()
}

override suspend fun grantMarkerReward(
amount: Int,
rewardTransactionId: String
): Flow<Result<MarkerRewardResult>> =
remoteMarkerQuotaDataSource.grantMarkerReward(
amount = amount,
rewardTransactionId = rewardTransactionId
).mapToFlowResult {
it.toMarkerRewardResult()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.runnect.runnect.data.service

import com.runnect.runnect.data.dto.request.RequestConsumeMarkerQuota
import com.runnect.runnect.data.dto.request.RequestGrantMarkerReward
import com.runnect.runnect.data.dto.response.ResponseGrantMarkerReward
import com.runnect.runnect.data.dto.response.ResponseMarkerQuota
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST

interface MarkerQuotaService {

@GET("/api/marker-quota")
suspend fun getMarkerQuota(): Result<ResponseMarkerQuota>

@POST("/api/marker-quota/consume")
suspend fun consumeMarkerQuota(
@Body requestConsumeMarkerQuota: RequestConsumeMarkerQuota,
): Result<ResponseMarkerQuota>

@POST("/api/marker-quota/reward")
suspend fun grantMarkerReward(
@Body requestGrantMarkerReward: RequestGrantMarkerReward,
): Result<ResponseGrantMarkerReward>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.runnect.runnect.data.source.remote

import com.runnect.runnect.data.dto.request.RequestConsumeMarkerQuota
import com.runnect.runnect.data.dto.request.RequestGrantMarkerReward
import com.runnect.runnect.data.service.MarkerQuotaService
import javax.inject.Inject

class RemoteMarkerQuotaDataSource @Inject constructor(
private val markerQuotaService: MarkerQuotaService,
) {
suspend fun getMarkerQuota() = markerQuotaService.getMarkerQuota()

suspend fun consumeMarkerQuota(amount: Int) =
markerQuotaService.consumeMarkerQuota(RequestConsumeMarkerQuota(amount = amount))

suspend fun grantMarkerReward(amount: Int, rewardTransactionId: String) =
markerQuotaService.grantMarkerReward(
RequestGrantMarkerReward(amount = amount, rewardTransactionId = rewardTransactionId)
)
}
5 changes: 5 additions & 0 deletions app/src/main/java/com/runnect/runnect/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.runnect.runnect.domain.repository.BannerRepository
import com.runnect.runnect.domain.repository.CourseRepository
import com.runnect.runnect.domain.repository.DepartureSearchRepository
import com.runnect.runnect.domain.repository.LoginRepository
import com.runnect.runnect.domain.repository.MarkerQuotaRepository
import com.runnect.runnect.domain.repository.ReverseGeocodingRepository
import com.runnect.runnect.domain.repository.StorageRepository
import com.runnect.runnect.domain.repository.UserRepository
Expand Down Expand Up @@ -47,4 +48,8 @@ interface RepositoryModule {
@Singleton
@Binds
fun bindBannerRepository(bannerRepositoryImpl: BannerRepositoryImpl): BannerRepository

@Singleton
@Binds
fun bindMarkerQuotaRepository(markerQuotaRepositoryImpl: MarkerQuotaRepositoryImpl): MarkerQuotaRepository
}
6 changes: 6 additions & 0 deletions app/src/main/java/com/runnect/runnect/di/ServiceModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.runnect.runnect.di
import com.runnect.runnect.data.service.BannerService
import com.runnect.runnect.data.service.CourseService
import com.runnect.runnect.data.service.LoginService
import com.runnect.runnect.data.service.MarkerQuotaService
import com.runnect.runnect.data.service.ReverseGeocodingService
import com.runnect.runnect.data.service.SearchService
import com.runnect.runnect.data.service.UserService
Expand Down Expand Up @@ -46,4 +47,9 @@ object ServiceModule {
@Provides
fun providePBannerService(@RetrofitModule.RetrofitV2 retrofitV2: Retrofit) =
retrofitV2.create(BannerService::class.java)

@Singleton
@Provides
fun provideMarkerQuotaService(@RetrofitModule.RetrofitV2 retrofitV2: Retrofit) =
retrofitV2.create(MarkerQuotaService::class.java)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.runnect.runnect.domain.entity

data class MarkerQuota(
val balance: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.runnect.runnect.domain.entity

data class MarkerRewardResult(
val granted: Boolean,
val balance: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.runnect.runnect.domain.repository

import com.runnect.runnect.domain.entity.MarkerQuota
import com.runnect.runnect.domain.entity.MarkerRewardResult
import kotlinx.coroutines.flow.Flow

interface MarkerQuotaRepository {

suspend fun getMarkerQuota(): Flow<Result<MarkerQuota>>

suspend fun consumeMarkerQuota(amount: Int): Flow<Result<MarkerQuota>>

suspend fun grantMarkerReward(amount: Int, rewardTransactionId: String): Flow<Result<MarkerRewardResult>>
}
Loading
Loading