Firstly, sorry about my english; I am not a native speaker.
Secondly, I'm making an app for Android using the framework Ionic and I'm using Django as an REST API.
I have issues with a factory: the HTTP status from the request in Django is 200 and the database registers the change, but in the app the HTTP status is 0. This happens only in this factory that contains two POST requests. The other POST requests made on the other factories work fine.
To test the app I use Google Chrome (with the command --disable-web-security), Ionic version 1.5.0, Django version 1.8.2, Cordova version 5.0 (I couldn't find which version of AngularJS I'm using). I have the same issues on several mobile devices.
Here are 3 controllers that cause the problem:
.controller('PlanesCtrl', function($scope, $ionicModal, $ionicPopup,$location, Planes, $window) {
$scope.planes = JSON.parse($window.localStorage['planes']);
$scope.usuario = JSON.parse($window.localStorage['user']);
var usuario_id = {
codusuario: $scope.usuario["codusuario"]
};
$scope.mascotaEscogida = JSON.parse($window.localStorage['mascotaEscogida']);
var especie_id = {
codespecie: $scope.mascotaEscogida.codespecie
};
var mascota_id = {
codmascota: $scope.mascotaEscogida.id
};
var data = {
codespecie: $scope.mascotaEscogida.codespecie,
codmascota: $scope.mascotaEscogida.id
}
$scope.ver_plan = function(plan){
Planes.selectChosenPlan(plan.id);
if (plan.suscrito == 0){
$location.path("/app/planes/" + plan.id);
}
else{
$location.path("/app/entrenar/" + plan.id);
}
};
})
.controller('PlanCtrl', function($scope, $ionicModal,$location, $ionicPopup, $window, Planes) {
$scope.mascotaEscogida = JSON.parse($window.localStorage['mascotaEscogida']);
var mascota_id = {
codmascota: $scope.mascotaEscogida.codmascota
};
$scope.plan = JSON.parse($window.localStorage['planActual']);
var data = {
codplan: $scope.plan.id,
codespecie: $scope.mascotaEscogida.codespecie,
codmascota: $scope.mascotaEscogida.id
};
$scope.suscribir = function(){
var data = {
codplan: $scope.plan.id,
codespecie: $scope.mascotaEscogida.codespecie,
codmascota: $scope.mascotaEscogida.id
};
console.log($scope.plan.id);
console.log($scope.mascotaEscogida.codespecie);
console.log($scope.mascotaEscogida.id);
Planes.suscribir(data, function() {
alert("Su mascota ha sido suscrita al plan con éxito");
} , function() {
} , function() {
console.log("No funciona suscribir en funcion suscribir, PlanCtrl");
});
Planes.buscar(data, function() {
} , function() {
} , function() {
console.log("No funciona buscar en funcion suscribir, PlanCtrl");
});
$location.path("/app/pet/" + mascota_id);
$window.location.reload(true);
};
})
.controller('PetCtrl', function($scope, $stateParams, $filter, $location, Mascota, Planes, $window, $ionicModal) {
$scope.mascotaEscogida = JSON.parse($window.localStorage['mascotaEscogida']);
$scope.usuario_logged = JSON.parse($window.localStorage['user_data']);
$scope.usuario_info = JSON.parse($window.localStorage['user']);
var data = {
codespecie: $scope.mascotaEscogida.codespecie,
codmascota: $scope.mascotaEscogida.id
}
$scope.ver_entrenamientos = function(mascota){
Planes.buscar(data, function() {
alert("Planes encontrados con exito");
} , function() {
alert("La mascotas no posee especie registrada (esto es muy extraño)");
} , function() {
console.log("No funciona buscar en ver_entrenamientos, PetCtrl");
});
$location.path("/app/planes");
$window.location.reload(true);
};
if($scope.usuario_logged === false) {
$location.path('/login');
}
else {
$scope.test = function() {
fecha_hora = $filter('date')(new Date(), 'yyyy-MM-dd HH:mm:ss', '-0300');
var info = {
fecha: fecha_hora,
codmascota: $scope.mascotaEscogida.id,
codusuario: $scope.usuario_info.codusuario
}
Mascota.alimentar(info, function() {
alert("La mascota ha sido alimentada con exito :)");
} , function() {
alert("Lo sentimos, algo ha ocurrido y no podemos registrar la alimentación");
} , function() {
alert("Verifica la conexión a internet");
});
}
}
})
And here is the factory:
.factory("Planes", function($http, $window){
var url = "http://localhost:8000/plan/";
var currentPlanes = function(data){
$window.localStorage['planes'] = JSON.stringify(data);
};
return {
selectChosenPlan: function(id) {
var arregloPlanes = JSON.parse($window.localStorage['planes']);
for (var i = 0; i <= arregloPlanes.length - 1; i++) {
if (parseInt(arregloPlanes[i].id) == id) {
$window.localStorage['planActual'] = JSON.stringify(arregloPlanes[i]);
}
}
},
buscar: function(inf, successFunction, errorFunction, connectionError) {
$http({
method: 'POST',
url: url + 'planes/',
headers: {'Content-Type': 'application/json'},
data: JSON.stringify(inf),
timeout: 20000
}).then(function successCallback(response) {
if (response.data.length > 0) {
console.log("buscar" + response.data[0]);
currentPlanes(response.data);
successFunction();
}
else{
currentPlanes(response.data);
errorFunction();
}
}, function errorCallback(response) {
connectionError();
});
},
suscribir: function(inf, successFunction, errorFunction, connectionError) {
$http({
method: 'POST',
url: url + 'suscribir/',
headers: {'Content-Type': 'application/json'},
data: JSON.stringify(inf),
timeout: 20000
}).then(function successCallback(response) {
if (response.data.length > 0) {
console.log("suscribir" + response.data[0]);
currentPlanes(response.data);
successFunction();
}
else{
currentPlanes(response.data);
errorFunction();
}
}, function errorCallback(response) {
connectionError();
});
}
};
})
I've made some research in the internet, but all the solutions I've found point to the CORS. If that were the problem, the other factory wouldn't work either, so I don't think that's the problem. Some other answers say that the problem could be in the HTML, on the button that calls 'ver_plan' or 'ver_entrenamiento', but both are set with type="button", so the submit wasn't the problem either. The error happens randomly and I can't find the issue in the flow of events. Sometimes, I even get a 'broken pipe' message from Django, but this also happens randomly.
I know that the JSON answer is valid and has the correct format; I'm out of ideas and I need to solve these issues.
Edit: Also, the line console.log("No funciona buscar en funcion suscribir, PlanCtrl"); doesn't appear in the console when I get the problem.
I found the answer a couple of weeks ago. The problem was
$window.location.reload(true); and $location.path();
It is not necessary the line $window.location.reload(true); if $location.path(); is located inside the factory call. For example:
Planes.buscar(data, function() {
$location.path("/app/pet/" + mascota_id);
} , function() {
} , function() {
console.log("No funciona buscar en funcion suscribir, PlanCtrl");
});
This way, the redirection occurs only if the answer from the server was successful and there is no need to use $window.location.reload(true);
I wish I can give you more details about the reason of the problem but my english is not good enough.
Related
My issue is very similar to this question Cordova - Reading Large Image corrupts image
but I haven't had any success with the solution. I'm also attempting to use the image picker plugin for Cordova
Cordova 7.0.1
Android 6.2.3
SapUI5 1.44.17
fileToBase64: function(fileUrl, callback) {
window.resolveLocalFileSystemURL(fileUrl, function(fileEntry) {
fileEntry.file(function(file) {
var reader = new FileReader();
reader.onload = function(evt) {
callback(evt.target.result);
};
reader.readAsDataURL(file);
}, function(error) {
console.log("File entry error " + error);
});
}, function(error) {
console.log("Resolve system file error " + error);
});
},
The result returned is an incomplete base64 string. Here's the loop through my images
handleImagePicker: function(oEvent) {
var _this = this;
window.imagePicker.getPictures(
function(results) {
var numOfImagesLeftToProcess = results.length;
if(numOfImagesLeftToProcess)
_this.appBusy(true);
for (var i = 0; i < results.length; i++) {
_this.fileToBase64(results[i], function(base64Str) {
console.log(base64Str);
numOfImagesLeftToProcess--;
if(numOfImagesLeftToProcess == 0) {
_this.appBusy(false);
}
});
}
}, function (error) {
console.log('Error: ' + error);
},
{
//outputType: imagePicker.OutputType.BASE64_STRING // default .FILE_URI
}
);
},
Not sure if the callback is being called prematurely. I'm able to view the images fine on the device and I've tested this code on two different devices with two different version of Android.
Any help would be appreciated.
I try to create Cordova mobile app based on angularjs following this tutorial: https://mobilefirstplatform.ibmcloud.com/blog/2016/08/11/best-practices-for-building-angularjs-apps-with-mobilefirst-foundation-8.0/
and LTPA Based Security Check login flow (in Mobilefirst 8.0) based on sample from: https://github.com/mfpdev/ldap-and-ltpa-sample
Mobile app is using angular. Authorisation implementation:
app.factory('Auth', function ($rootScope) {
var securityCheckName = 'LTPA',
_$scope = null,
challengeHandler = null,
URL = '',
challengeHandler = WL.Client.createSecurityCheckChallengeHandler(securityCheckName);
challengeHandler.securityCheckName = securityCheckName;
WLAuthorizationManager.login(securityCheckName, {'username': '', 'password': ''});
challengeHandler.handleChallenge = function (challenge) {
if (challenge && challenge.loginURL) {
URL = challenge.loginURL;
}
};
challengeHandler.handleSuccess = function (data) {
// code
};
challengeHandler.handleFailure = function (error) {
// code
};
return {
login: function ($scope, username, password) {
_$scope = $scope;
var request = new WLResourceRequest(URL, WLResourceRequest.POST);
request.send("j_username=" + username + "&j_password=" + password + "&action=Login").then(
function(response) {
challengeHandler.submitChallengeAnswer({});
},
function(error) {
// on error
});
}
};
});
This seems to work only on iOS. On Android handleSuccess function is not invoked.
As in the past, there was a problem with sending cookies on Android devices (with older MF versions) so I tried workaround in login function, that the hidden InAppBrowser was opened with logon form, then a user login process was made and once token was received, it was set via cordova-cookie-master-plugin and submitChallengeAnswer was invoked:
login: function ($scope, username, password) {
_$scope = $scope;
var request = new WLResourceRequest(URL, WLResourceRequest.POST);
request.send("j_username=" + username + "&j_password=" + password + "&action=Login").then(
function(response) {
if (device.platform == "iOS") {
challengeHandler.submitChallengeAnswer({});
} else {
iab = cordova.InAppBrowser.open(URL, "_blank", "hidden=yes");
iab.addEventListener('loadstop', function(event){
iab.executeScript({code:
'var field1 = document.getElementsByTagName("input")[0];' +
'var field2 = document.getElementsByTagName("input")[1];' +
'field1.setAttribute("value", "' + username + '");' +
'field2.setAttribute("value", "' + password + '");' +
'document.forms[0].submit();'
}, function(){
// on error
});
try {
cookieMaster.getCookieValue(URL, 'LtpaToken2', function(data) {
WL.Client.setCookie({
"name" : "LtpaToken2",
"value" : data.cookieValue,
"domain" : ".example.com",
"path" : "/",
"expires" : "Thu, 18 Dec 2999 12:00:00 UTC"
}).then(function() {
challengeHandler.submitChallengeAnswer({});
}).fail(function(err) {
// on error
});
}, function(error) {
// on error
});
} catch(err) {
// on error
}
});
iab.addEventListener('exit', function(){
iab.removeEventListener('loadstop', function() { /* on success */ });
});
}
},
function(error) {
// on error
});
}
This solution also not working for me. I've expect that after challengeHandler.submitChallengeAnswer() was fired, the handleSuccess will be invoked, but it is not happened. handleChallenge is invoked instead.
We are customizing the DirectUpdate process as in the documentation (https://www-01.ibm.com/support/knowledgecenter/SSHS8R_7.1.0/com.ibm.worklight.dev.doc/dev/c_customizing_direct_update_ui_android_wp8_ios.html - with a directUpdateCustomListener) but in the onFinish callback the status is FAILURE_UNZIPPING.
I am testing on an Android (5.1.1) emulator.
function wlCommonInit(){
WL.Client.connect({
onSuccess: function() {
console.log("Successfully connected to Worklight Server.");
}, onFailure: function() {
console.log("Failed connecting to Worklight Server.");
}
});
}
var busyInd = new WL.BusyIndicator('content');
var savedDirectUpdateContext = null;
var restartDirectUpdate = function () {
if (savedDirectUpdateContext != null) {
savedDirectUpdateContext.start(directUpdateCustomListener); // use saved direct update context to restart direct update
}
};
var directUpdateCustomListener = {
onStart: function(totalSize) {
busyInd.show();
},
onProgress: function(status, totalSize, completeSize) {},
onFinish: function(status) {
busyInd.hide();
console.log("[MFP - DirectUpdate] Finish status: " + status);
var posSuccess = status.indexOf("SUCCESS");
if (posSuccess > -1) {
WL.Client.reloadApp();
} else {
WL.SimpleDialog.show('Update Failed', 'Press try again button', [{
text: "Try Again",
handler: restartDirectUpdate // restart direct update
}]);
wl_directUpdateChallengeHandler.submitFailure();
}
}
};
wl_directUpdateChallengeHandler.handleDirectUpdate = function(directUpdateData, directUpdateContext) {
savedDirectUpdateContext = directUpdateContext
WL.SimpleDialog.show('Update Avalible', 'Press Update button to download the new version!', [{
text : 'Update',
handler : function() {
directUpdateContext.start(directUpdateCustomListener);
}
}, {
text : 'Cancel',
handler : function() {
wl_directUpdateChallengeHandler.submitFailure();
}
}]);
};
How can we fix this?
The custom code is working fine without zxing installed. I suggest that you will try the same without this library. If it works, I suspect that it may be initializing or otherwise interfering with the Direct Update process once an update has been received.
Considering loading the library later in the app life cycle and see if this helps.
I'm using simple Websocket connection on react native framework, with ios it works great, but on Android I'm in 70% getting message: WebSocketEvent {type: "error", message: null} and this error is closing socket connection. I don't know why does it happenning?
My code is:
self._ws = new WebSocket("wss://fe01-ws.wearetv.com/platform/simchacr/some_code");
var initPing = function (){
pingInterval = setInterval(function(){
ping.timestamp = new Date().getTime();
ping.sequenceNumber++;
ping.params.timestamp = ping.timestamp;
ping.params.sent_ts = ping.timestamp;
ping.params.seq = ping.sequenceNumber.toString();
self._ws.send(JSON.stringify(ping.params));
console.log("Ping is sent");
isPinged = false;
pongTimeout = setTimeout(function(){
if (isPinged === false) {
self._ws.close();
}
}, PONG_DELAY);
}, PING_INTERVAL);
};
var initConnection = (function me() {
isPinged = false;
self._ws.onopen = function () {
console.log("Connection opened");
initPing();
};
self._ws.onerror = function(error) {
console.error(error);
self._ws.close();
};
self._ws.onclose = function() {
console.log("Connection closed");
clearInterval(pingInterval);
clearTimeout(pongTimeout);
clearTimeout(reconnectTimeout);
reconnectTimeout = setTimeout(function(){
console.log("Ping reconnection");
initConnection();
initPing();
}, PING_RECONNECT_TIME);
isPinged = false;
};
self._ws.onmessage = function (message) {
//var data = JSON.parse(message.data);
//console.log(data);
//if (data[REQUEST_PROPERTY_MAIN] === "ACK") {
// clearTimeout(pongTimeout);
// clearTimeout(reconnectTimeout);
// isPinged = true;
//}
//self._getMessage(data);
};
return me;
})();
Have you configured Gradle to compile the same react-native version as the one you installed from the npm?
For example: compile project(':ReactAndroid')
as opposed to com.facebook.react:react-native:0.12.+
I'm developing an android app that needs to detect internet connection and if the device has no internet connection there will be an alert that the device has no internet connection.
here is my code:
<script>
var lform = $("#loginform");
function verifyfirst(){
if($( "#txtusername" ).val() == "" || $( "#txtpassword" ).val() == "")
{
return;
}
else
{
$.mobile.loading("show");
$.getJSON("http://url/verifyfirst.php?callback=?", lform.serialize(),function(data)
{
if (data.verified == "v1")
{
localStorage.setItem("datausername", data.txtusername);
if (localStorage.getItem("datausername") == "admin")
{
location.href="admin.html";
}
else
{
//$.mobile.changePage( "menu.html", { changeHash: true });
location.href="menu.html";
}
}
else
{
$("#popuptext").html("<b>The account you've entered is not associated with Happy Au Pair. Please check your username or password.</b>");
$( "#popupAfter" ).popup( "open", {
positionTo: "window",
transition: "pop" });
$.mobile.loading("hide");
}
}).fail(function(data){
$("#popuptext").html("<b>There is a problem with your login, please try again later.</b>");
$( "#popupAfter" ).popup( "open", {
positionTo: "window",
transition: "pop"});
$.mobile.loading("hide");
});
}
}
</script>
I tried it combining it here but it's not working:
<script>
var online = navigator.onLine;
if(online) {
//I placed the ajax here
} else {
alert("Internet Connectivity is not available.");
}
</script>
Please help me achieve this. And I'm using build.phonegap.com in exporting apk file.
Thanks in advance.
var condition = navigator.onLine ? "ONLINE" : "OFFLINE";
you will get online or offline and can use it accordingly. Also you test it by making an ajax call
$.ajax({
url: url,
type: 'GET',
contentType: "application/json;charset=utf-8",
success: function (data) {
// Yor success logic
},
error: function (request) {
// alert(request.responseText);
// alert(request.status);
if(request.status==0)
{
alert("Please connect to the internet");
}
}
});
try sending dummy ajax request before you send an actual request
$.ajax({
url: 'TestUrl',
type: 'GET',
success: function (data) {
// Go ahead with you request
},
error: function (x, y, z) {
if (x.status == 0) {
alert("Please connect to the internet");
}
else{
alert("Other Error Occured")
}
}
});
Phonegap also have online and offline whish is fired when there is a change in connectivity