I added a deepLink to `NavGraphBuilder.scrollable`...
# compose-wear
y
I added a deepLink to
NavGraphBuilder.scrollable
, called the deepLink with a PendingIntent from complication, and got
java.lang.IllegalArgumentException: The WearNavigator backstack is empty, there is no navigation destination to display.
Is this normal?
The first time as I clicked on my complication, the IllegalArgumentException raised, but i can still see the composable open. Close the MainActivty and tap on the complication second time, the whole watchface was then dead by the same
java.lang.IllegalArgumentException: The WearNavigator backstack is empty, there is no navigation destination to display.
My deep link intent:
Copy code
val deepLinkIntent = Intent(
    Intent.ACTION_VIEW,
    DeepLinkHelper.historyLink.toUri(),
    ctx,
    HomeActivity::class.java, // there is navHost defined in HomeActivity
    )
// adding the complication flag
// <https://stackoverflow.com/questions/2232238/how-to-bring-an-activity-to-foreground-top-of-stack/2235130#2235130>
deepLinkIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
My PendingIntent:
Copy code
val deepLinkPendingIntent: PendingIntent? =
return TaskStackBuilder.create(ctx).run {
    addNextIntentWithParentStack(intent)
    getPendingIntent(requestCode, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}
I also tried building PendingIntent with:
Copy code
PendingIntent.getActivity(
    ctx,
    requestCode,
    intent, // buildHistoryDeepLinkIntent(ctx),
    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE // Immutable is necessary due to a security fix
)
and the same result,
IllegalArgumentException: The WearNavigator backstack is empty
I created the
navController
in the onCreate() of HomeActivity,
Copy code
override fun onCreate(savedInstanceState: Bundle?) {
    mAmbientCallback = HomeActivityAmbientCallback()
    super.onCreate(savedInstanceState)
    setContent {
        WearAppTheme {
            navController = rememberSwipeDismissableNavController()
            WearApp(
                navController = navController!!,
I noticed that navController is null while onResume() of the HomeActivity is called, it seems to me the composable code is called later then onResume() ? Any hints are really appreciated.
s
When we see "The WearNavigator backstack is empty, there is no navigation destination to display" it usually means that the ComposeNavigator is being used to add destinations rather than the WearNavigator - hence the Wear navigation backstack is empty. But here, it looks like you are using the correct one (worth checking the imports though).
You don't show it - have you defined a navigation graph, as well as creating a deep link for the Intent?
y
I defined the <data> in the <intent-filter>
Copy code
<activity
    android:name=".ui.home.HomeActivity"
    android:launchMode="singleInstance"
    android:theme="@style/composeWearAppTheme"
    android:label="@string/wear_menu_activity_label"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <!-- implicit deeplink -->
        <data android:scheme="https" android:host="www.example.com"/>
    </intent-filter>
I used the
NavGraphBuilder
from the
horologist.WearNavScaffold
, but I don’t have a
nav_graph.xml
The
DeepLinkHelper.historyLink = "<http://www.example.com/my_route|www.example.com/my_route>"
The
NavGraphBuilder
code is
Copy code
WearNavScaffold(
     …
     builder = {
          scrollable(
              route = "my_route",
              deepLinks = listOf(navDeepLink { 
                    uriPattern = "<http://www.example.com/my_route|www.example.com/my_route>" })
          ) { ... }
})
@stevebower You might be right with the Navigator and import statement. I am NOT using
androidx.wear.compose.navigation.NavGraphBuilder
, but with
com.google.android.horologist.compose.navscaffold.NavGraphBuilder
from`horologist` . Could this be the issue? Where can i found out which Navigator i have imported?
s
I'm sure horologist is using the correct one - @yschimke
y
What really strange is that, the deep link seem to work only for the first time. It does shown up with an exception.
@stevebower @yschimke Oh, I found the issue, it is the
uriPattern
,
<http://www.example.com/my_route|www.example.com/my_route>
doesn’t work, but
<http://www.example.com|www.example.com>
works.
Copy code
deepLinks = listOf(navDeepLink { 
                    uriPattern = "<http://www.example.com/my_route|www.example.com/my_route>" })
But why it is the case, how can i define multiple deep links with the same host
<http://www.example.com|www.example.com>
@stevebower @yschimke I am not sure, but it might have something to do with my activity
android:launchMode="singleInstance"
thus the deepLinks with subpath
uriPattern
www.example.com/my_route”, doesn’t work. I added
navController.handleDeepLink(intent)
to my activity
Copy code
override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    navController.handleDeepLink(intent)
}
now it works. Referen: https://stackoverflow.com/questions/69781886/deep-links-navigation-in-jetpack-compose/70276252#70276252 We shall document this also on the wear navi doc, if it is the root cause. Can any of you double check my assumption. Thanks in advance.
s
Yes, I would expect that you need to add NavArguments in order to build a URL like
<http://www.example.com/my_route|www.example.com/my_route>
so I think you've found the answer.
y
Sounds like you have this covered. If it's still an issue and a bug with WearNavScaffold, I can dig into it when I'm back from holidays on Monday
y
I am all good now. Will report back should i found any further issue regarding deep link with wear navigation.
y
Any feedback on WearNavScaffold/scrollable? Is it laying out well automatically?
y
I like
WearNavScaffold/scrollable
very much 🙂 A couple of things I noticed: • The timeTextMode, positionIndicatorMode, etc in ScrollableScaffoldContext is really great, it makes more fun to build app. • While using the default autoCentering itemIndex=1, for two 3 items in SLC, the first items can be very close to the time text. • Using the
AnimatedVisibility(visible = expanded)
sometimes the time text in
WearNavScaffold/scrollable
jumps a little bit. Overall, WearNavScaffold is really a bless, thanks for making it.
y
While using the default autoCentering itemIndex=1, for two items in SLC, the first items can be very close to the time text.
Is it text or a Chip?
y
Is it text or a Chip?
Text, I add sometimes an empty item without spacer, things goes better.
y
You shouldn't have to. If you can make a repro as a small @ Preview, I can see why it's going wrong.
This is with
scrollable
, right
y
yes.
y
It should place it sensibly for a list header of text, you can override if you have a full width item like a Chip, and it places it 20 dp lower.
y
Will put something together for tomorrow.
y
Perfect. the whole point is you shouldn't have to add that spacer, so I'd love to dig into why you do. Thanks, no rush, just like to respond to early users.
y
You are the best.
y
One thing I'm confused about...
autoCentering itemIndex=1, for two items in SLC
the
scrollable
fun has a param defaulted to
ScalingLazyColumnDefaults.belowTimeText()
that stops is using itemIndex=1, offset = 0, you end up with itemIndex = 0 and
offset = screenHeightPx / 2 - topPaddingPx
y
I may mistaken it, could also be 3 items 😞
y
No prob, when you have time I'll take a look.
y
I have a three item from the picture, the time text can not be scrolled down any more.
y
Yep, looks like a bug.
y
Another one is better
y
That still doesn't look right. It shouldn't be cut off on sides. That one, might just need to pass in
ScalingLazyColumnDefaults.belowTimeText(firstItemIsFullWidth = true)
j
If you can't scroll your time text down then typically you have you offsets for
Modifier.scrollAway()
,
ScalingLazyListState
and/or
AutoCentering
inconsistent
y
Yep, unfortunately it's probably my buggy library code :)
j
Regarding the clipping if the content is in a
ScalingLazyColumn
then it looks like the the normal horizontal padding has been overridden
y
Sorry for confusion, regarding the clipping of chips, I was the one overridden the
contentPadding
in SLC
Copy code
contentPadding = PaddingValues(horizontal = 6.dp), // to make less padding
@yschimke I opened an issue at horologist repo https://github.com/google/horologist/issues/919, also attached the sample repo reproducing two issues: 1. Time Text not scroll down 2. Time Text overlap with head text Thanks again for looking into these.
y
I'm travelling so it might be monday
Think this is down to poor documentation on this very new code. Sorry!
timetext.mp4
y
Oh, I missed the
columnStateFactory
as you have already posted. Sorry for that. 🙂 https://kotlinlang.slack.com/archives/C02GBABJUAF/p1672277001696559?thread_ts=1672146428.263589&amp;cid=C02GBABJUAF
@yschimke How do you think about this implementation change https://github.com/google/horologist/issues/931 I need to change the contentPadding of SLC without duplicating your factory code.
y
It can't be a var, it needs to be immutable. So we should pass it in. I'd prefer to add an optional param. I'm happy to do that.
Before jumping to that, can you give a screenshot, or show in that existing sample project, what you need it for.
The idea of ScalingLazyColumnDefaults.belowTimeText is meant to be that it does the right thing without a lot of tuning params. Any counter examples, I'd like to understand why it's breaking.
I'm also seeing the original exception "IllegalArgumentException: The WearNavigator backstack is empty, there is no navigation destination to display" https://issuetracker.google.com/issues/277700155
y
Yes, can you check if the launchMode
android:launchMode="singleInstance"
is set for your activity, and does adding onNewIntent to trigger
navController.handleDeepLink
manually works for you?
Copy code
override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    navController.handleDeepLink(intent)
}
Update: this also happens, as i call the startActivity() with FLAG_ACTIVITY_SINGLE_TOP , if the activity is already created. It will not trigger the
navController.handleDeepLink
.
y
@Hardik Khandelwal nice fix!
165 Views