I have an iOS/Android app built on cordova 2.6 and jqm 1.3. I need to open a link to an external website after the user clicks on a button. The code I am using is:
var ref = window.open('http://google.com','_self','location=yes');
ref.addEventListener('loadstart',function(event) {
console.log('load started');
});
ref.addEventListener('loadstop',function(event) {
console.log('load stopped');
});
ref.addEventListener('loaderror',function(event) {
console.log('load error = ' + JSON.stringify(event));
});
On iOS everything performs like I would expect. A new browser window opens with the google website loaded. But I cannot get anything to to load in Android. When I click on the button, nothing happens. I have put in console statements before and after the window.open, so I know the code is at least being executed.
My config.xml should be wide open for white listed sites:
<access origin=".*"/>;
I have tested on a Nexus 7 (android 4.2) and an android 2.2 emulator with the same results on both.
Does anyone know why window.open would not be firing correctly on android?
It looked like it was a problem with 2.6 loading plugins on Android. I upgraded to 2.7 and everything started to work.
Perhaps it's a solution to use the ChildBrowser plugin? This gives you a bit more control over the operation itself, while still preserving platform compatibility between iOS and Android.
In most cases, I use something like the following snippet to use the childbrowser to display an external page.
function openBrowser(url) {
// determine if the childbrowser plugin is available
var useChildBrowser = ('plugins' in window && window.plugins.childBrowser);
if (useChildBrowser) {
popup = window.plugins.childBrowser;
popup.showWebPage(url, { showLocationBar: false, showAddress: false });
} else {
popup = window.open(url, 'Share', "['width=600px', 'height=400px', 'resizable=0', 'fullscreen=yes']");
}
}
Note that this falls back to using window.open if the ChildBrowser plugin isn't available, so you won't break anything else with this. Could be worth a shot, perhaps?
Related
I have a web page that is often launched from inside an Android/iOS app in their respective "tab system", Chrome Custom Tabs / SFSafariViewController.
The requirement I have is to have some urls redirect and open in the full browser app instead of navigating in the tab/controller.
I tried adding to one of those URLs the href target="_blank" or use window.open()` but in Android at least that opens a custom tab inside of the existing tab. Haven't had the chance to test that on iOS as of yet but I have the sneaking suspicion it will do nothing as the Safari View Controller does not support windows.
Any ideas on how I can force these 2 tools to open a url in the full apps would be much appreciated.
Thanks.
For people who might come across this and are interested.
Unfortunately it is not possible to force the in app browser to open a new tab in the full version of it. Like I mention in he question iOS simply can't do that due to the nature of the SFSafariViewController, while in Android it does not work... for reasons I guess, could not find something concrete and I will not go into speculating the reasons.
The solution I ended up using on my side is:
Have the site send a deep link to the app with the URL that should it should open externally, the app then closes the in app browser and launches the receive URL to the full browser.
I am setting this as the answer for now. If anyone comes with a better solution or an immediate solution to the problem, I am more than happy to change it.
Cheers
Twitter and whatsapp open webpages in CCT and SVC, but FB messenger doesn't, because it opens in its in-app-browser (IAB), unless you change your phone settings.
But. I found this javascript which works for me, for safari on iphone and chrome on android. Put it in the beginning of your index page at the end of your header and refer to this same index page.
Of course change yourwebpagetoopenoutsidewbhere to your own page.
var standalone = window.navigator.standalone,
userAgent = window.navigator.userAgent.toLowerCase(),
safari = /safari/.test(userAgent),
ios = /iphone|ipod|ipad/.test(userAgent);
var qq;
if (ios) {
if (!standalone && safari) {
// Safari
} else if (!standalone && !safari) {
// iOS webview
s=location.toString().split('?');s=s[1];
qq="https://www.yourwebpagetoopenoutsidewbhere.com/index.php?" + s;
window.close(); // Close the empty view window
window.open(qq,'_system', 'location=yes', replace);
}
} else {
if (userAgent.includes('wv')) {
// Android webview
s=location.toString().split('?');s=s[1];
qq="https://www.yourwebpagetoopenoutsidewbhere.com/index.php?" + s;
window.close(); // Close the empty view window
var winloc = 'intent:' + qq + '#Intent;end';
window.location = winloc;
} else {
// Chrome
}
}
i've to work with phonegap build, cli 5.x and try to build a search form with several inputs, 3 of them are select boxes.
all works fine till i wanted to set the css of the select nodes to 100% with. If i enable this css the selection does not open any more.
My Android Device for testing that won't work is a Nexus 7 with Android 5.1.1 (Lollipop). On IOS and Android Devices with 4.x all is working fine.
The language we use is Typescript with JQuery and will be compiled to Javascript ES5 (commonJS Style).
Sample Script:
var sampleData = [{"val": 1, "text": "sample A"}, {"val": 2, "text": "sample B"}];
var myContainer $('#content-box');
var selectBox = $('<select>').attr('id', 'mySelectBox');
selectBox.append($('<option>').attr('value', 'none').html('-- none --'));
for(var index in sampleData) {
var obj = sampleData[index];
selectBox.append($('<option>').attr('value', obj['val']).html(obj['text']));
}
// code above works fine
$('select').css('width', '100%');
// this crashes the popup after compilation
// and i have to use phonegap-build
by the way, if i have extreme long content going over 100% of the screen with it works. just stretching seems to crash.
i don't work with jquery mobile, some features we build won't work with it !!!
tried external css also, same failure.
somebody has a workaround or a fix for it? somebody can confirm this solution?
Try setting an id for the element you want to modify,
then try
$('#select').css('width', '100%');
if id="select"
I've built and app for android with meteor and phonegap/cordova:
https://play.google.com/store/apps/details?id=com.idqkd3gsl4qt51152xgy
It works decently OK (especially given that I'm not really a programmer), but one UX issue I've been struggling with is that the app will not consistently close when pressing the back button on my phone. Every once in a while it works on the first press, but most of the time I have to jam it 5-6 times in a row to get the app to close.
I'm using the latest iron-router. The rest of the packages I'm using don't seem particularly relevant to this issue but they are as follows just in case:
standard-app-packages
coffeescript
natestrauser:font-awesome#4.1.0
accounts-password
aldeed:autoform
aldeed:collection2
nemo64:bootstrap
less
alanning:roles
joshowens:accounts-entry
mrt:accounts-admin-ui-bootstrap-3
mizzao:jquery-ui
iron:router
sacha:spin
raix:push
mizzao:bootboxjs
meteorhacks:kadira
bootstrap3-media-query
the repo can be seen here: https://github.com/The3vilMonkey/BrewsOnTap
I can't specify the exact reason for this issue other than it seems like at startup there is a sort of redirect happening with cordova apps. Best solution I've found is to catch the popstate event and when you get back to the beginning exit or suspend the application.. I prefer suspend that way when the user comes back to the app it doesn't start it's lifecycle from the beginning.
if(Meteor.isCordova){
Meteor.startup(function(){
window.onpopstate = function () {
if (history.state && history.state.initial === true){
navigator.app.exitApp();
//or to suspend meteor add cordova:org.android.tools.suspend#0.1.2
//window.plugins.Suspend.suspendApp();
}
};
});
}
One caveat that got me when I first used this was redirecting to a login page if the user wasn't logged in.. If you're using this method in an app that does this, you'll want to switch to rendering the login page in place rather than redirecting otherwise your app will exit/suspend immediately.
In my case, I made a mix of the two previous answers so that it works well.
document.addEventListener("backbutton", function(){
if (history.state && history.state.initial === true) {
navigator.app.exitApp();
} else {
history.go(-1);
}
});
While Kelly's answer does work, it did not end up being functionally correct for my particular situation. An important point to note about that solution is that it will exit as soon as the back button causes you to return to the initial page and not when you press the back button while on the initial page.
Ultimately I used cordova's backbutton listener to see if the backbutton was pressed:
if Meteor.isCordova
Meteor.startup ->
document.addEventListener("backbutton", ->
if document.location.pathname is "/"
navigator.app.exitApp()
else
history.go(-1)
and then if I am at the root of my application I exit/suspend, otherwise I simply go back in the history.
Using the backbutton event listener does seem to override it's default functionality so calling history.go(-1) was necessary in my case.
Also note that this solution would break if you want a true history that could go back through the history (potentially hitting the root of your application multiple times) before existing on the initial entry point. A combination of my answer and Kelly's might work for that. I find that while that might be the expected behavior for websites, it isn't really for mobile apps.
Here's a meteor package available to do this for you as well:
https://github.com/remcoder/fix-back-button-android
EDIT:
I actually went ahead and forked that repo, fixed the cordova plugin dependency issues, and used Kelly's code instead of the code from the original repo, find my fork here:
https://github.com/tripflex/fix-back-button-android
Or install in Meteor using:
meteor add tripflex:fix-back-button-android
I can confirm it works correctly, when adding via GitHub method described below, and using Kelly's answer for detecting the root page (do not use the example on the GitHub repo).
I'm no meteor expert as well (but am a full time dev), but going off of Kelly's answer, I would move the check for isCordova inside the Meteor Startup (as i'm sure you will have more startup code as your app progresses)
Meteor.startup(function(){
// Mobile specific code
if(Meteor.isCordova) {
window.onpopstate = function () {
if (history.state && history.state.initial === true) {
navigator.app.exitApp();
//or to suspend meteor add cordova:org.android.tools.suspend#0.1.2
//window.plugins.Suspend.suspendApp();
}
};
}
// Any other startup code below here
});
EDIT: If you decide you want to use the cordova suspend package, it will not work like most cordova plugins in Meteor due to the plugin not existing in npm, so this will NOT work:
meteor add cordova:org.android.tools.suspend#0.1.2
You MUST add it like this using the GitHub repo:
meteor add cordova:org.android.tools.suspend#https://github.com/Lamerchun/org.android.tools.suspend.git#0dbb52cca0244ba22a8c7975895f0f45d2e9a4a9
I have a small phonegap application with jquery mobile and backbone.
I'm trying to show popup to user by manually calling .popup() method.
Everything works fine on iOS but on android I got strange issue: popup is showing for few moments and than disappear.
Here the actual code:
var PostView = Backbone.View.extend({
events: {
'touchend .add-comment-button': 'addComment'
},
addComment: function() {
this.$(".comment-popup").popup('open', { history: false });
return false; // Stop bubbling.
}
});
I'm using history: false because this popup is actualy part of subpage.
The code looks very simple, I'm just can't understand why it can disappear, and why this happen only on android devices.
Thanks, and sorry for my bad english.
I spent hours trying to fix this problem.
Finally I ended up doing the following two things that seemed to fix the problem.
1 - Use the uncompressed jqm file. i.e jquery.mobile.1.2.0.js
2 - I was triggering the popup programatically using the 'tap' option - once changed to the 'click' option it worked.
$('.option').live('click', function() {
$('#popup-div').popup('open');
});
I spent hours trying to fix this problem.
Finally I ended up doing the following two things that seemed to fix the problem.
this code snippet may help you ->
$('#testBtn').on('tap',function(e){
console.log("button clicked");
e.preventDefault();
$('#testPOPUP').popup("open");
});
Please note i have used e.perventDefault().
I didn't feel like changing my .tap() events to the click event and I didn't have a case where I could use preventDefault()so I just added a timeout to the popup('open') line. My hoverdelay in jqm is set to 150 so I set this timeout to 600 just to be on the safe side. Works fine, doesn't feel sluggish for the user.
One way to 'fix' it is by setting data-history="false" on the popup div
See also this question
JQuery Mobile popup with history=false autocloses
I have the exact same problem when trying to use popup('open') on an android 2.3 device (both in native browser and in firefox) and it works just fine on browsers on other devices. I'm also using backbone event management to open my popup (used the tap event and no aditionnal options to popup).
What I did to 'correct' the problem is that I removed the backbone event management for this event and added a listener in the render function. In your case this would look something like this :
events: {
// 'touchend .add-comment-button': 'addComment'
},
render: function() {
$(this.el).html(this.template(this.model));
$(this.el).find('.add-comment-button').tap(function(el){
this.addComment(el);
return false;
}.bind(this));
}
I have no idea where the problem comes from (must be some incompatibility between backbone and jquery mobile) and why we only see it on android but for the moment with this workaround my app seems to work fine on any device.
Edit: oops, it turns out that in my case the problem was I was missing "return false;" in the function dealing with the event.
Now that I added it, it works correctly with the backbone event management.
Sadly that doesn't explain why you have the issue and why I was seeing it only on android.
In case it helps anyone, I had the same problem occurring with Bing Maps, with the Microsoft.Maps.Events.addHandler(pin, 'click', callback) method.
Not particularly nice, but instead I stored an ID in pushpin._id and did the following:
$("#page").on('vclick', function (event) {
if (event.target.parentElement.className === "MapPushpinBase") {
$("#stopPopup").popup('open');
}
});
One brute force option is to check whether popup was hidden and reopen it.
In a loop, because the exact time the popup becomes hidden seems to be varied.
var hidden = $('#' + id + '-popup') .hasClass ('ui-popup-hidden')
if (hidden) $('#' + id) .popup ('open')
A working example: http://jsfiddle.net/ArtemGr/hgbdv9s7/
Another option could be to bind to popupafterclose:
var reopener = function() {$('#' + id) .popup ('open')}
$('#' + id) .on ('popupafterclose', reopener)
$('#' + id) .popup ('open')
Like here: http://jsfiddle.net/ArtemGr/gmpczrdm/
But for some reason the popupafterclose binding fails to fire on iPhone 4 half of the time.
I'm creating a mobile site where I have a video I'd like to play when someone clicks on a link:
<div id="player"></div>
<?php echo $result_videos[$i]["camera_name"]; ?>
<script type="text/javascript">
function DoNav(theUrl)
{
// only add the player if it doesn't yet exist
if($('#myfileplayer').length == 0) {
var mydiv = $("#player");
var myvideo = $("<video id='myfileplayer' src='"+ theUrl + "' width='320' height='240' controls></video>");
mydiv.append(myvideo);
} else {
$('#myfileplayer').attr("src",theUrl);
}
}
</script>
With the iPhone, this works great, I click on video and it goes full screen. Android works as well but it requires you to click the video to play then click on the full screen. Is it possible to get to the full screen like iPhone just when you hit play?
This should work, with plain Javascript:
var myVideo = document.getElementById('myVideoTag');
myVideo.play();
if (typeof(myVideo.webkitEnterFullscreen) != "undefined") {
// This is for Android Stock.
myVideo.webkitEnterFullscreen();
} else if (typeof(myVideo.webkitRequestFullscreen) != "undefined") {
// This is for Chrome.
myVideo.webkitRequestFullscreen();
} else if (typeof(myVideo.mozRequestFullScreen) != "undefined") {
myVideo.mozRequestFullScreen();
}
You have to trigger play() before the fullscreen instruction, otherwise in Android Browser it will just go fullscreen but it will not start playing.
Tested with the latest version of Android Browser, Chrome, Safari.
I've given up on this. My conclusion is that the html5 video tag on Android devices blows chunks. It works in some devices but not on others. And there is no common criteria like 3.x or 4.x, it just seems to be random. I hope this gets better sometime soon especially since flash support is not longer existent.
Oddly sticking with a simple href seems to be the most consistent. You lose some controls but way better than the video tag...at least so far.
Have you checked out mediaelement.js?
Try something along the lines of:
document.getElementById('myfileplayer').addEventListener('play', function (e) { this.mozRequestFullScreen ? this.mozRequestFullScreen() : this.webkitRequestFullScreen ? this.webkitRequestFullScreen() : null; }, false);
Either that or maybe something along the lines of:
document.getElementById('myfileplayer').addEventListener('play', function (e) { this.webkitEnterFullscreen(); }, false);
webkitEnterFullscreen is the fullscreen method of a VIDEO element that is currently working on iOS. I'm not sure about support on Android devices.
mozRequestFullScreen and webkitRequestFullScreen are implementations of Mozilla and Google's FullScreen API which is used to activate full screen mode on practically any DOM element.
Hopefully that gives you at least a starting point to work from...
Most vendors require user interaction to go full screen, which is why natalee's answer doesn't work. For Andriod, you can call webkitEnterFullScreen() inside your anchor's click handler since it's a valid user interaction:
myvideo[0].webkitEnterFullScreen();
myvideo[0].play();
or
$('#myfileplayer')[0].webkitEnterFullScreen();
$('#myfileplayer')[0].play();
Note how I'm stripping jQuery's wrapper with [0]. It doesn't work otherwise.