I would like to determine an installed app using custom URL scheme on iPhone Safari.
You may believe it is impossible to do this, but JavaScript helped me to figure this out.
<script>(function(){
var fallbackLink = '<?=$info['failed_url']?>'+window.location.search+window.location.hash;
var isiOS = navigator.userAgent.match('iPad') || navigator.userAgent.match('iPhone'),
isAndroid = navigator.userAgent.match('Android');
if (isiOS || isAndroid) {
document.getElementById('loader').src = '<?=$info['scheme']?>://'+window.location.search+window.location.hash;
fallbackLink = isAndroid ? '<?=$info['failed_url']?>' :
'<?=$info['failed_url']?>' ;
}
window.setTimeout(function (){ window.location.replace(fallbackLink); }, 1000);
})();</script>
here is my script.
I already know custom URL scheme of the iPhone application. It successfully launches the application if it exists on the iPhone. However, if the iPhone doesn't have the application, it redirects to a different page.
I put certain code on the failed web page to notice that user doesn't have the application. My plan was perfect until I found this.
The JavaScript redirection works even though the application is launched on iPhone after timeout.
Is there a way to stop JavaScript if iPhone launched application?
Thank you.
You can always cancel the timeout when the window loses focus.
var countdown = window.setTimeout(function (){
window.location.replace(fallbackLink);
}, 1000);
window.addEventListener("blur", function (){
window.clearTimeout(countdown);
}, false);
Related
I would like to create a web-page, a page that will redirect to App Store if App is not installed in iPhone, and will redirect to The App if App is installed in iPhone.
I wrote Javascript like below.
function launchApp(){
let URI_SCHEME = 'myapp://';
let APP_STORE_URL = 'https://itunes.apple.com/jp/app/myapp/id111111111';
let userAgent = navigator.userAgent.toLowerCase();
if(userAgent.search(/iphone|ipad|ipod/) > -1){
location.href = URI_SCHEME;
setTimeout(function (){
let aTag = document.createElement('a');
aTag.href = APP_STORE_URL;
aTag.Click();
}, 1200)
}
}
I tried this code, and in iOS Safari, it works as I expected.
However, in iOS Chrome app, it does not work.
To be more specific, when I tap the link button to the page that I am creating, the new tab opens but closes immediately.
Does anyone know why it does not work in iOS Chrome app?
Moreover, does anyone know better solution?
Thank you for your cooperation.
This is for Windows.
I have a flash application I am converting to AIR. I built a captive installer using NSIS and it works fine. However I would like to have an icon on a website which checks if the application is already installed and ask the user if they wish to run it. If it is not installed, they get the option to download it.
I am fairly certain this is doable, because Zoom and GoToMeeting both do this.
My searching skills seem to be failing me when looking for this.
Edit:
It appears the best/only way to do this is to create a custom protocol for the application. Something like DoDaApp://.
Which brings up the next set of questions;
How to create an NSIS file which will create the appropriate registry entries on the client computer? As a user, not admin.
How to check if the protocol is currently installed on the computer?
This is a partial answer as it does not work in Edge. I'll explain the issue below.
As recommended in How to detect browser's protocol handlers you can use timeout & blur event handlers. Here is my interpretation of the code;
function checkCustomProtocol(inProtocol,inInstalLink,inTimeOut)
{
var timeout = inTimeOut;
window.addEventListener('blur',function(e)
{
window.clearTimeout(timeout);
}
)
timeout = window.setTimeout(function()
{
console.log('timeout');
window.location = inInstalLink;
}, inTimeOut
);
window.location = inProtocol;
}
Microsoft Edge is ever so helpful by popping up a dialog box telling you "You'll Need a new app to open this" which "blurs" the screen, not allowing download of the file.
So I will be posting another question on how to make it work in Edge. I have reviewed ismailhabib's code but the known issues section says it doesn't work with Edge either.
Here is a more complete answer. It has been lightly tested in IE 11, Microsoft Edge, Chrome and Firefox. I also added comments;
/*
checkCustomProtocol - check if custom protocol exists
inProtocol - URL of application to run eg: MyApp://
inInstallLink - URL to run when the protocol does not exist.
inTimeOut - time in miliseconds to wait for application to Launch.
*/
function checkCustomProtocol(inProtocol,inInstalLink,inTimeOut)
{
// Check if Microsoft Edge
if (navigator.msLaunchUri)
{
navigator.msLaunchUri(inProtocol, function ()
{
//It launched, nothing to do
},
function()
{
window.location = inInstalLink; //Launch alternative, typically app download.
}
);
}
else
{
// Not Edge
var timeout = inTimeOut;
//Set up a listener to see if it navigates away from the page.
// If so we assume the papplication launched
window.addEventListener('blur',function(e)
{
window.clearTimeout(timeout);
}
)
//Set a timeout so that if the application does not launch within the timeout we
// assume the protocol does not exist
timeout = window.setTimeout(function()
{
console.log('timeout');
window.location = inInstalLink; //Try to launch application
}, inTimeOut
);
window.location = inProtocol; //Launch alternative, typically app download.
}
}
Goal
I am using an idle timer I found on github to see if my users are AFK from the webapp. https://github.com/HackedByChinese/ng-idle
It works well and I have no issues with it. But I am unable to set the users to away if they close the browser or leave the site.
Therefore I need a way to detect if they navigate to a site that is not apart of my site and if they close browser or tab that my site is on.
Code Below Works But Still Happens If I Redirect A Different Page On My Site
var exitEvent = window.attachEvent || window.addEventListener;
var chkevent = window.attachEvent ? 'onbeforeunload' : 'beforeunload';
exitEvent(chkevent, function (e) {
DashboardService.setIdle();
var confirmationMessage = ' ';
(e || window.event).returnValue = "Are you sure that you'd like to close this page?";
return confirmationMessage;
});
Code Below Just Doesn't Work
$window.onbeforeunload = function () {
DashboardService.setIdle();
}
Could not find a way to tell if browser has closed by user.
Instead timeout created to disassoicate user on backend of application
I'm attempting to use the Skype javascript API and noticing some craziness: If my page is HTTP, everything works fine (all the skype buttons, and skype: protocol hrefs) but once I move it to HTTPS it breaks in Chrome, iPad, and iPhone. Case and point:
Call buttons work here:
http://developer.skype.com/skype-uris/skype-uri-tutorial-webpages#uriTJS_Generator
Call buttons DO NOT work here:
https://developer.skype.com/skype-uris/skype-uri-tutorial-webpages#uriTJS_Generator
This is on their own site and it's no workie...
Can anyone suggest some series of rain dances I should do to fix this? Praying to the Skype gods? I'm only a mere mortal.
On click script is creating iframe and adding src="skype:echo123;+16505550123?call" and then as mb21 said bug occurs or "restrictive security policy" happens.
function a(s, v, t) {
var u = true;
window.onblur = function () {
u = false
};
var r = document.getElementById(v);
if (r !== null) {
r.src = s //here error happens....
}
setTimeout(function () {
if (u) {
alert(Skype.installSkypeMsg);
Skype.tryAnalyzeSkypeUri("redirect", t);
window.location = Skype.SkypeClientDownloadUrl
}
}, 2000)
}
How about just using:
<a onclick="window.location='skype:echo123;+16505550123?call';return false;" href="">link</a>
I think this is a bug (or a quite restrictive security policy) in Chrome (and other browsers). In the Chrome developer console I get:
[blocked] The page at https://developer.skype.com/skype-uris/skype-uri-tutorial-webpages#uriTJS_Generator ran insecure content from skype:echo123;+16505550123?call.
It treats skype:echo123;+16505550123?call as a URL and finds it not to be secure (i.e. not https) so the browser refuses to load it. Probably, the JavaScript in the Skype SDK uses window.open or something similar, so digging around in their code might bring up a solution.
Maybe you can adapt this ugly workaround?
(works fine in Chrome on the iPhone)
I get this error:
TypeError: 'undefined' is not an object (evaluating 'win.location') in dg.js line 3
And the lightbox does not open.
The code in question inside PayPal's dg.js is:
startFlow: function (url) {
var win = that._render();
if (win.location) {
win.location = url;
} else {
win.src = url;
}
}
So does mobile Safari not understand that._render()? How do I get around this?
If it matters, I'm using Adaptive Payments, calling it like so:
var dg = new PAYPAL.apps.DGFlow({
trigger: null,
expType: 'light'
});
dg.startFlow('https://www.paypal.com/webapps/adaptivepayment/flow/pay?expType=light&payKey=' +data.paykey);
I don't have any problems getting the payKey & the entire payflow works on desktops and in mobile browsers other than Safari (it works on desktop Safari). It also does not work when our site is run as an iOS web app, which I assume is just a shell for Safari anyway.
I can explain why you are seeing this error.
Safari on iOS only allows a window to be opened as a result of a user click/touch event.
The DGFlow._render() function executes:
window.open('', "PPDG");
which returns null if triggered by anything other than a user click/touch event.
I am guessing you are issuing an XMLHttpRequest to generate a PayRequest/PayKey on the server and then in the onsuccess callback you are calling DGFlow.startFlow().
The solution is two split the process into two steps:
When the user is ready to checkout, issue the call to the server to
generate the pay key.
Then, present the user with a button to Checkout with PayPal and when that is clicked, call DGFlow.startFlow()
Found a couple of ways to get around this...location.replace with the PayPal URL or using your own lightbox. I used easybox.
// Replace
dg.startFlow('https://www.paypal.com/webapps/adaptivepayment/flow/pay?expType=light&payKey=' +data.paykey);
// with
var RUNNING_AS_WEB_APP = (window.navigator.standalone == true ? true : false);
if (RUNNING_AS_WEB_APP === false) {
dg.startFlow('https://www.paypal.com/webapps/adaptivepayment/flow/pay?expType=light&payKey=' +data.paykey);
} else {
location.replace('https://www.paypal.com/webapps/adaptivepayment/flow/pay?expType=light&payKey=' +data.paykey);
// Or, lightbox option:
// $.easybox([{url: 'https://www.paypal.com/webapps/adaptivepayment/flow/pay?expType=light&payKey=' +data.paykey, width: 320, height: 480}]);
}
Try using the mini browser experience where expType=mini. Seems to work better than the lightbox on mobile devices.
Adaptive Payments without modal box or popups?