From d5519d3e8902db252ac7bdfe1772ff365e04f890 Mon Sep 17 00:00:00 2001 From: juhwankim-dev Date: Sun, 12 Oct 2025 21:13:16 +0900 Subject: [PATCH 01/14] =?UTF-8?q?=EA=B2=B0=EC=A0=9C=20=EC=A7=84=ED=96=89?= =?UTF-8?q?=20=EC=A4=91=20=EC=97=90=EB=9F=AC=20=EB=B0=9C=EC=83=9D=EC=8B=9C?= =?UTF-8?q?=20=ED=8C=9D=EC=97=85=EC=9C=BC=EB=A1=9C=20=EC=95=88=EB=82=B4=20?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/SubscriptionPromotionBottomSheet.kt | 28 +++++++++++--- .../presentation/ui/billing/BillingEvent.kt | 2 +- .../ui/billing/BillingViewModel.kt | 14 +++---- .../ui/purchase/PurchaseFragment.kt | 37 +++++++++++++------ presentation/src/main/res/values/strings.xml | 1 + 5 files changed, 56 insertions(+), 26 deletions(-) diff --git a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/SubscriptionPromotionBottomSheet.kt b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/SubscriptionPromotionBottomSheet.kt index 6f182d34..321c2dc6 100644 --- a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/SubscriptionPromotionBottomSheet.kt +++ b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/SubscriptionPromotionBottomSheet.kt @@ -17,10 +17,12 @@ import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.nextroom.nextroom.presentation.NavGraphDirections import com.nextroom.nextroom.presentation.R +import com.nextroom.nextroom.presentation.common.NROneButtonDialog import com.nextroom.nextroom.presentation.databinding.BottomSheetSubscriptionPromotionBinding import com.nextroom.nextroom.presentation.databinding.ItemBenefitBinding import com.nextroom.nextroom.presentation.extension.dpToPx import com.nextroom.nextroom.presentation.extension.repeatOnStarted +import com.nextroom.nextroom.presentation.extension.safeNavigate import com.nextroom.nextroom.presentation.extension.snackbar import com.nextroom.nextroom.presentation.extension.toast import com.nextroom.nextroom.presentation.ui.billing.BillingEvent @@ -95,11 +97,15 @@ class SubscriptionPromotionBottomSheet : BottomSheetDialogFragment() { binding.acbSubscribe.setOnClickListener { viewModel.container.stateFlow.value.plan.plans.firstOrNull()?.let { binding.pbLoading.isVisible = true - billingViewModel.buyPlans( - productId = it.subscriptionProductId, - tag = "", - upDowngrade = false, - ) + try { + billingViewModel.buyPlans( + productId = it.subscriptionProductId, + tag = "", + upDowngrade = false, + ) + } catch (e: Exception) { + showErrorDialog(e.message ?: "") + } } } binding.ivClose.setOnClickListener { @@ -167,6 +173,18 @@ class SubscriptionPromotionBottomSheet : BottomSheetDialogFragment() { } } + private fun showErrorDialog(errorText: String) { + NavGraphDirections + .moveToNrOneButtonDialog( + NROneButtonDialog.NROneButtonArgument( + title = getString(R.string.dialog_noti), + message = getString(R.string.error_something), + btnText = getString(R.string.text_confirm), + errorText = errorText + ) + ).also { findNavController().safeNavigate(it) } + } + data class Benefit( val title: String, val desc: String, diff --git a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/billing/BillingEvent.kt b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/billing/BillingEvent.kt index 50b8b7f2..9416eaa3 100644 --- a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/billing/BillingEvent.kt +++ b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/billing/BillingEvent.kt @@ -2,5 +2,5 @@ package com.nextroom.nextroom.presentation.ui.billing sealed interface BillingEvent { data object PurchaseAcknowledged : BillingEvent - data class PurchaseFailed(val purchaseState: Int) : BillingEvent + data class PurchaseFailed(val errorMessage: String = "", val purchaseState: Int? = null) : BillingEvent } diff --git a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/billing/BillingViewModel.kt b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/billing/BillingViewModel.kt index 0b3bf003..9070d947 100644 --- a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/billing/BillingViewModel.kt +++ b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/billing/BillingViewModel.kt @@ -197,18 +197,16 @@ class BillingViewModel Constants.MEMBERSHIP_PRODUCT -> membershipProductWithProductDetails.value else -> null }?.also { productDetails -> - productDetails.subscriptionOfferDetails?.let { offerDetailsList -> - retrieveEligibleOffers( - offerDetails = offerDetailsList, - tag = tag, - ) - }.let { offers -> - offers?.let { leastPricedOfferToken(it) }.toString() + retrieveEligibleOffers( + offerDetails = requireNotNull(productDetails.subscriptionOfferDetails), + tag = tag, + ).let { offers -> + leastPricedOfferToken(offers) }.also { offerToken -> launchFlow(upDowngrade, offerToken, productDetails) } } ?: run { - Timber.e("Could not find product details.") + throw Exception("Could not find product details.") } } diff --git a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/purchase/PurchaseFragment.kt b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/purchase/PurchaseFragment.kt index cecdb978..363b6cab 100644 --- a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/purchase/PurchaseFragment.kt +++ b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/purchase/PurchaseFragment.kt @@ -10,12 +10,12 @@ import androidx.navigation.fragment.findNavController import com.nextroom.nextroom.presentation.NavGraphDirections import com.nextroom.nextroom.presentation.R import com.nextroom.nextroom.presentation.base.BaseFragment +import com.nextroom.nextroom.presentation.common.NROneButtonDialog import com.nextroom.nextroom.presentation.databinding.FragmentPurchaseBinding import com.nextroom.nextroom.presentation.extension.repeatOnStarted import com.nextroom.nextroom.presentation.extension.safeNavigate import com.nextroom.nextroom.presentation.extension.snackbar import com.nextroom.nextroom.presentation.extension.strikeThrow -import com.nextroom.nextroom.presentation.extension.toast import com.nextroom.nextroom.presentation.ui.billing.BillingEvent import com.nextroom.nextroom.presentation.ui.billing.BillingViewModel import dagger.hilt.android.AndroidEntryPoint @@ -48,11 +48,15 @@ class PurchaseFragment : BaseFragment(FragmentPurchaseB binding.btnSubscribe.setOnClickListener { (viewModel.uiState.value as? PurchaseViewModel.UiState.Loaded)?.let { loaded -> binding.pbLoading.isVisible = true // TODO JH: 개선 - billingViewModel.buyPlans( - productId = loaded.subscriptionProductId, - tag = "", - upDowngrade = false, - ) + try { + billingViewModel.buyPlans( + productId = loaded.subscriptionProductId, + tag = "", + upDowngrade = false, + ) + } catch (e: Exception) { + showErrorDialog(errorText = e.message ?: "") + } } } } @@ -90,12 +94,9 @@ class PurchaseFragment : BaseFragment(FragmentPurchaseB } is BillingEvent.PurchaseFailed -> { - toast( - getString( - R.string.purchase_error_message, - event.purchaseState, - ), - ) + val errorText = event.errorMessage + "\n" + + event.purchaseState?.let { getString(R.string.text_error_code, it) } + showErrorDialog(errorText) binding.pbLoading.isVisible = false // TODO JH: 개선 } } @@ -122,4 +123,16 @@ class PurchaseFragment : BaseFragment(FragmentPurchaseB } } } + + private fun showErrorDialog(errorText: String) { + NavGraphDirections + .moveToNrOneButtonDialog( + NROneButtonDialog.NROneButtonArgument( + title = getString(R.string.dialog_noti), + message = getString(R.string.error_something), + btnText = getString(R.string.text_confirm), + errorText = errorText + ) + ).also { findNavController().safeNavigate(it) } + } } diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index 5309fc76..a0ce21fd 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -229,4 +229,5 @@ 에 게임이 종료됩니다. 시간 수정 + 에러 코드: %d \ No newline at end of file From 5851701d2cd03f838744131bdfe0c2e675a33b63 Mon Sep 17 00:00:00 2001 From: juhwankim-dev Date: Sun, 12 Oct 2025 21:13:49 +0900 Subject: [PATCH 02/14] version up (1.4.6 -> 1.4.7) --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0a22b49c..475b8de2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,8 +3,8 @@ minSdk = "24" review = "2.0.1" reviewKtx = "2.0.1" targetSdk = "34" -versionCode = "61" -versionName = "1.4.6" +versionCode = "64" +versionName = "1.4.7" compileSdk = "34" targetJvm = "17" kotlin = "1.9.10" From 6a1bdc17433b7d940fb6c7355a6fbecb422e8910 Mon Sep 17 00:00:00 2001 From: juhwankim-dev Date: Sun, 12 Oct 2025 23:51:03 +0900 Subject: [PATCH 03/14] =?UTF-8?q?=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20?= =?UTF-8?q?=EA=B2=B0=EC=A0=9C=20=EA=B4=80=EB=A0=A8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 왜? 과거에 참고했던 코드들 중 현재 우리 프로젝트에 필요하지 않음에도 사용되고 있는 코드들이 있어 삭제함. retrieveEligibleOffers: 특정 태그가 붙어있는 Offer를 반환하는 함수. 우리 서비스는 단일 요금제를 제공하고 있고 태그로 구분하고 있지도 않으므로 불필요 leastPricedOfferToken: 가장 저렴한 offer를 반환하는 함수. 우리 서비스는 한 상품에 여러개의 플랜을 제공하고 있지 않으므로 불필요 ex) 월 요금제, 연 요금제 --- .../ui/SubscriptionPromotionBottomSheet.kt | 1 - .../ui/billing/BillingViewModel.kt | 74 ++----------------- .../ui/purchase/PurchaseFragment.kt | 1 - 3 files changed, 5 insertions(+), 71 deletions(-) diff --git a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/SubscriptionPromotionBottomSheet.kt b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/SubscriptionPromotionBottomSheet.kt index 321c2dc6..eabd1f4e 100644 --- a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/SubscriptionPromotionBottomSheet.kt +++ b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/SubscriptionPromotionBottomSheet.kt @@ -100,7 +100,6 @@ class SubscriptionPromotionBottomSheet : BottomSheetDialogFragment() { try { billingViewModel.buyPlans( productId = it.subscriptionProductId, - tag = "", upDowngrade = false, ) } catch (e: Exception) { diff --git a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/billing/BillingViewModel.kt b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/billing/BillingViewModel.kt index 9070d947..7427888d 100644 --- a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/billing/BillingViewModel.kt +++ b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/billing/BillingViewModel.kt @@ -114,63 +114,6 @@ class BillingViewModel ).build() } - /** - * Calculates the lowest priced offer amongst all eligible offers. - * In this implementation the lowest price of all offers' pricing phases is returned. - * It's possible the logic can be implemented differently. - * For example, the lowest average price in terms of month could be returned instead. - * - * @param offerDetails List of of eligible offers and base plans. - * - * @return the offer id token of the lowest priced offer. - * - */ - private fun leastPricedOfferToken( - offerDetails: List, - ): String { - var offerToken = String() - var leastPricedOffer: ProductDetails.SubscriptionOfferDetails - var lowestPrice = Int.MAX_VALUE - - if (offerDetails.isNotEmpty()) { - for (offer in offerDetails) { - for (price in offer.pricingPhases.pricingPhaseList) { - if (price.priceAmountMicros < lowestPrice) { - lowestPrice = price.priceAmountMicros.toInt() - leastPricedOffer = offer - offerToken = leastPricedOffer.offerToken - } - } - } - } - return offerToken - - TODO("Replace this with least average priced offer implementation") - } - - /** - * Retrieves all eligible base plans and offers using tags from ProductDetails. - * - * @param offerDetails offerDetails from a ProductDetails returned by the library. - * @param tag string representing tags associated with offers and base plans. - * - * @return the eligible offers and base plans in a list. - * - */ - private fun retrieveEligibleOffers( - offerDetails: MutableList, - tag: String, - ): - List { - val eligibleOffers = emptyList().toMutableList() - offerDetails.forEach { offerDetail -> - if (offerDetail.offerTags.contains(tag)) { - eligibleOffers.add(offerDetail) - } - } - return eligibleOffers - } - // 이미 구독 중인 상품이 있는지 체크 private fun purchaseForProduct(purchases: List?, product: String) = purchases?.firstOrNull { it.products.first() == product } @@ -182,11 +125,10 @@ class BillingViewModel /** * 요금제 구매 * - * @param tag: 요금제와 관련된 태그를 나타내는 문자열 * @param productId: 구매 하려는 상품의 id * @param upDowngrade: 구매가 업그레이드 또는 다운그레이드인지, 요금제를 전환하려는 경우에 true */ - fun buyPlans(tag: String, productId: String, upDowngrade: Boolean) { + fun buyPlans(productId: String, upDowngrade: Boolean) { val isProductOnDevice = deviceHasGooglePlaySubscription(purchases.value, productId) if (isProductOnDevice) { Timber.d("The user already owns this item: $productId") @@ -196,17 +138,11 @@ class BillingViewModel when (productId) { Constants.MEMBERSHIP_PRODUCT -> membershipProductWithProductDetails.value else -> null - }?.also { productDetails -> - retrieveEligibleOffers( - offerDetails = requireNotNull(productDetails.subscriptionOfferDetails), - tag = tag, - ).let { offers -> - leastPricedOfferToken(offers) - }.also { offerToken -> - launchFlow(upDowngrade, offerToken, productDetails) - } + }?.let { productDetails -> + val offerToken = requireNotNull(productDetails.subscriptionOfferDetails?.firstOrNull()?.offerToken) + launchFlow(upDowngrade, offerToken, productDetails) } ?: run { - throw Exception("Could not find product details.") + throw Exception("Could not find product details. productId: $productId") } } diff --git a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/purchase/PurchaseFragment.kt b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/purchase/PurchaseFragment.kt index 363b6cab..f319c39f 100644 --- a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/purchase/PurchaseFragment.kt +++ b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/purchase/PurchaseFragment.kt @@ -51,7 +51,6 @@ class PurchaseFragment : BaseFragment(FragmentPurchaseB try { billingViewModel.buyPlans( productId = loaded.subscriptionProductId, - tag = "", upDowngrade = false, ) } catch (e: Exception) { From cfc449ed40f95c564c4245dc5bb183f055b1f9c8 Mon Sep 17 00:00:00 2001 From: juhwankim-dev Date: Sun, 12 Oct 2025 23:52:33 +0900 Subject: [PATCH 04/14] version code up (64 -> 65) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 475b8de2..4eafa388 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ minSdk = "24" review = "2.0.1" reviewKtx = "2.0.1" targetSdk = "34" -versionCode = "64" +versionCode = "65" versionName = "1.4.7" compileSdk = "34" targetJvm = "17" From c5a6d62df406f148cba88ec2fa27efc5294ad5c4 Mon Sep 17 00:00:00 2001 From: juhwankim-dev Date: Wed, 12 Nov 2025 00:15:06 +0900 Subject: [PATCH 05/14] =?UTF-8?q?NR-120=20debug=20=EB=B9=8C=EB=93=9C?= =?UTF-8?q?=EC=97=90=EC=84=9C=EB=A7=8C=20flipper=EB=A5=BC=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 왜? 지금은 flipper interceptor를 추가하고, application에서 초기 설정을 하기 위해 debug, release 빌드 옵션에 상관없이 flipper를 사용하고 있다. debug에서만 flipper를 사용할 수 있도록 수정이 필요함 어떻게? - source sets를 사용해 빌드 옵션에 따라 참조할 파일을 분리 - debug 빌드때 참조할 파일에서 flipper interceptor를 반환하는 함수와 초기세팅 함수를 만듬 - app 모듈 gradle에서는 더이상 flipper를 추가할 필요가 없으므로 삭제 --- app/build.gradle.kts | 3 -- .../nextroom/nextroom/NextRoomApplication.kt | 30 +------------ data/build.gradle.kts | 6 +++ .../nextroom/nextroom/FlavorExtraFunction.kt | 45 +++++++++++++++++++ .../nextroom/data/di/NetworkModule.kt | 36 +++++++++++---- .../nextroom/nextroom/FlavorExtraFunction.kt | 17 +++++++ 6 files changed, 98 insertions(+), 39 deletions(-) create mode 100644 data/src/debug/java/com/nextroom/nextroom/FlavorExtraFunction.kt create mode 100644 data/src/release/java/com/nextroom/nextroom/FlavorExtraFunction.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 45ac2e69..18756fe7 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -78,9 +78,6 @@ dependencies { implementation(libs.timber) implementation(libs.billing) - debugImplementation(libs.bundles.flipper) - releaseImplementation(libs.flipper.noop) - implementation(libs.hilt.android) kapt(libs.hilt.compiler) } diff --git a/app/src/main/java/com/nextroom/nextroom/NextRoomApplication.kt b/app/src/main/java/com/nextroom/nextroom/NextRoomApplication.kt index 2a56218a..e6387b85 100644 --- a/app/src/main/java/com/nextroom/nextroom/NextRoomApplication.kt +++ b/app/src/main/java/com/nextroom/nextroom/NextRoomApplication.kt @@ -1,13 +1,6 @@ package com.nextroom.nextroom import android.app.Application -import com.facebook.flipper.android.AndroidFlipperClient -import com.facebook.flipper.android.utils.FlipperUtils -import com.facebook.flipper.plugins.inspector.DescriptorMapping -import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin -import com.facebook.flipper.plugins.network.NetworkFlipperPlugin -import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin -import com.facebook.soloader.SoLoader import dagger.hilt.android.HiltAndroidApp import timber.log.Timber import javax.inject.Inject @@ -15,32 +8,13 @@ import javax.inject.Inject @HiltAndroidApp class NextRoomApplication : Application() { @Inject - lateinit var flipperNetworkPlugin: NetworkFlipperPlugin + lateinit var flavorExtraFunction: FlavorExtraFunction override fun onCreate() { super.onCreate() if (BuildConfig.DEBUG) { Timber.plant(Timber.DebugTree()) - } - - setDebugTool() - } - - private fun setDebugTool() { - SoLoader.init(this, false) - - if (BuildConfig.DEBUG && FlipperUtils.shouldEnableFlipper(this)) { - val client = AndroidFlipperClient.getInstance(this) - client.addPlugin(InspectorFlipperPlugin(this, DescriptorMapping.withDefaults())) - client.addPlugin( - InspectorFlipperPlugin( - applicationContext, - DescriptorMapping.withDefaults(), - ), - ) - client.addPlugin(SharedPreferencesFlipperPlugin(this, "app-settings.json")) - client.addPlugin(flipperNetworkPlugin) - client.start() + flavorExtraFunction.initializeFlipper() } } } diff --git a/data/build.gradle.kts b/data/build.gradle.kts index a4e558f5..37efe54b 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -46,6 +46,12 @@ android { buildFeatures { buildConfig = true } + sourceSets.getByName("debug") { + java.setSrcDirs(listOf("src/debug/java")) + } + sourceSets.getByName("release") { + java.setSrcDirs(listOf("src/release/java")) + } } dependencies { diff --git a/data/src/debug/java/com/nextroom/nextroom/FlavorExtraFunction.kt b/data/src/debug/java/com/nextroom/nextroom/FlavorExtraFunction.kt new file mode 100644 index 00000000..bd9ff609 --- /dev/null +++ b/data/src/debug/java/com/nextroom/nextroom/FlavorExtraFunction.kt @@ -0,0 +1,45 @@ +package com.nextroom.nextroom + +import android.content.Context +import com.facebook.flipper.android.AndroidFlipperClient +import com.facebook.flipper.android.utils.FlipperUtils +import com.facebook.flipper.plugins.inspector.DescriptorMapping +import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin +import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor +import com.facebook.flipper.plugins.network.NetworkFlipperPlugin +import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin +import com.facebook.soloader.SoLoader +import com.nextroom.nextroom.data.BuildConfig +import okhttp3.Interceptor +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class FlavorExtraFunction @Inject constructor( + private val context: Context, +) { + private lateinit var flipperNetworkPlugin: NetworkFlipperPlugin + + fun initializeFlipper() { + SoLoader.init(context, false) + + if (BuildConfig.DEBUG && FlipperUtils.shouldEnableFlipper(context)) { + flipperNetworkPlugin = NetworkFlipperPlugin() + val client = AndroidFlipperClient.getInstance(context) + client.addPlugin(InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())) + client.addPlugin( + InspectorFlipperPlugin( + context, + DescriptorMapping.withDefaults(), + ), + ) + client.addPlugin(SharedPreferencesFlipperPlugin(context, "app-settings.json")) + client.addPlugin(flipperNetworkPlugin) + client.start() + } + } + + fun getFlipperInterceptor(): Interceptor { + return FlipperOkhttpInterceptor(flipperNetworkPlugin, true) + } +} \ No newline at end of file diff --git a/data/src/main/java/com/nextroom/nextroom/data/di/NetworkModule.kt b/data/src/main/java/com/nextroom/nextroom/data/di/NetworkModule.kt index a7088530..192c2b63 100644 --- a/data/src/main/java/com/nextroom/nextroom/data/di/NetworkModule.kt +++ b/data/src/main/java/com/nextroom/nextroom/data/di/NetworkModule.kt @@ -1,7 +1,7 @@ package com.nextroom.nextroom.data.di -import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor -import com.facebook.flipper.plugins.network.NetworkFlipperPlugin +import android.content.Context +import com.nextroom.nextroom.FlavorExtraFunction import com.nextroom.nextroom.data.BuildConfig import com.nextroom.nextroom.data.datasource.AuthDataSource import com.nextroom.nextroom.data.datasource.TokenDataSource @@ -12,7 +12,9 @@ import com.nextroom.nextroom.data.network.ResultCallAdapterFactory import dagger.Module import dagger.Provides import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent +import okhttp3.Interceptor import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit @@ -76,7 +78,7 @@ object NetworkModule { fun provideAuthOkHttpClient( authInterceptor: AuthInterceptor, authAuthenticator: AuthAuthenticator, - flipperPlugin: NetworkFlipperPlugin, + flipperInterceptor: Interceptor?, ): OkHttpClient { val loggingInterceptor = HttpLoggingInterceptor().apply { level = if (BuildConfig.DEBUG) { @@ -91,7 +93,11 @@ object NetworkModule { .authenticator(authAuthenticator) .addInterceptor(authInterceptor) .addInterceptor(loggingInterceptor) - .addInterceptor(FlipperOkhttpInterceptor(flipperPlugin, true)) + .apply { + flipperInterceptor?.let { + addInterceptor(it) + } + } .build() } @@ -99,7 +105,7 @@ object NetworkModule { @Provides @Named("defaultOkHttpClient") fun provideDefaultOkHttpClient( - flipperPlugin: NetworkFlipperPlugin, + flipperInterceptor: Interceptor?, ): OkHttpClient { val loggingInterceptor = HttpLoggingInterceptor().apply { level = if (BuildConfig.DEBUG) { @@ -112,7 +118,11 @@ object NetworkModule { .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .addInterceptor(loggingInterceptor) - .addNetworkInterceptor(FlipperOkhttpInterceptor(flipperPlugin)) + .apply { + flipperInterceptor?.let { + addInterceptor(it) + } + } .build() } @@ -134,7 +144,17 @@ object NetworkModule { @Singleton @Provides - fun provideNetworkFlipperPlugin(): NetworkFlipperPlugin { - return NetworkFlipperPlugin() + fun provideFlipperInterceptor( + flavorExtraFunction: FlavorExtraFunction, + ): Interceptor? { + return flavorExtraFunction.getFlipperInterceptor() + } + + @Singleton + @Provides + fun provideFlavorExtraFunction( + @ApplicationContext context: Context, + ): FlavorExtraFunction { + return FlavorExtraFunction(context) } } diff --git a/data/src/release/java/com/nextroom/nextroom/FlavorExtraFunction.kt b/data/src/release/java/com/nextroom/nextroom/FlavorExtraFunction.kt new file mode 100644 index 00000000..b6e379f8 --- /dev/null +++ b/data/src/release/java/com/nextroom/nextroom/FlavorExtraFunction.kt @@ -0,0 +1,17 @@ +package com.nextroom.nextroom + +import android.content.Context +import okhttp3.Interceptor +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class FlavorExtraFunction @Inject constructor( + private val context: Context, +) { + fun initializeFlipper() { + // do nothing + } + + fun getFlipperInterceptor(): Interceptor? = null +} \ No newline at end of file From a09ccaeb501ffe3cfa4b1fd7b778d28471a81f9a Mon Sep 17 00:00:00 2001 From: juhwankim-dev Date: Fri, 14 Nov 2025 22:32:40 +0900 Subject: [PATCH 06/14] =?UTF-8?q?=ED=99=98=EA=B2=BD=EB=B3=80=EC=88=98=20?= =?UTF-8?q?=EC=9E=AC=EC=84=A4=EC=A0=95=20=ED=9B=84=20feature=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=EC=97=90=EC=84=9C=20ci/cd=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index b0abe117..7bf33751 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -2,7 +2,7 @@ name: Android CI CD on: push: - branches: [ "main", "develop", "release" ] + branches: [ "main", "develop", "release", "feature" ] pull_request: branches: [ "main", "develop", "release" ] From a401f620a04b6927732c58b7fd92af002e5e58a2 Mon Sep 17 00:00:00 2001 From: juhwankim-dev Date: Fri, 14 Nov 2025 22:59:49 +0900 Subject: [PATCH 07/14] =?UTF-8?q?feature=EB=A1=9C=20=EC=8B=9C=EC=9E=91?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EB=B8=8C=EB=9E=9C=EC=B9=98=20=EB=AA=A8?= =?UTF-8?q?=EB=91=90=20ci/cd=EB=A5=BC=20=EC=88=98=ED=96=89=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 7bf33751..b3b5c23e 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -2,7 +2,7 @@ name: Android CI CD on: push: - branches: [ "main", "develop", "release", "feature" ] + branches: [ "main", "develop", "release", "feature/*" ] pull_request: branches: [ "main", "develop", "release" ] From a1cd528fac0c20fe810a893b14b6eca1392f366c Mon Sep 17 00:00:00 2001 From: juhwankim-dev Date: Fri, 14 Nov 2025 23:14:39 +0900 Subject: [PATCH 08/14] =?UTF-8?q?(=ED=85=8C=EC=8A=A4=ED=8A=B8)=20feature?= =?UTF-8?q?=EB=A1=9C=20=EC=8B=9C=EC=9E=91=ED=95=98=EB=8A=94=20=EB=B8=8C?= =?UTF-8?q?=EB=9E=9C=EC=B9=98=EB=A9=B4=20firebase=20distribution=EC=97=90?= =?UTF-8?q?=20=EC=98=AC=EB=A6=AC=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/android.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index b3b5c23e..072f63f1 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -70,7 +70,7 @@ jobs: run: ./gradlew bundleRelease --stacktrace - name: Upload Debug APK - if: github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/release') + if: github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/release' || github.ref == 'refs/heads/feature/*' ) uses: actions/upload-artifact@v4 with: name: debug @@ -84,7 +84,7 @@ jobs: path: ./app/build/outputs/bundle/release/app-release.aab - name: Upload apk to Firebase App Distribution - if: github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/release') + if: github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/release' || github.ref == 'refs/heads/feature/*') uses: wzieba/Firebase-Distribution-Github-Action@v1 with: appId: ${{ secrets.FIREBASE_APP_ID }} From 4b62fe3a0889e8eef9722ad94940cc0884ce3b7d Mon Sep 17 00:00:00 2001 From: juhwankim-dev Date: Fri, 14 Nov 2025 23:32:52 +0900 Subject: [PATCH 09/14] =?UTF-8?q?(=ED=85=8C=EC=8A=A4=ED=8A=B8)=20debug,=20?= =?UTF-8?q?distribution=20job=EC=97=90=20if=20=EC=A1=B0=EA=B1=B4=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/android.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 072f63f1..c3c30951 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -70,7 +70,6 @@ jobs: run: ./gradlew bundleRelease --stacktrace - name: Upload Debug APK - if: github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/release' || github.ref == 'refs/heads/feature/*' ) uses: actions/upload-artifact@v4 with: name: debug @@ -84,7 +83,6 @@ jobs: path: ./app/build/outputs/bundle/release/app-release.aab - name: Upload apk to Firebase App Distribution - if: github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/release' || github.ref == 'refs/heads/feature/*') uses: wzieba/Firebase-Distribution-Github-Action@v1 with: appId: ${{ secrets.FIREBASE_APP_ID }} From b7f65fc45dde7d848d5adff1d1c675822e33bf8a Mon Sep 17 00:00:00 2001 From: juhwankim-dev Date: Sat, 15 Nov 2025 00:09:47 +0900 Subject: [PATCH 10/14] =?UTF-8?q?(=ED=85=8C=EC=8A=A4=ED=8A=B8)=20firebase?= =?UTF-8?q?=EC=97=90=20=EC=95=B1=20=EC=97=85=EB=A1=9C=EB=93=9C=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=EC=8B=9C=20=EC=8A=AC=EB=9E=99=20=EC=B1=84=EB=84=90?= =?UTF-8?q?=EC=97=90=20=EC=95=8C=EB=A6=BC=20=EA=B0=80=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/android.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index c3c30951..bb6b5aa9 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -90,6 +90,17 @@ jobs: groups: testers file: app/build/outputs/apk/debug/app-debug.apk + - name: Notify Slack about new distribution + if: github.event_name == 'push' + run: | + curl -X POST -H 'Content-type: application/json' \ + --data "{ + \"text\": \"🔥 Firebase Distribution 업로드 완료! \n🔧 브랜치: ${GITHUB_REF##*/}\n🔗 커밋: ${GITHUB_SHA}\" + }" \ + SLACK_WEBHOOK_URL_FIREBASE_DISTRIBUTION + env: + SLACK_WEBHOOK_URL_FIREBASE_DISTRIBUTION: ${{ secrets.SLACK_WEBHOOK_URL_FIREBASE_DISTRIBUTION }} + - name: Publish to Play Store if: github.event_name == 'push' && github.ref == 'refs/heads/main' uses: r0adkll/upload-google-play@v1 From d8ec120a8623a19f1621a01434774ca2e850fd6d Mon Sep 17 00:00:00 2001 From: juhwankim-dev Date: Sat, 15 Nov 2025 00:18:30 +0900 Subject: [PATCH 11/14] =?UTF-8?q?(=ED=85=8C=EC=8A=A4=ED=8A=B8)=20$=20?= =?UTF-8?q?=EB=AC=B8=EC=9E=90=20=EB=B9=A0=EC=A7=84=EA=B2=83=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=EC=9D=BC=EB=B6=80=20job=20=EC=A3=BC?= =?UTF-8?q?=EC=84=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/android.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index bb6b5aa9..0ffec1db 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -60,8 +60,8 @@ jobs: - name: Build clean run: ./gradlew clean - - name: Run Android lint - run: ./gradlew lint + # - name: Run Android lint + # run: ./gradlew lint - name: Build assemble debug apk run: ./gradlew assembleDebug --stacktrace @@ -75,12 +75,12 @@ jobs: name: debug path: ./app/build/outputs/apk/debug/app-debug.apk - - name: Upload Release APK - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: actions/upload-artifact@v4 - with: - name: release - path: ./app/build/outputs/bundle/release/app-release.aab + # - name: Upload Release APK + # if: github.event_name == 'push' && github.ref == 'refs/heads/main' + # uses: actions/upload-artifact@v4 + # with: + # name: release + # path: ./app/build/outputs/bundle/release/app-release.aab - name: Upload apk to Firebase App Distribution uses: wzieba/Firebase-Distribution-Github-Action@v1 @@ -97,7 +97,7 @@ jobs: --data "{ \"text\": \"🔥 Firebase Distribution 업로드 완료! \n🔧 브랜치: ${GITHUB_REF##*/}\n🔗 커밋: ${GITHUB_SHA}\" }" \ - SLACK_WEBHOOK_URL_FIREBASE_DISTRIBUTION + "$SLACK_WEBHOOK_URL_FIREBASE_DISTRIBUTION" env: SLACK_WEBHOOK_URL_FIREBASE_DISTRIBUTION: ${{ secrets.SLACK_WEBHOOK_URL_FIREBASE_DISTRIBUTION }} From a1d95155ad41b4913b89bc45bb834564ace38e34 Mon Sep 17 00:00:00 2001 From: juhwankim-dev Date: Sat, 15 Nov 2025 00:24:58 +0900 Subject: [PATCH 12/14] =?UTF-8?q?(=ED=85=8C=EC=8A=A4=ED=8A=B8)=20Build=20a?= =?UTF-8?q?ssemble=20release=20aab=20=EC=A3=BC=EC=84=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/android.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 0ffec1db..56f3ff18 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -66,8 +66,8 @@ jobs: - name: Build assemble debug apk run: ./gradlew assembleDebug --stacktrace - - name: Build assemble release aab - run: ./gradlew bundleRelease --stacktrace + # - name: Build assemble release aab + # run: ./gradlew bundleRelease --stacktrace - name: Upload Debug APK uses: actions/upload-artifact@v4 From e9e5efca82eb767134522af3a32f13b3d4f75360 Mon Sep 17 00:00:00 2001 From: juhwankim-dev Date: Sat, 15 Nov 2025 00:40:53 +0900 Subject: [PATCH 13/14] =?UTF-8?q?(=ED=85=8C=EC=8A=A4=ED=8A=B8)=20startsWit?= =?UTF-8?q?h=EB=A1=9C=20=EB=B8=8C=EB=9E=9C=EC=B9=98=20=EA=B5=AC=EB=B6=84?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/android.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 56f3ff18..63f20e19 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -83,6 +83,10 @@ jobs: # path: ./app/build/outputs/bundle/release/app-release.aab - name: Upload apk to Firebase App Distribution + if: github.event_name == 'push' && ( + github.ref == 'refs/heads/develop' || + startsWith(github.ref, 'refs/heads/feature/') + ) uses: wzieba/Firebase-Distribution-Github-Action@v1 with: appId: ${{ secrets.FIREBASE_APP_ID }} From e3f26ceb7da3386202b61b6ec148d64b2ae32e6b Mon Sep 17 00:00:00 2001 From: juhwankim-dev Date: Sat, 15 Nov 2025 00:49:41 +0900 Subject: [PATCH 14/14] =?UTF-8?q?(=ED=85=8C=EC=8A=A4=ED=8A=B8)=20pull=20re?= =?UTF-8?q?quest=20=ED=95=A0=EB=95=8C=20job=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/android.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 63f20e19..d748086e 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -4,7 +4,7 @@ on: push: branches: [ "main", "develop", "release", "feature/*" ] pull_request: - branches: [ "main", "develop", "release" ] + branches: [ "main", "develop", "release", "feature/*" ] jobs: build: @@ -83,7 +83,7 @@ jobs: # path: ./app/build/outputs/bundle/release/app-release.aab - name: Upload apk to Firebase App Distribution - if: github.event_name == 'push' && ( + if: github.event_name == 'pull_request' && ( github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/heads/feature/') )