Skip to content
This repository was archived by the owner on Feb 27, 2025. It is now read-only.
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.kts
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,6 @@ dependencies {
implementation(project(":feature:detail"))
implementation(project(":feature:recipe"))
implementation(project(":feature:collection"))

implementation("io.airbridge:sdk-android:4.1.0")
}
22 changes: 20 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,35 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<!-- firebase dynamic links -->
<!-- Airbridge deeplinks -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data
android:host="duckee.abr.ge"
android:scheme="https" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data
android:host="duckee.page.link"
android:host="duckee.airbridge.io"
android:scheme="https" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="duckee" />
</intent-filter>
Comment on lines +41 to +69
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the AndroidManifest.xml to include Airbridge deeplink schemes and hosts. This configuration is crucial for the app to intercept and handle Airbridge deeplinks correctly. Without these intent filters, the app won't be able to respond to Airbridge deeplinks.

</activity>

<!-- App Startup -->
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/kotlin/xyz/duckee/android/DuckeeApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,24 @@ import android.app.Application
import coil.ImageLoader
import coil.ImageLoaderFactory
import dagger.hilt.android.HiltAndroidApp
import co.ab180.airbridge.Airbridge
import co.ab180.airbridge.AirbridgeOption
import co.ab180.airbridge.AirbridgeOptionBuilder

@HiltAndroidApp
class DuckeeApplication : Application(), ImageLoaderFactory {

override fun onCreate() {
super.onCreate()
initializeAirbridge()
}

private fun initializeAirbridge() {
val option = AirbridgeOptionBuilder("duckee", "fc57a50c7b39453fb2582e4991e326a7")
.build()
Airbridge.initializeSDK(this, option)
}

override fun newImageLoader(): ImageLoader =
ImageLoader.Builder(this)
.crossfade(true)
Expand Down
93 changes: 47 additions & 46 deletions app/src/main/kotlin/xyz/duckee/android/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,13 @@ package xyz.duckee.android

import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.view.WindowManager
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.core.view.WindowCompat
import androidx.navigation.NavHostController
import com.google.firebase.dynamiclinks.PendingDynamicLinkData
import com.google.firebase.dynamiclinks.ktx.dynamicLinks
import com.google.firebase.ktx.Firebase
import com.stripe.android.paymentsheet.PaymentSheet
import com.stripe.android.paymentsheet.PaymentSheetResult
import dagger.hilt.android.AndroidEntryPoint
Expand All @@ -48,6 +44,7 @@ import xyz.duckee.android.core.navigation.navigateToDetailScreen
import xyz.duckee.android.core.navigation.navigateToExploreTab
import xyz.duckee.android.core.navigation.navigateToRecipeScreen
import xyz.duckee.android.core.navigation.navigateToSignInScreen
import co.ab180.airbridge.Airbridge

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
Expand Down Expand Up @@ -118,51 +115,55 @@ class MainActivity : ComponentActivity() {

override fun onResume() {
super.onResume()
handleAirbridgeDeeplink()
}

Firebase.dynamicLinks
.getDynamicLink(intent)
.addOnSuccessListener(this) { pendingDynamicLinkData: PendingDynamicLinkData? ->
pendingDynamicLinkData?.link?.let { deepLink ->
val path = deepLink.path ?: return@let
when {
path.startsWith("/recipe/") -> {
val recipePattern = "/recipe/(\\d+)".toRegex()
val matchResult = recipePattern.find(path)
matchResult?.let { result ->
val recipeId = result.groupValues[1]
navigationController?.navigateToRecipeScreen(recipeId)
}
}

path.startsWith("/detail/") -> {
val detailPattern = "/detail/([\\w-]+)".toRegex()
val matchResult = detailPattern.find(path)
matchResult?.let { result ->
val detailId = result.groupValues[1]
navigationController?.navigateToDetailScreen(detailId)
}
}

path == "/explore" -> {
navigationController?.navigateToExploreTab()
}

path == "/collection" -> {
navigationController?.navigateToCollectionTab()
}

path == "/signin" -> {
navigationController?.navigateToSignInScreen()
}

else -> {
Timber.tag("[DuckeeMainActivity]").w("Unhandled deep link path: $path")
}
}
private fun handleAirbridgeDeeplink() {
Airbridge.handleDeeplink(intent) { deeplink ->
handleDeeplink(deeplink)
}

Airbridge.handleDeferredDeeplink { deeplink ->
deeplink?.let { handleDeeplink(it) }
}
}
Comment on lines +121 to +129
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented Airbridge deeplink handling logic. This code is called when the app is launched or resumed via a deeplink, and navigates the user to the appropriate screen. The navigation controller is used to move to the screen corresponding to the deeplink URL.


private fun handleDeeplink(deeplink: Uri) {
val path = deeplink.path ?: return
when {
path.startsWith("/recipe/") -> {
val recipePattern = "/recipe/(\\d+)".toRegex()
val matchResult = recipePattern.find(path)
matchResult?.let { result ->
val recipeId = result.groupValues[1]
navigationController?.navigateToRecipeScreen(recipeId)
}
}

path.startsWith("/detail/") -> {
val detailPattern = "/detail/([\\w-]+)".toRegex()
val matchResult = detailPattern.find(path)
matchResult?.let { result ->
val detailId = result.groupValues[1]
navigationController?.navigateToDetailScreen(detailId)
}
}
.addOnFailureListener(this) { e ->
Timber.tag("[DuckeeMainActivity]").w(e, "getDynamicLink:onFailure")

path == "/explore" -> {
navigationController?.navigateToExploreTab()
}

path == "/collection" -> {
navigationController?.navigateToCollectionTab()
}

path == "/signin" -> {
navigationController?.navigateToSignInScreen()
}

else -> {
Timber.tag("[DuckeeMainActivity]").w("Unhandled deep link path: $path")
}
}
}
Comment on lines +131 to 168
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored the deeplink handling logic to support both Airbridge deeplinks and deferred deeplinks. This change ensures that the app can handle various types of deeplinks, including those that might be triggered after the app is installed.

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ class AndroidFirebaseConventionPlugin : Plugin<Project> {
"implementation"(platform(libs.findLibrary("firebase.bom").get()))
"implementation"(libs.findLibrary("firebase.auth").get())
"implementation"(libs.findLibrary("firebase.authUI").get())
"implementation"(libs.findLibrary("firebase.dynamicLink").get())
// Remove the following line
// "implementation"(libs.findLibrary("firebase.dynamicLink").get())
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pluginManagement {
google()
mavenCentral()
gradlePluginPortal()
maven { url = uri("https://sdk-download.airbridge.io/maven") }
}
}
dependencyResolutionManagement {
Expand All @@ -15,6 +16,7 @@ dependencyResolutionManagement {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") }
maven { url = uri("https://sdk-download.airbridge.io/maven") }
}
}

Expand Down