Fixed
Status Update
Comments
il...@google.com <il...@google.com> #2
Project: platform/frameworks/support
Branch: androidx-master-dev
commit c60f33e229e31ab328ef6b59dab63b264954831c
Author: Alexandre Elias <aelias@google.com>
Date: Fri Jul 10 16:23:09 2020
Semantics no-op cleanups
Partly in response to lmr's broad code review, I did a pass of
superficial API/implementation cleanup. The main changes are:
- I changed each Boolean SemanticsProperty where false is equivalent to
not being present to take "Unit" instead. This is conceptually
clearer: it avoids questions like "can I cancel out a semantics from a
merged child by setting it to false?" Because "property = Unit" looks
weird, I also changed the style of these to "property()".
- I moved the Semantics id generator closer to where it's used, in
SemanticsModifierCore. I made it internal and an AtomicInt.
(Note that integer ids are heavily used in the Android
AccessibilityNodeInfo APIs so I can't simply remove them entirely.)
- I deleted dead code. Some examples include SemanticsHintOverrides,
a public API not connected to anything, and SemanticsPropertyKey
merge() open method which is never called. (In both cases I have
a different plan in mind for accessibility.)
Fixes: 145951226
Fixes: 145955412
Test: existing tests
Relnote: "Single-value semantics properties now use a calling style.
For example, 'semantics { hidden = true }' is now written as:
'semantics { hidden() }'."
Change-Id: Ic1afd12ea22c926babc9662f1804d80b33aa0cfc
M ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/LayoutNodeModifierBenchmark.kt
M ui/ui-core/api/0.1.0-dev15.txt
M ui/ui-core/api/current.txt
M ui/ui-core/api/public_plus_experimental_0.1.0-dev15.txt
M ui/ui-core/api/public_plus_experimental_current.txt
M ui/ui-core/api/restricted_0.1.0-dev15.txt
M ui/ui-core/api/restricted_current.txt
M ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/graphics/vector/VectorTest.kt
M ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/semantics/SemanticsTests.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidActuals.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeView.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeViewAccessibilityDelegateCompat.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidPopup.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/Expect.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsConfiguration.kt
D ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsHintOverrides.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsModifier.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsNode.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsOwner.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsWrapper.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/semantics/SemanticsProperties.kt
M ui/ui-foundation/api/0.1.0-dev15.txt
M ui/ui-foundation/api/current.txt
M ui/ui-foundation/api/public_plus_experimental_0.1.0-dev15.txt
M ui/ui-foundation/api/public_plus_experimental_current.txt
M ui/ui-foundation/api/restricted_0.1.0-dev15.txt
M ui/ui-foundation/api/restricted_current.txt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/Clickable.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/Dialog.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/Scroller.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Selectable.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Toggleable.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/semantics/FoundationSemanticsProperties.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/ButtonTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/CardTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/CheckboxScreenshotTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/RadioButtonScreenshotTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/ScaffoldTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/SnackbarTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/SurfaceTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/ripple/RippleIndicationTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/textfield/TextFieldScreenshotTest.kt
M ui/ui-material/src/main/java/androidx/ui/material/AppBar.kt
M ui/ui-material/src/main/java/androidx/ui/material/TextFieldImpl.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/AssertsTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/CallSemanticsActionTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/ErrorMessagesTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/FindersTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/PrintToStringTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/ScrollToTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/TextActionsTest.kt
M ui/ui-test/src/main/java/androidx/ui/test/Actions.kt
M ui/ui-test/src/main/java/androidx/ui/test/Filters.kt
M ui/ui-text/api/0.1.0-dev15.txt
M ui/ui-text/api/current.txt
M ui/ui-text/api/public_plus_experimental_0.1.0-dev15.txt
M ui/ui-text/api/public_plus_experimental_current.txt
M ui/ui-text/api/restricted_0.1.0-dev15.txt
M ui/ui-text/api/restricted_current.txt
M ui/ui-text/src/commonMain/kotlin/androidx/ui/text/CoreTextField.kt
M ui/ui-text/src/commonMain/kotlin/androidx/ui/text/TextSemanticsProperties.kt
https://android-review.googlesource.com/1360099
Branch: androidx-master-dev
commit c60f33e229e31ab328ef6b59dab63b264954831c
Author: Alexandre Elias <aelias@google.com>
Date: Fri Jul 10 16:23:09 2020
Semantics no-op cleanups
Partly in response to lmr's broad code review, I did a pass of
superficial API/implementation cleanup. The main changes are:
- I changed each Boolean SemanticsProperty where false is equivalent to
not being present to take "Unit" instead. This is conceptually
clearer: it avoids questions like "can I cancel out a semantics from a
merged child by setting it to false?" Because "property = Unit" looks
weird, I also changed the style of these to "property()".
- I moved the Semantics id generator closer to where it's used, in
SemanticsModifierCore. I made it internal and an AtomicInt.
(Note that integer ids are heavily used in the Android
AccessibilityNodeInfo APIs so I can't simply remove them entirely.)
- I deleted dead code. Some examples include SemanticsHintOverrides,
a public API not connected to anything, and SemanticsPropertyKey
merge() open method which is never called. (In both cases I have
a different plan in mind for accessibility.)
Fixes: 145951226
Fixes: 145955412
Test: existing tests
Relnote: "Single-value semantics properties now use a calling style.
For example, 'semantics { hidden = true }' is now written as:
'semantics { hidden() }'."
Change-Id: Ic1afd12ea22c926babc9662f1804d80b33aa0cfc
M ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/LayoutNodeModifierBenchmark.kt
M ui/ui-core/api/0.1.0-dev15.txt
M ui/ui-core/api/current.txt
M ui/ui-core/api/public_plus_experimental_0.1.0-dev15.txt
M ui/ui-core/api/public_plus_experimental_current.txt
M ui/ui-core/api/restricted_0.1.0-dev15.txt
M ui/ui-core/api/restricted_current.txt
M ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/graphics/vector/VectorTest.kt
M ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/semantics/SemanticsTests.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidActuals.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeView.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeViewAccessibilityDelegateCompat.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidPopup.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/Expect.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsConfiguration.kt
D ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsHintOverrides.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsModifier.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsNode.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsOwner.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsWrapper.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/semantics/SemanticsProperties.kt
M ui/ui-foundation/api/0.1.0-dev15.txt
M ui/ui-foundation/api/current.txt
M ui/ui-foundation/api/public_plus_experimental_0.1.0-dev15.txt
M ui/ui-foundation/api/public_plus_experimental_current.txt
M ui/ui-foundation/api/restricted_0.1.0-dev15.txt
M ui/ui-foundation/api/restricted_current.txt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/Clickable.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/Dialog.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/Scroller.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Selectable.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Toggleable.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/semantics/FoundationSemanticsProperties.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/ButtonTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/CardTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/CheckboxScreenshotTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/RadioButtonScreenshotTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/ScaffoldTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/SnackbarTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/SurfaceTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/ripple/RippleIndicationTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/textfield/TextFieldScreenshotTest.kt
M ui/ui-material/src/main/java/androidx/ui/material/AppBar.kt
M ui/ui-material/src/main/java/androidx/ui/material/TextFieldImpl.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/AssertsTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/CallSemanticsActionTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/ErrorMessagesTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/FindersTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/PrintToStringTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/ScrollToTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/TextActionsTest.kt
M ui/ui-test/src/main/java/androidx/ui/test/Actions.kt
M ui/ui-test/src/main/java/androidx/ui/test/Filters.kt
M ui/ui-text/api/0.1.0-dev15.txt
M ui/ui-text/api/current.txt
M ui/ui-text/api/public_plus_experimental_0.1.0-dev15.txt
M ui/ui-text/api/public_plus_experimental_current.txt
M ui/ui-text/api/restricted_0.1.0-dev15.txt
M ui/ui-text/api/restricted_current.txt
M ui/ui-text/src/commonMain/kotlin/androidx/ui/text/CoreTextField.kt
M ui/ui-text/src/commonMain/kotlin/androidx/ui/text/TextSemanticsProperties.kt
th...@gmail.com <th...@gmail.com> #3
I did a crazy thing which helps to control this. I made a deep link forwarder that reformats a deep link into one that the navigation framework knows how to handle, and used NEW_TASK and CLEAR_TASK to fire those.
class ShortcutForwarderActivity : AppCompatActivity() {
@Inject
lateinit var analytics: Analytics
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
forwardIntent(intent)
finish()
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
forwardIntent(intent)
finish()
}
private fun forwardIntent(intent: Intent?) {
intent?.apply {
data?.let {
if (it.pathSegments[0] == "shortcut") {
it.pathSegments[1]?.let { path ->
try {
analytics.logEvent(AnalyticsEvent.AppShortcut(path))
// Attempt to forward to a standard deep link
val newIntent = Intent(Intent.ACTION_VIEW, Uri.parse("myapp://www.myapp.com/$path "))
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(newIntent)
} catch (notFound: ActivityNotFoundException) {
// Default to the base deep link
try {
val newIntent = Intent(Intent.ACTION_VIEW, Uri.parse("myapp://www.myapp.com/ "))
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(newIntent)
} catch (ex: Throwable) {
Timber.d(ex, "Unable to process default deep link.")
}
}
}
}
}
}
}
}
In AndroidManifest.xml declared as:
<activity android:name=".presentation.main.ShortcutForwarderActivity">
<nav-graph android:value="@navigation/shortcut_nav_graph" />
</activity>
And the nav graph for that looks like:
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android "
xmlns:app="http://schemas.android.com/apk/res-auto "
android:id="@+id/onelink_nav_graph.xml"
app:startDestination="@id/shortcutForwarderActivity">
<activity
android:id="@+id/shortcutForwarderActivity"
android:name="com.myapp.presentation.main.ShortcutForwarderActivity"
android:label="ShortcutForwarderActivity">
<deepLink app:uri="myapp://www.myapp.com/shortcut/.* " />
</activity>
</navigation>
Though this all comes down to internal implementation inside the navigation component which handles NEW_TASK without CLEAR_TASK differently from NEW_TASK combined with CLEAR_TASK. I guess I'm not really understanding the reason behind this separation.
class ShortcutForwarderActivity : AppCompatActivity() {
@Inject
lateinit var analytics: Analytics
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
forwardIntent(intent)
finish()
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
forwardIntent(intent)
finish()
}
private fun forwardIntent(intent: Intent?) {
intent?.apply {
data?.let {
if (it.pathSegments[0] == "shortcut") {
it.pathSegments[1]?.let { path ->
try {
analytics.logEvent(AnalyticsEvent.AppShortcut(path))
// Attempt to forward to a standard deep link
val newIntent = Intent(Intent.ACTION_VIEW, Uri.parse("myapp://
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(newIntent)
} catch (notFound: ActivityNotFoundException) {
// Default to the base deep link
try {
val newIntent = Intent(Intent.ACTION_VIEW, Uri.parse("myapp://
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(newIntent)
} catch (ex: Throwable) {
Timber.d(ex, "Unable to process default deep link.")
}
}
}
}
}
}
}
}
In AndroidManifest.xml declared as:
<activity android:name=".presentation.main.ShortcutForwarderActivity">
<nav-graph android:value="@navigation/shortcut_nav_graph" />
</activity>
And the nav graph for that looks like:
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="
xmlns:app="
android:id="@+id/onelink_nav_graph.xml"
app:startDestination="@id/shortcutForwarderActivity">
<activity
android:id="@+id/shortcutForwarderActivity"
android:name="com.myapp.presentation.main.ShortcutForwarderActivity"
android:label="ShortcutForwarderActivity">
<deepLink app:uri="myapp://
</activity>
</navigation>
Though this all comes down to internal implementation inside the navigation component which handles NEW_TASK without CLEAR_TASK differently from NEW_TASK combined with CLEAR_TASK. I guess I'm not really understanding the reason behind this separation.
br...@gmail.com <br...@gmail.com> #4
@Ian, it makes sense why it needs NEW_TASK and CLEAR_TASK, and yeah, disabling the animations would do the trick.
As for the message app using NEW_TASK on the emulator, it's worth noting that I see the same behavior with the messages app on an actual device (again Pixel 3XL, API 28), which IMO lends more credence to idea of disabling animations on the second activity creation, as it appears that there are lots of apps (including "core" Google apps) that do this.
the "shortcutForwarder" workaround posted in #3 is interesting. We may end up having to use something like that anyway, because our URL's use query strings, and it seems that the intent-filters that get generated from the nav graph can't handle 2 destinations that have deeplinks with the same url path, and only differ in their query string parameters. I anyone knows a way around that, let me know.
As for the message app using NEW_TASK on the emulator, it's worth noting that I see the same behavior with the messages app on an actual device (again Pixel 3XL, API 28), which IMO lends more credence to idea of disabling animations on the second activity creation, as it appears that there are lots of apps (including "core" Google apps) that do this.
the "shortcutForwarder" workaround posted in #3 is interesting. We may end up having to use something like that anyway, because our URL's use query strings, and it seems that the intent-filters that get generated from the nav graph can't handle 2 destinations that have deeplinks with the same url path, and only differ in their query string parameters. I anyone knows a way around that, let me know.
il...@google.com <il...@google.com>
ap...@google.com <ap...@google.com> #5
Project: platform/frameworks/support
Branch: androidx-master-dev
commit bf078f4a67eba20592a5830e75a5e6adbd63d1a0
Author: jbwoods <jbwoods@google.com>
Date: Mon Jun 03 13:12:21 2019
Disable double activity animation when opening app with deeplink
When using handleDeepLink(Intent) to open an app, Navigation enforces
that Intents that set the NEW_TASK flag also set the CLEAR_TASK flag.
This ensures a consistent activity back stack, and means that the
Activity should be created twice when the calling app only uses
NEW_TASK. Both Activity creations are currently being animated, causing
what appears as a flash before the app starts.
This change ensures that the second Activity creation animation is
disabled.
Test: Tested in app, all tests pass.
BUG: 130362979
Change-Id: Ie765aea34176508b7c1b4b897ca25e0d11b2d819
M navigation/runtime/src/main/java/androidx/navigation/NavController.java
https://android-review.googlesource.com/975586
https://goto.google.com/android-sha1/bf078f4a67eba20592a5830e75a5e6adbd63d1a0
Branch: androidx-master-dev
commit bf078f4a67eba20592a5830e75a5e6adbd63d1a0
Author: jbwoods <jbwoods@google.com>
Date: Mon Jun 03 13:12:21 2019
Disable double activity animation when opening app with deeplink
When using handleDeepLink(Intent) to open an app, Navigation enforces
that Intents that set the NEW_TASK flag also set the CLEAR_TASK flag.
This ensures a consistent activity back stack, and means that the
Activity should be created twice when the calling app only uses
NEW_TASK. Both Activity creations are currently being animated, causing
what appears as a flash before the app starts.
This change ensures that the second Activity creation animation is
disabled.
Test: Tested in app, all tests pass.
BUG: 130362979
Change-Id: Ie765aea34176508b7c1b4b897ca25e0d11b2d819
M navigation/runtime/src/main/java/androidx/navigation/NavController.java
jb...@google.com <jb...@google.com> #6
This has been fixed internally, and will be available in the Navigation 2.1.0-alpha06 release.
Description
Version used: 2.1.0-alpha02
Devices/Android versions reproduced on: Pixel 3XL, APi 28
When using an implicit deep link to open an app to a destination that is not the root/home destination, the user experiences a weird "flash" on the device, where it appears to open the app, and then open the app again. See the attached animated gif for a demo of the flash effect.
The attached sample app, QueryString can be used to reproduce the issue. The app contains two destination fragments, RootFragment and ChildFragment. In the navigation graph, RootFragment is the start destination, and contains an action to navigate to ChildFragment. Child Fragment also has a <deeplink> with it's URI set to "
To reproduce the "flash" effect:
1. open, build, and install the sample app on a device or emulator
2. Open the app to make sure it's working
3. Close the app (swipe it away from the recents screen).
3. Open a link to
When you tap on the link in the messages app, you'll see the "flash" of the app opening, and the the app opening again.