I created a PhoneGap app for iPhone that uses geolocation via JavaScript inside webview.
When I run the app the first time, it'll prompt me to allow geolocation for this app.
When I hit "ok", it'll prompt me again with the same question but this time it states that "index.html" wants permission to use geolocation.
That makes sense because iOS probably wants permission to allow geolocation for the app itself for the first time and the 2nd time the browser wants permission.
However, since doesn't lead to a great user experience:
How can I prevent this double prompt? (I'd be enough if the 2nd prompt could be prevented)
I found the cause for the issue.
The call to navigator.geolocation.getCurrentPosition(onsuccess, onerror) happens before Phonegap was fully loaded.
This means that the geolocation call of webview (and not a native call via PhoneGap) is being triggered which will again ask for permission (which does make sense). Compare it to the normal Safari browser on your Smartphone. It'll ask for geolocation permission for every new website. It's the same when loading index.html via PhoneGap on application startup.
However, the solution is to wait for the deviceready event which gets fired when PhoneGap has fully loaded:
document.addEventListener("deviceready", function(){
navigator.geolocation.getCurrentPosition(onsuccess, onerror, params);
}, false);
This will make the PhoneGap API available which overwrites the default HTML5 gelocation call of the browser and get the device's geo location via a native call (which you already accepted in the first prompt).
This will work because PhoneGap's API calls are identical to the standard W3C call for HTML5: http://docs.phonegap.com/en/2.2.0/cordova_geolocation_geolocation.md.html#Geolocation
Have a look at this:
Location permission alert on iPhone with PhoneGap
The second one seems to be the Webkit alert. In order to prevent this, you seem to have to simply move all your js files to the root directory. Tell me, if it works since I'll have to address the same issue soon.
Finally fixed the issue.
IN the index.html just move your cordova.js up
<script src="cordova.js"></script>
as the first js file to be included (especially make sure it is above maps include js). This will make sure that the prompt shows only once
I solved this problem by moving the
<script src="cordova.js"></script>
as the last script to be included
Related
I'm working on a web app that requires the user's location to get weather data. It's critical for the purpose of the app, and the location call has to be made basically every time the app is used.
It works fine on Chrome on desktop, but when I try to use my site on Android Chrome it asks for the location permission every time. Is there a way to use the Geolocation API that will remember the permission and not make the user approve it every time?
This is how I'm calling the API, as inline javascript on the page that uses the coordinates.
navigator.geolocation.getCurrentPosition(setCoords);
function setCoords(position) {
// Do stuff to the page
}
It turned out this was happening in a web view when I opened the page from a Facebook message. It remembers the location permission on Android Chrome.
I'm developing a simple app with phonegap which every 30 seconds send user current coordinates to my database via ajax call.It works very well
$(document).ready(function() {
setInterval(function() {
SetLocationUpdates();
}, 30000);
});
but if the user navigates to another app(google maps app) or if I open google maps app with this code
<div><a href="geo:41.897096,27.036545">Open maps app</div>
it(sending coordinates to my database via ajax) fails because getCurrentPosition does not work maybe google maps lock it althoug my app is still work(my app and google map app work separately.Two apps work at same time.Maybe my app go background)
More specifically, it does nothing.
navigator.geolocation.getCurrentPosition(SetLocationUpdates, onError);
this line not execute.
The success or error callbacks are never called, and setting a timeout does not affect this. I am using Phonegap Build to compile the app from html and javascript.
What should I do?
You need a native background geolocation solution - JS execution on the main thread gets paused when your app goes into the background.
In my experience, the most resilient solution is cordova-background-geolocation-lt. I've tested on multiple OS versions, including Android 8 and iOS 11, and this has worked consistently on all.
Please be aware that Firefox currently continues to work when the phone is asleep or the App is backgrounded. (I believe this is a bug)
IMHO the most appropriate and battery friendly solution relies on ServiceWorkers receiving and actioning TravelEvents from the TravelManager.
See this Web App for proof of how well Background geolocation fits with ServiceWorker infrastructure. All source can be found here including a aaa_readme.txt.
Please ask W3C/IETF to standardize this and your UA vendors to implement it!
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 made an app using PhoneGap that needs to access the user's current latitude and longitude to function.
Here's what I did:
navigator.geolocation.getCurrentPosition(function(pos) {
// code using pos
});
On the browser this asks your permission to access the info, but on the finished app it doesn't ask anything and just doesn't work.
Is there anything I'm doing wrong/missing?
#Dogmatics,
there is not enough information to debug your problem. Assuming you turned on the GPS and Location services, then you forgot to wait for the 'deviceready' event.
From the documentation:
This is a very important event that every Cordova application should use.
Cordova consists of two code bases: native and JavaScript. While the native code is loading, a custom loading image is displayed. However, JavaScript is only loaded once the DOM loads. This means your web application could, potentially, call a Cordova JavaScript function before it is loaded.
The Cordova deviceready event fires once Cordova has fully loaded. After the device has fired, you can safely make calls to Cordova function.
If this proves to be correct, you will want to read #4 in:
Top Mistakes by Developers new to Cordova/Phonegap
https://github.com/jessemonroy650/top-phonegap-mistakes/blob/master/new-to-Phonegap.md
Best of Luck
I am working on an extension for Chrome that utilizes a native messaging host. My background.js registers a listener immediately to process all onBeforeRequest events (i.e., all requests) and pass them on to the native helper application. This is all well and good when a page is visited after Chrome has started up, but when I click a URL that launches Chrome, my listener does not fire.
Here is the basic structure of the listener at the top of my background.js:
chrome.webRequest.onBeforeRequest.addListener(function (details) {
alert('forwarding request!');
chrome.runtime.sendNativeMessage('<extension name>', { url: details.url });
}, { urls: ['http://*', 'https://*'] }, ['blocking']);
Obviously, there are conditions in place that determine whether to pass off the request and block it in Chrome, but they are not relevant here. Even without the sendNativeMessage bit, I cannot produce an alert for the URL that is clicked to launch an instance of Chrome.
Any clever ways to register this listener before the first request at startup goes through?
You can try giving your extension the background permission:
Makes Chrome start up early and and shut down late, so that apps and extensions can have a longer life.
When any installed hosted app, packaged app, or extension has "background" permission, Chrome runs (invisibly) as soon as the user logs into their computer—before the user launches Chrome. The "background" permission also makes Chrome continue running (even after its last window is closed) until the user explicitly quits Chrome.
This way the Chrome process and extensions will be loaded before you click any URL. The user can still circumvent this by explicitly killing the Chrome process.
As a side note, keep in mind that the response from your onBeforeRequest listener needs to be synchronous if you want to block a request, so you can't base the decision to block on the response from a native messaging host.
One way to solve the problem is to use the chrome.declarativeWebRequest API to declaratively register a webRequest listener. The disadvantage of this API is that it is only available to Chrome users on the beta and dev channel at the moment, and less flexible than the webRequest API (the rules are declarative, so you cannot make runtime decisions about request handling that are not supported by the DWR API).
Another way to work around the problem is to use chrome.tabs.query to find tabs that had been opened before the extension was launched.