Android Navigation Deep Link - Ignore Query - android

I'm attempting to add a deep-link for a URL that has the following format:
<deepLink
android:id="#+id/deep_link"
android:autoVerify="true"
app:uri="my.example.com/articles/{slug}" />
This causes the slug argument passed to my destination to also include the query if it exists. For example, the URL my.example.com/articles/recent-article?utm=1 results in the slug argument being recent-article?utm=1.
I've tried using the following pattern format in an attempt to ignore the query, but URLs no longer match correctly.
<deepLink
android:id="#+id/deep_link"
android:autoVerify="true"
app:uri="my.example.com/articles/{slug}?*.*" />
Is there a way to effectively ignore the query?

Assuming you're using the latest Navigation 2.2.0-rc04 (or one of the other Navigation 2.2 releases that adds support for query parameters), it sounds like you're hitting this issue where deeplinks without query parameters don't ignore query parameters.
The workaround mentioned in the bug is to include a dummy parameter:
<deepLink
android:id="#+id/deep_link"
android:autoVerify="true"
app:uri="my.example.com/articles/{slug}?dummy={dummy} />

Related

Intent filter: Handel hashtag sign on pathPattern and pathPrefix

I need your help to fix a problem with an intent filter that launches the activity after clicking a URI that looks like this https://myapp.com/#/path1/path2. Is there a way to escape hashtag signs when creating a path pattern?
I’ve tried /\\#/ , /%23/ and /.*/ without success.
Is there a way to override the default UriMatcher?
I need your help to fix a problem with an intent filter that launches the activity after clicking a URI that looks like this https://myapp.com/#/path1/pathe2.
My guess is that you would need to create an <intent-filter> just with the scheme and host, accepting all paths. You might be able to limit it to just a path of / — I have not tried matching only the / path of a domain.
Is there a way to escape hashtag signs when creating a path pattern?
In your example, your path is /. # is not part of the path. In URL syntax, # represents the separator that precedes the fragment portion of the URL. Your fragment is /path1/pathe2. You cannot match on a fragment (or query parameters) in an <intent-filter>.
Is there a way to override the default UriMatcher?
In custom firmware? Yes. In an app? No, because it is not part of your app.

Deep-linking with Navigation Uri issue when using strings.xml

I am checking below google sample code for test Deep-linking with Navigation.
Navigation with Deep linking Basic Sample
It works well. But in navigation.xml file I don't want to add uri directly , I want to use strings.xml file for same.
Not this :
<deepLink app:uri="www.example.com/user/{userName}" />
but , Want to do like this ,
<deepLink app:uri="#string/profile_url" />
the reason is that, if there is any changes in URL then I just have to go in strings.xml file and replace relative things.
Let me know if you have better idea about it or any better optimized solution.

Android app-action with custom query pattern

I have an android app that using com.google.android.gms.actions.SEARCH_ACTION
to search a phrase on my app using search for PHRASE on APP_NAME, but now I want use custom voice command like APP_NAME PHRASE to open my app and pass that phrase using google assistant.
So is it possible to implement this feature?
I have tried with https://github.com/actions-on-google/appactions-fitness-kotlin to get deep idea about actually how action intent works and found that it may be possible using deep linking.
Here in this example in actions.xml file one action actions.intent.GET_EXERCISE_OBSERVATION implemented as you can see below code.
<action intentName="actions.intent.GET_EXERCISE_OBSERVATION">
<fulfillment
fulfillmentMode="actions.fulfillment.SLICE"
urlTemplate="content://com.devrel.android.fitactions.FitSliceProvider/stats{?exerciseType}">
<parameter-mapping
entityMatchRequired="true"
intentParameter="exerciseObservation.aboutExercise.name"
required="true"
urlParameter="exerciseType" />
</fulfillment>
<fulfillment
fulfillmentMode="actions.fulfillment.DEEPLINK"
urlTemplate="https://fit-actions.firebaseapp.com/stats" />
<parameter name="exerciseObservation.aboutExercise.name">
<entity-set-reference entitySetId="ExerciseEntitySet" />
</parameter>
</action>
<!-- Defines an entity set with our supported entities -->
<entity-set entitySetId="ExerciseEntitySet">
<entity
name="#string/activity_running"
alternateName="#array/runningSynonyms"
identifier="RUNNING" />
<entity
name="#string/activity_walking"
alternateName="#array/walkingSynonyms"
identifier="WALKING" />
<entity
name="#string/activity_cycling"
alternateName="#array/cyclingSynonyms"
identifier="CYCLING" />
</entity-set>
But now I have some questions regarding this code.
How urlTemplate content://com.devrel.android.fitactions.FitSliceProvider/stats{?exerciseType} for actions.fulfillment.SLICE is generated?
Can exerciseObservation.aboutExercise.name have any custom value rather then defined in entity-set ?
How urlTemplate https://fit-actions.firebaseapp.com/stats for actions.fulfillment.DEEPLINK is generated?
After implementing this I think actions.intent.OPEN_APP_FEATURE will be helpful with the help of DEEPLINK fulfillment.
So is it possible to implement this using actions.intent.OPEN_APP_FEATURE"?
How urlTemplate content://com.devrel.android.fitactions.FitSliceProvider/stats{?exerciseType}
for actions.fulfillment.SLICE is generated?
The urlTemplate value (whether fulfilling via slice or deep link) is fully up to you to define. In the case of a deep link, this is the URL the system will call to open up your app. In the case of a Slice, this is the contentUri the system will call to render the Slice. The parameters inside the {} will be expanded with values at runtime. To get a better understanding of how that works, see the docs here and here or the Google I/O 2019 session.
Can exerciseObservation.aboutExercise.name have any custom value rather then defined in entity-set ?
I'm not exactly sure what you mean here but let me try and give more detail. The param name of exerciseObservation.aboutExercise.name is set for each Assistant Intent can cannot be changed. These values are listed in the documentation (example). The actual values of the parameters (that are populated by the user's query at runtime) are dynamic and will change based on the user's query and the Assistant Intent. For each Assistant Intent, you can refer to the docs to see what the possible values can be. In some cases they are from a set list of values (like for GET_EXERCISE_OBSERVATION), for others it could be a free form value based on the user's input, and for others still you can optionally extend the values using inline inventory (this is what you use <entity-set> for in your example).
How urlTemplate https://fit-actions.firebaseapp.com/stats for
actions.fulfillment.DEEPLINK is generated?
As per #1, the value of urlTemplate is totally up to you to configure. It can be any Android Intent URI. The system will call this Uri to start up your app/Activity.
After implementing this I think
actions.intent.OPEN_APP_FEATURE will be helpful with the
help of DEEPLINK fulfillment.
So is it possible to implement this using
actions.intent.OPEN_APP_FEATURE"?
OPEN_APP_FEATURE is just another Assistant Intent that allows a generic call into a feature of your app. The docs were recently updated with some example queries. Eg.
Open Youtube history
This example will open the app named "YouTube" and pass the feature name "history" to the app to handle.
Open Example App Example feature
This example will open the app named "Example App" and pass the feature name "Example feature" to the app to handle.

Deep link with optional query parameters

Edit: This is a bug (missing feature?) in the manifest merger. It works in Android Studio 3.5 Canary 5 and above. So what one want's to do is to add one <deepLink /> per uri. Which in my case would be
<deepLink
android:id="#+id/deepLink"
app:uri="https://www.example.com/foo?cn={cardNumber}&bd={birthDate}"/>
<deepLink
android:id="#+id/deepLink2"
app:uri="https://www.example.com/foo?cn={cardNumber}"/>
I have a deep link in the form "https://www.example.com/foo?cn=L349DA&bd=1982-03-12"
and I parse it in my navigation graph with
<deepLink
android:id="#+id/deepLink"
app:uri="https://www.example.com/foo?cn={cardNumber}&bd={birthDate}"/>
That all works well. But my parameter bd is optional, so I'm not guaranteed that it will be included in the url. How do we handle this case?
I've tried with wildcards * on the parameter with no luck. And I've tried with adding two <deepLink .../> elements, but that yields a Manifest merger failed: Multiple destinations... error.
Thanks in advance!
In "androidx.navigation:navigation-*:2.2.0-alpha02"
September 5, 2019
Deep links with query parameters now support reordered query parameters; arguments that have a default value or are nullable are now optional when matching deep links. (b/133273839)
Android Developers Jetpack AndroidX Navigation

"URL not defined in the manifest" when running Instant App that uses #string for host name

Seeing issue running Instant App in Android Studio when #string value is used for host name (getting "URL not defined in the manifest" error). For example:
<data android:scheme="https" android:host="#string/SOME_DOMAIN" />
This is working fine if android:host is set to raw domain string. I can work around this by setting that value to specific domain value when running/debugging from AS but not ideal (always danger of pushing code that contains the hard coded string!)
Also, this works fine if I build/deploy base and feature apks from command line and trigger using something like adb shell am start -W -a android.intent.action.VIEW -d "<my url>"
Maybe this is because it's not the main
Manifest.xml
, but the debug Manifest.. Try editing
app/src/main/Manifest
Note: host name matching in the Android framework is case-sensitive, unlike the formal RFC. As a result, you should always specify host names using lowercase letters.
Reference Android developer String Resources
as alternative you can use manifestPlaceholders
<data android:scheme="https" android:host="${SOME_DOMAIN} />
in you build.gradle:
flavor {
dimension "instant"
manifestPlaceholders = [SOME_DOMAIN: "https://instantapp.example.com/"]
}
The documentation is a bit unclear on whether android:host can contain a string resource, or just a simple string:
<data android:scheme="string"
android:host="string"
android:port="string"
android:path="string"
android:pathPattern="string"
android:pathPrefix="string"
android:mimeType="string" />
But according to Google employee #dchai:
String resources are supposed to be supported … This is a bug in Android Studio.
The bug in question has been fixed in Android Studio 3.2, so
now it's possible to use string resource and manifest build variable as a value for data attributes.

Categories

Resources