ngCordova InAppBrowser plugin freeze app on iOS but no on Android - ios

I am currently using, IONIC v1.0.0, AngularJs and ngCordova v0.1.23-alpha on IOS and Android.
I have come across an issue with my login view freezing up.
It happens after opening InAppBrowser and hitting "back to app" (close button caption used for IOS to get back) is freezes my login view disabling the ability to touch on the whole screen and making me unable to login. It only happens if I call InAppBrowser when starting the app, if I use it during the app life cycle (after login in), it doesn't do it.
Here are some of my code pieces
In app.js:
angular.module('MyApp', ['ionic', 'MyApp', 'ngCordova', 'mainController', 'loginController', 'pascalprecht.translate', 'ngStorage', 'ngSanitize', 'ngAnimate', 'ngTouch', 'ngCookies', 'ngLocale', 'testController'])
In mainController I have Factory:
.factory('customMainFunction', function ($rootScope, $ionicLoading, $ionicScrollDelegate, $ionicPopup,
$timeout, $localStorage, $location, $ionicHistory, $window, $cordovaInAppBrowser) {
var Token = "";
return {
openBrowser: function (link) {
var options = {
location: 'yes',
clearcache: 'yes',
toolbar: 'yes',
closebuttoncaption: 'Back to App'
};
document.addEventListener("deviceready", function () {
$cordovaInAppBrowser.open(link, '_blank', options)
.then(function (event) {
// success
})
.catch(function (event) {
// error
});
}, false);
$rootScope.$on('$cordovaInAppBrowser:loadstart', function (e, event) {
//console.log(event);
var url = "";
var positionNumber;
var res;
url = event.url;
positionNumber = url.search("ssoToken=");
res = url.substr(Number(positionNumber)+9);
/*positionNumber = url.search("module=");
res = url.substr(Number(positionNumber)+6);*/
if(url !== "" && positionNumber >= 0 && res.length > 0) {
$rootScope.$broadcast('ssoToken', { token: res });
$cordovaInAppBrowser.close();
}
});
$rootScope.$on('$cordovaInAppBrowser:loadstop', function (e, event) {
console.log("loadstop");
//console.log(event);
// insert CSS via code / file
//$cordovaInAppBrowser.insertCSS({
// code: ''
//});
// insert Javascript via code / file
//$cordovaInAppBrowser.executeScript({
// file: ''
//});
});
$rootScope.$on('$cordovaInAppBrowser:loaderror', function (e, event) {
});
$rootScope.$on('$cordovaInAppBrowser:exit', function (e, event) {
});
}
}
})
If anybody has encounter such issue please let me know what can be done to resolve it. Any question or clarifications let me know. Thanks in advance.

Found the issue of my own problem. Basically the problem is related to Threading. Look for Threading. How did I find out about it? On XCode I was able to see a message saying:
THREAD WARNING: ['InAppBrowser'] took '108.12' ms. Plugin should use a
background thread
There are two ways to solve this (I believe):
1- Using background threading (just like the message states). Please refer to:
How to run cordova plugins in the background?
2- Wrap the openBrowser function call (in my case) in a setTimeout. That will delay the call until the thread is done and UI won't be blocked. Once done (in my case) it opened the inAppBrowser and when I hit "Back to app" UI was not block at all.
Hope this helps someone out there.

Related

nativescript-webview-interface event call back to app there is an issue - Migrating the pure Nativescript 5.x project to Nativescript 6

Using nativescript-webview-interface and event is registered to webview. Event is fired to app and it is working fine. But in nativescript 6 same code is not working.
var webViewInterfaceModule = require('nativescript-webview-interface');
exports.onWebViewLoaded = function(args) {
var webview = args.object;
oWebViewInterface = new webViewInterfaceModule.WebViewInterface(webview, buildSrc());
// where build source returns the html string
webview.on(webViewModule.WebView.loadFinishedEvent, (args) => {
//do something specific to app
});
oWebViewInterface.on("watchInc", (data) => {
console.log("event watchInc - want to do something app specific");
//not receiving this event
});
oWebViewInterface.on("watchEnd", (data) => {
console.log("event watchEnd - want to do something app specific");
//not receiving this event
}, 200); // Timeout needed as loading event is fired when nothing ready...
}
Thanks manoj. Moved to nativescript-webview-ext plugin and communication between webview and javascript is working fine.

Ionic Angular. $http and geolocation.getCurrentPosition do not appear to work in iOS simulator

I'm developing a simple iOS app using Ionic.
I have 2 bits of functionality that do not appear to work in the iOS simulator that are working fine when I run the app in chrome.
Firstly, I am using the $http service in a factory to pull in some data:
var harbours = function () {
var deferred = $q.defer();
$http({
method: 'GET',
url: '../data/harbourData.json'
}).success(function (data, status, headers, config) {
deferred.resolve(data);
}).error(function(data, status, headers, config) {
deferred.reject(status);
});
return deferred.promise;
}
.....
return {
all: harbours
....
}
and then set it in my scope in the controller with:
var harboursPromise = Harbours.all();
harboursPromise.then(function(response){
console.log('response from controller', response);
$scope.harbours = response.harbours;
});
This does not appear to execute as I do not get the data in my template, whereas I do when running the app in chrome.
Secondly, geolocation. This piece of code is working fine in the browser but not when I build and run the app in the simulator:
$scope.position = 'Trying to find your location...'
if (navigator.geolocation){
navigator.geolocation.getCurrentPosition(function(position){
$scope.$apply(function(){
$scope.position = position.coords.latitude+", "+position.coords.longitude;
})
})
} else {
$scope.position = "Sorry, we can't get your location";
}
In the running app, it appears to have access to navigator.geolocation as $scope.position does not get changed to "Sorry, we can't get your location". I'm sure there is something fundamentally wrong that I am / am not doing. Can anyone point me in the right direction, please?
Thank you.

Potential causes of Ionic function not working in Ionic View, but working on web

I am building a food delivery app using Ionic. And I am having problems getting the app to work on mobile for the address creation step. After creating an account the user must create a delivery address, at which point the app figures out what delivery location to use.
Address creation works in Chrome (ionic serve) and in iOS simulator (ionic run ios -l -c -s).
However, once I've uploaded the app to my Ionic View iOS app for testing, it gets stuck at the Address creation step.
But at the address creation step, the Ionic loading wheel starts but it doesn't go away and there is no state transition to the menu.
Here is the implementation in the controller.
Address.create($scope.newAddress, $scope.user)
.then(function(response) { // never gets a response back in Ionic View
console.log("address created");
user.save(null,
{ success: function(user) {
// success callback
}, error: function(error) {
// throw error
}
});
}, function(error) {
// throw error
});
The Address.create() method I have implemented is fairly lengthy:
...
.factory('Address', ['$http', '$q', 'PARSE_HEADERS'
function ($http, $q, PARSE_HEADERS) {
return {
create: function(data, userID) {
var deferred = $q.defer();
var zipArray = ['1111','22222','33333'];
var inZone = false;
var restaurantCoords = {
latitude: 11.11111, longitude: 22.22222
};
for (var i=0, bLen=zipBrooklyn.length; i<bLen; i++) {
if(data.zipCode==zipArray[i]) {
inZone = true;
}
}
if (inZone == true ) { // valid zip
function onSuccess(coords) {
var limit = 3041.66;
var meters = getDistance(coords, restaurantCoords);
if (meters < limit) {
$http.post('https://api.parse.com/1/classes/Address', data, {
headers: PARSE_HEADERS
})
.success(function(addressData) {
deferred.resolve(addressData);
})
.error(function(error, addressData) {
deferred.reject(error);
});
}
function onError() {
deferred.reject("Unable to Geocode the coordinates");
}
// GET COORDS
navigator.geocoder.geocodeString(onSuccess, onError, data.address1 + ',' + data.zipCode);
}
}
return deferred.promise;
}]);
I've stripped out all of the code that I believe was working.
So a valid answer for this question could take multiple forms:
I'd accept an answer giving a decent way to debug apps IN Ionic View.
Or, if someone could provide an answer as to why it might be working in the browser and in iOS Simulator, but not iOS itself, that would be appreciated even more.
Ionic view doesn't support all the plugins yet. please take a look at this link for the list of supported plugins.
Device is always better (First Option). If you have a ios device and apple developer account. You can create and configure the required certificate with the device id and run the app using 'ionic run ios'. Second option is iOS simulator. You can use the simulator for your whole app, though few tasks would need a device.
Even if you use the simulator for the whole development, it is always advisable to test in the device before launcing the app.

Phonegap app won't reopen after close (Failed to load webpage with error: CDVWebViewDelegate: Navigation started when state=1)

I'm building an app for iOS using Phonegap and I've run into some problems. The app runs fine on both a simulator and real device until I close the app using the multi-tasking shutdown (double tap home button sequence..)
Upon reopening the app I find that it becomes unresponsive and you can't interact with it in any way. I've spent a fair amount of time trying to debug this and I've had no joy.
Error wise I have been getting the error Failed to load webpage with error: CDVWebViewDelegate: Navigation started when state=1 appear in the xcode console. After lots of googling it seems that this is caused due to hash tags within the URLs (something that I'm using for scrolling down to links both on the same and different pages). Most of the suggestions recommend updating phonegap/cordova to the latest version. I was previously on 2.8 and I went up to 2.9 and it still didn't work, i'm now on 3 and i'm still getting the same issues.
I've checked the cordova git and updated my CDVWebViewDelegate.m file several times with supposed fixes, nothing seems to work. I had a previous version of the app working on earlier versions of Cordova/Phonegap but I've recently upgraded and i'd rather not downgrade to get it to work..
I should probably note that I'm using zepto for my ajax calls and not JQM, for the hash tag scrolling i'm using the following code (figured this may help given it seems to be a hash issue..)
Hash Change function
// Ajax
var wrap = $('#contentScroller .scroller')
// get href
$('a.ajax').click(function () {
location.hash = $(this).attr('href').match(/(^.*)\./)[1]
return false
})
// load page
function hashChange() {
var page = location.hash.slice(1)
if (page != "" && window.location.hash) {
wrap.hide();
spinner.spin(target);
//setTimeout(function () {
wrap.load('pages/' + page + ".html .page-wrapper")
contentScroller.scrollTo(0,0);
refreshScroll();
//}, 1500);
snapper.close();
$(menuBtn).removeClass('active');
}else{
wrap.hide();
spinner.spin(target);
//setTimeout(function () {
wrap.load('pages/Welcome.html .page-wrapper')
refreshScroll();
//}, 1500);
snapper.close();
$(menuBtn).removeClass('active');
}
}
// check for hash change
if ("onhashchange" in window) {
$(window).on('hashchange', hashChange).trigger('hashchange')
} else { // lame browser
var lastHash = ''
setInterval(function () {
if (lastHash != location.hash)
hashChange()
lastHash = location.hash
contentScroller.scrollTo(0,0);
}, 100)
}
Scrolling
$(document)
.on('ajaxStart', function () {
wrap.hide();
})
.on('ajaxStop', function () {
//wrap.show();
})
.on('ajaxSuccess', function () {
//setTimeout(function () {
spinner.stop();
wrap.fadeIn(700);
refreshScroll();
//}, 1000);
// Local storage scrollTo
var storage = window.localStorage;
var url = window.location.href.substr(window.location.href.lastIndexOf("/") + 1);
$('a.scroll-link').click(function (event) {
event.preventDefault();
url = url.replace('home.html?firstrun#', "");
url = url.replace(url, url+".html");
var myHref = $(this).attr('href');
if (url == myHref) {
var sameScroll = $(this).attr('data-scroll-same-page');
sameScroll = sameScroll.replace(sameScroll, "a#" + sameScroll);
contentScroller.scrollToElement(sameScroll, 1500);
} else {
var diffScroll = $(this).attr("data-scroll-diff-page");
storage.setItem("key", diffScroll);
//Alter value for iScroll
var value = window.localStorage.getItem("key");
value = value.replace(value, "a#" + value);
location.hash = $(this).attr('href').match(/(^.*)\./)[1]
$(window).on('hashchange', hashChange).trigger('hashchange')
// Scroll to element after .5 second
setTimeout(function () {
contentScroller.scrollToElement(value, 1500);
return false;
}, 2000)
// Clear local storage to prevent scrolling on page reload
localStorage.clear();
}
Sample link
<a href="IndexOfTerms.html" class="ajax scroll-link" data-scroll-diff-page="First_year_allowance">
this will then pass the attr "first_year_allowance" through to the IndexOfTerms pages and then scroll down to the element that has that id
Can anybody shed some light on how I might be able to fix this? It's really starting to annoy me so I'd quite like to get a fix pretty sharpish!
Note: Libraries used: iScroll, Zepto, fastclick, snapjs, spinjs
Thanks!

no device ready and no console.log with xcode using cordova 1.5

This is all the code I have and I do not get neither the logs in xcode nor the deviceReady event (which I don't get on any other platform either. On Ubuntu+Android+Eclipse I do get the console logs, but no deviceReady. nor in chrome )
The js/cordova-1.5.0.js exists and being loaded as indicates an alert statement i've put in there.
Any clues where should I look ?
Thanks in advance ;)
<div id="d"></div>
<script>
function foo() {console.log('test'); document.getElementById('d').innerHTML += 'called';}
window.setTimeout(foo, 5000);
window.setTimeout(foo, 15000);
window.setTimeout(foo, 25000);
window.setTimeout(foo, 35000);
alert('hi');
console.log('non timed console.log');
</script>
<script src="js/cordova-1.5.0.js"></script>
<script>
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
alert('deviceReady');
//somewhy this never happens
}
</script>
Console.log works only after deviceReady event
Phonegap uses different phonegap.js files for android and ios, and only the
android one is distributed with the downloadable archive. Read
Dhaval's comment to learn where to get the ios version.
I used Weinre for debugging and almost missed that it overrides the console.log method,
therefore console.log doesn't work with weinre
As Alex pointed out, console.log is not available until after your PhoneGap device is ready. By calling it too soon, you're triggering a reference error.
Remove ALL of your existing javascript, and try this instead (replacing the alert on the second-last line with your own custom code):
var app = {
// denotes whether we are within a mobile device (otherwise we're in a browser)
iAmPhoneGap: false,
// how long should we wait for PhoneGap to say the device is ready.
howPatientAreWe: 10000,
// id of the 'too_impatient' timeout
timeoutID: null,
// id of the 'impatience_remaining' interval reporting.
impatienceProgressIntervalID: null,
// 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);
// after 10 seconds, if we still think we're NOT phonegap, give up.
app.timeoutID = window.setTimeout(function(appReference) {
if (!app.iAmPhoneGap) // jeepers, this has taken too long.
// manually trigger (fudge) the receivedEvent() method.
appReference.receivedEvent('too_impatient');
}, howPatientAreWe, this);
// keep us updated on the console about how much longer to wait.
app.impatienceProgressIntervalID = window.setInterval(function areWeThereYet() {
if (typeof areWeThereYet.howLongLeft == "undefined") {
areWeThereYet.howLongLeft = app.howPatientAreWe; // create a static variable
}
areWeThereYet.howLongLeft -= 1000; // not so much longer to wait.
console.log("areWeThereYet: Will give PhoneGap another " + areWeThereYet.howLongLeft + "ms");
}, 1000);
},
// deviceready Event Handler
//
// The scope of `this` is the event. In order to call the `receivedEvent`
// function, we must explicity call `app.receivedEvent(...);`
onDeviceReady: function() {
app.iAmPhoneGap = true; // We have a device.
app.receivedEvent('deviceready');
// clear the 'too_impatient' timeout .
window.clearTimeout(app.timeoutID);
},
// Update DOM on a Received Event
receivedEvent: function(id) {
// clear the "areWeThereYet" reporting.
window.clearInterval(app.impatienceProgressIntervalID);
console.log('Received Event: ' + id);
myCustomJS(app.iAmPhoneGap); // run my application.
}
};
app.initialize();
function myCustomJS(trueIfIAmPhoneGap) {
// put your custom javascript here.
alert("I am "+ (trueIfIAmPhoneGap?"PhoneGap":"a Browser"));
}
I know the question was asked 9 month before but I stumbled over the same problem.
If you want debug messages to appear in the weinre console you have to call:
window.cordova.logger.useConsole(false);
after deviceready.
Update:
It seems that you need luck to get console messages into weinre - thats bad :(

Resources