I am developing an android app which accepts deeplink. For example consider this one:
<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="returnapp" android:scheme="testscheme" />
</intent-filter>
So if we call the url testscheme://returnapp/?status=1 then app should be opened.
In Google Chrome it opens up and everything goes right but in firefox, the app gets opened as child of browser task (which has the link to my app). But I want it to be opened independently.
So is there something to add to manifest to force this attribute or I should add some keyword in my HTML href?
UPDATE
I think I should make a change in the link showing in webpage in firefox. Currently I am using this link:
<h1>test</h1>
Something like target="_system" to tell firefox to open this link externally.
The browsers itself need to support and implment the browsability. The browsers have to find other activities supporting android.intent.category.BROWSABLE when opening a web-page.
So as you say, Firefox is not supported for opening app directly, however there is a solution you can try is to add android:autoVerify="true" in any one of the web URL intent filters in your app manifest that include the android.intent.action.VIEW intent action and android.intent.category.BROWSABLE intent category, as shown in the following manifest code snippet:
<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="returnapp" android:scheme="testscheme" />
</intent-filter>
Even though I'm still not sure this gonna work because of android:autoVerify="true" is for appLink not for deepLink
I'm creating a intent-filter in order to filter in my app urls like https://www.hotelsclick.com/?hotel_id=135738
I see in the documentation that I should create an intent filter like
<intent-filter android:label="#string/filter_title_viewgizmos">
<action android:name="android.intent.action.VIEW" />
<!-- Accepts URIs that begin with "http://example.com/gizmos” -->
<data android:scheme="http"
android:host="example.com"
android:pathPrefix="/gizmos" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
This intent-filter should filter URLs like "http://example.com/gizmos?1234, http://example.com/gizmos/1234, http://example.com/gizmos/toys/1234"
That's good but... my URL is different, it's like http://example.com?toys=1234 'cause it's got a named GET parameter just in the home page, which is hotel_id.
How can I filter such URLs? Is there some more parameter to put in the intent-filter definition?
Edit: I put the following intent-filter in my Manifest.xml
<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="hotelsclick.com" />
<data android:scheme="http"
android:host="hotelsclick.com" />
</intent-filter>
and I CAN open the app by providing this ADB command
adb shell am start -a android.intent.action.VIEW -d "http://hotelsclick.com?hotel_id=135738" com.towers.hotelsclick
BUT it doesn't work from the page self-generated with the deep-link tool: https://developers.google.com/app-indexing/webmasters/test?hl=it
I put in the webpage the following URI in the editText: "android-app://com.towers.hotelsclick/hotelsclick.com?hotel_id=135738" and I got this page: https://applinktest.appspot.com/app-link.html?url=android-app%3A%2F%2Fcom.towers.hotelsclick%2Fhotelsclick.com%3Fhotel_id%3D135738
As you can see the link in the page is intent://#Intent;scheme=hotelsclick.com?hotel_id=135738;package=com.towers.hotelsclick;end and I expected this intent-link to be opened by the app itself when clicked on mobile on the same phone I used for the adb command before. But it doesn't work and takes me straight to the google play store, suggesting to open the app from there
So, since I can make the intent-filter work via ADB but not with a proper link, can I say I succeeded or not?
Thank you
The generated link is not valid. It should be
intent://hotelsclick.com?hotel_id=135738#Intent;scheme=http;package=com.towers.hotelsclick;end
instead of
intent://#Intent;scheme=hotelsclick.com?hotel_id=135738;package=com.towers.hotelsclick;end
The closest I could find was this question here. but it doesnt quite cover the problem im having.
I have deep links in my app setup to use /app as the path prefix. The problem I'm having is that links like http://example.com/upgrade are also trying to open in my app even though it doesn't have /app anywhere in the url. I understand you cant exclude urls specified by the prefix, but isn't the whole point of path prefix to include only those urls?
basically I want links like these to deep link:
http://example.com/app/home
http://example.com/app/specials
but not links like these:
http://exaple.com/
http://example.com/login
and here is what I have in my manifest:
<data android:scheme="http"
android:host="example.com"
android:pathPrefix="/app"/>
Edit 1
also found this link but i dont have any empty prefixes, only ones with just a slash "/"
Edit 2
The url that was triggering it was http://example.com/upgrade.php?app=1&method=1&uid=1, I wasn't sure if app after the ? would also trigger it so I changed the prefix to /application but that also didn't work, its still triggering them.
Edit 3
here are the other deep link data tags in the manifest:
profile activity
<data android:scheme="myapp"
android:host="profile"
android:pathPrefix="/"/>
login/signup activity
<data android:scheme="myapp"
android:host="login"
android:pathPrefix="/signup"/>
main activity
<data android:scheme="myapp"
android:host="main"
android:pathPrefix="/"/>
<data android:scheme="http"
android:host="test.example.com"
android:pathPrefix="/app"/>
<data android:scheme="http"
android:host="live.example.com"
android:pathPrefix="/app"/>
Edit 4
This is getting more and more confusing, if I remove the data tag with myapp as the scheme from the activity (or if i remove the pathPrefix from everything with a prefix of "/") it no longer triggers the deep links from the web urls, even if they have /app in them.
I figured it out, It seems like the data tags sort of bleed into one another, so the prefix of "/" on the data with scheme "example" was also applying to all of the schemes in the other data tags. I just had to use separate Intent filters for my custom scheme deep links and the url deep links like so:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- must start with http://test.example.com/app -->
<!-- http://test.example.com/ won't work since prefix / is in a different intent-filter -->
<data android:scheme="http"
android:host="test.example.com"
android:pathPrefix="/app"/>
<!-- must start with http://live.example.com/app -->
<data android:scheme="http"
android:host="live.example.com"
android:pathPrefix="/app"/>
</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" />
<!-- must start with example://main/ -->
<!-- http://test.example.com/ won't work since http is in a different intent-filter -->
<data android:scheme="example"
android:host="main"
android:pathPrefix="/"/>
</intent-filter>
</activity>
As explained here, your attributes get merged:
Although it's possible to include multiple <data> 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 <data> elements in the same intent filter are actually merged together to account for all variations of their combined attributes.
Putting them into separate instances of <intent-filter> therefore fixes your problem.
Running a few tests on my own I think you have created this problem yourself, before continuing to test any more deep links from your app go to
Settings -> Your App Name -> Launch by Default and select Clear defaults
Then navigate back to your app manifest and add the intent filter to your Activity for each url:
In your example you ask for
http://example.com/app/home
http://example.com/app/specials
I am going to assume you have an Activity that would launch each one of these for the URI given above.
for HomeActivity in manifest do:
<activity android:name=".HomeActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- http://example.com/app/home -->
<data android:scheme="http"
android:host="example.com"
android:pathPrefix="/app/home"/>
<!-- https://example.com/app/home -->
<data android:scheme="https"
android:host="example.com"
android:pathPrefix="/app/home"/>
<!-- custom url scheme example://app/home -->
<data android:scheme="example"
android:host="app"
android:pathPrefix="/home"/>
</intent-filter>
</activity>
Test with adb shell am start -W -a android.intent.action.VIEW -d http://example.com/app/home and adb shell am start -W -a android.intent.action.VIEW -d example.com/app/home From your terminal
then for your SpecialsActivity
<activity android:name=".SpecialsActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- http://example.com/app/specials -->
<data android:scheme="http"
android:host="example.com"
android:pathPrefix="/app/specials"/>
<!-- https://example.com/app/specials -->
<data android:scheme="https"
android:host="example.com"
android:pathPrefix="/app/specials"/>
<!-- custom url scheme example://app/specials -->
<data android:scheme="example"
android:host="app"
android:pathPrefix="/specials"/>
</intent-filter>
</activity>
Test with adb shell am start -W -a android.intent.action.VIEW -d http://example.com/app/specials and adb shell am start -W -a android.intent.action.VIEW -d example.com/app/specials From your terminal
this is pretty much how it works, if you set your app to handle a http://example.com/ url and select choose by default then, well its going to try to open http://example.com/{anything} using your app
So in short, when you specify your pathPrefix, make sure you include what you really want to intercept and don't choose your app by default if you test a link that shouldn't open your app, just adjust your pathPrefix so it won't be triggered by your app.
For example the URLS above won't open
http://example.com/app
because we haven't defined a <data /> tag to handle this.
UPDATE
And to add straight from the docs when using \ or *:
Because '\' is used as an escape character when the string is read from XML (before it is parsed as a pattern), you will need to double-escape: For example, a literal '*' would be written as '\\*' and a literal '\' would be written as '\\\\'. This is basically the same as what you would need to write if constructing the string in Java code.
Good luck and happy coding!
Can we implement deeplinking for a mobile app without having a website or do we have to have a predefined specific website to implemment it?
Deep linking can work without having a specific website. All you need for it to work is add the <intent-filter> ... </intent-filter> tag to your preferred activity via the AndroidManifest.
Then create a unique URI pattern intended to match any HTTP URI such as http://your-app-domain/content or a custom scheme such as your-app://content. Add this scheme to the <data ... /> tag.
Here's what your activity should look like when you're done.
<activity
android:name=".activities.DeepLinkingActivity"
android:label="#string/title_activity_deeplink">
<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="your-app-domain"
android:pathPrefix="/content"
android:scheme="http" />
</intent-filter>
</activity>
Regardless of the URI scheme you choose, you should be able to begin your activity when an intent with the scheme is triggered.
If you are familiar with adb commands, enter this command
adb shell am start -a android.intent.action.VIEW -d "http://your-app-domain/content" com.your-app-package
Further reading https://developers.google.com/app-indexing/android/app
Can anybody please guide me regarding how to launch my android application from the android browser?
Use an <intent-filter> with a <data> element. For example, to handle all links to twitter.com, you'd put this inside your <activity> in your AndroidManifest.xml:
<intent-filter>
<data android:scheme="http" android:host="twitter.com"/>
<action android:name="android.intent.action.VIEW" />
</intent-filter>
Then, when the user clicks on a link to twitter in the browser, they will be asked what application to use in order to complete the action: the browser or your application.
Of course, if you want to provide tight integration between your website and your app, you can define your own scheme:
<intent-filter>
<data android:scheme="my.special.scheme" />
<action android:name="android.intent.action.VIEW" />
</intent-filter>
Then, in your web app you can put links like:
<a href="my.special.scheme://other/parameters/here">
And when the user clicks it, your app will be launched automatically (because it will probably be the only one that can handle my.special.scheme:// type of uris). The only downside to this is that if the user doesn't have the app installed, they'll get a nasty error. And I'm not sure there's any way to check.
Edit: To answer your question, you can use getIntent().getData() which returns a Uri object. You can then use Uri.* methods to extract the data you need. For example, let's say the user clicked on a link to http://twitter.com/status/1234:
Uri data = getIntent().getData();
String scheme = data.getScheme(); // "http"
String host = data.getHost(); // "twitter.com"
List<String> params = data.getPathSegments();
String first = params.get(0); // "status"
String second = params.get(1); // "1234"
You can do the above anywhere in your Activity, but you're probably going to want to do it in onCreate(). You can also use params.size() to get the number of path segments in the Uri. Look to javadoc or the android developer website for other Uri methods you can use to extract specific parts.
All above answers didn't work for me with CHROME as of 28 Jan 2014
my App launched properly from http://example.com/someresource/ links from apps like hangouts, gmail etc but not from within chrome browser.
to solve this, so that it launches properly from CHROME you have to set intent filter 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:host="example.com"
android:pathPrefix="/someresource/"
android:scheme="http" />
<data
android:host="www.example.com"
android:pathPrefix="/someresource/"
android:scheme="http" />
</intent-filter>
note the pathPrefix element
your app will now appear inside activity picker whenever user requests http://example.com/someresource/ pattern from chrome browser by clicking a link from google search results or any other website
Please see my comment here: Make a link in the Android browser start up my app?
We strongly discourage people from using their own schemes, unless they are defining a new world-wide internet scheme.
In my case I had to set two categories for the <intent-filter> and then it worked:
<intent-filter>
<data android:scheme="my.special.scheme" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
For example, You have next things:
A link to open your app: http://example.com
The package name of your app: com.example.mypackage
Then you need to do next:
Add an intent filter to your Activity
(Can be any activity you want. For more info check the documentation).
<activity
android:name=".MainActivity">
<intent-filter android:label="#string/filter_title_view_app_from_web">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with "http://example.com" -->
<data
android:host="example.com"
android:scheme="http" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Create a HTML file to test the link or use this methods.
Open your Activity directly (just open your Activity, without a choosing dialog).
Open this link with browser or your programm (by choosing dialog).
Use Mobile Chrome to test
That's it.
And its not necessary to publish app in market to test deep linking =)
Also, for more information, check documentation and useful presentation.
There should also be <category android:name="android.intent.category.BROWSABLE"/> added to the intent filter to make the activity recognized properly from the link.
The following link gives information on launching the app (if installed) directly from browser. Otherwise it directly opens up the app in play store so that user can seamlessly download.
https://developer.chrome.com/multidevice/android/intents
Please note if your icon is disappear from android launcher when you implement this feature, than you have to split intent-filter.
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</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="your-own-uri" />
</intent-filter>
</activity>
Yeah, Chrome searches instead of looking for scheme. If you want to launch your App through URI scheme, use this cool utility App on the Play store. It saved my day :)
https://play.google.com/store/apps/details?id=com.naosim.urlschemesender
Xamarin port of Felix's answer
In your MainActivity, add this (docs: Android.App.IntentFilterAttribute Class):
....
[IntentFilter(new[] {
Intent.ActionView },
Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },
DataScheme = "my.special.scheme")
]
public class MainActivity : Activity
{
....
Xamarin will add following in the AndroidManifest.xml for you:
<activity
android:label="Something"
android:screenOrientation="portrait"
android:theme="#style/MyTheme"
android:name="blah.MainActivity">
<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="my.special.scheme" />
</intent-filter>
</activity>
And in order to get params (I tested in OnCreate of MainActivity):
var data = Intent.Data;
if (data != null)
{
var scheme = data.Scheme;
var host = data.Host;
var args = data.PathSegments;
if (args.Count > 0)
{
var first = args[0];
var second = args[1];
...
}
}
As far as I know, above can be added in any activity, not only MainActivity
Notes:
When user click on the link, Android OS relaunch your app (kill prev instance, if any, and run new one), means the OnCreate event of app's MainLauncher Activity will be fired again.
With this link: <a href="my.special.scheme://host/arg1/arg2">, in above last code snippet values will be:
scheme: my.special.scheme
host: host
args: ["arg1", "arg2"]
first: arg1
second: arg2
Update: if android creates new instance of your app, you should add android:launchMode="singleTask" too.
Felix's approach to handling deep links is the typical approach to handling deep links. I would also suggest checking out this library to handle the routing and parsing of your deep links:
https://github.com/airbnb/DeepLinkDispatch
You can use annotations to register your Activity for a particular deep link URI, and it will extract out the parameters for you without having to do the usual rigmarole of getting the path segments, matching it, etc. You could simply annotate and activity like this:
#DeepLink("somePath/{someParameter1}/{someParameter2}")
public class MainActivity extends Activity {
...
}
Hey I got the solution. I did not set the category as "Default". Also I was using the Main activity for the intent Data. Now i am using a different activity for the intent data. Thanks for the help. :)
You need to add a pseudo-hostname to the CALLBACK_URL 'app://' doesn't make sense as a URL and cannot be parsed.
example.php:
<?php
if(!isset($_GET['app_link'])){ ?>
<iframe src="example.php?app_link=YourApp://blabla" style="display:none;" scrolling="no" frameborder="0"></iframe>
<iframe src="example.php?full_link=http://play.google.com/xyz" style="display:none;" scrolling="no" frameborder="0"></iframe>
<?php
}
else { ?>
<script type="text/javascript">
self.window.location = '<?php echo $_GET['app_link'];?>';
window.parent.location.href = '<?php echo $_GET['full_link'];?>';
</script>
<?php
}
Look #JRuns answer in here. The idea is to create html with your custom scheme and upload it somewhere. Then if you click on your custom link on your html-file, you will be redirected to your app. I used this article for android. But dont forget to set full name Name = "MyApp.Mobile.Droid.MainActivity" attribute to your target activity.
As of 15/06/2019
what I did is include all four possibilities to open url.
i.e, with http / https and 2 with www in prefix and 2 without www
and by using this my app launches automatically now without asking me to choose a browser and other option.
<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:scheme="https" android:host="example.in" />
<data android:scheme="https" android:host="www.example.in" />
<data android:scheme="http" android:host="example.in" />
<data android:scheme="http" android:host="www.example.in" />
</intent-filter>