Phonegap Crew,
I have an problem with accessing a webservice using android. I have no problem accessing it using iOS.
The enclosed code uses a public webservice so you can try the code if you are so inclined.
On iOS we get a xmlhttp.status == 200 and returned data.
On Android we get a xmlhttp.status == 0.
We are using cordova-1.8.1.jar
We have the white list set in res/xml/cordova.xml
like this:
<access origin=".*"/>
I am bring that up because I am suspicious that our white list is not working.
here is the code:
function testweather(){
var xhr= new XMLHttpRequest();
xhr.onreadystatechange = function(){
alert(xhr.readyState);
if(xhr.readyState == 4){
if(xhr.status == 200){
$( "#result" ).append( xhr.responseText );
}
else{
alert("can't get response. a.status:"+xhr.status);
}
}
}
var url = "http://graphical.weather.gov/xml/SOAP_server/ndfdXMLserver.php";
xhr.open("POST", url,true);
xhr.setRequestHeader("SOAPAction", "http://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl#NDFDgenByDayLatLonList");
xhr.setRequestHeader("Content-Type", "text/xml;charset=UTF-8");
xhr.setRequestHeader("Content-Length", 1536);
xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
xhr.setRequestHeader("Accept", "application/soap+xml, application/dime, multipart/related, text/*");
xhr.setRequestHeader("User-Agent", "IBM Web Services Explorer");
xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.setRequestHeader("Pragma", "no-cache");
xhr.setRequestHeader("Connection", "close");
var soapEnv = '' +
'<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ndf="http://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl">' +
' <soapenv:Header/>' +
' <soapenv:Body>' +
' <ndf:NDFDgenByDayLatLonList soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' +
' <listLatLon xsi:type="dwml:listLatLonType" xmlns:dwml="http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd">35.4,-97.6</listLatLon>' +
' <startDate xsi:type="xsd:date">2012-06-27</startDate>' +
' <numDays xsi:type="xsd:integer">3</numDays>' +
' <Unit xsi:type="dwml:unitType" xmlns:dwml="http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd">e</Unit>' +
' <format xsi:type="dwml:formatType" xmlns:dwml="http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd">24 hourly</format>' +
' </ndf:NDFDgenByDayLatLonList>' +
' </soapenv:Body>' +
'</soapenv:Envelope>';
xhr.send( soapEnv );
}
Sometimes when you do an AJAX request from the file protocol you will get a status of
0 but that is effectively a 200. Just change you if to be:
if(xhr.status == 200 || xhr.status == 0)
and you should be good to go.
Here is a blog post I wrote on using AJAX from PhoneGap.
http://simonmacdonald.blogspot.com/2011/12/on-third-day-of-phonegapping-getting.html
Updated: Apparently there is a bug in Android 2.x where setting the "Content-length" header causes the problem you describe. It looks like the bug has been fixed in Android 4.0.3. So try this code unmodified in the 4.0.3 emulator and it should work then come back to 2.x and remove the Content-length header to see if it works as well.
We gave up trying to run the webservice in Javascript and wrote a Java plugin to run the webservice. We needed it to work on a wide variety of devices and not rely on the user updating their device.
Try adding the below code in src > com.domain.appname > appname.java after
super.onCreate(savedInstanceState);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
Related
I´m making a simple GET request in titanium and it seems to be that in versions of android 5.0 and up doesn´t work correctly. Here is the response of the console that im receiving.
< ANDROID 5.0
[INFO] : Status: 200, connectionType: GET
=> ANDROID 5.0
{"source":{"password":null,"status":0,"username":null,"autoRedirect":true,"bubbleParent":true,"allResponseHeaders":"","location":"","autoEncodeUrl":true,"apiName":"Ti.Network.HTTPClient","responseXML":null,"validatesSecureCertificate":false,"readyState":1,"domain":null,"responseText":"","responseData":null,"connectionType":"GET","statusText":null,"connected":false,"_events":{"disposehandle":{}}},"error":"Handshake
failed","code":-1,"success":false}
ERROR: "Handshake failed"
Here is the code that im using.
var url = "MY URL";
var loader = Titanium.Network.createHTTPClient();
loader.onload = function()
{
Titanium.API.info('Status: ' + this.status);
Titanium.API.info('ResponseText: ' + this.responseText);
Titanium.API.info('connectionType: ' + this.connectionType);
Titanium.API.info('location: ' + this.location);
};
loader.onerror = function (e) {
console.log(JSON.stringify(e));
console.log("ERROR: " + JSON.stringify(e.error));
};
loader.open("GET",url);
loader.send();
Hope you can help me with this.
This is an issue with the SSL certificate of the webserver.
You can verify that the certificate is valid from Chrome:
I'm trying to get the http response headers every time I visit some site. I thought that using an observer like the following is enough to do it:
const OBS = Cc['#mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
let httpRequestObserver ={
observe: function(subject, topic, data){
var httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
if (topic == "http-on-examine-response") {
headers=httpChannel.getAllResponseHeaders();
}
}
};
And in the startup method I add it then in the shutdown I remove it:
OBS.addObserver(httpRequestObserver, "http-on-examine-response", false);//startup methode
OBS.addObserver(httpRequestObserver, "http-on-examine-response", false);//shutdown
But I'm getting this in the log:
JavaScript Error: "httpChannel.getAllResponseHeaders is not a function"
Am I taking the wrong way and the operation is more complicated than it seem? this is for an extension for firefox for android and i'm not using sdk. Thanks for your help.
nsIHttpChannel is not XMLHttpRequest. Instead XMLhttpRequest is a nice wrapper class around channels - not just http ones -, which also adds convenience functions such as getAllResponseHeaders().
You may use nsIHttpChannel.visitResponseHeaders to simulate getAllResponseHeaders.
if (subject instanceof Ci.nsIHttpChannel) {
var headers = "";
subject.visitResponseHeaders(function(header, value) {
headers += header + ": " + value + "\r\n";
});
}
I am using Microsoft Sync Framework to sync the details from the Datadictionary on android device with SQL Server. Initially get success to sync all data from sql server. But after adding some data and when clicking on the Sync button getting the following error. Can you please tell me is anybody came across this?
[Sync Error]:Error occurs during sync. Please check logs below.
[Upload Change Response Error]: 500 Response: <ServiceError xmlns="http://schemas.datacontract.org/2004/07/Microsoft.Synchronization.Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><ErrorDescription>System.InvalidOperationException
serverBlob is empty
at Microsoft.Synchronization.Services.SqlProvider.SqlSyncProviderService.ApplyChanges(Byte[] serverBlob, List`1 entities)
at Microsoft.Synchronization.Services.UploadChangesRequestProcessor.ProcessRequest(Request incomingRequest)
at Microsoft.Synchronization.Services.SyncService`1.ProcessRequestForMessage(Stream messageBody)
</ErrorDescription></ServiceError>
In the below code, i'm getting xmlHttp.status=500 when clicking on the Sync button
this.sendRequest = function (serviceUri, successCallback, errorCallback, dir) {
TraceObj("[" + dir + " Request]:", serviceUri, this.dataObject());
// Construct HTTP POST request
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", serviceUri);
xmlHttp.setRequestHeader("Accept", "application/json");
xmlHttp.setRequestHeader("Content-Type", "application/json");
// Handle success & error response from server and then callback
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
var res = new SyncFormatter();
if (res.parse(xmlHttp.responseText)) {
TraceObj("[" + dir + " Response]:", serviceUri, res.dataObject());
alert("[" + dir + " Response]:", serviceUri, res.dataObject());
successCallback(res);
return;
}
}
TraceMsg("[" + dir + " Response Error]: ", xmlHttp.status + " Response: " + xmlHttp.responseText);
errorCallback(xmlHttp.responseText);
}
};
xmlHttp.send(this.toString());
};
}
I have found the root cause of the problem. That is when i get the values from datadictionary storage, value has the single quotes in the values so not able to load the values in webview. Now i have replaced single quotes by \'. Now working fine.
I have an AJAX function I am building which makes a call on scroll or click/touchtstart to append some content to my HTML. Everything works great for me in the desktop environment, both on click and on scroll events. However neither of them work on my Android 2.3.7 HTC EVO or my Nexus 7 on Android 4.1.1.
Here is my click JavaScript event handler:
$('.loadMore').each(function() {
//Set URL and start on the first page
var self = this;
var path2root = ".";
var loc = window.location.origin;
var url = loc + "/process.php";
var subcategoryId = $(this).parent().attr('data-subcategoryId');
var page = 1;
// Build the updated URL
$(self).bind('touchstart', function(e) {
e.preventDefault();
page++;
// AJAX function for processing JSON
$.ajax({
url: url + "?subcategoryId=" + subcategoryId + "&page=" + page,
type: "GET",
contentType: "application/json; charset=utf-8",
dataType: "json",
async: false,
success: function (data) {
var i = 0;
for(i = 0 ; i < data.length; i++) {
var articleId = data[i].articleResult.articleId;
var title = data[i].articleResult.title;
var subhead = data[i].articleResult.subhead;
var image = data[i].articleResult.image;
var response = "<td><div class='articleResult'><a href='" + path2root + "/article/article.php?articleId=" + articleId + "'><img src='" + image + "' width='120'/></a><br><h3><a href='" + path2root + "/article/article.php?articleId=" + articleId + "'>" + title.substring(0,25) + "</a></h3></div></td>";
$("table tr td:nth-last-child(2)").after(response);
};
}
});
});
});
My scroll function is very similar, only I bind the event to a different element, and on scroll:
// Collecting scroll info
$('.overthrow').each(function() {
// SAME VARIABLES
$(this).scroll(function () {
if ($(self).scrollLeft() >= parseInt($(document).width() - 50)) {
if (finished == 1) {
page++;
finished = 0;
// SAME AJAX FUNCTION
};
};
});
});
Keep in mind this is a mobile optimized webpage, not a native PhoneGap app, and I am using regular jQuery 1.8.0, not jQuery Mobile or PhoneGap.
I had found THIS issue over on Google Code in regards to Android 2.3 not receiving touchstart events very effectively, which led me to start building the on scroll function instead.
According to your link from Google Code the fix would be to include an e.preventDefault() at the start of your touchstart event like so:
$(self).bind('touchstart', function(e) { // include e as a reference to the event
e.preventDefault(); // prevents the default behaviour on this element
....
});
The above works on my Android 2.X devices; I hope it helps!
So I was able to get the AJAX call functioning properly for the on scroll event. I have abandoned the click/touchstart event all together as that seems to be buggy in Android.
For whatever reason, Android was not reading dynamic URL correctly when uploaded to the webserver:
var loc = window.location.origin;
var url = loc + "/process.php";
So when I was building my ajax call with the compiled URL:
$.ajax({
url: url + "?subcategoryId=" + subcategoryId + "&page=" + page,
the window.origin.location was being misinterpreted. Instead I needed to hard-code the location of my process.php file:
url: "process.php?subcategoryId=" + subcategoryId + "&page=" + page,
I discovered my solution through another SO post HERE
The only catch being my code was working on iPhone, but not on Android. If anyone knows the reason behind this, that would be great information to have.
I am using $getJSON to hit a node.js endpoint under Phonegap and Android. The code looks like this
$.getJSON(
serverURL + "/login?callback=?",
"playerId=" + playerId + "&pwd=" + pwd,
function(data){
theCallbackFunction.call(null, JSON.parse(data));
},
function(jqXHR, textStatus, errorThrown) {
alert('error ' + textStatus + " " + errorThrown);
}
);
In response to the login request, my server sends back a session cookie. This cookie is only accepted and returned in subsequent AJAX requests if 'Third-Party Cookies' are enabled in the browser. I have found that older Android devices (e.g. 2.2) allow this by default but new ones (3.2) do not.
Is it possible to force Phonegap to enable Third-Party Cookies for my Android application?
I had a similar problem when trying to authenticate with my server. I instead resorted to the use of localStorage. See the code below or here.
var store = window.localStorage,
request = {
url: {SERVER_URL},
headers : {
Cookie: store.getItem('session')
},
complete: function (jqXHR, status){
if (status != 'success') {
console.log('ajax status: failure');
} else if (store.getItem('session') != null) {
console.log('ajax status: session exists');
} else {
console.log('ajax status: saving cookie');
var header = jqXHR.getAllResponseHeaders();
var match = header.match(/(Set-Cookie|set-cookie): (.+?);/);
if (match) {
session = match[2];
store.setItem("session", session);
}
}
}
}
$.ajax(request);
In the above, I'm checking for the localStorage variable 'session' and if it exists, it will send the stored cookie. If it doesn't exist, it will take the 'set-cookie' paramater sent in the headers by the server, match the pertinent part and store it in the 'session' variable of localStorage.
Phonegap does not support cookie abstraction. Never really needed to as there are already apps/plug-ins that do. Plus it is intended to wrap up the functionality of the phone/device, not the browser. You CAN however do this with a jQuery plug-in.
https://github.com/carhartl/jquery-cookie