How to check if a native app exists from browser/javascript - javascript

I want to check if a native app exists from browser/javascript, if it does then launch the native app or else redirect to Webapp.
I have tried below code (on Mac) it launches native app if it exists but when native app does not exist I get an error and does not redirect to Webapp
Failed to launch 'abcnativeapp://' because the scheme does not have a registered handler.
var now = new Date().valueOf();
setTimeout(function () {
if (new Date().valueOf() - now > 500) return;
window.location = "https://abcnativeapp.com";
}, 400);
window.location = "abcnativeapp://";
Ref: https://www.codegrepper.com/code-examples/shell/detect+if+app+is+installed+javascript
Is it possible to query using javascript to check if there are native app handlers for a URI scheme?

Related

How to check using JavaScript that custom application is installed in the system?

I have installed a custom application in my system and I want to check..Is application is installed or registered in registry?
I want to perform some action based on that status but I am unable to detect or read registry from Browser. I have gone through sooo many question/solutions but they did not work for me.
If you can help me to achieve my wish...that would be really helpful for me.
When I trigger my custom URI then following Log prints in console based on
If Application installed then Launched external handler for 'myApp://dgsda'.
If Not Installed then Not allowed to launch 'myApp://dgsda' because a user gesture is required.
But I am unable to catch these logs.
I am sharing few approaches that I have tried.
Custom URI : myapp://anything
var timeout = setTimeout(function () {
window.location = newUri
}, 1000)
window.location = uri;
With Above approach Timeout is always executing
var iframe = document.querySelector('#hiddenIframeUriHandler')
if (!iframe) {
iframe = _createHiddenIframe(document.body, 'about:blank')
}
try {
iframe.contentWindow.location.href = uri;
successCb()
} catch (e) {
if (e.name === 'NS_ERROR_UNKNOWN_PROTOCOL') {
failCb()
}
}
Please do let me know if you need any further information.

Implementing Dropbox API V2 in Cordova Application

I have a Cordova application with previous Dropbox implementation using rossmartin/phonegap-dropbox-sync-android. Now as the API V1 is going to be deprecated I want to upgrade to Dropbox API V2. I have searched for plugins for Cordova applications using Dropbox API V2 but didn't find any.So I am trying to implement it using dropbox/dropbox-sdk-js.
For Authentication, I am using authenticateWithCordova method which returns me the Access token (Full documentation here).This method returns Access token once the user completes authentication with Dropbox and uses the redirect URL to redirect the user to Cordova application.
This method works perfectly when the user clicks the button for the first time, but when the user clicks the button again calling this method shows a blank screen and return a new access token. How to avoid seeing the blank screen?
This is the method from Dropbox-sdk.js file, which I have called from my application,
DropboxBase.prototype.authenticateWithCordova = function (successCallback, errorCallback)
{
var redirect_url = 'https://www.dropbox.com/1/oauth2/redirect_receiver';
var url = this.getAuthenticationUrl(redirect_url);
var browser = window.open(url, '_blank');
var removed = false;
var onLoadError = function(event) {
// Try to avoid a browser crash on browser.close().
window.setTimeout(function() { browser.close() }, 10);
errorCallback();
}
var onLoadStop = function(event) {
var error_label = '&error=';
var error_index = event.url.indexOf(error_label);
if (error_index > -1) {
// Try to avoid a browser crash on browser.close().
window.setTimeout(function() { browser.close() }, 10);
errorCallback();
} else {
var access_token_label = '#access_token=';
var access_token_index = event.url.indexOf(access_token_label);
var token_type_index = event.url.indexOf('&token_type=');
if (access_token_index > -1) {
access_token_index += access_token_label.length;
// Try to avoid a browser crash on browser.close().
window.setTimeout(function() { browser.close() }, 10);
var access_token = event.url.substring(access_token_index, token_type_index);
successCallback(access_token);
}
}
};
Here is my code which I use to call the method,
function authenticateWithCordova()
{
var dbx = new Dropbox({ clientId: CLIENT_ID });
dbx.authenticateWithCordova(AuthSuccess,AuthFail);
}
function AuthSuccess(accessToken)
{
localStorage.accessToken = accessToken;
}
function AuthFail()
{
alert("Auth Fail");
}
I have found an analog issue right yesterday. This is the way I solved it.
First, I have set var dbx as global. In my index.js I put these lines immediately after app.initialize():
var CLIENT_ID = 'xxxxxxxxxxxxxxx';
var dbxt;
var dbx = new Dropbox({clientId: CLIENT_ID});
Then I check if dbxt is null: if it is, I create a new Dropbox object using accessToken, otherwise I go with the dropbox connection already established:
if (dbxt == null) {
dbx.authenticateWithCordova(function (accessToken) {
dbxt = new Dropbox({accessToken: accessToken});
dbxt.filesUpload({
path: '/mydump.sql',
contents: sql,
mode: 'overwrite',
mute: true
}).then(function (response) {
alert('Your backup has been successfully uploaded to your Dropbox!')
}).catch(function (error) {
alert('Error saving file to your Dropbox!')
console.error(error);
});
}, function (e){
console.log("failed Dropbox authentication");
}
}else{//dbxt already created
dbxt.filesUpload... //and the rest
}
This is just to avoid to create a new connection and get a new access token everytime and I confess I'm not sure this is a good practice: I only know that before to apply this code I got a lot of bad requests responses by Dropbox server:)
When I used the above code, after the first login, I started to see the blank page: that's is the inappbrowser page which Dropbox OAuth2 uses as redirect URI (set to https://www.dropbox.com/1/oauth2/redirect_receiver in your Dropbox app page).
So the problem was how to make this page invisible. I found a dirty trick applying a small tweak to inappbrowser.js script.
Near the bottom of the script, immediately before this line:
strWindowFeatures = strWindowFeatures || "";
I have put this small block:
if (strUrl.indexOf('dropbox') > -1){
strWindowFeatures += "location=no,hidden=yes";
}
I would have expected to can just use 'hidden=yes' but surprisingly if I remoce 'location=no' the blkank page appears again.
Notice 1: you don't have to modify the script inappbrowser.js located at plugins\cordova-plugin-inappbrowser\www\ but the one you find in platforms\android\platform_www\plugins\cordova-plugin-inappbrowser\www\
Notice 2: I have found this workaround right now so I'm not 100% sure it works perfectly.
Notice 3: making the inappbrowser page invisible, depending on the Internet connection, it could look like nothing is happening for a while, so you'll have to add some loader to inform your user that the app is working.
Hope this help.
UPDATE
I've just realized we can tweak directly the dropbox-sdk instead of inappbrowser.
If you are using Dropbox with browserify you have to open dropbox-base.js and look for authenticateWithCordova() method (it should be at line 107. Then change the line
var browser = window.open(url, '_blank');
to
var browser = window.open(url, '_blank', "location=no,hidden=yes");
If you are using Dropbox-sdk.min.js, you have to look for 'window.open' using the search function of your code editor. It will be easy because 'window.open' is used only once. So you'll have to change the following:
i=window.open(n,"_blank"),
to
i=window.open(n,"_blank","location=no,hidden=yes"),
And this seems to work fine (I prefer to be careful before I get excited).
UPDATE 2
Forgive previous update. My previous check:
if (strUrl.indexOf('dropbox') > -1){
strWindowFeatures += "location=no,hidden=yes";
}
is wrong because it makes invisible any inappbrowser window which tries to connect to dropbox so it prevent us from even logging into Dropbox. So we need to change it to
if (strUrl == 'https://www.dropbox.com/1/oauth2/redirect_receiver') {
strWindowFeatures += "location=no,hidden=yes";
}
This way we can do the login correctly and next connections won't show the inappbrowser window, as we want.
So summarizing:
Ignore my first update
Use UPDATE 2 to modify the url check in inappbrowser.js
Forgive me for the confusion...

How to reload page on a Cordova project?

I am building an app, using polymer starter kit & cordova to wrap the project. Now, since I use firebase as a database for storing data, I ended up using two native firebase javascript function to find user data:
getAuth()
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
var authData = ref.getAuth();
if (authData) {
console.log("Authenticated user with uid:", authData.uid);
}
onAuth()
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
ref.onAuth(function(authData) {
if (authData) {
console.log("Authenticated with uid:", authData.uid);
} else {
console.log("Client unauthenticated.")
}
});
Those two functions require a reload to bring back data from firebase, but :
window.location.reload();
doesn't work
Alos looked for a Cordova plugin: webview-reloader, installed it but redirect and reload still not working.
When i use the reload() function the screen of my android phone is going white and the application stop working. Need to close the app and open it again.
Since Cordova is a wrapper around a browser window:
window.location.reload(true);
It works for the browser windows as well as a Cordova app.
This works for iOS and Android (at least with 2016 platform versions).
// keep startup url (in case your app is an SPA with html5 url routing)
var initialHref = window.location.href;
function restartApplication() {
// Show splash screen (useful if your app takes time to load)
navigator.splashscreen.show();
// Reload original app url (ie your index.html file)
window.location = initialHref;
}
if (this.cordovaService) { // is cordova
this.window.location.href = `${this.window.location.protocol}//${this.window.location.host}`;
} else {
this.window.location.reload();
}

Cordova ibeacon; Send local notification after the app got killed, but does not work on android

I am using Cordova / Phonegap iBeacon plugin with ionicframework at my cordova project. I am tryin to send a local notification both on android and ios with cordova local notification plugin while entering monitored region , when the app is killed.
Here is my code :
document.addEventListener("deviceready", onDeviceReady, false);
function didDetermineStateForRegion(pluginResult) {
}
function didStartMonitoringForRegion (pluginResult) {
}
function didExitRegion(pluginResult) {
$cordovaLocalNotification.add({
id: 30244234234,
title: "Good By!",
text: "Hope to see you again."
}).then(function () {
});
}
function didEnterRegion (pluginResult) {
$cordovaLocalNotification.add({
title: "Welcome",
text: "Tap to launch app"
}).then(function () {
});
};
function didRangeBeaconsInRegion (pluginResult) {
}
function onDeviceReady() {
// Now safe to use device APIs
function createBeacon(uuid,nofiyState) {
var uuid = uuid; // mandatory
var identifier = 'estimote'; // mandatory
// throws an error if the parameters are not valid
var beaconRegion = new cordova.plugins.locationManager.BeaconRegion(identifier, uuid);
beaconRegion.notifyEntryStateOnDisplay = true;
return beaconRegion;
}
var delegate = new cordova.plugins.locationManager.Delegate();
delegate.didDetermineStateForRegion = didDetermineStateForRegion;
delegate.didStartMonitoringForRegion = didStartMonitoringForRegion;
delegate.didRangeBeaconsInRegion = didRangeBeaconsInRegion;
delegate.didEnterRegion = didEnterRegion;
delegate.didExitRegion = didExitRegion;
var beaconRegion = createBeacon('02681445-8D1B-4F58-99D4-B25F4B129A58',true);
// var beaconRegionBlue = createBeacon('02681445-8D1B-4F58-99D4-B25F4B129A58',1,,true);
cordova.plugins.locationManager.setDelegate(delegate);
// required in iOS 8+
//cordova.plugins.locationManager.requestWhenInUseAuthorization();
cordova.plugins.locationManager.requestAlwaysAuthorization();
cordova.plugins.locationManager.startMonitoringForRegion(beaconRegion)
.fail(console.error)
.done();
}
cordova plugins :
com.unarin.cordova.beacon 3.3.0 "Proximity Beacon Plugin"
de.appplant.cordova.plugin.local-notification 0.8.1 "LocalNotification"
nl.x-services.plugins.socialsharing 4.3.16 "SocialSharing"
org.apache.cordova.console 0.2.13 "Console"
org.apache.cordova.device 0.3.0 "Device"
cordova version : 4.3.0
this works fine for ios even if the app is killed but on android notifications cames only if app in the background. When i kill the app from task manager on android i never seen any local notification.
Is it possible to receive notification on android even if app is killed ?
thanks for help.
lets clear some stuff , there are states that yo are confusing :
App as a service
App running in background (i.e minimized).
App killed (not running at all)
in all cases the 3rd state when you kill app ( via long press back button in custom roms , or force stop from app menu in your OS ) , the app is simply removed from memory , no code is being excuted !
what usually is done in this case is automatically relaunching the service after it has been stopped check this answer , and as you can read :
it is really very bad pattern to run service forcefully against the
user's willingness.
there are so many cordova plugins to create BroadcasteReceiver , however the simple answer to your question , if app is killed it is not possible to receive notification .
But you should consider this: if user kills your app , it means it was done intentionally , so you shouldnt really worry if your app will work or not , as this is the user's issue , and not yours as a developer.

How to open an app if installed through a webpage in Safari?

We have an app, lets call it: xyz_app for which I have a custom URL scheme in form of xyz_app://.
We are sending an email to the user.
when he clicks on the link, he is suppose to go to the app and in case the app is not installed, our mobile website.
so from the Link in the email, how do I make sure that if the app is not installed, that link should send the user to the mobile website instead ?
The URL scheme works directly only if the app is installed on the iDevice. If not installed then it will throw an error.
1) To implement this functionality you will have to redirect the user to a webpage that will detect if app is installed, from your email link. Something like this www.yourwebsite/detectapp
2) Your detectapp page will have a javascript-
var appstoreFail = "www.your_redirect_website.com";
//Check is device is iOS
var iOS = /(iPad|iPhone|iPod)/.test(navigator.userAgent);
var appUrlScheme = "xyz_app://";
if (iOS) {
// If the app is not installed the script will wait for 2sec and redirect to web.
var loadedAt = +new Date;
setTimeout(function() {
if (+new Date - loadedAt < 2000)
window.location = appstoreFail;
} ,25);
// Try launching the app using URL schemes
window.open(appUrlScheme, "_self");
} else {
// Launch the website
window.location = appstoreFail;
}

Categories