diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f41bec51..2008ace7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -86,14 +86,15 @@ android:name=".presentation.scheme.SchemeActivity" android:exported="true"> - + diff --git a/app/src/main/java/com/runnect/runnect/presentation/detail/CourseDetailActivity.kt b/app/src/main/java/com/runnect/runnect/presentation/detail/CourseDetailActivity.kt index edbb0cc4..c51a9de9 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/detail/CourseDetailActivity.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/detail/CourseDetailActivity.kt @@ -3,7 +3,6 @@ package com.runnect.runnect.presentation.detail import android.app.Activity import android.content.Intent import android.graphics.Rect -import android.net.Uri import android.os.Bundle import android.view.MotionEvent import android.view.View @@ -13,8 +12,6 @@ import androidx.activity.viewModels import androidx.core.view.isVisible import androidx.lifecycle.lifecycleScope import coil3.load -import com.google.firebase.dynamiclinks.DynamicLink -import com.google.firebase.dynamiclinks.FirebaseDynamicLinks import com.naver.maps.geometry.LatLng import com.runnect.runnect.R import com.runnect.runnect.binding.BindingActivity @@ -50,7 +47,7 @@ import com.runnect.runnect.util.custom.dialog.RequireLoginDialogFragment import com.runnect.runnect.util.custom.popup.PopupItem import com.runnect.runnect.util.custom.popup.RunnectPopupMenu import com.runnect.runnect.util.custom.toast.RunnectToast -import com.runnect.runnect.util.dynamiclink.RunnectDynamicLink +import com.runnect.runnect.util.link.RunnectShareLink import com.runnect.runnect.util.extension.applyScreenEnterAnimation import com.runnect.runnect.util.extension.applyScreenExitAnimation import com.runnect.runnect.util.extension.getCompatibleSerializableExtra @@ -112,7 +109,7 @@ class CourseDetailActivity : } private fun initCourseIdExtra() { - val idFromLink = intent.getIntExtra(SchemeActivity.EXTRA_FROM_DYNAMIC_LINK, -1) + val idFromLink = intent.getIntExtra(SchemeActivity.EXTRA_FROM_APP_LINK, -1) if (idFromLink != -1) { isFromDeepLink = true publicCourseId = idFromLink @@ -230,49 +227,17 @@ class CourseDetailActivity : private fun initShareButtonClickListener() { binding.btnShare.setOnClickListener { - sendFirebaseDynamicLink( - title = courseDetail.title, - desc = courseDetail.description, - image = courseDetail.image - ) + shareLink("${RunnectShareLink.BASE_URL}?${RunnectShareLink.KEY_PUBLIC_COURSE_ID}=$publicCourseId") Analytics.logClickedItemEvent(EVENT_CLICK_SHARE) } } - private fun sendFirebaseDynamicLink(title: String, desc: String, image: String) { - val link = - "${RunnectDynamicLink.BASE_URL}/?${RunnectDynamicLink.KEY_PUBLIC_COURSE_ID}=$publicCourseId" - - FirebaseDynamicLinks.getInstance().createDynamicLink() - .setLink(Uri.parse(link)) - .setDomainUriPrefix(RunnectDynamicLink.BASE_URL) - .setAndroidParameters(DynamicLink.AndroidParameters.Builder().build()) - .setIosParameters( - DynamicLink.IosParameters.Builder(RunnectDynamicLink.IOS_BUNDLE_ID).build() - ) - .setSocialMetaTagParameters( - DynamicLink.SocialMetaTagParameters.Builder() - .setTitle(title) - .setDescription(desc) - .setImageUrl(Uri.parse(image)) - .build() - ) - .buildShortDynamicLink() - .addOnSuccessListener { result -> - val shortLink = result.shortLink - shareLink(shortLink.toString()) - } - .addOnFailureListener { - it.printStackTrace() - } - } - private fun shareLink(url: String) { val intent = Intent(Intent.ACTION_SEND).apply { - type = RunnectDynamicLink.SEND_INTENT_MIME_TYPE + type = RunnectShareLink.SEND_INTENT_MIME_TYPE putExtra(Intent.EXTRA_TEXT, url) } - startActivity(Intent.createChooser(intent, RunnectDynamicLink.INTENT_CHOOSER_TITLE)) + startActivity(Intent.createChooser(intent, RunnectShareLink.INTENT_CHOOSER_TITLE)) } private fun initShowMoreButtonClickListener() { diff --git a/app/src/main/java/com/runnect/runnect/presentation/scheme/SchemeActivity.kt b/app/src/main/java/com/runnect/runnect/presentation/scheme/SchemeActivity.kt index 5ab78006..a96f97de 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/scheme/SchemeActivity.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/scheme/SchemeActivity.kt @@ -6,7 +6,6 @@ import android.net.Uri import android.os.Bundle import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity -import com.google.firebase.dynamiclinks.FirebaseDynamicLinks import com.runnect.runnect.application.PreferenceManager import com.runnect.runnect.presentation.detail.CourseDetailActivity import com.runnect.runnect.presentation.login.LoginActivity @@ -14,8 +13,8 @@ import com.runnect.runnect.presentation.storage.mydrawdetail.MyDrawDetailActivit import com.runnect.runnect.util.analytics.Analytics import com.runnect.runnect.util.analytics.EventName import com.runnect.runnect.util.analytics.EventName.Param -import com.runnect.runnect.util.dynamiclink.RunnectDynamicLink.KEY_PRIVATE_COURSE_ID -import com.runnect.runnect.util.dynamiclink.RunnectDynamicLink.KEY_PUBLIC_COURSE_ID +import com.runnect.runnect.util.link.RunnectShareLink.KEY_PRIVATE_COURSE_ID +import com.runnect.runnect.util.link.RunnectShareLink.KEY_PUBLIC_COURSE_ID import dagger.hilt.android.AndroidEntryPoint import timber.log.Timber @@ -26,7 +25,7 @@ class SchemeActivity : AppCompatActivity() { super.onCreate(savedInstanceState) if (isUserLoggedIn()) { - handleDynamicLinks() + handleAppLink() } else { navigateToLoginScreen() } @@ -37,54 +36,45 @@ class SchemeActivity : AppCompatActivity() { return accessToken != "none" } - private fun handleDynamicLinks() { - FirebaseDynamicLinks.getInstance().getDynamicLink(intent) - .addOnSuccessListener(this) { pendingDynamicLinkData -> - val link = pendingDynamicLinkData.link - - if (link != null) { - val publicCourseId = getCourseId(link, KEY_PUBLIC_COURSE_ID) - val privateCourseId = getCourseId(link, KEY_PRIVATE_COURSE_ID) - - val targetScreen = when { - publicCourseId != null -> "CourseDetail" - privateCourseId != null -> "MyDrawDetail" - else -> "unknown" - } - Analytics.logEvent( - EventName.SYS_DEEPLINK_OPEN, - Param.DEEPLINK_URL to link.toString(), - Param.TARGET_SCREEN to targetScreen - ) + private fun handleAppLink() { + val link = intent.data + if (link == null) { + Timber.e("FAIL: no data in intent") + finish() + return + } - when { - publicCourseId != null -> navigateToCourseDetail( - publicCourseId - ) + val publicCourseId = getCourseId(link, KEY_PUBLIC_COURSE_ID) + val privateCourseId = getCourseId(link, KEY_PRIVATE_COURSE_ID) - privateCourseId != null -> navigateToCourseDetail( - privateCourseId - ) + val targetScreen = when { + publicCourseId != null -> "CourseDetail" + privateCourseId != null -> "MyDrawDetail" + else -> "unknown" + } + Analytics.logEvent( + EventName.SYS_DEEPLINK_OPEN, + Param.DEEPLINK_URL to link.toString(), + Param.TARGET_SCREEN to targetScreen + ) - else -> { - Timber.e("FAIL: could not find course id") - finish() - } - } - } - } - .addOnFailureListener(this) { t -> - Timber.e("FAIL: getDynamicLink from intent : ${t.message}") + when { + publicCourseId != null -> navigateToCourseDetail(publicCourseId) + privateCourseId != null -> navigateToCourseDetail(privateCourseId) + else -> { + Timber.e("FAIL: could not find course id") + finish() } + } } private fun getCourseId(link: Uri, key: String): Int? { - return link.getQueryParameter(key)?.toInt() + return link.getQueryParameter(key)?.toIntOrNull() } private inline fun navigateToCourseDetail(courseId: Int) { Intent(this, T::class.java).apply { - putExtra(EXTRA_FROM_DYNAMIC_LINK, courseId) + putExtra(EXTRA_FROM_APP_LINK, courseId) startActivity(this) } } @@ -97,7 +87,7 @@ class SchemeActivity : AppCompatActivity() { } companion object { - const val EXTRA_FROM_DYNAMIC_LINK = "fromDynamicLink" + const val EXTRA_FROM_APP_LINK = "fromAppLink" private const val TOKEN_KEY_ACCESS = "access" } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/mydrawdetail/MyDrawDetailActivity.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/mydrawdetail/MyDrawDetailActivity.kt index 25e53e64..c1aad698 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/mydrawdetail/MyDrawDetailActivity.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/mydrawdetail/MyDrawDetailActivity.kt @@ -2,7 +2,6 @@ package com.runnect.runnect.presentation.storage.mydrawdetail import android.app.Activity import android.content.Intent -import android.net.Uri import android.os.Bundle import android.widget.TextView import androidx.activity.OnBackPressedCallback @@ -12,8 +11,6 @@ import androidx.core.view.isVisible import androidx.core.widget.addTextChangedListener import com.bumptech.glide.Glide import com.google.android.material.bottomsheet.BottomSheetDialog -import com.google.firebase.dynamiclinks.DynamicLink -import com.google.firebase.dynamiclinks.FirebaseDynamicLinks import com.naver.maps.geometry.LatLng import com.runnect.runnect.R import com.runnect.runnect.binding.BindingActivity @@ -35,7 +32,7 @@ import com.runnect.runnect.util.custom.toolbar.ToolbarMenu import com.runnect.runnect.util.analytics.Analytics import com.runnect.runnect.util.analytics.EventName import com.runnect.runnect.util.analytics.EventName.Param -import com.runnect.runnect.util.dynamiclink.RunnectDynamicLink +import com.runnect.runnect.util.link.RunnectShareLink import com.runnect.runnect.util.extension.PermissionUtil import com.runnect.runnect.util.extension.applyScreenExitAnimation import com.runnect.runnect.util.extension.hideKeyboard @@ -44,7 +41,6 @@ import com.runnect.runnect.util.extension.showSnackbar import com.runnect.runnect.util.extension.showToast import com.runnect.runnect.util.extension.showWebBrowser import dagger.hilt.android.AndroidEntryPoint -import timber.log.Timber @AndroidEntryPoint class MyDrawDetailActivity : @@ -56,7 +52,7 @@ class MyDrawDetailActivity : private val touchList = arrayListOf() private val selectList = arrayListOf() private var courseId = -1 - private var isFromDynamicLink = false + private var isFromAppLink = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -74,9 +70,9 @@ class MyDrawDetailActivity : } private fun initCourseIdExtra() { - val idFromLink = intent.getIntExtra(SchemeActivity.EXTRA_FROM_DYNAMIC_LINK, -1) + val idFromLink = intent.getIntExtra(SchemeActivity.EXTRA_FROM_APP_LINK, -1) if (idFromLink != -1) { - isFromDynamicLink = true + isFromAppLink = true courseId = idFromLink return } @@ -283,7 +279,7 @@ class MyDrawDetailActivity : } private fun initBackButtonClickListener() { - if (isFromDynamicLink) { + if (isFromAppLink) { navigateToMainScreen() return } @@ -292,7 +288,7 @@ class MyDrawDetailActivity : } private fun addRightMenu() { - if (isFromDynamicLink) { + if (isFromAppLink) { if (myDrawCourseDetail.isNowUser) { addShareEditDeleteMenu() } @@ -334,43 +330,12 @@ class MyDrawDetailActivity : } private fun initShareButtonClickListener() { - createDynamicLink( - title = viewModel.courseTitle, - imgUrl = myDrawCourseDetail.imgUrl - ) - } - - private fun createDynamicLink(title: String, imgUrl: String) { - val link = "${RunnectDynamicLink.BASE_URL}/?${RunnectDynamicLink.KEY_PRIVATE_COURSE_ID}=${courseId}" - FirebaseDynamicLinks.getInstance().createDynamicLink() - .setLink(Uri.parse(link)) - .setDomainUriPrefix(RunnectDynamicLink.BASE_URL) - .setAndroidParameters(DynamicLink.AndroidParameters.Builder().build()) - .setIosParameters( - DynamicLink.IosParameters.Builder(RunnectDynamicLink.IOS_BUNDLE_ID).build() - ) - .setSocialMetaTagParameters( - DynamicLink.SocialMetaTagParameters.Builder() - .setTitle(title) - .setImageUrl(Uri.parse(imgUrl)) - .build() - ) - .buildShortDynamicLink() - .addOnSuccessListener { result -> - Timber.d("shortLink: ${result.shortLink}") - shareDynamicLink(result.shortLink.toString()) - } - .addOnFailureListener { t -> - Timber.e("sendDynamicLink fail: ${t.message}") - } - } - - private fun shareDynamicLink(shortLink: String) { + val url = "${RunnectShareLink.BASE_URL}?${RunnectShareLink.KEY_PRIVATE_COURSE_ID}=$courseId" val intent = Intent(Intent.ACTION_SEND).apply { - type = RunnectDynamicLink.SEND_INTENT_MIME_TYPE - putExtra(Intent.EXTRA_TEXT, shortLink) + type = RunnectShareLink.SEND_INTENT_MIME_TYPE + putExtra(Intent.EXTRA_TEXT, url) } - startActivity(Intent.createChooser(intent, RunnectDynamicLink.INTENT_CHOOSER_TITLE)) + startActivity(Intent.createChooser(intent, RunnectShareLink.INTENT_CHOOSER_TITLE)) } private fun createTitleEditBottomSheet(): BottomSheetDialog { diff --git a/app/src/main/java/com/runnect/runnect/util/dynamiclink/RunnectDynamicLink.kt b/app/src/main/java/com/runnect/runnect/util/link/RunnectShareLink.kt similarity index 53% rename from app/src/main/java/com/runnect/runnect/util/dynamiclink/RunnectDynamicLink.kt rename to app/src/main/java/com/runnect/runnect/util/link/RunnectShareLink.kt index f223bbe5..dce79f0b 100644 --- a/app/src/main/java/com/runnect/runnect/util/dynamiclink/RunnectDynamicLink.kt +++ b/app/src/main/java/com/runnect/runnect/util/link/RunnectShareLink.kt @@ -1,8 +1,7 @@ -package com.runnect.runnect.util.dynamiclink +package com.runnect.runnect.util.link -object RunnectDynamicLink { - const val BASE_URL = "https://rnnt.page.link" - const val IOS_BUNDLE_ID = "com.runnect.Runnect-iOS" +object RunnectShareLink { + const val BASE_URL = "https://runnect-ios.web.app/share" const val SEND_INTENT_MIME_TYPE = "text/plain" const val INTENT_CHOOSER_TITLE = "Share Link" const val KEY_PUBLIC_COURSE_ID = "courseId" diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ea96cc8d..3a0f2fa4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -150,7 +150,6 @@ coil-network-okhttp = { group = "io.coil-kt.coil3", name = "coil-network-okhttp" # Firebase (BOM 관리 - 개별 버전 불필요) firebase-bom = { group = "com.google.firebase", name = "firebase-bom", version.ref = "firebase-bom" } firebase-common-ktx = { group = "com.google.firebase", name = "firebase-common-ktx" } -firebase-dynamic-links-ktx = { group = "com.google.firebase", name = "firebase-dynamic-links-ktx" } firebase-database-ktx = { group = "com.google.firebase", name = "firebase-database-ktx" } firebase-firestore-ktx = { group = "com.google.firebase", name = "firebase-firestore-ktx" } firebase-storage-ktx = { group = "com.google.firebase", name = "firebase-storage-ktx" } @@ -194,7 +193,6 @@ androidx-core-testing = { group = "androidx.arch.core", name = "core-testing", v [bundles] firebase = [ "firebase-common-ktx", - "firebase-dynamic-links-ktx", "firebase-database-ktx", "firebase-firestore-ktx", "firebase-storage-ktx",