How to open an Android application from a webpage - android

I'm currently trying to open an Android application from a webpage. And to pass two parameters.
I went for the intent solution as it seems that custom scheme are not recommended, and in this case, I don't need a deeplink.
Currently, in debug, the only thing that happens is that my intent url is opened inside chrome and display a white page.
It never opens the application.
This is my AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.MyApp">
<application android:allowBackup="true" android:icon="#mipmap/appicon" android:roundIcon="#mipmap/appicon_round" android:supportsRtl="true">
<activity
android:name="com.MyApp.activity.MainActivity"
android:exported="true"
android:label="MyApp">
<intent-filter>
<action android:name="com.MyApp.LAUNCH"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<category android:name="android.intent.category.BROWSABLE"></category>
<data android:scheme="MyScheme" android:host="MyHost" android:path="/"/>
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
This is my javascript:
if (navigator.userAgent.match(/Android/i)) {
var uri = "intent://MyApp#Intent;scheme=MyScheme;action=com.MyApp.LAUNCH;package=com.MyApp;S.p=" + p + ";S.c=" + c + ";end";
window.open(uri);
}
I've seen a lot of way of doing this and tried a lot of things, but I don't get what is the good way to do with API 33.
I tried to use "intent:#Intent", "intent://#Intent", I tried with and without data property under activity, I tried my own scheme "MyScheme://".
I would like to avoid using deeplink as I would like to keep my website accessible without launching the app (different goals).

You need to check Handling Android App Link documentation.
Basically, to open the app you need to specify some specific scheme, for example:
<activity
android:name=".MyMapActivity"
android:exported="true"
...>
<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" />
</intent-filter>
</activity>
And the link to open will be: myapp://anypath_here?param1=value1&param2=value2
Try to use a unique scheme, otherwise, you will have an 'Open with..' dialog opening if another app can open it.

To enable link handling verification for your app, add intent filters that match the following format:
<!-- Make sure you explicitly set android:autoVerify to "true". -->
<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" />
<!-- If a user clicks on a shared link that uses the "http" scheme, your
app should be able to delegate that traffic to "https". -->
<data android:scheme="http" />
<data android:scheme="https" />
<!-- Include one or more domains that should be verified. -->
<data android:host="..." />
</intent-filter>
More information you can refer to Verify Android App Links.

Related

prevent the app to be displayed in ( open as dialog ) for specific keywords in url using manifest intent filter

Right now in my manifest code I have
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter
android:autoVerify="true"
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" />
<data android:scheme="http" />
<data
android:name="default-url"
android:host="#string/bc"
android:scheme="#string/bc" />
</intent-filter>
which allow the user to get open with dialog if he click on URL that start with domain of my application for example: pop-up dialog to select the app
and its working fine, however, I'm facing an issue when the user request forgets password he receives a link on his email to reset his password.
the link he received is like this: www.domain.com/forget_password/email.
what I want is to keep the app link working but if the domain contains /forget_password open the browser by default, not the application.
Sorry, there is no "exclude" logic in <intent-filter>. You cannot create an <intent-filter> that says "I accept everything except this".
You will need to handle the forget_password path in your app, perhaps by launching a Web browser yourself.

How to implement Android App Links with wildcard domains?

Android has a guide about how to implement app links. That is, if my app declares that it handles certain web links, and I try to open this link in any other app, the system intercepts this and takes the user straight to my app, instead of the browser, so that I can show relevant content straight in my app. Very handy.
What I am missing in the guide is two things:
How to implement app links with wildcard domains. I would like my app to handle links to *.example.com, that is, all links to subdomains of example.com (test.example.com, something.example.com etc);
How to implement app links only to specific paths on my site. For example I want to intercept test.example.com/something, but not test.example.com/other. The first one should come to my app, the other one to my browser;
The corresponding iOS guide shows that iOS handles both of these scenarios (though the wildcard part was unclear from the docs and I had to clarify with Apple Support that you need to place the association file in the root domain, not a subdomain).
Can Android App Links handle wildcard domains and only a subset of paths?
Update: now you can handle wildcard domains, using the Digital Asset Links
aurilio explained it in his newer answer
The whole process is documented here: https://developer.android.com/training/app-links/verify-site-associations
To sum it up, now you can use a wildcard in the host tag, and you must upload a json file called assetlinks.json to the /.well-known folder/route on your root domain.
Alternatively, if you declare your hostname with a wildcard (such as *.example.com), you must publish your assetlinks.json file at the root hostname (example.com)
You will also need to add the attribute android:autoVerify="true" to your intent-filter tag.
Here's the whole example on the Android side:
<application>
<activity android:name=”MainActivity”>
<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.com" />
</intent-filter>
</activity>
</application>
Here's the previous answer from 2016:
Unfortunately it seems that Android cannot handle wildcard domains.
If you look at the API guide for the data tag (https://developer.android.com/guide/topics/manifest/data-element.html), you can see they mention that wildcard is available for pathPattern and mimeType, but not for host.
The thing is that, as explained by CommonsWare in an other post on the subject (https://stackoverflow.com/a/34068591/4160079),
the domains are checked at install time, and there is no means to add new domains except by shipping a new edition of the app with a new manifest.
So you will have to manually list all the subdomains available, and update the app whenever a new subdomain is launched.
Here's how you declare multiple subdomains:
<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" />
<data android:scheme="http" />
<data android:host="subdomain1.example.com" />
<data android:host="subdomain2.example.com" />
<data android:host="subdomain3.example.com" />
</intent-filter>
</activity>
Yes, you can handle only a subset of paths
It is the same idea, just list the paths you want using the path attribute (again, see data tag API guide above).
If you use query strings or path params, prefer using pathPrefix.
If necessary, you can use wildcards here, by choosing pathPattern instead.
The path part of a URI which must begin with a /. The path attribute specifies a complete path that is matched against the complete path in an Intent object. The pathPrefix attribute specifies a partial path that is matched against only the initial part of the path in the Intent object. The pathPattern attribute specifies a complete path that is matched against the complete path in the Intent object, but it can contain the following wildcards:
An asterisk ('') matches a sequence of 0 to many occurrences of the immediately preceding character.
A period followed by an asterisk (".") matches any sequence of 0 to many characters.
Here's a few examples:
<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" />
<data android:scheme="http" />
<data android:host="subdomain1.example.com" />
<data android:host="subdomain2.example.com" />
<data android:host="subdomain3.example.com" />
<data android:path="/path1" /> <!-- matches /path1 only -->
<data android:pathPrefix="/path2" /> <!-- matches /path2, /path2/something or also /path2?key=value etc... -->
<data android:pathPattern="/wild.*" /> <!-- matches /wild, /wild3, /wilderness etc... -->
</intent-filter>
</activity>
Android cannot handle wildcard domain as such(as per their documentation as of today), but, this will answer your query on inclusion and exclusion of certain /paths.
To implement deep linking for URL's like-
http://example.com/gizmos?1234, 
http://example.com/gizmos/1234,
http://example.com/gizmos/toys/1234,
etc.
Your XML should look something like this-
<activity android:name="com.example.android.GizmosActivity" 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 "example://gizmos” -->
<data android:scheme="example" android:host="gizmos" />
</intent-filter>
<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://example.com/gizmos” -->
<data android:scheme="http" android:host="example.com" android:pathPrefix="/gizmos" />
</intent-filter>
</activity>
Now considering that you were able to achieve this, Here is how you restrict access to parts of your app content-
<?xml version="1.0" encoding="utf-8"?>
<search-engine xmlns:android="http://schemas.android.com/apk/res/android">
<noindex uri="http://example.com/gizmos/hidden_uri"/>
<noindex uriPrefix="http://example.com/gizmos/hidden_prefix"/>
<noindex uri="gizmos://hidden_path"/>
<noindex uriPrefix="gizmos://hidden_prefix"/>
</search-engine>
And The Manifest part-
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.Gizmos">
<application>
<activity android:name="com.example.android.GizmosActivity" android:label="#string/title_gizmos" >
<intent-filter android:label="#string/filter_title_viewgizmos">
<action android:name="android.intent.action.VIEW"/> ...
</activity>
<meta-data android:name="search-engine" android:resource="#xml/noindex"/>
</application>
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
For more details and explanation of this example, you can take a look at-
Android Deep Linking
Hope it helps, Happy Coding
Quoting from: https://developer.android.com/training/app-links/verify-site-associations.html
Alternatively, if you declare your hostname with a wildcard (such as *.example.com), you must publish your assetlinks.json file at the root hostname (example.com). For example, an app with the following intent filter will pass verification for any sub-name of example.com (such as foo.example.com) as long as the assetlinks.json file is published at https:/ /example.com/.well- known/assetlinks.json:
<application>
<activity android:name=”MainActivity”>
<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="www.example.com" />
<data android:scheme="https" android:host="mobile.example.com" />
</intent-filter>
</activity>
</application>

Android Intent filter for https scheme not working

I know this question may appear duplicated with some other similar questions. I've reviewed all of them and still can't fix this issue.
I want to launch my android app when clicking a link on a webpage. It works as desired when I use a custom Scheme:
<!-- In the deployed webpage: -->
Launch application
<!-- The Intent filter: -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="test" android:host="test.com" />
</intent-filter>
But when changing the scheme to "https":
<!-- In the deployed webpage: -->
Launch application
<!-- The Intent filter: -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="https" android:host="test.com"/>
</intent-filter>
the browser attempts to open the (nonexistent) page and ignores the intent filter.
It does not work for http, https, ftp, etc.
I'm running the app on Android 6.0, compiling: Minimum 11, target 23.
It seems like some mechanism is not allowing me to use the "reserved" schemes to launch an app, but I've not seen anything related to this in the posts.
Do you have any clue on what could it be?
Beginning with Android Marshmallow there's a new android:autoVerify flag you can use to request Android to verify that a certain domain belongs to you and that you want links to open in your app and not the browser.
"Android 6.0 (API level 23) and higher allow an app to designate
itself as the default handler of a given type of link"
See: https://developer.android.com/training/app-links/index.html#intent-handler
Try joining the two data tags like so and removing the first android.intent.category.DEFAULT category as its not needed on the first intent-filter at all, but necessary on the 2nd so that "the activity should be an option for the default action to perform on a piece of data"
<activity android:name=".MainActivity">
<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.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="https" android:host="test.com" />
</intent-filter>
</activity>

Intent Filter to Launch My Activity when custom URI is clicked

I am trying to allow a URI to be registered to open up with my app. Like the PatternRepository on the Blackberry and the CFBundleURLName/CFBundleURLSchemes on the iPhone. How do I achieve the same results on the Android?
The system will be sending emails with the following link: myapp://myapp.mycompany.com/index/customerId/12345. The idea is that the user should be able to click on the link to open up the customer activity in the application.
I've tried numerous suggestions from other SO posts but I cannot get the OS to recognize the pattern and open my app.
On The Gmail app it looks like this: myapp://myapp.mycompany.com/index/customerId/12345. It recognizes and underlines the myapp.mycompany.com/index/customerId/12345 portion of the link and it opens it in a browser. The myapp:// part is not linkified.
The standard mail application treats the entire link as plain text.
What am I missing here?
PS: I've already looked at
How to implement my very own URI scheme on Android
and How to register some URL namespace (myapp://app.start/) for accessing your program by calling a URL in browser in Android OS?
The Manifest:
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="2"
android:versionName="0.0.8"
package="com.mycompany.myapp.client.android">
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="7"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application
android:label="#string/app_name"
android:name="myappApplication"
android:icon="#drawable/ic_icon_myapp"
android:debuggable="true">
<activity
android:label="My App"
android:name=".gui.activity.LoginActivity"
label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".gui.activity.CustomerDetailActivity" >
<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"/>
</intent-filter>
</activity>
<activity android:name=".gui.activity.CustomerDetailActivity"/>
<activity android:name=".gui.activity.CustomerImageViewerActivity" />
<activity android:name=".gui.activity.CustomerListActivity" android:configChanges="orientation|keyboardHidden"/>
<activity android:name=".gui.activity.HomeActivity" android:configChanges="orientation|keyboardHidden"/>
<activity android:name=".gui.activity.AboutActivity" android:configChanges="orientation|keyboardHidden"/>
<activity android:name=".gui.activity.AccountActivity" android:configChanges="orientation|keyboardHidden" />
</application>
</manifest>
The final solution was a hacky workaround to cover all bases. The email now also contains an attachment with an extension that is registered to open with the app.
AndroidManifest.xml :
<activity android:name=".gui.activity.CustomerDetailActivity" >
<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="https"
android:host="myapp.mycompany.com" />
</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="myapp"
android:host="myapp.mycompany.com" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<action android:name="android.intent.action.PICK" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="application/myapp" />
</intent-filter>
</activity>
When I was working on OAuth with Google Calendar, I had to add this filter to the Activity I wanted to receive the callback:
<intent-filter>
<action android:name="android.intent.action.VIEW"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<category android:name="android.intent.category.BROWSABLE"></category>
<data android:scheme="yourapp" android:host="goog"></data>
</intent-filter>
The when the browser invoked the yourapp://goog URL, it would return to my Activity.
You can get around the issue of GMail not linking non-standard protocols by using a standard HTTP URL with a 302 redirect. You could either set it up on your website's webserver or application server, or for the quick and dirty test you could use a URL shortener like http://bit.ly.
This is solution for me. Thanks #DanO
<intent-filter>
<data android:scheme="yourcustomname"/>
<data android:host="*"/>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
Have you dried adding a category to your intent-filter:
<category android:name="android.intent.category.BROWSABLE" />
You could always try sending your emails using HTML and then use an <a> tag around to create the URL. I don't think there is a way to change the way the Gmail or Mail parse their text, since they probably use the Linkify class.
Another option would be use use http:// and then just parse for a specific custom subdomain which would provide your users with the option to open in a browser or your application.
I just ran into this also, but for standard http: scheme urls. Gmail doesn't appear to add any categories to the Intent. Now I check for BROWSABLE, but I also include a check for !intent.hasCategories() and allow that to go through as well.

Oauth Callback not found after allowing the app on Twitter

Hey. I am developing an application using the Twitter4j api. In order to allow the application and get an access token, I launch the browser with the callback parameters which I had set in the manifest file.
<data android:scheme="scheme" android:host="authenticatorapp"></data>
After allowing the application, the browser calls the following and fails with a not found message.
scheme://authenticatorapp?oauth_token=n5vd99dfnmnf...
I tried it both on the emulator and the device.
In the emulator, LogCat gives me this :
12-12 15:04:05.743: ERROR/browser(230): onReceivedError -10 scheme://authenticatorapp?oauth_token=Jj...M&oauth_verifier=3ZfuY... The protocol is not supported.
-- The manifest file :
<activity android:name=".AuthenticatorApp"
android:launchMode="singleInstance"
>
<intent-filter>
<category android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.LAUNCHER" />
<data android:scheme="scheme" android:host="authenticatorapp"></data>
</intent-filter>
</activity>
<!-- Broadcast Receiver that will process AppWidget updates -->
<receiver android:name=".ZaytungWidget" android:label="#string/widget_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/tweet_metadata" />
</receiver>
<!-- Service to perform web API queries -->
<service android:name=".ZaytungWidget$UpdateService" />
</application>
<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.INTERNET" />
Can you please post the whole manifest file?
I found the following question which may be useful later on: OAuth instance state in Android
The question linked to the following example application, which may be helpful:
http://code.google.com/p/jpoco/source/browse/trunk/jpoco-android-app/AndroidManifest.xml
This is what I have in my working Manifest.xml, where org.gpsagenda.OAUTH is the activity doing the Authenticating.
<activity android:name="org.gpsagenda.OAUTH" >
<intent-filter>
<action android:name="android.intent.action.VIEW"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<category android:name="android.intent.category.BROWSABLE"></category>
<data android:scheme="gpsagenda" android:host="twitt" />
</intent-filter>
</activity>
If you're developing a native app, you don't use the callback parameters, but need to let the user enter the pin in your app somewhere - which he gets when you open the authorization_url in a browser or probably more comfortably within your app in a webview.
You could also automatically fetch the pin after the user has clicked on 'yes' in the authorization twitter webpage, but not sure if it's against the twitter ToS.

Categories

Resources