Handling links from other apps: how does stackexchange android app do it? - android

If you're an avid user of stackexchange android app, you might have noticed this: make a Google search with chrome, if the SERP contains any link from any stackexchange site and you click it, it will automatically open stackexchange app and the clicked question will be loaded.
See an example :
Please, how can I achieve something similar with my app?

You should see Deep-linking chapter
https://developer.android.com/training/app-indexing/deep-linking.html
Define intent filter for the activity (which is going to handle the url ) you want to launch in Manifest
<activity
android:name="com.example.android.LinkHandlerActivity"
android:label="#string/title_gizmos" >
<intent-filter android:label="#string/filter_title_viewgizmos">
<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://www.example.com/gizmos” -->
<data android:scheme="http"
android:host="www.example.com"
android:pathPrefix="/gizmos" />
<!-- note that the leading "/" is required for pathPrefix-->
<!-- Accepts URIs that begin with "example://gizmos” -->
<data android:scheme="example"
android:host="gizmos" />
</intent-filter>
And then handle link in activity like this
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = getIntent();
String action = intent.getAction();
Uri data = intent.getData();
}

It is called Deep App Linking. Here is the tutorial. But, I read some stuff a while ago, that Google no longer use Deep App Linking. I guess they use App Indexing now. Here is the info about App Indexing. Note that, maybe you can use Deep App Linking for now, but it can be deprecated. You can google it for further info.
You need to add deep app links to your webpage html files. Which when clicked from mobile browser, sends an intent to app. In Deep Indexing you don't need to do that I guess.
Sorry, I could've commented that, but my reputation is not enough.

Related

share link from a link of a web page [duplicate]

Is it possible to make a link such as:
click me!
cause my Anton app to start up?
I know that this works for the Android Market app with the market protocol, but can something similar be done with other apps?
Here is an example of a link that will start up the Android Market:
click me!
Update:
The answer I accepted provided by eldarerathis works great, but I just want to mention that I had some trouble with the order of the subelements of the <intent-filter> tag. I suggest you simply make another <intent-filter> with the new subelements in that tag to avoid the problems I had. For instance my AndroidManifest.xml looks like this:
<activity android:name=".AntonWorld"
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>
<data android:scheme="anton" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Please DO NOT use your own custom scheme like that!!! URI schemes are a network global namespace. Do you own the "anton:" scheme world-wide? No? Then DON'T use it.
One option is to have a web site, and have an intent-filter for a particular URI on that web site. For example, this is what Market does to intercept URIs on its web site:
<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="market.android.com"
android:path="/search" />
</intent-filter>
Alternatively, there is the "intent:" scheme. This allows you to describe nearly any Intent as a URI, which the browser will try to launch when clicked. To build such a scheme, the best way is to just write the code to construct the Intent you want launched, and then print the result of intent.toUri(Intent.URI_INTENT_SCHEME).
You can use an action with this intent for to find any activity supporting that action. The browser will automatically add the BROWSABLE category to the intent before launching it, for security reasons; it also will strip any explicit component you have supplied for the same reason.
The best way to use this, if you want to ensure it launches only your app, is with your own scoped action and using Intent.setPackage() to say the Intent will only match your app package.
Trade-offs between the two:
http URIs require you have a domain you own. The user will always get the option to show the URI in the browser. It has very nice fall-back properties where if your app is not installed, they will simply land on your web site.
intent URIs require that your app already be installed and only on Android phones. The allow nearly any intent (but always have the BROWSABLE category included and not supporting explicit components). They allow you to direct the launch to only your app without the user having the option of instead going to the browser or any other app.
I think you'll want to look at the <intent-filter> element of your Manifest file. Specifically, take a look at the documentation for the <data> sub-element.
Basically, what you'll need to do is define your own scheme. Something along the lines of:
<intent-filter>
<data android:scheme="anton" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <--Not positive if this one is needed
...
</intent-filter>
Then you should be able to launch your app with links that begin with the anton: URI scheme.
I have a jQuery plugin to launch native apps from web links: https://github.com/eusonlito/jquery.applink
You can use it easily:
<script>
$('a[data-applink]').applink();
</script>
My Facebook Profile
I also faced this issue and see many absurd pages. I've learned that to make your app browsable, change the order of the XML elements, this this:
<activity
android:name="com.example.MianActivityName"
android:label="#string/title_activity_launcher">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<data android:scheme="http" />
<!-- or you can use deep linking like -->
<data android:scheme="http" android:host="xyz.abc.com"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
This worked for me and might help you.
Here's my recipe:
Create a static HTML that redirects to your requested app URL, put that page on the web.
That way, the links you share are 'real' links as far as Android is concerned ( they will be 'clickable').
You 'share' a regular HTTP link, www.your.server.com/foo/bar.html
This URL returns a simple 8 line HTML that redirects to your app's URI (window.location = "blah://kuku") (note that 'blah' doesn't have to be HTTP or HTTPS any more).
Once you get this up and running, you can augment the HTML with all the fancy capabilities as suggested above.
This works with the built-in browser, Opera, and Firefox (haven't tested any other browser). Firefox asks 'This link needs to be opened with an application' (ok, cancel). Other browsers apparently don't worry about security that much, they just open the app, no questions asked.
This method doesn't call the disambiguation dialog asking you to open either your app or a browser.
If you register the following in your Manifest
<manifest package="com.myApp" .. >
<application ...>
<activity ...>
<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="gallery"
android:scheme="myApp" />
</intent-filter>
</activity>
..
and click this url from an email on your phone for example
<a href="intent://gallery?directLink=true#Intent;scheme=myApp;package=com.myApp;end">
Click me
</a>
then android will try to find an app with the package com.myApp that responds to your gallery intent and has a myApp scheme. In case it can't, it will take you to the store, looking for com.myApp, which should be your app.
Once you have the intent and custom url scheme for your app set up, this javascript code at the top of a receiving page has worked for me on both iOS and Android:
<script type="text/javascript">
// if iPod / iPhone, display install app prompt
if (navigator.userAgent.match(/(iPhone|iPod|iPad);?/i) ||
navigator.userAgent.match(/android/i)) {
var store_loc = "itms://itunes.com/apps/raditaz";
var href = "/iphone/";
var is_android = false;
if (navigator.userAgent.match(/android/i)) {
store_loc = "https://play.google.com/store/apps/details?id=com.raditaz";
href = "/android/";
is_android = true;
}
if (location.hash) {
var app_loc = "raditaz://" + location.hash.substring(2);
if (is_android) {
var w = null;
try {
w = window.open(app_loc, '_blank');
} catch (e) {
// no exception
}
if (w) { window.close(); }
else { window.location = store_loc; }
} else {
var loadDateTime = new Date();
window.setTimeout(function() {
var timeOutDateTime = new Date();
if (timeOutDateTime - loadDateTime < 5000) {
window.location = store_loc;
} else { window.close(); }
},
25);
window.location = app_loc;
}
} else {
location.href = href;
}
}
</script>
This has only been tested on the Android browser. I am not sure about Firefox or Opera. The key is even though the Android browser will not throw a nice exception for you on window.open(custom_url, '_blank'), it will fail and return null which you can test later.
Update: using store_loc = "https://play.google.com/store/apps/details?id=com.raditaz"; to link to Google Play on Android.
You may want to consider a library to handle the deep link to your app:
https://github.com/airbnb/DeepLinkDispatch
You can add the intent filter on an annotated Activity like people suggested above. It will handle the routing and parsing of parameters for all of your deep links. For example, your MainActivity might have something like this:
#DeepLink("somePath/{useful_info_for_anton_app}")
public class MainActivity extends Activity {
...
}
It can also handle query parameters as well.
Try my simple trick:
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url.startsWith("classRegister:")) {
Intent MnRegister = new Intent(getApplicationContext(), register.class); startActivity(MnRegister);
}
view.loadUrl(url);
return true;
}
and my html link:
Go to register.java
or you can make < a href="classRegister:true" > <- "true" value for class filename
however this script work for mailto link :)
if (url.startsWith("mailto:")) {
String[] blah_email = url.split(":");
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setType("text/plain");
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{blah_email[1]});
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, what_ever_you_want_the_subject_to_be)");
Log.v("NOTICE", "Sending Email to: " + blah_email[1] + " with subject: " + what_ever_you_want_the_subject_to_be);
startActivity(emailIntent);
}
Just want to open the app through browser? You can achieve it using below code:
HTML:
Click here
Manifest:
<intent-filter>
<action android:name="packageName" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
This intent filter should be in Launcher Activity.
If you want to pass the data on click of browser link, just refer this link.

Handling external links in android webview

I want to open my app and load the URL when specific links are clicked.
This is my Manifest for handling external links.
<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="http" android:host="www.android.com" />
<data android:scheme="https" android:host="www.android.com" />
</intent-filter>
And for handling incoming links this is the code
intentData = getIntent().getData();
if(intentData !=null){
loadUrl = intentData.toString();
}else {
loadUrl = "https://www.android.com";
}
webView.loadUrl(loadUrl);
Now when I clicked https://www.android.com from external app like whatsapp its loaded in webview but the webview is attached to whatsapp. Check screenshots below.
And if anyone can give me any hints or guide me on how to open my app when I open the URL(https://www.android.com) from Google Chrome(in my phone) will be a great help
For second part of your question:
And if anyone can give me any hints or guide me on how to open my app
when I open the URL(https://www.android.com) from Google Chrome(in my
phone) will be a great help
take a look at this answer:
"Essentially, the Chrome team feels that if a user actually types something into the address bar, no redirect should ever happen. As you've discovered, this is counter to behavior in all other browsers."
Use this line in Manifest file of your Activity which is Handling that intent to avoid such problem.
android:launchMode="singleTask"
You can find detail implementation here, https://developer.android.com/guide/webapps/webview.html
You have to override methods, and handle clicks.

Firebase Deep-link opening play store even when the app is installed

I'm developing an android app.
Upon clicking a button, a deep-link is generated and shared with friends.
The problem is that upon clicking that shared deep-link, play store is getting opened even when the app is installed.
I followed this documentation.
Here's the intent-filter:
<!-- [START link_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:host="example.com" android:scheme="http"/>
<data android:host="example.com" android:scheme="https"/>
</intent-filter>
<!-- [END link_intent_filter] -->
Here's how I'm creating the url (manually):
Uri BASE_URI = Uri.parse("https://domainname.com/");
packageName = getBaseContext().getPackageName();
APP_URI = BASE_URI.buildUpon().path(requestID.getText().toString().trim())
.appendQueryParameter("query1", query1.getText().toString())
.appendQueryParameter("query2", query2.getText().toString())
.appendQueryParameter("query3", query3.getText().toString()).build();
try {
String encodedUri = URLEncoder.encode(APP_URI.toString(), "UTF-8");
deepLink = Uri.parse("https://myappcode.app.goo.gl/?link="+encodedUri+"&apn="+holder.packageName+"&amv="+16+"&ad="+0);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Here's the received deep-link/url: http://domainname.com/-KcldzAeJHrPS5tnfxTk?query1=query1&query2=query2&query3=query3
What could be wrong here?
There are at least three things that could possibly be wrong:
The way you are opening the url:
I saw similar problem when writing the url to browser window on Android device. When adding the link to an email and clicking it, the app was opened. You write "click" so perhaps this is not the problem.
Your url and your app/manifest do not match:
You have not added proper intent handler for the protocol or the host to correct place in your manifest or your url does not match with what you have added. Or apn given in the url does not match your apps package name. Based on the question in the current state the host does not match.
You are not sharing the deeplink url, but just an ordinary url:
If you expect the shared url to open preinstalled app, your friends will need to click (on an email or similar) the complete deeplink url, which then either directs the link to play store (if app is not installed) or opens the app (if correctly implemented). Normal url is just opened in the browser. Based on the current state of the question, this could be the case.
If fixing the above does not work:
Try adding specific Android link to your url, something like this:
https://<myappcode>.app.goo.gl/?link=http://domainname.com&apn=com.doman.app&amv=16&ad=0&al=myscheme://any-string-you-choose
after which your intent filter should be something like this:
<!-- [START link_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:host="any-string-you-choose" android:scheme="myscheme"/>
</intent-filter>
<!-- [END link_intent_filter] -->
I prefer this way since it is a bit more flexible compared to using only link. Naturally the package name and other things need to be correct also when using this method. Android link is url to be opened only in android app, a bit poorly documented, check it from here (the example). Also my reply to another question gives some examples on how to use it.
(edit 19.3.2018) It seems that Firebase does not fully support 'al=' anymore. The code works, but it is missing from the documentation and Firebase console generated urls.

How to make a android app that can be used as a default program for opening certain kind of link? [duplicate]

This question already has answers here:
How to implement my very own URI scheme on Android
(5 answers)
Closed 7 years ago.
I want to make an android app that can be used as a default application for opening a certain kind of link (like if I click http://facebook.com it will show me suggested app to open that link, browser or facebook's app)
These are called Implicit Intents
Assume you want to open your app on web link click with link "myApp://someapp"
then in your App Manifest
<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="myApp" android:host="path" />
</intent-filter>
</activity>
Whenever you click the above link, it will suggest to open your app.
If you want to developed application that allow the other application to complete the action using your application, for example in your case you want to handle the any of url user click, your application will be listed for complete the action. You have to create the activity that will handle the deep linking. For that you need to add some attributes to your handle activity in your android manifest. see below example
The following XML snippet shows how you might specify an intent filter in your manifest for deep linking. The URIs that start with “http”
<activity
android:name="com.example.android.BrowseActivity"
>
<intent-filter>
<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://www.example.com/gizmos” -->
<data android:scheme="http"
android:host="www.example.com"
android:pathPrefix="/gizmos" />
<!-- note that the leading "/" is required for pathPrefix-->
<!-- Accepts URIs that begin with custom url "example://gizmos” -->
<data android:scheme="com.example.android"
android:host="gizmos" />
</intent-filter>
</activity>
Once you've added intent filters with URIs for activity content to your app manifest, Android is able to route any Intent that has matching URIs to your app at runtime.
Once the system starts your activity(BrowseActivity) through an intent filter, you can use data provided by the Intent to determine what you need to render. Call the getData() and getAction() methods to retrieve the data and action associated with the incoming Intent. You can call these methods at any time during the lifecycle of the activity, but you should generally do so during early callbacks such as onCreate() or onStart().
Here’s a snippet that shows how to retrieve data from an Intent inside BrowseActivity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = getIntent();
String action = intent.getAction();
Uri data = intent.getData();
}
Let me know if you need more help on this point thank you.

Launch android app when a link is tapped on SMS

I don't know if many people have tried this but I am trying a build an app that requires user to tap on a link on the sms he/she receives and this will launch the android app. Is it possible to do in android? If yes, how can I do this? I know this can be done in IOS. Any suggestions or help will be appreciated. Thank You.
In you Manifest, under an Activity that you want to handle incoming data from a link clicked in the messaging app, define something like this:
<activity android:name=".SomeActivityName" >
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.VIEW" />
<data android:scheme="com.your_package.something" />
</intent-filter>
</activity>
The android:scheme="" here is what will ensure that the Activity will react to any data with this in it:
<data android:scheme="com.your_package.something" />
In the SomeActivityName (Name used as an illustration. Naturally, you will use your own :-)), you can run a check like this:
Uri data = getIntent().getData();
String strData = data.toString();
if (strScreenName.equals("com.your_package.something://")) {
// THIS IS OPTIONAL IN CASE YOU NEED TO VERIFY. THE ACTUAL USAGE IN MY APP IS BELOW THIS BLOCK
}
My app's similar usage:
Uri data = getIntent().getData();
strScreenName = data.toString()
.replaceAll("com.some_thing.profile://", "")
.replaceAll("#", "");
I use this to handle clicks on twitter #username links within my app. I need to strip out the com.some_thing.profile:// and the # to get the username for further processing. The Manifest code, is the exact same (with just the name and scheme changed).
Add an intent-filter to your app that listens for links that follow the format you want your app to be launched on.
However, this will be a global listener, and any link that fits the format even outside the SMS app will trigger your app. So if the user taps a similar link in the web browser, your app will attempt to respond to it.
Additionally, if there is another app besides yours that can handle this link, Android will create a chooser that allows the user to pick whichever app they want to use. There is nothing you can do about this, except suggest that the user make your app the default handler for such links.
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE"
<data android:scheme="https" android:host="${hostName}" android:pathPattern="/.*" />
</intent-filter>
Previous answers are OK but don't forget to specify the pattern.
See more details here.
Also define your hostname inside Gradle file like:
android {
defaultConfig {
manifestPlaceholders = [hostName:"subdomain.example.com"]
}
}
More info about manifestPlaceholders here.

Categories

Resources