PhoneGap Build 6.3.0 geolocation getCurrentPosition slow on IOS - ios

I am new in developing on PhoneGap Build. While testing some basic app functionalities I experience a timeout problem when doing a simple geolocation request on my Iphone 6 / IOS 10 / PhoneGap Build 6.3.0.
After re-installing the app I start it and initiate the geolocation by onclick -> geolocation().
Only when I turn the app to the background, I receive the IOS request to allow the location request (should come when I first do the onclick -> geolocation while having the app in the foreground).
Sometimes I get a geolocation result after a long time, sometimes not. I've tried all possible combinations on the three PositionOptions.
When I ask the Google Maps app it shows me the location immediately.
Any idea what I am doing wrong?
Thank you, Kim
function do_geolocation(){
alert('do geoloc');
navigator.geolocation.getCurrentPosition(geo_onSuccess, geo_onError, {maximumAge:120000, enableHighAccuracy:false} );
}
onclick=do_geolocation();
function geo_onSuccess(position){
alert('Latitude: ' + position.coords.latitude + '\n' +
'Longitude: ' + position.coords.longitude + '\n' +
'Altitude: ' + position.coords.altitude + '\n' +
'Accuracy: ' + position.coords.accuracy + '\n' +
'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' +
'Heading: ' + position.coords.heading + '\n' +
'Speed: ' + position.coords.speed + '\n' +
'Timestamp: ' + position.timestamp + '\n');
var arr = new Array();
arr['lat'] = position.coords.latitude;
arr['lng'] = position.coords.longitude;
var x = new Date();var cb = x.getTime();
}
function geo_onError(position){
alert('code: '+error.code+'\nmessage: '+error.message+'\n');
return false;
}
<?xml version="1.0" encoding="UTF-8" ?>
<widget xmlns = "http://www.w3.org/ns/widgets"
xmlns:gap = "http://phonegap.com/ns/1.0"
id = "de.vvvvvv.secapp"
versionCode = "10"
version = "1.0.0" >
<!-- versionCode is optional and Android only -->
<name>vvvvvvv</name>
<description>
vvvvvvvvvvvv
</description>
<author href="http://vvvvvvv.de" email="info#vvvvvv.de">
Kim
</author>
<plugin name="cordova-plugin-geolocation" spec="2.4.1" />
<plugin name="cordova-plugin-whitelist" spec="1.3.1" />
<access origin="*"/>
<allow-intent href="http://*/*"/>
<allow-intent href="https://*/*"/>
<preference name="orientation" value="portrait" />
<!-- https://makeappicon.com/ios10icon -->
<icon src="res/icons/ios/Icon-App-20x20#2x.png" platform="ios" width="20" height="20" />
<icon src="res/icons/ios/Icon-App-20x20#3x.png" platform="ios" width="40" height="40" />
...

Only when I turn the app to the background, I receive the IOS request to allow the location request (should come when I first do the onclick -> geolocation while having the app in the foreground).
The activation only on backgrounding the app sounds sympomatic of a Content-Security-Policy issue (here's another example).
To resolve, ensure that your Content-Security-Policy meta tag contains gap://ready and file: entries for default-src. For example:
<meta http-equiv="Content-Security-Policy" content="default-src * gap://ready file:; style-src 'self' 'unsafe-inline'; img-src 'self' data:; script-src * 'unsafe-inline' 'unsafe-eval'">
Sometimes I get a geolocation result after a long time, sometimes not. I've tried all possible combinations on the three PositionOptions.
Setting maximumAge to 120000 means a position up to 2 minutes old (cached by the OS) can be used. To force a fresh position, set it to zero:
{
enableHighAccuracy: false
maximumAge: 0,
timeout: 2000
}
If setting enableHighAccuracy to true, this engages GPS hardware to get a lock, so set a sufficient timeout to allow it to lock enough satellites:
{
enableHighAccuracy: true
maximumAge: 0,
timeout: 30000
}
For a full explanation of PositionOptions, see the Mozilla docs

Related

IOS 13 XMLHttpRequest Blob audio/mpeg returns as text/html

The code I have used to work on both Android and IOS, until I had to make the IOS version on ionic use WKWebViewOnly.
This is the code that was working on IOS (still works on Android):
var type = window.PERSISTENT;
var size = 50*1024*1024; // 50MB
window.requestFileSystem(type, size, successCallback, errorCallback);
function successCallback(fs) {
window.resolveLocalFileSystemURL(app.folder, function(dirEntry) {
dirEntry.getFile(mix_name, {create: true}, function(fileEntry) {
fileEntry.createWriter(function(fileWriter) {
fileWriter.onwriteend = function(e) {
alert('Write success');
};
fileWriter.onerror = function(e) {
alert('Write failed: ' + e.toString());
};
var oReq = new XMLHttpRequest();
// Make sure you add the domain name to the Content-Security-Policy <meta> element.
oReq.open("GET", "https://domain-to-get-file.com/path/to/file.mp3", true);
// Define how you want the XHR data to come back
oReq.responseType = "blob";
oReq.onload = function (oEvent) {
var blob = oReq.response; // Note: not oReq.responseText
blob = blobToFile(blob, fileName);
fileWriter.write(blob);
};
oReq.send(null);
}, errorCallback);
}, errorCallback);
}, errorCallback);
}
function errorCallback(error) {
alert("ERROR: " + error.code)
}
function blobToFile(theBlob, fileName) {
// A Blob() is almost a File() - it's just missing the two properties below which we will add
theBlob.lastModifiedDate = new Date();
theBlob.name = fileName;
return theBlob;
}
In my index.html I have the meta tag:
<meta http-equiv="Content-Security-Policy" content="
default-src * data: cdvfile: gap: blob:;
script-src 'self' 'unsafe-inline' *.domain-to-get-file.com;
style-src 'self' 'unsafe-inline';">
And the plugins I have used are:
<plugin name="cordova-plugin-wkwebview-engine" source="npm" />
<plugin name="cordova-plugin-wkwebview-file-xhr" spec="~2.1.4" />
Works fine on Android but not on IOS 13.
I think i'm missing a security thing, but I have no idea how to fix that.
Thanks :)
This was a miss leading issue, but for anyone stumbling upon it.
The fix was to switch from using XMLHttpRequest to Fetch: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
I had no clue about Fetch until I saw this video: https://www.youtube.com/watch?v=tc8DU14qX6I&list=PLRqwX-V7Uu6YxDKpFzf_2D84p0cyk4T7X
and you will also need this: https://www.youtube.com/watch?v=zswi0cPMxsU to solve the CORS issue
I also did removed the plugins:
<plugin name="cordova-plugin-wkwebview-engine" source="npm" />
<plugin name="cordova-plugin-wkwebview-file-xhr" spec="~2.1.4" />
and adding this all-in-one plugin seemed to fix the issue.
https://www.npmjs.com/package/cordova-plugin-wkwebview-ionic-xhr
Added these two preferences in the ios platform in config.xml
<preference name="allowFileAccessFromFileURLs" value="true" />
<preference name="allowUniversalAccessFromFileURLs" value="true" />

How to allow only these orientations in my Cordova/Phonegap app?

I created an iOS (iPhone) App using Cordova and want to only allow the following orientations:
Portrait
Landscape Left
Landscape Right
This also means that "upside down" should not be allowed:
I know that I can set this in Xcode but when ever I start a new Cordova build this setting gets overwritten.
So I checked Cordova docs and found this: http://cordova.apache.org/docs/en/5.1.1/config_ref_index.md.html#The%20config.xml%20File
It says that I can set orientation in config.xml like this:
<preference name="Orientation" value="landscape" />
But I don't see how I can set a more fine granular setting as I described above. How can this be done?
Note: I am on Cordova 5.1.1
You can use config.xml'
<platform name="ios">
<preference name="Orientation" value="all" />
</platform>
along with shouldRotateToOrientation(degrees) callback as stated in the docs like this:
onDeviceReady: function() {
app.receivedEvent('deviceready');
window.shouldRotateToOrientation = function(degrees) {
return degrees !== 180;
};
},
You can use an after_prepare hook which will apply the settings after the cordova prepare and therefore avoid them getting overwritten on each cordova build. Place the following code in <your_project>/hooks/after_prepare/some_file.js:
#!/usr/bin/env node
// Set support for all orienations in iOS .plist - workaround for this cordova bug: https://issues.apache.org/jira/browse/CB-8953
var platforms = process.env.CORDOVA_PLATFORMS.split(',');
platforms.forEach(function(p) {
if (p == "ios") {
var fs = require('fs'),
plist = require('plist'),
xmlParser = new require('xml2js').Parser(),
plistPath = '',
configPath = 'config.xml';
// Construct plist path.
if (fs.existsSync(configPath)) {
var configContent = fs.readFileSync(configPath);
// Callback is synchronous.
xmlParser.parseString(configContent, function (err, result) {
var name = result.widget.name;
plistPath = 'platforms/ios/' + name + '/' + name + '-Info.plist';
});
}
// Change plist and write.
if (fs.existsSync(plistPath)) {
var pl = plist.parseFileSync(plistPath);
configure(pl);
fs.writeFileSync(plistPath, plist.build(pl).toString());
}
process.exit();
}
});
function configure(plist) {
var iPhoneOrientations = [
'UIInterfaceOrientationLandscapeLeft',
'UIInterfaceOrientationLandscapeRight',
'UIInterfaceOrientationPortrait'
];
var iPadOrientations = [
'UIInterfaceOrientationLandscapeLeft',
'UIInterfaceOrientationLandscapeRight',
'UIInterfaceOrientationPortrait'
];
plist["UISupportedInterfaceOrientations"] = iPhoneOrientations;
plist["UISupportedInterfaceOrientations~ipad"] = iPadOrientations;
}
Note: you'll need to install the plist and xml2js node modules if you don't already have them.

Android - write to a file . Can't find the file

I'm new to android, so this might be prety basic.
I'm trying to write data into a file, yet I can not find the file in the device.
I'm trying to get the file in the following directory:
"Computer\Nexus 5\Internal storage\Android\data\application name"
I have tried different method but none of them has worked:
FileOutputStream stream;
try {
stream = openFileOutput(filename,Context.MODE_APPEND | Context.MODE_WORLD_READABLE);
stream.write(string.getBytes());
stream.close();
}catch(IOException e){
}}
and
String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/Android/data/" + packageName + "/files/";
try {
boolean exists = (new File(path )).exists();
if (!exists) {
new File(path ).mkdirs();
}
// Open output stream
FileOutputStream fOut = new FileOutputStream(path + filename,true);
// write integers as separated ascii's
fOut.write((Integer.valueOf(content).toString() + " ").getBytes());
// Close output stream
fOut.flush();
fOut.close();
} catch (IOException e) {
e.printStackTrace();
}
I have added the permission in the manifest :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.proLeague"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE"/>
<group gid="sdcard_rw" />
<group gid="media_rw" />
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:debuggable= "true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
I thought maybe the file is logged properly but I need to pull it out from the ADB, is that possible?
I had manage to solve my issues on my own :
Evantually the code was fine, the problem was that on my nexus 5 phone I need to reboot the phone before I search for new files in the flash storage.
I saw in some blogs it is pretty common.

phonegap build generic push plugin - no valid aps-environment

im trying to use the generic push for my app. it works on android but on ios i get the error msg: no valid aps-environment
i have added support to push notifications in apple provisioning
profile
i created and downloaded the provisioning profile after enabling the push
i have <key>aps-environment</key> in mobileprovision
i have installed the mobile provision and app on my phone
i have checked and tested every solution
my config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<widget xmlns = "http://www.w3.org/ns/widgets"
xmlns:gap = "http://phonegap.com/ns/1.0"
id = "---.-------.-----"
versionCode="10"
version = "1.1.0">
<!-- versionCode is optional and Android only -->
<name>PhoneGap push Example</name>
<description>
An example for phonegap build docs.
</description>
<author href="http://-----------" email="---------------">------</author>
<access origin="*" />
<!--DEVICE FEATURES ACCESS-->
<feature name="http://api.phonegap.com/1.0/camera"/>
<feature name="http://api.phonegap.com/1.0/file"/>
<feature name="http://api.phonegap.com/1.0/geolocation"/>
<feature name="http://api.phonegap.com/1.0/media"/>
<feature name="http://api.phonegap.com/1.0/network"/>
<feature name="http://api.phonegap.com/1.0/notification"/>
<gap:plugin name="GenericPush" /> <!-- latest release -->
</widget>
my js
<script type="text/javascript" charset="utf-8" src="phonegap.js"></script>
<script type="text/javascript" charset="utf-8" src="jquery_1.5.2.min.js"></script>
<script type="text/javascript" src="PushNotification.js"></script>
<script type="text/javascript">
var pushNotification;
function onDeviceReady() {
$("#app-status-ul").append('<li>deviceready event received</li>');
pushNotification = window.plugins.pushNotification;
if (device.platform == 'android' || device.platform == 'Android') {
pushNotification.register(successHandler, errorHandler, {"senderID":"661780372179","ecb":"onNotificationGCM"});
} else {
pushNotification.register(tokenHandler, errorHandler, {"badge":"true","sound":"true","alert":"true","ecb":"onNotificationAPN"});
}
}
// handle APNS notifications for iOS
function onNotificationAPN(event) {
if (event.alert) {
$("#app-status-ul").append('<li>push-notification: ' + event.alert + '</li>');
navigator.notification.alert(event.alert);
}
if (event.sound) {
var snd = new Media(event.sound);
snd.play();
}
if (event.badge) {
pushNotification.setApplicationIconBadgeNumber(successHandler, event.badge);
}
}
// handle GCM notifications for Android
function onNotificationGCM(e) {
$("#app-status-ul").append('<li>EVENT -> RECEIVED:' + e.event + '</li>');
switch( e.event )
{
case 'registered':
if ( e.regid.length > 0 )
{
$("#app-status-ul").append('<li>REGISTERED -> REGID:' + e.regid + "</li>");
// Your GCM push server needs to know the regID before it can push to this device
// here is where you might want to send it the regID for later use.
console.log("regID = " + regID);
}
break;
case 'message':
$("#app-status-ul").append('<li>MESSAGE -> MSG: ' + e.message + '</li>');
$("#app-status-ul").append('<li>MESSAGE -> MSGCNT: ' + e.msgcnt + '</li>');
break;
case 'error':
$("#app-status-ul").append('<li>ERROR -> MSG:' + e.msg + '</li>');
break;
default:
$("#app-status-ul").append('<li>EVENT -> Unknown, an event was received and we do not know what it is</li>');
break;
}
}
function tokenHandler (result) {
$("#app-status-ul").append('<li>token: '+ result +'</li>');
// Your iOS push server needs to know the token before it can push to this device
// here is where you might want to send it the token for later use.
}
function successHandler (result) {
$("#app-status-ul").append('<li>success:'+ result +'</li>');
}
function errorHandler (error) {
$("#app-status-ul").append('<li>error:'+ error +'</li>');
}
document.addEventListener('deviceready', onDeviceReady, true);
</script>
<div id="app-status-div">
<ul id="app-status-ul">
<li>Cordova PushNotification Plugin Demo</li>
</ul>
</div>
According to the Phonegap Build community forums, you need to use a distribution provision certificate for the APS registration to work : http://community.phonegap.com/nitobi/topics/ios_problem_with_push_notification_plugin_for_phonegap_build
Some people have succeeded after switching to production certificates.
However, I have the same problem and still cannot get it working with production certificates.
after long research and trial and error. i found out that i need to use:
on IOS (adhoc provision profile) and on push server(production aps cert and key)

C2DM registration results never receive

I have used "Android Cloud to Device Messaging (C2DM) - Tutorial" by Lars Vogel.
When i start my applcation, registration response never received.
How It can be solved?
my Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<application android:icon="#drawable/appicon" android:label="#string/app_name" android:debuggable="true">
<activity android:name=".activities.MainActivity"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar.Fullscreen"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ui.DailyTripList" android:screenOrientation="portrait" />
<activity android:name=".ui.TripActivity" android:screenOrientation="portrait" />
<activity android:name=".ui.StationsList" android:screenOrientation="portrait" />
<activity android:name=".ui.StationActivity" android:screenOrientation="portrait" />
<activity android:name=".ui.PassengerList" android:screenOrientation="portrait" />
<activity android:name=".ui.DriverMsgList" android:screenOrientation="portrait" />
<service android:name=".services.SecurityReqestTransmitter" android:exported="false"/>
<service android:name=".services.LocationTransmitter" android:exported="false"/>
<activity android:name=".cardReader.IDTUniMagActivity" android:screenOrientation="portrait" />
<receiver android:name="com.google.android.c2dm.C2DMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<!-- Receive the actual message -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.em_projects.MyWay.receivers" />
</intent-filter>
<!-- Receive the registration id -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.em_projects.MyWay.receivers" />
</intent-filter>
</receiver>
</application>
CatLog
08-15 23:57:41.624: WARN/KeyCharacterMap(959): No keyboard for id 0
08-15 23:57:41.634: WARN/KeyCharacterMap(959): Using default keymap: /system/usr/keychars/qwerty.kcm.bin
08-15 23:57:44.645: DEBUG/dalvikvm(150): GC_EXTERNAL_ALLOC freed 698 objects / 37712 bytes in 273ms
08-15 23:58:01.374: DEBUG/SntpClient(70): request time failed: java.net.SocketException: Address family not supported by protocol
08-15 23:58:17.365: INFO/EventLogService(236): Aggregate from 1313450896472 (log), 1313450896472 (data)
08-15 23:58:22.704: DEBUG/dalvikvm(236): GC_EXPLICIT freed 473 objects / 120056 bytes in 276ms
08-15 23:58:29.744: DEBUG/dalvikvm(150): GC_EXTERNAL_ALLOC freed 611 objects / 29936 bytes in 198ms
08-15 23:58:32.754: DEBUG/MainActivity(959): onClick
08-15 23:58:33.944: INFO/global(959): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required.
08-15 23:58:33.974: DEBUG/Communicator(959): # parseData <?xml version="1.0" encoding="UTF-8"?><root><row internal_code="644" external_code="1442" ws_string="http://wap.y-it.co.il:8080/wapdb/ws_redirect/http://localhost:8080/fltctrl_11" report_location_period="60" reject_mission="1"/></root>
08-15 23:58:34.124: DEBUG/MainActivity(959): Rows counter = 1
08-15 23:58:34.155: DEBUG/MainActivity(959): handleMessage
08-15 23:58:34.184: INFO/ActivityManager(70): Starting activity: Intent { flg=0x4000000 cmp=com.em_projects.MyWay/.ui.DailyTripList }
08-15 23:58:34.494: DEBUG/DailyTripList(959): onCreate
08-15 23:58:35.444: DEBUG/dalvikvm(959): GC_FOR_MALLOC freed 7436 objects / 493624 bytes in 90ms
08-15 23:58:43.254: ERROR/C2DMRegistrar(236): [C2DMReg] handleRequest caught java.io.IOException: SSL shutdown failed: I/O error during system call, Broken pipe
08-15 23:58:43.534: DEBUG/SecurityReqestTransmitter(959): onCreate
08-15 23:58:43.584: DEBUG/SecurityReqestTransmitter(959): initServiceThread
08-15 23:58:43.624: DEBUG/SecurityReqestTransmitter(959): run
08-15 23:58:43.634: DEBUG/SecurityReqestTransmitter(959): onStartCommand
08-15 23:58:43.875: DEBUG/LocationTransmitter(959): onCreate
08-15 23:58:43.944: DEBUG/LocationTransmitter(959): spd = 0.0
08-15 23:58:44.024: WARN/GpsLocationProvider(70): Duplicate add listener for uid 10040
08-15 23:58:44.224: WARN/ActivityManager(70): Launch timeout has expired, giving up wake lock!
08-15 23:58:44.414: INFO/global(959): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required.
08-15 23:58:44.454: WARN/ActivityManager(70): Activity idle timeout for HistoryRecord{44ec58c0 com.em_projects.MyWay/.ui.DailyTripList}
08-15 23:58:44.534: DEBUG/Communicator(959): # parseData <?xml version="1.0" encoding="UTF-8"?><root><row line_code="90476" acc_name="אי סי אי" order_start_time="08:00" order_end_time="08:30" line_description="איסוף עובדים איזור הדרום" line_status="-1" t_Pass_QTY="4" Pass_QTY="4" group_name="שם הקבוצה" department_name="שם המחלקה" line_date="2011-08-15" long_remarks="הערות ארוכות...
שורה שניה
שורה שלישית
שורה רביעית
שורה אחרונה !" short_remarks="הערות קצרות של הנסיעה"/><row line_code="90377" acc_name="מפעל תע"ש רכש" order_start_time="12:00" order_end_time="12:45" line_description="מרוחובות+נס ציונה לתע"ש" line_status="-1" t_Pass_QTY="0" Pass_QTY="0" line_date="2011-08-15" long_remarks="" short_remarks=""/><row line_code="90406" acc_name="משתלת ציפורן" order_start_time="15:00" order_end_time="15:40" line_description="הסעות עובדים אמצע שבוע" line_status="5" t_Pass_QTY="0" Pass_QTY="0" department_name="מחלקה 1" line_date="2011-08-15" long_remarks="על הנהג להתקשר לשלמה 050-3344334 בעל המשתלה
כל יום לאחר סיום ההסעה." short_remarks="הערה ליום ב'"/><row line_code="90439" acc_name="טבע כפר סבא" order_start_time="18:00" order_end_time="18:00" line_description="נתב"ג כ"ס" line_status="-1" t_Pass_QTY="0" Pass_QTY="0" line_date="2011-08-15" long_remarks="" short_remarks=""/></root>
08-15 23:58:47.554: INFO/ActivityManager(70): Displayed activity com.em_projects.MyWay/.ui.DailyTripList: 13122 ms (total 13122 ms)
Is your app package name com.em_projects.MyWay.receivers?
If no, try to use only your package name instead of com.em_projects.MyWay.receivers in categories
<receiver android:name="com.google.android.c2dm.C2DMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<!-- Receive the actual message -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="***your_app_package_name***" />
</intent-filter>
<!-- Receive the registration id -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="***your_app_package_name***" />
</intent-filter>
</receiver>

Resources