diff --git a/advanceddeeplinkapp/.gitignore b/advanceddeeplinkapp/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/advanceddeeplinkapp/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/advanceddeeplinkapp/build.gradle.kts b/advanceddeeplinkapp/build.gradle.kts new file mode 100644 index 00000000..c82a3eb3 --- /dev/null +++ b/advanceddeeplinkapp/build.gradle.kts @@ -0,0 +1,67 @@ +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.kotlin.compose) + alias(libs.plugins.kotlin.serialization) +} + +android { + namespace = "com.example.nav3recipes.deeplink.advanced" + compileSdk = 36 + + defaultConfig { + applicationId = "com.example.nav3recipes.deeplink.advanced" + minSdk = 24 + targetSdk = 36 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + kotlinOptions { + jvmTarget = "11" + } + buildFeatures { + compose = true + } +} + +dependencies { + + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.activity.compose) + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.ui) + implementation(libs.androidx.ui.graphics) + implementation(libs.androidx.ui.tooling.preview) + implementation(libs.androidx.material3) + + implementation(libs.kotlinx.serialization.core) + implementation(libs.kotlinx.serialization.json) + implementation(libs.androidx.navigation3.runtime) + implementation(libs.androidx.navigation3.ui) + implementation(project(":common")) + + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.ui.test.junit4) + debugImplementation(libs.androidx.ui.tooling) + debugImplementation(libs.androidx.ui.test.manifest) +} \ No newline at end of file diff --git a/advanceddeeplinkapp/proguard-rules.pro b/advanceddeeplinkapp/proguard-rules.pro new file mode 100644 index 00000000..481bb434 --- /dev/null +++ b/advanceddeeplinkapp/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/advanceddeeplinkapp/src/main/AndroidManifest.xml b/advanceddeeplinkapp/src/main/AndroidManifest.xml new file mode 100644 index 00000000..d9ea26a7 --- /dev/null +++ b/advanceddeeplinkapp/src/main/AndroidManifest.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/AdvancedDeeplinkAppActivity.kt b/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/AdvancedDeeplinkAppActivity.kt new file mode 100644 index 00000000..de163ea1 --- /dev/null +++ b/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/AdvancedDeeplinkAppActivity.kt @@ -0,0 +1,111 @@ +package com.example.nav3recipes.deeplink.advanced + +import android.content.Intent +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.navigation3.runtime.NavBackStack +import androidx.navigation3.runtime.NavKey +import androidx.navigation3.runtime.entryProvider +import androidx.navigation3.runtime.rememberNavBackStack +import androidx.navigation3.ui.NavDisplay +import com.example.nav3recipes.deeplink.advanced.util.buildBackStack +import com.example.nav3recipes.deeplink.advanced.util.navigateUp +import com.example.nav3recipes.deeplink.advanced.util.toKey +import com.example.nav3recipes.deeplink.common.EntryScreen +import com.example.nav3recipes.deeplink.common.FriendsList +import com.example.nav3recipes.deeplink.common.LIST_USERS +import com.example.nav3recipes.deeplink.common.PaddedButton + +class AdvancedDeeplinkAppActivity: ComponentActivity() { + + @OptIn(ExperimentalMaterial3Api::class) + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + val startKey = intent.data.toKey() + + val flags = intent.flags + val isNewTask = flags and Intent.FLAG_ACTIVITY_NEW_TASK != 0 && + flags and Intent.FLAG_ACTIVITY_CLEAR_TASK != 0 + + val syntheticBackStack = buildBackStack( + startKey = startKey, + buildFullPath = isNewTask + ) + setContent { + val backStack: NavBackStack = rememberNavBackStack(*(syntheticBackStack.toTypedArray())) + + Scaffold( + topBar = { + // top app bar to display up button + TopAppBar( + colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.primary, + titleContentColor = MaterialTheme.colorScheme.primary, + ), + title = { stringResource(R.string.app_name)}, + navigationIcon = { + /** + * Up button should never exit your app. Do not display it + * on the root Screen. + */ + if (backStack.last() != Home) { + IconButton(onClick = { + backStack.navigateUp( + this@AdvancedDeeplinkAppActivity, + this@AdvancedDeeplinkAppActivity + ) + }) { + Icon( + painter = painterResource(id = R.drawable.outline_arrow_upward_24), + contentDescription = "Up Button", + ) + } + } + }, + ) + }, + ) { innerPadding -> + NavDisplay( + backStack = backStack, + onBack = { backStack.removeLastOrNull()}, + modifier = Modifier.padding(innerPadding), + entryProvider = entryProvider { + entry { key -> + EntryScreen(key.screenTitle) { + PaddedButton("See Users") { + backStack.add(Users) + } + } + } + entry { key -> + EntryScreen(key.screenTitle) { + FriendsList(LIST_USERS) { user -> + backStack.add(UserDetail(user)) + } + } + } + entry { result -> + EntryScreen(result.screenTitle) { + FriendsList(listOf(result.user)) + } + } + } + ) + } + } + } +} \ No newline at end of file diff --git a/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/NavRecipeKey.kt b/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/NavRecipeKey.kt new file mode 100644 index 00000000..773e99e3 --- /dev/null +++ b/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/NavRecipeKey.kt @@ -0,0 +1,63 @@ +package com.example.nav3recipes.deeplink.advanced + +import androidx.navigation3.runtime.NavKey +import com.example.nav3recipes.deeplink.common.User +import kotlinx.serialization.Serializable +import androidx.navigation3.runtime.NavBackStack +import com.example.nav3recipes.deeplink.advanced.util.navigateUp + +internal const val PATH_BASE = "https://www.nav3deeplink.com" + +/** + * Defines the NavKey used for this app. + * + * The keys are defined with this inheritance structure: + * [NavDeepLinkRecipeKey] extends [NavRecipeKey] extends [NavKey]. + * + * [NavKey] - the base Navigation 3 interface that can be used with [NavBackStack] + * + * [NavRecipeKey] - a sub-interface to supports member variables and functions + * specific to this app + * + * [NavDeepLinkRecipeKey] - a sub-interface to ensure that all keys + * that support deeplinking (or all keys that have children keys that can be deeplinked into) + * implement these two fields: + * 1. parent - the hierarchical parent of this key, required for building a synthetic backStack + * 2. deeplinkUrl - the deeplink url associated with this key, required for supporting the + * Up button (see [navigateUp] for more on this). + */ + +internal interface NavRecipeKey: NavKey { + val screenTitle: String +} + +internal interface NavDeepLinkRecipeKey: NavRecipeKey { + val parent: NavKey + val deeplinkUrl: String +} + +@Serializable +object Home: NavRecipeKey { + override val screenTitle: String = "Home" +} + +@Serializable +object Users: NavDeepLinkRecipeKey { + override val screenTitle: String = "Users" + override val parent: NavKey = Home + override val deeplinkUrl: String + get() = "$PATH_BASE/$DEEPLINK_URL_TAG_USERS" +} + +@Serializable +internal data class UserDetail( + val user: User +): NavDeepLinkRecipeKey { + override val screenTitle: String = "User" + override val parent: NavKey = Users + override val deeplinkUrl: String + get() = "$PATH_BASE/$DEEPLINK_URL_TAG_USER/${user.firstName}/${user.location}" +} + +internal const val DEEPLINK_URL_TAG_USER = "user" +internal const val DEEPLINK_URL_TAG_USERS = "users" \ No newline at end of file diff --git a/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/ui/theme/Color.kt b/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/ui/theme/Color.kt new file mode 100644 index 00000000..17953810 --- /dev/null +++ b/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/ui/theme/Color.kt @@ -0,0 +1,11 @@ +package com.example.nav3recipes.deeplink.advanced.ui.theme + +import androidx.compose.ui.graphics.Color + +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFFEFB8C8) + +val Purple40 = Color(0xFF6650a4) +val PurpleGrey40 = Color(0xFF625b71) +val Pink40 = Color(0xFF7D5260) \ No newline at end of file diff --git a/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/ui/theme/Theme.kt b/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/ui/theme/Theme.kt new file mode 100644 index 00000000..6e844b83 --- /dev/null +++ b/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/ui/theme/Theme.kt @@ -0,0 +1,58 @@ +package com.example.nav3recipes.deeplink.advanced.ui.theme + +import android.app.Activity +import android.os.Build +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext + +private val DarkColorScheme = darkColorScheme( + primary = Purple80, + secondary = PurpleGrey80, + tertiary = Pink80 +) + +private val LightColorScheme = lightColorScheme( + primary = Purple40, + secondary = PurpleGrey40, + tertiary = Pink40 + + /* Other default colors to override + background = Color(0xFFFFFBFE), + surface = Color(0xFFFFFBFE), + onPrimary = Color.White, + onSecondary = Color.White, + onTertiary = Color.White, + onBackground = Color(0xFF1C1B1F), + onSurface = Color(0xFF1C1B1F), + */ +) + +@Composable +fun Nav3RecipesTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + content: @Composable () -> Unit +) { + val colorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> DarkColorScheme + else -> LightColorScheme + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + content = content + ) +} \ No newline at end of file diff --git a/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/ui/theme/Type.kt b/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/ui/theme/Type.kt new file mode 100644 index 00000000..421ee93a --- /dev/null +++ b/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/ui/theme/Type.kt @@ -0,0 +1,34 @@ +package com.example.nav3recipes.deeplink.advanced.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +// Set of Material typography styles to start with +val Typography = Typography( + bodyLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ) + /* Other default text styles to override + titleLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ) + */ +) \ No newline at end of file diff --git a/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/util/DeepLinkBackStackUtil.kt b/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/util/DeepLinkBackStackUtil.kt new file mode 100644 index 00000000..d79f53e9 --- /dev/null +++ b/advanceddeeplinkapp/src/main/java/com/example/nav3recipes/deeplink/advanced/util/DeepLinkBackStackUtil.kt @@ -0,0 +1,175 @@ +package com.example.nav3recipes.deeplink.advanced.util + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.net.Uri +import androidx.core.app.TaskStackBuilder +import androidx.core.net.toUri +import androidx.navigation3.runtime.NavBackStack +import androidx.navigation3.runtime.NavKey +import com.example.nav3recipes.deeplink.advanced.DEEPLINK_URL_TAG_USER +import com.example.nav3recipes.deeplink.advanced.DEEPLINK_URL_TAG_USERS +import com.example.nav3recipes.deeplink.advanced.Home +import com.example.nav3recipes.deeplink.advanced.NavDeepLinkRecipeKey +import com.example.nav3recipes.deeplink.advanced.UserDetail +import com.example.nav3recipes.deeplink.advanced.Users +import com.example.nav3recipes.deeplink.common.LIST_USERS + +/** + * A function that build a synthetic backStack. + * + * This helper returns one of two possible backStacks: + * + * 1. a backStack with only the deeplinked key if [buildFullPath] is false. + * 2. a backStack containing the deeplinked key and its hierarchical parent keys + * if [buildFullPath] is true. + * + * In the context of this recipe, [buildFullPath] is true if the deeplink intent has the + * [android.content.Intent.FLAG_ACTIVITY_NEW_TASK] and [android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK] + * flags. + * These flags indicate that the deeplinked Activity was started as the root Activity of a new Task, in which case + * a full synthetic backStack is required in order to support the proper, expected back button behavior. + * + * If those flags were not present, it means the deeplinked Activity was started + * in the app that originally triggered the deeplink. In this case, that original app is assumed to + * already have existing screens that users can system back into, therefore a synthetic backstack + * is OPTIONAL. + * + */ +internal fun buildBackStack( + startKey: NavKey, + buildFullPath: Boolean +): List { + if (!buildFullPath) return listOf(startKey) + /** + * iterate up the parents of the startKey until it reaches the root key (a key without a parent) + */ + return buildList { + var node: NavKey? = startKey + while (node != null) { + add(0, node) + val parent = if (node is NavDeepLinkRecipeKey) { + node.parent + } else null + node = parent + } + } +} + +/** + * If this app was started on its own Task stack, then navigate up would simply + * pop from the backStack. + * + * Otherwise, it will restart this app in a new Task and build a full synthetic backStack + * starting from the root key to current key's parent (current key is "popped" upon user click on up button). + * This operation is required because by definition, an Up button is expected to: + * 1. Move from current screen to its hierarchical parent + * 2. Stay within this app + * + * Therefore, we need to build a synthetic backStack to fulfill expectation 1., and we need to + * restart the app in its own Task so that this app's screens are displayed within + * this app instead of being displayed within the originating app that triggered the deeplink. + */ +internal fun NavBackStack.navigateUp( + activity: Activity, + context: Context +) { + /** + * The root key (the first key on synthetic backStack) would/should never display the Up button. + * So if the backStack only contains a non-root key, it means a synthetic backStack had not + * been built (aka the app was opened in the originating Task). + */ + if (size == 1) { + val currKey = last() + /** + * upon navigating up, the current key is popped, so the restarted activity + * lands on the current key's parent + */ + val deeplinkKey = if (currKey is NavDeepLinkRecipeKey) { + currKey.parent + } else null + + /** + * create a [androidx.core.app.TaskStackBuilder] that will restart the + * Activity as the root Activity of a new Task + */ + val builder = createTaskStackBuilder(deeplinkKey, activity, context) + // ensure current activity is finished + activity.finish() + // trigger restart + builder.startActivities() + } else { + removeLastOrNull() + } + +} + +/** + * Creates a [androidx.core.app.TaskStackBuilder]. + * + * The builder takes the current context and Activity and builds a new Task stack with the + * restarted activity as the root Activity. The resulting TaskStack is used to restart + * the Activity in its own Task. + */ +private fun createTaskStackBuilder( + deeplinkKey: NavKey?, + activity: Activity, + context: Context +): TaskStackBuilder { + /** + * The intent to restart the current activity. + */ + val intent = Intent(context, activity.javaClass) + + /** + * Pass in the deeplink url of the target key so that upon restart, the app + * can build the synthetic backStack starting from the deeplink key all the way up to the + * root key. + * + * See [buildBackStack] for building synthetic backStack. + */ + if (deeplinkKey != null && deeplinkKey is NavDeepLinkRecipeKey) { + intent.data = deeplinkKey.deeplinkUrl.toUri() + } + + /** + * Ensure that the Activity is restarted as the root of a new Task + */ + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) + + /** + * Lastly, attach the intent to the TaskStackBuilder. + * + * By using `addNextIntentWithParentStack`, the TaskStackBuilder will automatically + * add the intents for the parent activities (if any) of [activity]. + */ + return TaskStackBuilder.create(context).addNextIntentWithParentStack(intent) +} + +/** + * A function that converts a deeplink uri into a NavKey. + * + * This helper is intentionally simple and basic. For a recipe that focuses on parsing a + * deeplink uri into a NavKey, please see [com.example.nav3recipes.deeplink.basic]. + */ +internal fun Uri?.toKey(): NavKey { + if (this == null) return Home + + val paths = pathSegments + + if (pathSegments.isEmpty()) return Home + + return when(paths.first()) { + DEEPLINK_URL_TAG_USERS -> Users + DEEPLINK_URL_TAG_USER -> { + val firstName = pathSegments[1] + val location = pathSegments[2] + val user = LIST_USERS.find { + it.firstName == firstName && it.location == location + } + if (user == null) Users else UserDetail(user) + } + else -> Home + } +} \ No newline at end of file diff --git a/advanceddeeplinkapp/src/main/res/drawable/ic_launcher_background.xml b/advanceddeeplinkapp/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000..f1566239 --- /dev/null +++ b/advanceddeeplinkapp/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/advanceddeeplinkapp/src/main/res/drawable/ic_launcher_foreground.xml b/advanceddeeplinkapp/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 00000000..2b068d11 --- /dev/null +++ b/advanceddeeplinkapp/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/advanceddeeplinkapp/src/main/res/drawable/outline_arrow_upward_24.xml b/advanceddeeplinkapp/src/main/res/drawable/outline_arrow_upward_24.xml new file mode 100644 index 00000000..2d898ede --- /dev/null +++ b/advanceddeeplinkapp/src/main/res/drawable/outline_arrow_upward_24.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/advanceddeeplinkapp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/advanceddeeplinkapp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 00000000..6f3b755b --- /dev/null +++ b/advanceddeeplinkapp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/advanceddeeplinkapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/advanceddeeplinkapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 00000000..6f3b755b --- /dev/null +++ b/advanceddeeplinkapp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/advanceddeeplinkapp/src/main/res/mipmap-hdpi/ic_launcher.webp b/advanceddeeplinkapp/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 00000000..c209e78e Binary files /dev/null and b/advanceddeeplinkapp/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/advanceddeeplinkapp/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/advanceddeeplinkapp/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 00000000..b2dfe3d1 Binary files /dev/null and b/advanceddeeplinkapp/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/advanceddeeplinkapp/src/main/res/mipmap-mdpi/ic_launcher.webp b/advanceddeeplinkapp/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 00000000..4f0f1d64 Binary files /dev/null and b/advanceddeeplinkapp/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/advanceddeeplinkapp/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/advanceddeeplinkapp/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 00000000..62b611da Binary files /dev/null and b/advanceddeeplinkapp/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/advanceddeeplinkapp/src/main/res/mipmap-xhdpi/ic_launcher.webp b/advanceddeeplinkapp/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 00000000..948a3070 Binary files /dev/null and b/advanceddeeplinkapp/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/advanceddeeplinkapp/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/advanceddeeplinkapp/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 00000000..1b9a6956 Binary files /dev/null and b/advanceddeeplinkapp/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/advanceddeeplinkapp/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/advanceddeeplinkapp/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 00000000..28d4b77f Binary files /dev/null and b/advanceddeeplinkapp/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/advanceddeeplinkapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/advanceddeeplinkapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 00000000..9287f508 Binary files /dev/null and b/advanceddeeplinkapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/advanceddeeplinkapp/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/advanceddeeplinkapp/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 00000000..aa7d6427 Binary files /dev/null and b/advanceddeeplinkapp/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/advanceddeeplinkapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/advanceddeeplinkapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 00000000..9126ae37 Binary files /dev/null and b/advanceddeeplinkapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/advanceddeeplinkapp/src/main/res/values/colors.xml b/advanceddeeplinkapp/src/main/res/values/colors.xml new file mode 100644 index 00000000..a720bc5d --- /dev/null +++ b/advanceddeeplinkapp/src/main/res/values/colors.xml @@ -0,0 +1,11 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + #7AFFFFFF + \ No newline at end of file diff --git a/advanceddeeplinkapp/src/main/res/values/strings.xml b/advanceddeeplinkapp/src/main/res/values/strings.xml new file mode 100644 index 00000000..2124e90d --- /dev/null +++ b/advanceddeeplinkapp/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Nav3 Deeplink App + \ No newline at end of file diff --git a/advanceddeeplinkapp/src/main/res/values/themes.xml b/advanceddeeplinkapp/src/main/res/values/themes.xml new file mode 100644 index 00000000..d0035769 --- /dev/null +++ b/advanceddeeplinkapp/src/main/res/values/themes.xml @@ -0,0 +1,5 @@ + + + +