I have a simple nginx docker container, ip => 192.168.99.100, which serves static html file with a bit of javascript in it. I mapped docker's port 80 to my machines, 172.20.16.34:8080, so I can access it from mobile device on local network.
I have a simple button with an 'click' event listener. On click this code is triggered:
window.location = "xyz_app://hello_world"
I expect this code to launch our native application on the device, with the registered URL scheme. However what always happens is that browser tries to redirect to:
172.20.16.34:8080/xyz_app://hello_world
instead of to:
xyz_app://hello_world
and opening the application. Any idea why?
When I was looking for ways of launching native applications from Safari, this:
window.location = "xyz_app://hello_world"
was the most commonly suggested way.
You need to make sure that your URL scheme does not have an underscore in it, as if it does it will not be correctly recognised as a URL scheme.
Related
On Android, there are intents for apps as seen here:
https://developer.android.com/guide/topics/manifest/data-element.html
So if I have URL scheme www.google.com/calendar, Calendar app will be opened, etc.
However, I have question where/when this detection happens? I have experienced that tapping on the URL with supported scheme will cause intents recognition and if the scheme is recognised, the associated app will be opened. However, if I do redirection (javascript) to this supported URL in android Chrome, no recognition will happen so no redirection occurs. How can I build the URL in background (by tapping on the button), redirect to that URL and associated app will be opened?
That feature called Deep linking in android. As per document you can see
Open the user's preferred app that can handle the URI, if one is
designated.
Open the only available app that can handle the URI.
And for implementation you can refer this link
We currently have an Cordova application that needs to start an external browser with a POST.
We have it coded to use the inAppBrowser plugin to start a browser that is embedded within the app.
I don't like using the internal browser because I will be blamed for any bugs in the webpage that render in the default browser and don't work in the inAppBrowser.
How can we start the default browser with a POST request?
Once the browser starts we do NOT need to have a back button in the browser that will take the user back to our app.
We are only worried about iOS and Android. We can use different solutions on each of those platforms.
I have googled but there is so much conflicting information; there will be a response that it works, then another person replies that it does not. There also caveats to getting it to work; for instance, it seems that one can get the URL to open in the default browser, but it also leaves the page open in the in-app-browser as well. This would be confusing for the end user.
[EDIT] I have created an upwork.com project to pay someone to create a cordova plugin specific for starting the external browser with a POST request. Feel free to comment on any anticipated problems with doing that.
[EDIT] Here are the steps I used to test on iOS:
clear all background tasks on iPhone
Start the app that has link intended to start external browser
click the link that is intended to start external browser
Observe that browser starts
double tap the home key to expose all running apps
if successfully running in default browser I should observe the original app and the browser running.
if successful we should also observe that the original app is not displaying the target webpage. This point is important because some people are able to start the default browser, but the original app is left in the state of having the webpage also displayed.
Looks like the "_blank" can not open url in external browser on iOS.
I tried by this:
1) Install inappbrowser plugin.
2) call window.open(encodeURI('https://openclipart.org/'), "_blank");
when button pressed.
The url open in app, not external browser.
Update:
Use "_system" will open url in Safari on iOS, to open url :
1) Install inappbrowser plugin.
2) call cordova.InAppBrowser.open(encodeURI('https://openclipart.org/'), "_system");
Unfortunately this way only work to send get request.
Some people suggest submit post form on loadstop event like this:
Cordova InAppBrowser post form to url
The method worked when target is "_blank", when target is "_system", because open url in browser not app windows, the loadstop event will not be fired.
You can open a browser outside of the app with inAppBrowser by specifying the target eg.;
var linkTarget = "_blank" ; ( was using for desktop ; had coded target as _system for Android. Apologies.)
[EDITED]
openclipart.org;
This doesn't open web page in the app - opens in system browser.
If the browser defaults have been cleared in the device settings app manager page this link will prompt the user for their choice of browser ( I'm assuming it otherwise uses the previously set default though you might want to double check particularly if you're using crosswalk )
There are other target options but seem to recall _system not working as expected - give it a try if _blank doesn't work
I don't think there's any straight forward way to launch a browser doing a post even if you had a special plugin ;
Looks like using a dataUrl might allow you to open browser doing a post - if so prob the cleanest approach. ( see link in Wu's answer below ) [EDIT] looks like won't work on Windows mobile platforms though; see caniuse dataURIs.
Alternatively, you might try a separate html file as part of your app files - load it into a new browser as above (except "file://.." )and have it run some startup javascript (maybe using a querystring for control) to do the post eg. via a jquery ajax call. There will be security issues with this approach - the file will have to be somewhere the browser has access to ( can have app copy it there from internal www folder - need read/write permissions ) . Not sure if there will be CORS issues etc. I'd definitely look into the dataUrl first if windows not a consideration.
I'm trying to create a web page that automatically opens an Android app but only if app is installed. In case it's not it should redirect to another web page.
The app is already in production and is properly handling deep links like example://content?id=42. The format of the link could not be changed.
What I've already tried
1) Redirects and timeout:
window.location.replace('example://content?id=42');
setTimeout(function() {
window.location.replace = 'http://example.com/content?id=42';
}, 500);
Works fine for iOS but for Android it redirects to example:// immediately and thus gives me ERR_UNKNOWN_URL_SCHEME. Seems to be no go for Android.
2) iframe approach. Impossible in rencent Chrome versions. Also doesn't seem to work in Samsung browser.
3) Intents with S.browser_fallback_url. Works well but in Chrome only. Doesn't work in Opera and Samsung browser... most probably nowhere else but Chrome 25+.
use http://example.com/content?id=42 as the link and add the intent filter to your activity in manifest
<intent-filter>
<data android:scheme="http" android:host="example.com" />
...
</intent-filter>
However, a list of app registered, e.g. browsers, will show up when the link is first accessed on the machine.
You need to be aware of the browser of the client, and its operating system and adapt your site to them. For example, if the browser is Chrome and the OS is Android, use the Intent solution; if the browser is Safari use the example:// schema. You can get the info looking at the User-Agent header of the request, but I'm sure there are many open source libraries that can help you to get infos related to browser and OS.
Seems like you could at least approximate the experience by letting the user give a one-time assist:
Have your web page itself have the fallback url content.
When the page is hit check the user agent to see if the os is Android
If its Android, show the user a choice prompt/dialog to use web or Android
If they choose web (remember the choice with local storage), dismiss the dialog and show the fallback
If they choose android (remember the choice), redirect to the app with the intent:// URL (without fallback_url), will take them to market to install if necessary
After the first interaction, it'll work as you describe - automatically taking them to the web page or the installed app.
You can try using this scheme(to be sent to the user):
intent://details?id=X&url=Y&referrer=Z#Intent;scheme=market;action=android.intent.action.VIEW;package=com.android.vending;end";
X: Package name of the App
Y: Deep link scheme which should be defined in the App's manifest.
(Please refer this)
Here, they have used this URL as an example: "http://www.example.com/gizmos" , therefore Y should be replaced by this URL.
Z: Can be any data which you want to pass to the App via Google Play.
Please take note that any data which you pass should not be '&' separated because the original parameters are itself '&' separated.
PS: The Google Play makes a broadcast to the app. So make sure you receive the broadcast in a receiver.
Can I detect a redirection happening in a browser, which is not pointed to HTTP(s) protocol?
For example, my script redirects to something like ftp://, sms://, ws:// using
location.href=ws://abc/a
Is there a way to detect such redirection using JS? If useful, I can involve chrome ext environment in this as well.
Though this is not straight away, if you are using chrome extension, you can rely on chrome.webRequest.onHeadersReceived.* API which would give some clue via responseHeaders and you can detect the non-http redirects and setup actions accordingly.
Is it possible to communicate with a desktop application from browser?
I want to do something like this,
Let's say there is a button in my web application with a URL to a data source and when button is clicked desktop application opens and get that data source URL and process data with desktop application.
Is it difficult to do such thing? Any examples?
On windows its trivial to create a custom URL Protocol that's invokable via
..
This works in IE, FF and Chrome, although in the latter the link must be opened via javascript to avoid omni-bar confusion.
You will need to have something running on the deskop, like a server, and make a request to it for the server to open up an application. You could do it with a Node.js. Of course that requires the server to be running on the client's desktop.
The alternative would be to make a browser extension / plugin, and have people install that. Those extensions could probably launch an application on the desktop.
You can easily add Fleck WebSocket server to your desktop application, and then access this using Websocket.
Note: Only Windows 8 and 10 support WebSockets through Microsoft's WebSockets implementation, but Fleck will work with Windows 7.
https://github.com/statianzo/Fleck
It's quite easy to add Fleck to your project using NuGet Package Manager:
Install-Package Fleck
Here is the echo example from Fleck webpage (add this to the C# program to execute during startup):
var server = new WebSocketServer("ws://127.0.0.1:8181");
server.Start(socket =>
{
socket.OnOpen = () => Console.WriteLine("Open!");
socket.OnClose = () => Console.WriteLine("Close!");
socket.OnMessage = message => socket.Send(message);
});
In the javascript:
var exampleSocket = new WebSocket("ws://127.0.0.1:8181", "protocolOne");
exampleSocket.send("Here's some text that the server is urgently awaiting!");
//and receive (make a listener for the socket) :
exampleSocket.onmessage = function (event) {
console.log(event.data);
}
Hm, you need something like client-server application. The server is a lightweight http server, which is waiting for messages from the client (browser). The browser can communicate with your server via ajax for example.
Here is a clunky suggestion, but I think worth mentioning all the options since the custom URI and running server solutions are pretty involved... Generate a small file containing the parameters of interest, with a custom extension associated with your desktop app. So when the user clicks the browser button they will have to go through the browser's file download dialog/toolbar and maybe some annoying security verification popups... not ideal user experience, but might be the easiest way to implement this type of communication, and doesn't require a process running in the background like a server.
I have a web app used within my company for interfacing to old databases and poorly organized files. I need a way to allow the users to open the actual files from the network and not download copies, so they can be edited in place. Considering a solution like this or the custom URI scheme so that a small executable not running in the background can simply be passed the filename and open it for the user directly.
the desktop application should embed a small server in it, like Jetty. Since the browser content source domain (e.g. www.myDomain.com) is different than the localhost domain of the Jetty, you would run into security problems. These should be overcome by the use of CORS (Cross Origin Resource Sharing) which is a new standard. Using CORS, the Jetty server tells the browser that it/localhost allows Cross domain access to its resources if the requests originate from the source domain www.myDomain.com. For security reasons, i would also make the Jetty reject any request whose source ip is not localhost
In addtion to Alex K's answer for windows... for those looking for solution on macOS and Linux.
Linux
Most of the modern distros implement freedesktop standards and one of them is desktop files. You can create a desktop file with [service]
section.
$ cat test.desktop
[Desktop Entry]
Version=1.0
Terminal=false
Type=Application
Comment=My test app
Name=TestApp
Icon=TestIcon
Exec=/opt/test/test.sh %u
DBusActivatable=true
Categories=Network;
MimeType=x-scheme-handler/test; <------ This is handler for test://somedata URLs
NoDisplay=false
Copy this file in /usr/share/applications/test.desktop
macOS
Simply add something like following in your applications Info.plist file
<array>
<dict>
<key>CFBundleTypeIconFile</key>
<string>/tmp/test.png</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLName</key>
<string>com.mytest</string>
<key>CFBundleURLSchemes</key>
<array>
<string>test</string> <---- This is handler for test://somedata URLs hit on browser
</array>
</dict>
</array>