[go: nahoru, domu]

Merge "Auto fill-in packageName for ${applicationId} pattern" into androidx-main am: fd8e6178f0

Original change: https://android-review.googlesource.com/c/platform/frameworks/support/+/2130557

Change-Id: I489c23451a4aa992c60944ee3b17c2e10f98212d
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavInflaterTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavInflaterTest.kt
index f0738a9..b9bc6fd 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavInflaterTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavInflaterTest.kt
@@ -152,6 +152,69 @@
     }
 
     @Test
+    fun testInflateWithDataPatternApplicationId() {
+        val context = ApplicationProvider.getApplicationContext() as Context
+        val activityNavigator = ActivityNavigator(context)
+        val navInflater = NavInflater(
+            context,
+            TestNavigatorProvider().apply { addNavigator(activityNavigator) }
+        )
+
+        val graph = navInflater.inflate(R.navigation.nav_applicationid_arg)
+        val destination = graph.nodes.get(R.id.dataPattern_appId) as ActivityNavigator.Destination
+
+        assertThat(destination.dataPattern)
+            .isEqualTo("http://www.example.com/${context.packageName}")
+    }
+
+    @Test
+    fun testInflateWithNullDataPattern() {
+        val context = ApplicationProvider.getApplicationContext() as Context
+        val activityNavigator = ActivityNavigator(context)
+        val navInflater = NavInflater(
+            context,
+            TestNavigatorProvider().apply { addNavigator(activityNavigator) }
+        )
+
+        val graph = navInflater.inflate(R.navigation.nav_applicationid_arg)
+        val destination = graph.nodes.get(R.id.dataPattern_null) as ActivityNavigator.Destination
+
+        assertThat(destination.dataPattern).isNull()
+    }
+
+    @Test
+    fun testInflateWithDataApplicationId() {
+        val context = ApplicationProvider.getApplicationContext() as Context
+        val activityNavigator = ActivityNavigator(context)
+
+        val navInflater = NavInflater(
+            context,
+            TestNavigatorProvider().apply { addNavigator(activityNavigator) }
+        )
+
+        val graph = navInflater.inflate(R.navigation.nav_applicationid_arg)
+        val destination = graph.nodes.get(R.id.data_appId) as ActivityNavigator.Destination
+
+        assertThat(destination.data)
+            .isEqualTo(Uri.parse("http://www.example.com/${context.packageName}"))
+    }
+
+    @Test
+    fun testInflateWithNullData() {
+        val context = ApplicationProvider.getApplicationContext() as Context
+        val activityNavigator = ActivityNavigator(context)
+        val navInflater = NavInflater(
+            context,
+            TestNavigatorProvider().apply { addNavigator(activityNavigator) }
+        )
+
+        val graph = navInflater.inflate(R.navigation.nav_applicationid_arg)
+        val destination = graph.nodes.get(R.id.data_null) as ActivityNavigator.Destination
+
+        assertThat(destination.data).isNull()
+    }
+
+    @Test
     fun testDefaultArgumentsInteger() {
         val defaultArguments = inflateDefaultArgumentsFromGraph()
 
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_applicationid_arg.xml b/navigation/navigation-runtime/src/androidTest/res/navigation/nav_applicationid_arg.xml
new file mode 100644
index 0000000..4c5ab73
--- /dev/null
+++ b/navigation/navigation-runtime/src/androidTest/res/navigation/nav_applicationid_arg.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<navigation xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/nav_applicationid_arg"
+    app:startDestination="@+id/dataPattern_appId">
+
+    <activity android:id="@+id/dataPattern_appId"
+        app:dataPattern="http://www.example.com/${applicationId}">
+    </activity>
+    <activity android:id="@+id/dataPattern_null">
+    </activity>
+
+    <activity android:id="@+id/data_appId"
+        app:data="http://www.example.com/${applicationId}">
+    </activity>
+    <activity android:id="@+id/data_null">
+    </activity>
+</navigation>
\ No newline at end of file
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavigator.kt b/navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavigator.kt
index b1b9279..bb6e488 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavigator.kt
+++ b/navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavigator.kt
@@ -233,6 +233,10 @@
          *
          * If a non-null arguments Bundle is present when navigating, any segments in the form
          * `{argName}` will be replaced with a URI encoded string from the arguments.
+         *
+         * When inflated from XML, you can use `${applicationId}` as an argument pattern
+         * to automatically use [Context.getPackageName].
+         *
          * @param dataPattern A URI pattern with segments in the form of `{argName}` that
          * will be replaced with URI encoded versions of the Strings in the
          * arguments Bundle.
@@ -264,13 +268,10 @@
                 attrs,
                 R.styleable.ActivityNavigator
             ).use { array ->
-                var targetPackage = array.getString(R.styleable.ActivityNavigator_targetPackage)
-                if (targetPackage != null) {
-                    targetPackage = targetPackage.replace(
-                        NavInflater.APPLICATION_ID_PLACEHOLDER,
-                        context.packageName
-                    )
-                }
+                var targetPackage = parseApplicationId(
+                    context,
+                    array.getString(R.styleable.ActivityNavigator_targetPackage)
+                )
                 setTargetPackage(targetPackage)
                 var className = array.getString(R.styleable.ActivityNavigator_android_name)
                 if (className != null) {
@@ -280,14 +281,28 @@
                     setComponentName(ComponentName(context, className))
                 }
                 setAction(array.getString(R.styleable.ActivityNavigator_action))
-                val data = array.getString(R.styleable.ActivityNavigator_data)
+                val data = parseApplicationId(
+                    context,
+                    array.getString(R.styleable.ActivityNavigator_data)
+                )
                 if (data != null) {
                     setData(Uri.parse(data))
                 }
-                setDataPattern(array.getString(R.styleable.ActivityNavigator_dataPattern))
+                val dataPattern = parseApplicationId(
+                    context,
+                    array.getString(R.styleable.ActivityNavigator_dataPattern)
+                )
+                setDataPattern(dataPattern)
             }
         }
 
+        private fun parseApplicationId(context: Context, pattern: String?): String? {
+            return pattern?.replace(
+                NavInflater.APPLICATION_ID_PLACEHOLDER,
+                context.packageName
+            )
+        }
+
         /**
          * The explicit application package name associated with this destination, if any
          */
@@ -370,6 +385,9 @@
          * use [setDataPattern], which will take precedence when arguments are
          * present.
          *
+         *  When inflated from XML, you can use `${applicationId}` for string interpolation
+         *  to automatically use [Context.getPackageName].
+         *
          * @param data A static URI that should always be used.
          * @see Destination.setDataPattern
          * @return this [Destination]