Hello everyone,
I write this post in sheer frustration with Ionic deeplinks, deeplinks plugins and configurations.
This is going to be a long(-ish) rant and a cry for help, but I believe this will be useful to everyone in the future if solved, as confusion around this subject is tremendous.
Yeah, sorry to the Ionic devs but your docs also don’t help there and if something, only aggravate the confusion.
Let’s try to make what I want to achieve clear and go from there.
So, I have an application that runs on the browser and also as a mobile application, being that the “primary” usage would be the app.
To run on the browser, I use the Hash Location Strategy (which is the default setting, even on ionic serve
) as well as the Ionic 2 API Deeplinker to allow navigation directly to certain pages, which happens on https://app.mysite.com/#/login/:paramName
style links (notice the hash).
This works flawlessly.
Now, when on a mobile phone, I want to be able to have my app those same links, e.g., https://app.mysite.com
or https://app.mysite.com/#/login/:paramName
links rather than going to the browser.
To do that, I use the Ionic Native Deeplinks Plugin, which, as a bonus, also allows me to open myscheme://myapp
style links (which I don’t really plan to use, but it’s there).
But this is where the frustration starts.
The app does respond to http://app.mysite.com
links without a issue, however, links with a hash (and then the path and parameters) ALWAYS fail to match.
I WANT and NEED to have this working. I’ve tried a bunch of different configurations but nothing seems to work.
I’ve read posts like this one (a search gets you more results) and opened 1 or 2 threads about it.
Also on the Native Plugin Github issues, like this one, this one or this other one.
It goes without saying that I’ve read the Android (1, 2) and iOS docs on Universal App Links. I’ve read the blog posts about it. Still nothing
Now, as for my configurations:
The Ionic API Deeplink in app.module.ts
:
export const deepLinkConfig: DeepLinkConfig = {
links: [
{ component: Login, name: 'Login', segment: 'login/:name', defaultHistory: [LoginSocialNetworks] },
{ component: LoginSocialNetworks, name: 'LoginSocialNetworks', segment: 'login-sn/:name' },
{ component: ConfirmEmail, name: 'ConfirmEmail', segment: 'confirmation/:hash' },
{ component: ResetPassword, name: 'ResetPassword', segment: 'reset-password/:hash/:pwdToken' }
]
};
And my Native Deeplinker configuration in app.component.ts
this.platform.ready().then(() => {
(...)
let routes = {
'/login/:name': Login,
'/login-sn/:name': LoginSocialNetworks,
'/confirmation/:hash': ConfirmEmail,
'/reset-password/:hash/:pwdToken': ResetPassword,
'/mission/:id': MissionExpanded,
'/brand/:id': BrandDetails
}
Deeplinks.route(routes).subscribe(
match => {
this.nav.push(match.$route, match.$args, { animate: false, animation: "none" });
}, (nomatch) => {
// nomatch.$link - the full link data
console.error('Got a deeplink that didn\'t match', JSON.stringify(nomatch));
}, () => {
// nomatch.$link - the full link data
console.error('Got a deeplink completed');
});
(...)
}
My config.xml
goes like this:
<plugin name="ionic-plugin-deeplinks" spec="~1.0.8">
<variable name="URL_SCHEME" value="myscheme"/>
<variable name="DEEPLINK_SCHEME" value="https"/>
<variable name="DEEPLINK_HOST" value="devapp.mysite.com"/>
<variable name="DEEPLINK_2_SCHEME" value="https"/>
<variable name="DEEPLINK_2_HOST" value="app.mysite.com"/>
<variable name="DEEPLINK_3_SCHEME" value="https"/>
<variable name="DEEPLINK_3_HOST" value="stgapp.mysite.com"/>
</plugin>
Yes, I’ve noticed I’m not including an ANDROID_PATH_PREFIX
. I’m pretty sure I don’t need it but if you can convince me otherwise, I will.
Another thing that p***** me off is that, not matter what I do, my AndroidManifest.xml
always ends up with stupid stuff that I didn’t ask to get in there related to the plugins, namely, adding 5 hosts and the ANDROID_PATH_PREFIX
which I explicitly told it to remove, and if I edit it manually, the next build is going to add even more junk to the file (notice the “repeated” 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="myscheme" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:host="devapp.mysite.com" android:scheme="https" />
<data android:host="app.mysite.com" android:scheme="https" />
<data android:host="stgapp.mysite.com" android:scheme="https" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:host="devapp.mysite.com" android:pathPrefix="$ANDROID_PATH_PREFIX" android:scheme="https" />
<data android:host="app.mysite.com" android:pathPrefix="$ANDROID_2_PATH_PREFIX" android:scheme="https" />
<data android:host="stgapp.mysite.com" android:pathPrefix="$ANDROID_3_PATH_PREFIX" android:scheme="https" />
<data android:host="$DEEPLINK_4_HOST" android:pathPrefix="$ANDROID_4_PATH_PREFIX" android:scheme="$DEEPLINK_4_SCHEME" />
<data android:host="$DEEPLINK_5_HOST" android:pathPrefix="$ANDROID_5_PATH_PREFIX" android:scheme="$DEEPLINK_5_SCHEME" />
</intent-filter>
So, what gives? How the hell are we supposed to handle this sort of behaviour? Wasn’t it all supposed to work without conflicts?
I need some help here folks.
Sorry for the long post.
EDIT:
So, I eventually went ahead and debugged the deeplinks plugin code and found out that when we are passing a hash in the url, the first character on the match path will be removed. This provided me with a solution. When I went over to github to file an issue I eventually found this post with an exact description of the issue and the same solution I came to found. Since github doesn’t look for the # symbol this never came up in the search results.
For anyone troubled by the same issue the solution is to remove the first forward slash from the deeplinks routes, like this:
let routes = {
'login/:name': Login,
'login-sn/:name': LoginSocialNetworks,
'confirmation/:hash': ConfirmEmail,
'reset-password/:hash/:pwdToken': ResetPassword,
'mission/:id': MissionExpanded,
'brand/:id': BrandDetails
}
This magically makes it work. Doesn’t solve other problems though (like the repeated intent-filter or the placeholders or the number of hosts/schemes) but at least it works.
However, I suspect (because I haven’t tested and won’t test) this will break mycheme://app
links, unless we add the forward slashed paths again, possibly “duplicating” those entries.
Best Regards,
Celso Santos