Android Deeplinking not working with multiple schemes - android

I am stuck with the following scenario. I defined the following deep link intent filters in the AndroidManifest.xml
Expected behavior is when I found a url of format http://​www.domain.com/a/blabla or when there is link in SMS/eMail of format domain/xyz the system should trigger my activity.
Case #1: Working fine
<activity
android:name=".MYActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="xyz"
android:scheme="domain" />
</intent-filter>
</activity>
Case #2: Working fine
<activity
android:name=".MYActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="http"
android:host="www.domain.com"
android:pathPrefix="/a"
/>
</intent-filter>
</activity>
Case #3: NOT working
<activity
android:name=".MYActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="xyz"
android:scheme="domain" />
<data
android:scheme="http"
android:host="www.domain.com"
android:pathPrefix="/a"
/>
</intent-filter>
</activity>
Any suggestions/points/help is really appreciated

I placed both the deeplinks in two different intent filters and it worked!!!.

See the documentation of <data>: it states that:
All the <data> elements contained within the same <intent-filter> element contribute to the same filter.
Hence
<intent-filter>
<data
android:host="xyz"
android:scheme="domain" />
<data
android:scheme="http"
android:host="www.domain.com"
android:pathPrefix="/a" />
<intent-filter>
is interpreted equivalently as (not real code)
<intent-filter>
<data
android:host="xyz"
android:scheme="domain"
android:scheme="http"
android:host="www.domain.com"
android:pathPrefix="/a" />
<intent-filter>
which clearly has some contradictions, for example host being xyz VS www.domain.com.

From Android official documentation site :
Although it's possible to include multiple elements in the same
filter, it's important that you create separate filters when your
intention is to declare unique URLs (such as a specific combination of
scheme and host), because multiple elements in the same intent
filter are actually merged together to account for all variations of
their combined attributes.
You will have to create separate intent-filters.

Slightly off topic but relates the the OP question above with extra information that might help someone else.
If you have intent filters with deeplinks across multiple manifests and want to merge them without overriding each other you can add a unique android:label on your <intent-filter>.
Example:
main/AndroidManifest.xml
(These deeplinks are available to all app flavours, debug, prodcution etc)
<intent-filter android:label="main_deeplink1">
<data
android:host="domain.com"
android:scheme="https" />
<intent-filter>
debug/AndroidManifest.xml
(These deeplinks are available only to the debug build flavour)
<intent-filter android:label="debug_deeplink1">
<data
android:host="dev.domain.com"
android:scheme="https" />
<intent-filter>
The merged Manifest file will now contain both deeplinks without overriding each other.

Here is the tutorial I hop it helps
Tutorial link

Related

It is mandatory to specify the "android:host" for all url in android for Deep Link?

I have to filter two URL for an activity. I'm using Deep Links to App Content by specifying a url for the Deep Link Screen.
These are my urls
appdemo://deeplink
native://
I'm already added these two scheme to my Android Manifest file, looks like
<data android:scheme="appdemo" android:host="deeplink" />
<data android:scheme="native" />
my question is that, by providing scheme and host on the Android Manifest file, native:// this link does not work. it requires the android:host name also
(native://deeplink).
It is mandatory to specify the "android:host" for all url in android?
If no, how can i specify the different scheme.
The idea beside deep links is to use the same structure as normal links:
scheme://host/path
The main benefit is that you can teach your app even to open some Internet links, e.g. to open youtube (Android will ask, if you want to open in browser or YouTube app or your app):
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:host="youtube.com"/>
<data android:host="www.youtube.com"/>
<data android:host="m.youtube.com"/>
<data android:host="youtu.be"/>
<data android:pathPattern=".*"/>
</intent-filter>
So, answering your questions:
Yes, it is mandatory to specify both scheme and host.
A good practice of handling two different links in one activity is to use different paths. Like this:
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="appdemo" android:host="deeplink" android:pathPrefix="/path1/"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="appdemo" android:host="deeplink" android:pathPrefix="/path2/"/>
</intent-filter>
Then you can get your path in onNewIntent:
Uri data = intent.getData();
String path = data == null ? null : data.getPath();
...and build some logic depending on this path.
The above answer is acceptable and, in my case i want to navigate a new activity through this intent filter, and i got some information to the above answer and made some changes in my code and fix the issue.
Also I'm not specifying the host name for my second intent.
<activity
android:name=".DeepLinkActivity"
android:exported="true"
android:screenOrientation="portrait"
android:theme="#style/AppTheme.Launcher">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="appdemo" android:host="deeplink" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="native" />
</intent-filter>
</activity>
Now my both url navigate to DeepLinkActivity.
appdemo://deeplink
native://
Do you think this is not an optimized way?
Any other suggestions for that please mention.

Deep linking: id as host

I added this code in my Activity in AndroidManifest.xml:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:path="*" />
<data android:scheme="schemetest" />
</intent-filter>
Then I have tested two deep links:
schemetest://videos
schemetest://542325
The first is working fine but the second one is not even considered.
When I modifiy it to: schemetest://542325q for example, it works.
So my question is: are numbers allowed as host?
Thanks a lot.

Android intent-filter not filtering pathPrefix

We have lots of activities, but two were designed to start optionally from a URL using intent-filter. These two activities have the same scheme and host, but they have different pathPrefix. When we used a URL that matched one of these, it would just show our app once along with any browsers. Now, it is showing our app for any URL that matches the scheme. What we most care about is that its showing our app twice in our supported testing scenarios.
Does anyone have a workaround or know that this is a bug since we used to get the desired behavior? Does someone know what we changed that broke this (we have switched API level, build tools version, etc).
<activity
android:name="com.ConfigurationLoadingActivity"
android:label="#string/title_activity_configuration_loading" android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:noHistory="true" >
<intent-filter android:label="#string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="#string/app_intent_filter_host" android:pathPrefix="/mobilecloud/configuration" />
</intent-filter>
</activity>
<activity
android:name="com.SchoolSelectionActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:label="#string/title_activity_school_selection"
android:noHistory="true" >
<intent-filter android:label="#string/configuration_list">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="#string/app_intent_filter_host" android:pathPrefix="/mobilecloud/cloud" />
</intent-filter>
</activity>

Regex in intent-filter of Android Manifest

I am trying to include a regex in order to implement deeplinking to my activity. We have to activities that share a similar schema which is as follows:
Activity A - http://www.google.com/a/process?abc=xyz
Activity B - http://www.google.com/a//?pqr=efg.
Now I declared the deeplink in the manifest as follows :
<activity
android:name="com.xyz.samples.ActiivtyB" >
<intent-filter android:label="SimpleB">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="www.google.com"
android:pathPrefix="/a/"
android:scheme="http" />
</intent-filter>
</activity>
The above declaration for Activity B resolves both urls (mentioned above) since they share the same path till '/a/'.
However this is not the problem with Activity A, since its manifest is declared as below :
<activity
android:name="com.xyz.samples.ActiivtyA" >
<intent-filter android:label="SimpleA">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="www.google.com"
android:pathPrefix="/a/process"
android:scheme="http" />
</intent-filter>
</activity>
Hence I came thought of using "regex" which identifies urls of type /a/, I verified the regex here and it is working. Even I wrote a simple Java program to verify this and it is working fine. The regex is /a/)(?!\bsuccess\b).*
When I tried to create the deeplink with the above regex, app is not able to resolve the URL of type http://www.google.com/a//?pqr=efg. The manifest is updated as follows :
<activity
android:name="com.xyz.samples.ActiivtyB" >
<intent-filter android:label="SimpleB">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="www.google.com"
android:pathPattern="(/a/)(?!\\bsuccess\\b).\\*"
android:scheme="http" />
</intent-filter>
</activity>
Any help or insights on how to declare regex in manifest will be really helpful.
I gone thru the Android documentation here and updated the regex accordingly.
You mis-escaped your pattern - .\\* matches the literal string .*. But also:
pathPattern isn't a real regex, but a weird subset of regex. I don't think there's a way to exclude /a/success with those options.

Cannot download unknown extensions

I cannot download (from web & from e-mail) unkwown extentions such as (*.ini, *.zip, *.ddd)
unless there exists an app that can understand the extention.
For example, I couldn't download *.ini file from the browser (or email) until I downloaded 'Astro' app.
How can you by pass so that they are downloadable?
How can you register your app to understan certain extention so that it can be downloadable?
How can you by pass so that they are downloadable?
You don't.
How can you register your app to understan certain extention so that it can be downloadable?
Ideally, you don't. You do it by MIME type. File extensions are very fragile. However, either can be achieved via the use of the <data> element in your activity's <intent-filter>. You will also want the BROWSEABLE category and probably the VIEW action.
For example, here is how you would arrange to be an option for viewing PDF files:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="application/pdf" />
</intent-filter>
<activity
android:name=".Main"
android:label="#string/app_name">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
<category
android:name="android.intent.category.DEFAULT" />
<category
android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="file" />
<data
android:pathPattern=".*\\.ini" />
<data
android:host="*" />
</intent-filter>
</activity>
Above code allowed me to download *.ini files.
Thank you for your help.

Categories

Resources