phonegap adobe ios iPad deviceReady not fired until notifications shown - ios

The deviceReady event is not fired when starting the app.
Dragging the notifications list down from the top of the screen and releasing then causes the deviceReady to fire.
Similarly, trying to display a page in the inAppBrowser doesn't display until the notifications are dragged down and released.
Key elements in the config.xml are:-
<gap:plugin name="cordova-plugin-whitelist" version="1.0.0" source="npm" />
<gap:plugin name="cordova-plugin-inappbrowser" source="npm" version="1.0.1" />
<gap:plugin name="cordova-plugin-device" source="npm" version="1.0.1" />
<preference name="permissions" value="none"/>
<preference name="fullscreen" value="true" />
<preference name="exit-on-suspend" value="true" />
Html:-
<!DOCTYPE html >
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Home</title>
<meta http-equiv="Content-Security-Policy" .... />
</head>
<body >
<div id="idSplash" class="textCenter" >
<div id="idSplashHeader">
<div class="headerImg"></div>
</div>
<div>
<div id="idSplashMessage">Starting up ...</div>
</div>
<div id="idSplashBody"></div>
<div id="idSplashFooter"><a id="idTestLink" href="javascript:null" target="_blank">Click here for google</a></div>
</div>
<!-- ************************************************************************** -->
<script src="js/jquery-2.0.3.min.js" type="text/JavaScript" ></script>
<script type="text/JavaScript">
$(document).ready(function () {
function onReady() {
$("#idSplashMessage").text("deviceReady");
alert("deviceReady");
}
document.addEventListener("deviceReady", onReady, false);
$("#idTestLink").click(function () {
var win = window.open(encodeURI("http://www.google.co.uk"), '_blank', 'location=yes');
return false;
});
});
</script>
<script src="cordova.js" type="text/JavaScript"></script>
</body>
</html>

The source of the problems was the inclusion of a content security policy in the html.
Although I believe the CSP was entirely valid, and did not cause any issues with Android, I removed it which allowed the IOS version to work.
The CSP was added in the first place due to an error log from the whitelist plug in suggesting it was required.

#Grebe,
this is a common misunderstanding with developers new to Cordova/Phonegap.
From: Top Mistakes by Developers new to Cordova/Phonegap
4. In the code, did not listen for the 'deviceready' event.
(...) the section of documentation we need.
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.
This means you must do this before you call any other libraries.
This also means you need to load cordova.js before jquery.
EXAMPLE
function onLoad() {
document.addEventListener("deviceready", onDeviceReady, false);
}
// _OR_ JUST
document.addEventListener("deviceready", onDeviceReady, false);
// Cordova is loaded and it is now safe to make calls Cordova methods
//
function onDeviceReady() {
document.addEventListener("pause", onPause, false);
$(document).ready(function () {
// Call the usual stuff.
}
}

Related

In Cordova app, physical iPhone SE can't display images from "file://" URLs; OK in iOS simulator and Android

I'm writing an app with Cordova 11.0.0, cordova-ios 6.2.0, and Xcode 13.3 that sets the background image to the user's choice. Everything works fine on Android and on the iOS simulator. However, when running on a physical iPhone SE (2022) with iOS 15.4, the background image is not displayed, though it seems to set style.backgroundImage correctly on the element, and I'm able to read the image file correctly using a standard FileReader object. It appears that any local images using a file:// URL are not displayed. I'm loading them from under cordova.file.dataDirectory, so I can't just convert to a relative http:// URL. I believe my Content-Security-Policy is permissive enough (?) (see index.html below).
I made a small demo of this; the only plugin it uses is cordova-plugin-file 6.0.2. My config.xml contains:
<content src="index.html" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<platform name="ios">
<preference name="allowFileAccessFromFileURLs" value="true" />
<preference name="allowUniversalAccessFromFileURLs" value="true" />
</platform>
My index.html is:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy"
content="default-src * file: filesystem: ; img-src * file: filesystem: ; style-src * file: filesystem: 'unsafe-eval' ;">
<meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover">
<link rel="stylesheet" href="css/index.css">
<title>Hello World</title>
<script src="cordova.js"></script>
<script src="js/index.js"></script>
</head>
<body>
<h1>Background image should show up</h1>
</body>
</html>
My index.js is:
// Wait for the deviceready event before using any of Cordova's device APIs.
document.addEventListener('deviceready', onDeviceReady, false);
async function onDeviceReady() {
try{
// this block just copies file from under cordova.file.applicationDirectory
// to under cordova.file.dataDirectory, for this demo
// FileEntry.copyTo() throws error on ios if file already exists, so use try/catch
try {
let entry= await new Promise((resolve, reject) =>
resolveLocalFileSystemURL(cordova.file.applicationDirectory + 'www/img/home_bg.jpg',
resolve, reject) ) ;
let dest_dir= await new Promise((resolve, reject) =>
resolveLocalFileSystemURL(cordova.file.dataDirectory, resolve, reject) ) ;
await new Promise((resolve, reject) =>
entry.copyTo(dest_dir, undefined, resolve, reject) ) ;
} catch(e) {}
// set full background property
let full_url= cordova.file.dataDirectory + 'home_bg.jpg' ;
document.body.style.background= 'url(' + full_url + ') center/cover' ;
// this shows the correct 'url("file:///Users/.../Library/NoCloud/home_bg.jpg")'
alert('computed backgroundImage=[' + getComputedStyle(document.body).backgroundImage + ']') ;
} catch(e) {
alert('in odr(): '+e) ;
}
}
My index.css is simply:
body {
height:100vh;
width:100vw;
}
h1 {
font-size:24pt;
margin:3rem;
text-align:center;
}
And finally, I have a background image in img/home_bg.jpg that is copied to be under cordova.file.dataDirectory.
I've read many questions here about file:// URLs, but none of the solutions have worked and are appropriate (e.g. using data: URLs for the images is impractical and unscalable). I know that the app paths change for every install on an iPhone, but the code above should still work.
How can I get images to display on a physical iPhone using file:// URLs? Am I missing some setting in Xcode or elsewhere?
Thanks for any help!
Thanks to this answer by #jcbdrn, I managed to work around this by using blob: URLs for all displayed images:
let blob= new Blob([await read_file_binary(file_entry)]) ;
img.src= URL.createObjectURL(blob) ;
... where read_file_binary() reads a file as an arrayBuffer. Note that the Content Security Policy must include blob: in the img-src directive.
This isn't as efficient as just using file: URLs, but it's much better than using data: URLs. It does seem like a bug in either cordova-ios (?) or in WKWebView (?), but I'm set for now.

Cordova/Phonegap Build geolocation on iOS timeout

I have been experiencing the same issue, and have tried in the past 2 weeks numerous solutions found online for this with no success, any help appreciated :)
I am writing a simple app using Cordova for IOS and Android and building it using Phonegap build. The problem is that I cannot get the "navigator.geolocation.getCurrentPosition" (or navigator.geolocation.watchPosition) calls to return anything except a timeout error on iOS. (works perfectly on Android)
Additionally, the location services dialog never appears (requesting user permission to allow GPS for the app)
To add to this strange behavior, it seems that i have to touch the screen after the app is loaded to initiate the geolocation call, on most cases the app just sits there and does nothing until the screen is touched.
Testing this on iPhone 5 with iOS 9
Things I tried:
Changing timeout settings (up to 30 seconds)
Setting enableHighAccuracy true/false
Running code with or without the geolocation plugin
Manually adding the NSLocationWhenInUseUsageDescription/NSLocationAlwaysUsageDescription settings (or both) to the plist file
Installing different plugin versions for the geolocation plugin
Changing Content Security Policy meta tag
Trying to add or remove the <plugin> declaration from root config.xml
Current plugins installed ($cordova plugin list):
cordova-plugin-dialogs 1.2.0 "Notification"
cordova-plugin-geolocation 1.0.1 "Geolocation"
cordova-plugin-whitelist 1.2.0 "Whitelist"
cordova.plugins.diagnostic 2.3.5 "Diagnostic"
Root config.xml:
<?xml version='1.0' encoding='utf-8'?>
<widget id="info.test" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>App name</name>
<description>
App Name
</description>
<author email="test#test.com" href="http://test.com">
App Team
</author>
<content src="index.html" />
<plugin name="cordova-plugin-whitelist" spec="1" />
<access origin="*" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<allow-intent href="tel:*" />
<allow-intent href="sms:*" />
<allow-intent href="mailto:*" />
<allow-intent href="geo:*" />
<platform name="android">
<allow-intent href="market:*" />
</platform>
<platform name="ios">
<allow-intent href="itms:*" />
<allow-intent href="itms-apps:*" />
</platform>
</widget>
index.js
var geo = {
getGeo: function() {
navigator.geolocation.getCurrentPosition(
geo.onSuccess,
geo.onError,
{maximumAge:0, timeout: 5000, enableHighAccuracy: false});
},
onSuccess: function(position) {
alert('GOT location');
alert(position.coords.latitude + ' --- ' + position.coords.longitude);
},
onError: function(error) {
alert('error getting geo!');
}
};
var app = {
// Application Constructor
initialize: function() {
this.bindEvents();
},
// Bind Event Listeners
//
// Bind any events that are required on startup. Common events are:
// 'load', 'deviceready', 'offline', and 'online'.
bindEvents: function() {
document.addEventListener('deviceready', this.onDeviceReady, false);
},
// deviceready Event Handler
//
// The scope of 'this' is the event. In order to call the 'receivedEvent'
// function, we must explicitly call 'app.receivedEvent(...);'
onDeviceReady: function() {
app.receivedEvent('deviceready');
},
// Update DOM on a Received Event
receivedEvent: function(id) {
var parentElement = document.getElementById(id);
var listeningElement = parentElement.querySelector('.listening');
var receivedElement = parentElement.querySelector('.received');
listeningElement.setAttribute('style', 'display:none;');
receivedElement.setAttribute('style', 'display:block;');
console.log('Received Event: ' + id);
geo.getGeo();
}
};
app.initialize();
iOS Plist file:
<key>NSLocationAlwaysUsageDescription</key>
<string>This app requires constant access to your location in order to track your position, even when the screen is off.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string/>
Index.html:
<html>
<head>
<!--
Customize this policy to fit your own app's needs. For more guidance, see:
https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy
Some notes:
* gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
* https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
* Disables use of inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
* Enable inline JS: add 'unsafe-inline' to default-src
-->
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
<link rel="stylesheet" type="text/css" href="css/index.css">
<title>Hello World</title>
</head>
<body>
<div class="app">
<h1>Apache Cordova</h1>
<div id="deviceready" class="blink">
<p class="event listening">Connecting to Device</p>
<p class="event received">Device is Ready</p>
</div>
</div>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/index.js"></script>
</body>
</html>
Any help in the right direction appreciated!
#daddio
Oh. that's it. I should be more dogmatic on this. This should take care of the problem.
It is not advisable to use Phonegap CLI to make your Phonegap Build build project. Phonegap build requires that index.html and config.xml both sit in the root directory. All the extra files that you are required to use with Phonegap CLI, never are created or needed with Phonegap Build.
So, I'm going to give you one of my working demos. Notice that all the files are in one (1) directory.
tutorial/blog entry - An HTML Boilerplate for Phonegap Build
source code Phonegap--Generic-Boilerplate
Notice how the compiler version is set to:
<preference name="phonegap-version" value="cli-5.2.0" />
Notice, if you change cli-5.2.0 to 3.7.0, nothing appears to change.
Basically for Phonegap Build, you need index.html and config.xml - that's it. Then for security reasons (as of Cordova Tools 5.0.0), it is advisable to create a css file and a javascript file. However, I'll show you how to get around this.
Here is my complete list of Demo Apps.
Phonegap Demo Apps
YOUR FIX
This is my working code, test with 3.5.0 and cli-5.1.1 and cli5.2.0
source code Phonegap-GPS-Test
On Your fix, notice how the version is set to: <preference name="phonegap-version" value="3.5.0" />
Okay, I trust all of this will work for you. As such, your documentation is here:
https://build.phonegap.com/docs
There are some special rules for adding plugins, but I'll give you those when your program is running.
How to add Plugins with Phonegap Build
FOR THE MOST IMMEDIATE FUTURE, get your *core* plugins from this list:
http://cordova.apache.org/docs/en/5.4.0/cordova/plugins/pluginapis.html
Get your 3rd-party plugin from this source:
http://cordova.apache.org/plugins/
When using Phonegap Build, sometimes the pluins get fixed (or updated) and this breaks Phonegap Build. This is because the "fixes" require the latest version of the compiler, and Phonegap Build is always at least one version behind.
There are two ways to deal with 3; see 4 and 5.
I have created this Worksheet. You may want to make a copy or just use it as a reference. I use this worksheet to create my demos, I so know the list is good. I am working on cli-5.2.0 right now. (Should finish by Monday or so.) However, I do not test ALL 3rd-party plugins; there are 800+ plugins.
If you fail to set the version number on a plugin, you will get the latest version. If your build fails, then set the version. If the build still fails, try the previous two or three version to find one that works. NOTE, these older plugins may have bugs that prevent you from using them. So, try an even earlier version.
Lastly, if you think you have hit a bug, then here is a page with links to the Bug respository for each plugin. Last Update is on the top left. Best of Luck.

Phonegap Facebook Connection can not find JavaScript

I know there are a few articles discussing this issue, I followed them all with no luck.
I am getting the ever issue - "Facebook variable does not exist. check that you have included the Facebook JS SDK file"
My bundle name in Xcode is org.apache.cordova.Game
So if I understood correctly in my config file I wrote:
<gap:plugin name="org.apache.cordova.Game.plugins.FacebookConnectPlugin">
<param name="APP_ID" value="123123" />
<param name="APP_NAME" value="Game" />
</gap:plugin>
I am trying to launch the sample index.html and the cdv-plugin-fb-connect.js and facebook-js-sdk.js are both in www folder (copied the js using finder and no action from Xcode)
index.html copied to www in finder as well and the source is :
<body>
<button onclick="login()">Login</button>
<button onclick="me()">Me</button>
<!--<button onclick="getSession()">Get session</button>-->
<button onclick="getLoginStatus()">Get login</button>
<button onclick="logout()">Logout</button>
<button onclick="facebookWallPost()">facebookWallPost</button>
<button onclick="publishStoryFriend()">friendstory</button>
<div id="data">loading ...</div>
<!--<script src="http://localhost:8080/target/target-script-min.js#anonymous"></script>-->
<div id="fb-root"></div>
<!-- cordova -->
<script src="cordova.js"></script>
<!-- cordova facebook plugin -->
<script src="cdv-plugin-fb-connect.js"></script>
<!-- facebook js sdk -->
<script src="facebook_js_sdk.js"></script>
<script>
.........
First of all from cordova 3 the one should add the the config file the plugin as feature and not as plugin
<feature name="org.apache.cordova.facebook.Connect">
<param name="ios-package" value="FacebookConnectPlugin" />
</feature>
Second of all in the html it should be on device ready and not as documented in the web dev API by FB:
document.addEventListener('deviceready', function() {
try {
FB.init({ appId: "12345", nativeInterface: CDV.FB, useCachedDialogs: false });
FB.Event.subscribe('auth.authResponseChange', function(response) {
getProfile();
});
} catch (e) {
alert(e);
}
}, false);

PhoneGap Notification.Alert not working

Okay I've been working on this issue for a while now and can't figure this thing out. Simple PhoneGap test app, trying to show an alert.
Using Cordova 2.9.0 for iOS. I've added some simple test code and tested it in chrome to see where it breaks, because it isn't working in the emulator
When I test in the Chrome (of course same result in emulator, but no error message is showing)
It executes the onDeviceReady as it should
It sets tb2 textbox value to 'before alert'
Then it breaks with the error: Uncaught TypeError: Cannot call method 'alert' of undefined, on this line: navigator.notification.alert(...
It should be referencing the cordova.js properly, here is the structure of my app folder:
cordova_plugins.js
cordova.js
/spec
spec.html
config.xml
/css
home.html
/img
index.html
/js
/res
Here is my config.xml code:
<?xml version='1.0' encoding='utf-8'?>
<widget id="com.blahblahblah.hello" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>Hello World</name>
<description>
Test blahblahblah Application
</description>
<author email="blahblahblah#blahblahblah.com" href="http://blahblahblah.com">
blahblahblah
</author>
<access origin="*" />
<preference name="fullscreen" value="true" />
<preference name="webviewbounce" value="true" />
<plugins>
<plugin name="Notification" value="CDVNotification" />
</plugins>
</widget>
Here is my index.html code:
<!DOCTYPE html>
<html>
<head>
<title>Notification Example</title>
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script type="text/javascript" charset="utf-8">
// Wait for Cordova to load
//
document.addEventListener("deviceready", onDeviceReady, false);
// Cordova is ready
//
function onDeviceReady() {
// Empty
document.getElementById('tb1').value = 'device ready';
}
// alert dialog dismissed
function alertDismissed() {
// do something
}
// Show a custom alert
//
function showAlert() {
document.getElementById('tb2').value = 'before alert';
navigator.notification.alert(
'You are the winner!', // message
alertDismissed, // callback
'Game Over', // title
'Done' // buttonName
);
document.getElementById('tb3').value = 'after alert';
}
</script>
</head>
<body>
<p>Show Alert</p>
<input type="text" id="tb1" value="" />
<input type="text" id="tb2" value="" />
<input type="text" id="tb3" value="" />
</body>
</html>
I have searched documentation, and haven't found any clue of why this isn't working, most answers to this question don't address version 2.9.0
Thanks in advance.
I know the question is about Phonegap 2.9, but that's the first thing Google spits when somebody looks for "phonegap alert not working". So here's what I did for it to work with Phonegap 3.0:
According to the manual, you need to add the plugin to your project. Just navigate to your project root folder and write this command:
$ phonegap local plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-dialogs.git
After that, I added this to my html:
<script type="text/javascript" charset="utf-8" src="phonegap.js"></script>
<script>
document.addEventListener("deviceready", onDeviceReady, true);
function onDeviceReady() {
navigator.notification.alert("PhoneGap is working", function(){}, "", "");
}
</script>
I'm using Phonegap 2.9.0 and the problem that i had is that I haven't add the script cordova.js to the page.
Also be aware that exist a cordova.js file specific to each platform so watch out of adding cordova.js from android on iOS.
Remember that all calls to the phonegap API should be done after deviceready has fired
try to add this feature to your config.xml file..
<feature name="Notification">
<param name="wp-package" value="Notification"/>
</feature>
..I hope that's help...
All you need is to add the plugin:
cordova-plugin-dialogs
Then use the alert function which will interrupt program flow:
alert("some problem here");
Works for iOS and Android.

Checking for navigator.globalization on deviceready returns undefined on iOS

I am using PhoneGap 2.2.0 on iOS and binding to the devicready event to see if the navigator.globalization object is there. I am getting undefined.
My code looks like this:
document.addEventListener('deviceready', onDeviceReady, false);
function onDeviceReady()
{
alert('deviceready');
navigator.globalization.getLocaleName(function(d)
{
window.localStorage.setItem('localeLanguage', d.value);
console.log('localeLanguage: is'+d.value);
},
function(error)
{
console.log('error getting locale language');
});
}
The alert('deviceready') never fires. I am really at a loss here. I'm setting up my scripts as follows.
<script src="js/jquery-1.8.2.min.js"></script>
<script src="js/jquery.mobile-1.2.0.min.js"></script>
<script type="text/javascript" src="cordova-2.2.0.js"></script>
<script type="text/javascript">
//alert(typeof navigator.globalization);
</script>
<script src="js/jquery.ui.map.full.min.js"></script>
<script src="js/jquery.ui.map.services.min.js"></script>
<script src="js/jquery.i18n.min.js"></script>
<script src="js/languages.js"></script>
<script src="js/oakglobalization.js"></script>
<script type="text/javascript" src="js/index.js"></script>
<script type="text/javascript">
app.initialize();
</script>
<script type="text/javascript" src="js/custom.js"></script>
Any ideas would be helpful as this is a showstopper now.
Try :
$(document).ready(function() {
document.addEventListener("deviceready", onDeviceReady, false);
});
to add you event listener.
And maybe try to update your cordova version. The current version is the 2.6.0.
Another point : with phonegap, use the Navigator.notification.alert method instead of the native javascript alert. More info here.
Hope this helps ! Bye !
Not sure if you solved it or not, but at least for me ( PG 3.3.0 ) using navigator.globalization I had to install the cordova plugin and change the XML accordingly.
command-line> cordova plugin add org.apache.cordova.globalization
config.xml>
<feature name="Globalization">
<param name="ios-package" value="CDVGlobalization" />
</feature>
On that note, it didn't work on browser emulators ( ie.: ripple ) only on the real iOS xcode emulator ...
Backup your project just in case ;)

Resources