I am developing an hybrid application for android and iOS. This is not my first app, but I don't consider myself an expert either. At the moment I'm targeting Android 4.4 or later. For iOS I got an iPhone 4S to test, not supporting anything below iOS 9.2. To make this app I'm currently using Phonegap Build, which outputs version=cli-5.2.0 and using jQuery Mobile 1.4.5 as the framework to handle the UI, navigation and so on. The Javascript is being loaded locally - from the device.
Considering some server interaction takes some time to load, I was thinking to show a loading gif while the server interaction processes. For this matter I'm using a loader widget from jQuery Mobile. The code for the ajax request calls has the following code:
$.serviceCall = function(web_method, web_root, params){
var ajax_response;
var request_url = 'http:/some.url.com/' + web_root + '/' + web_method;
$.mobile.loading( "show", {
text: "loading",
textVisible: false,
theme: "z",
html: ""
});
$.ajax({
type: 'get',
contentType: 'application/json; charset=utf-8',
async: false,
dataType: 'json',
url: request_url,
data: params,
}).done(function(data){
ajax_response = data
ajax_response.callback = 'done';
$.mobile.loading("hide");
}).fail(function(jqXHR, textStatus, errorThrown){
var failure_details = {
status: jqXHR.status,
text_status: textStatus,
error_thrown: errorThrown
};
ajax_response = failure_details;
ajax_response.callback = 'fail';
$.mobile.loading("hide");
});
return ajax_response;
};
Which works perfectly fine when accessing from a desktop browser or from ripple emulator to simulate the actual device.Once the request starts, the loader shows, hides as soon as the request ends and makes the page transition.
However, on android doesn't work. Whenever the request starts the loader doesn't show up no matter how long the request takes. Is there any trick for mobile OS that I need to apply in order to make it work?
check this guide on how to inspect the App.
I suggest taking out $.mobile.loading("hide"); so you can keep the loader running to see whats happening. might be a z-index issue or an error in the console
You have made a common mistake. You need to apply the whitelist system. It is required as of Cordova Tools 5.0.0 (April 21, 2015). For Phonegap Build, that means since cli-5.1.1 (16 Jun 2015)
Add this to your config.xml
<plugin name="cordova-plugin-whitelist" source="npm" spec="1.1.0" />
<allow-navigation href="*" />
<allow-intent href="*" />
<access origin="*" /> <!-- Required for iOS9 -->
NOTE YOUR APP IS NOW INSECURE. IT IS UP TO YOU TO SECURE YOUR APP.
Add the following to your index.html
<meta http-equiv="Content-Security-Policy"
content="default-src *;
style-src * 'self' 'unsafe-inline' 'unsafe-eval';
script-src * 'self' 'unsafe-inline' 'unsafe-eval';">
This whitelist worksheet should help.
HOW TO apply the Cordova/Phonegap the whitelist system
If it is not this, then there may be a JQuery Mobile setting which I may not be familiar with.
Related
I am new to ionic platform. I am trying to implement Google map in my app.Map is displaying when I am testing on browser but when running on real device on Android it is just displaying white screen. I have tried different number of things as recommended in different threads. I have applied changes in config file as mentioned in below link
https://github.com/driftyco/ionic-starter-maps/issues/10
but no luck and have applied changes using different number of meta tags individually as describes in other threads but no luck. In console I can see the error as 'Uncaught ReferenceError: google is not defined'. For this I have tried different thread as mentioned below
Uncaught ReferenceError: google is not defined
but still getting the same error. I am not able to figure this error out.What else I am missing below is the code I am sharing used in my app.Index page code is
This is my controller code
.controller('MapCtrl', function($scope, $ionicLoading) {
google.maps.event.addDomListener(window, 'load', function() {
var myLatlng = new google.maps.LatLng(37.3000, -120.4833);
var mapOptions = {
center: myLatlng,
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var myDiv=document.getElementById("map");
var map = new google.maps.Map(myDiv, mapOptions);
});
})
and below are the lines I have added in config file as recommended in different threads
<access origin="*"/>
<access origin="http://maps.google.com"/>
<access origin="https://maps.google.com"/>
<access origin="http://*.googleapis.com"/>
<access origin="https://*.googleapis.com"/>
Any help
It seems that you haven't well imported Google Maps in the file index.html.
The issue is the line :
<script src="//maps.google.com/maps/api/..."></script>
On a browser it will load this script : http://maps.google.com/maps/api/... since you are serving the file through http.
But on a device, you are serving the file through file:// so it will try to load this script : file://maps.google.com/maps/api/...
That is not available.
So you need to specify https like this :
<script src="https://maps.google.com/maps/api/..."></script>
I've been struggling with this for days now. I have an Ionic 1.3.0 application using ngCordova#0.1.26-alpha
I am using $cordovaFile.writeFile() to store images in cordova.file.applicationStorageDirectory. I've tried every storage location with the same result. The file is good, I can view it in a file manager app. I would like to use the file as an ng-src for an <img>. On Android, this might look something like: cdvfile://localhost/sdcard/Android/data/com.example.mobile/img-49444.jpg
So in my page, I bind the URL to the <img> and stick a sanity check <pre> in there to see that record.image_url has a valid URL:
<img ng-src="{{record.image_url}}">
<pre>{{record.image_url}}</pre>
While the URL looks good to me, the image simply doesn't render and it seems no amount of effort will convince it. I've tried file:///, cdvfile://, and http:// URLs, using entry.toURL(), entry.toInternalURL(), etc., from the response objects from $cordovaFile.writeFile(). All approaches fail with either a broken image icon or an empty <img> element rendering.
I've tried adding this CSP tag to index.html (and dozens of other attempts)
<meta http-equiv="Content-Security-Policy" content="img-src 'self' data: blob: filesystem: cdvfile://*;">
And I've tried messing around with $compileProvider, like:
$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|cdvfile):|data:image\//);
And throwing everything I can at config.xml Cordova whitelists
<plugin name="cordova-plugin-whitelist" spec="~1.2.1">
<access origin="*"/>
<access origin="cdvfile://*"/>
<access origin="file://*"/>
<access origin="file:///*"/>
<allow-intent href="cdvfile://*"/>
<allow-intent href="file://*"/>
<allow-intent href="file:///*"/>
<allow-navigation href="cdvfile://*"/>
<allow-navigation href="file://*"/>
<allow-navigation href="file:///*"/>
</plugin>
Nothing works. I don't think this is a white list plugin issue - my assumption is that when the image is rejected due to the white list, the image is displayed as a broken link, whereas the <img> element is instead empty and takes up no space when the white list is not rejecting it. This behavior is consistent on Android 4.4.4 and 6.0.1.
Any help would be greatly appreciated.
So as to not mislead others that come across this answer, I managed to get cdvfile:// URLs to work even in livereload mode without issue in a new app. Simply:
config.xml
<access origin="*"/>
<access origin="tel:*" launch-external="yes"/>
<access origin="geo:*" launch-external="yes"/>
<access origin="mailto:*" launch-external="yes"/>
<access origin="sms:*" launch-external="yes"/>
<access origin="market:*" launch-external="yes"/>
<access origin="cdvfile:*"/>
<plugin name="cordova-plugin-whitelist" spec="~1.2.2"/>
Note that <access> rules are NOT supposed to be nested under <plugin>. The documentation doesn't explicitly call that out.
app.js
.config(function ($stateProvider, $urlRouterProvider, $compileProvider) {
$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|file|blob|cdvfile|content|tel|geo|mailto|sms|market):|data:image\//);
I do not have a Content-Security-Policy meta tag declared in index.html
And all is well.
So it turns out I can use file:///* paths for ng-src if I deploy the built .apk to the device instead of using the Ionic livereload server (ionic run android -cls). It should be obvious that hardware-level functions won't work through something like the browser-based ionic serve, but it was less obvious that testing on actual hardware would fail like this based on the livereload server. I incorrectly assumed that the livereload server was just a file monitoring approach where it would stream assets onto the device as they change and maybe notify the app to reload. Instead it seems they are just hosting a web server directly on your host. $cordovaFile correctly reads/write files on the device even in livereload, but the web views in the app don't have native access to the files on the device in that mode. I could read the file contents with $cordovaFile.readAsText() and that would still work even on livereload, but when it comes to the web views in the app reaching files, well, it just doesn't have any access to native device URLs.
If anyone else runs into this issue, here's how I'm writing the file and capturing the URL so that it works in a view.
$ionicPlatform.ready(function () {
var targetDir = cordova.file.externalApplicationStorageDirectory + "files/";
$cordovaFile.writeFile(targetDir, name, imageData, true)
.then(function (info) {
console.log("File created", info.target.localURL, JSON.stringify(info));
$cordovaFile.checkFile(targetDir, name).then(function (entry) {
console.log("Got file entry", entry.toURL());
q.resolve(entry.toURL());
});
}, function (e) {
q.reject(e);
});
});
return q.promise;
}
On android this would return a URL like:
file:///storage/emulated/0/Android/data/com.example/files/<name>
I've found that cordova-plugin-whitelist can be empty in config.xml - we don't need any whitelist directives for file:///. Also, no $compileProvider.imgSrcSanitizationWhitelist() changes are necessary - the default whitelist should work.
I never did get cdvfile:// URLs to work, regardless of whitelist settings, Content-Security-Policy directives, or app.config tweaks.
In Chrome for Android on Lollipop, you can set a meta theme-color tag and favicon: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android?hl=en
My code:
<link rel="icon" sizes="192x192" href="//static.rizzo.co.uk/images/favicon_192.png">
<meta name="theme-color" content="#95c676">
This works for me on parts of the site that are http but as soon as it goes to https it loses the theme-color and favicon for the rest of the session.
I have tried the theme-color and favicon separately but can get neither to work with https. The favicon is available on https as well as http. Has anyone used these successfully with https or had a similar problem?
I thought I had the same issue, turns out it was a caching problem that somehow was fixed when I used android remote debugging (caching only the head tag?).
Anyway, it should work. You can try copy pasting the html in this page to your https server: http://useragentman.com/tests/theme-color/?test
or attach the following script (from useragentman, in case page is down):
<script>
var $themeColor = document.querySelector("meta[name='theme-color']");
function startAnim() {
if ($themeColor.content === '#ff0000') {
$themeColor.content = '#ffffff';
} else {
$themeColor.content = '#ff0000';
}
setTimeout(startAnim, 500);
}
startAnim();
</script>
I know this question has been asked before, but I've tried all the proposed solutions and nothing seems to work!
I'm working on a mobile app built with Phonegap (+Angular but I don't think that's important). In this app I'm using the geolocation plugin. More specifically my config.xml looks like the following:
<?xml version="1.0" encoding="UTF-8" ?>
<widget xmlns = "http://www.w3.org/ns/widgets"
xmlns:gap = "http://phonegap.com/ns/1.0"
id = "......"
version = "1.0.0" >
<name>.....</name>
<preference name="permissions" value="none"/>
<preference name="orientation" value="default" />
<preference name="target-device" value="universal" />
<preference name="phonegap-version" value="3.6.3" />
<gap:plugin name="org.apache.cordova.geolocation" />
<gap:plugin name="com.phonegap.plugins.PushPlugin" version="2.4.0" />
<gap:plugin name="org.apache.cordova.network-information" />
<gap:plugin name="org.apache.cordova.statusbar" />
<gap:plugin name="org.apache.cordova.device" />
<gap:plugin name="org.transistorsoft.cordova.background-geolocation"/>
</widget>
There are times that I want to get the current position of the user, so I'm doing it as follows:
navigator.geolocation.getCurrentPosition(function (position) {
.....
}, function (error) {}, {
enableHighAccuracy: true,
maximumAge: 30000,
timeout: 10000
});
This is working fine on iOS devices and it even works on the ripple emulator for Android.
But when I try to run the app on Android and more specifically on Nexus 4 and 5, the geolocation doesn't seem to work. It's not that it's giving me an error, it's just trying to retrieve the position without any luck.
However, all the other apps that are using geolocation and also the geolocation in the browser is working perfectly fine!
I would also like to note that I'm using Phonegap Build to build the app.
Does anyone know how I can fix this problem? Did anyone have the same issue?
From your code sample, how would you know that there's no error being raised when you have an empty error handler function (error) {}?
getCurrentPosition() makes a single request for the device position. If this is called just once, the position timeout may occur before the GPS hardware on the device has had a chance to get a position fix.
I'd suggest using watchPosition() instead to setup a watcher which will call the success function each time the OS receives a location update. If you only need a single position, you can clear the watcher, optionally checking to make sure you've got a position of acceptable accuracy.
For example:
var minAccuracyInMetres = 50;
var positionWatcher;
function onDeviceReady(){
positionWatcher = navigator.geolocation.watchPosition(
geolocationSuccess,
geolocationError,
{maximumAge:0, timeout: 10000, enableHighAccuracy: true});
}
function geolocationSuccess(position){
// Reject if accuracy is not sufficient
if(position.coords.accuracy > minAccuracyInMetres){
return;
}
// Only single position required so clear watcher
navigator.geolocation.clearWatch(positionWatcher);
// Do something with the user's location...
}
function geolocationError(error){
console.warn("Error while retrieving current position. " +
"Error code: " + error.code + ",Message: " + error.message);
}
document.addEventListener("deviceready", onDeviceReady, false);
I have a problem with phonegap and $.get (jQuery). It's actually only a webapp which exists already but I want to bring it on my Android Smartphone.
So my $.get is working and I have this settings:
In res/xml/config.xml:
<access origin="*"/>
In AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
But it's not working :(
Edit 1 (17.11.2013 15:23):
alert("getData: "+searchTerm+" in "+language);
$.get("http://mysite.de/search.php", {art: searchTerm, lang: language}).done(function(data){
alert("daten: "+data);
}, "html");
alert("ready");
Only the first and the third alert is working.
The problem is
XMLHttpRequest cannot load http://mysite.de/search.php. Origin http://localhost is not allowed by Access-Control-Allow-Origin.
You need to allow access to http://mysite.de/search.php from any domain
Allow it by adding code to your php page:
header("Access-Control-Allow-Origin: *");