Frequently PhoneGap applications consist of multiple screens represented by divs. Since Android users are conditioned to push the back button to return to the previous screen this causes some confusion as the default behaviour is to close the app. Luckily PhoneGap provides developers a way to over ride the default back button behaviour so they may provide their own back behaviour.
In release 0.9.4 the developer would have to wait for the deviceready event and call:
navigator.device.overrideBackButton();
document.addEventListener("backKeyDown", backPressed, false);
In order to setup and event handler for the back key and:
navigator.device.resetBackButton();
to revert to the default behaviour.
As of PhoneGap 0.9.5 we've made overriding the back button behaviour easier. You still have to wait for the deviceready event but the calls have been simplified to:
document.addEventListener("backbutton", onBackKey, false);
to register your event handler for the back key and:
document.removeEventListener("backbutton", onBackKey, false);
to revert to the default Android back button behaviour.
The following listing shows a full, yet contrived, example:
How about the menu and search buttons? can they be accesses the same ways?
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDeleteHey Mike,
ReplyDeleteYes, yes they can. In fact I just updated the documentation last night.
http://docs.phonegap.com/phonegap_events_events.md.html#Events
Hi Simon,
ReplyDeleteDid something change with phonegap 1.0? I spent all day yesterday trying to get the listener to fire on my app. I was finally able to make it work by switching back to phonegap 0.9.5, but that breaks the rest of my code. I'm using the code from the link you provided, and a simple print to logs, and it's just ignoring my listener. Do you have any ideas?
Thank you,
Josh
@Josh
ReplyDeleteNo nothing jumps to mind as to why the back button handler wouldn't work for you. Can you update how things are going over on google groups?
How to access webservices in phonegap.i am using asp.net webservices
ReplyDeleteI've downloaded PhoneGap 1.0 and I've implemented the code here, and it ignores the handler and the back key continues to exit the app.
ReplyDelete@karthick Your question is better answered over on the PhoneGap Google Group. The short answer is to make a XHR request to your ASP webservice to retrieve the data as XML or JSON.
ReplyDelete@Unknown did you make sure you updated the link to the phonegap.js file? In my example I use 0.9.5 but you have downloaded 1.0.0. Also, it still leaves the app when you are at the first screen as that is desired behaviour.
ReplyDeleteHi Simon.
ReplyDeleteIt is good to find helpful information on your blog. I need to handle the back button for certain pages in my app.
Because the button handling control using document.addEventListener('backbutton', ...) triggers on a button-down action, holding the back button down can cause a cascade of back button actions. e.g. from page 2 to page 1 to exiting the app.
I think "back button up" (NOT back button down) should trigger the PhoneGap back button event.
Is the success callback (e.g. onBackKey) needed for the document.removeEventListener("backbutton", onBackKey, false) API call? Logically, why would onBackKey be called when I am disabling backbutton handling?
Thanks,
David
@David Wong
ReplyDeleteYou have a good point about the back button up. Let me look into that.
Yes, you need the success callback in the removeEventListener in order for the framework to know what success call back to be removed as you can register more than one.
And what with alerts and prompts? When I do a navigator.notification.alert('hello!') and I try to remove it by pressing the backbutton, this does not work in phonegap 1.9.0...
ReplyDeleteIs there a solution for this? As it is standard android behaviour and I would like to mimick it...
Thanks in advance!
@Layla
ReplyDeleteThat is a bug. Thanks for finding it. I've raised an issue to track it and it should be fixed in 2.1.0.
https://issues.apache.org/jira/browse/CB-1217
@Layla
ReplyDeleteFixed checked in for 2.1.0.
Hi Simon,
ReplyDeletewhen an input field is focused in my Phonegap (Cordova 2.0.0) Application on Android the softkeyboard shows up. When pressing the backbutton it closes the softkeyboard and the input field still stays focues. Whenn pressing again the backButton the app is closing INSTEAD of going back in history. This only happens when an input field is focused.
How can I change this?
I found a solution to my question: in Android 4.0.3 (ICS) you do not have to override backButton with phongap API to stop closing/crashing the app after having focused an input text-field and then pressing the back button. Normally this closes the app, because webkit is creating a box-highlight with an additional outline that connot be changed with css.
ReplyDeleteWhen you focus the input the softkeyboard comes up. When you press the first time the softkeyboard disappears. When you click again to go back in navigation-history, the app is closing instead of jumping to the page visited before. This is because the highlighting jumps out of the navigation-structure.
FIX:
just add
input {
-webkit-user-modify: read-write-plaintext-only
}
This interrupts webkit doing a tap-highlight and you still stay in the app and can go back in History with your (not overriden) backButton.
Enjoy.
Hi Simon, big thanks! (sorry for the late answer, I was on holiday) Btw, I saw your twitter question whether you should keep your comments open... and yes, definitely!!!
ReplyDeleteHi Simon,
ReplyDeleteI`m trying to accomplish more than one addEventListener, but something is wrong?
For example if we have 3 divs on page and first one is displayed on the beginning and other two hidden.
div id="d1"
a onClick="
document.addEventListener("backbutton", show_div1, false);
$('#d1').hide();
$('#d2').show();
"
a
div
div id="d2" - initially hidden
div id="d3" - initially hidden
It shows div 2, hides div 1 and sets listener for back button to show_div1(), and everything works OK. On back key pressed it alerts "I should show #div1", as it should (//$('#d1').show(); is comented)
show_div1(){
//$('#d1').show(); $('#d2').hide();
alert ('I should show #div1');
}
But now comes the problem
div id="d2"
a onClick="
document.removeEventListener("backbutton", show_div1, false);
document.addEventListener("backbutton", show_div2, false);
$('#d2').hide();
$('#d3').show();
"
a
div
It immediately fires "I should show #div2" even back button is not pressed! addEventListener like started main function show_div2() and not just set listener on back button to that function.
show_div2(){
//$('#d2').show(); $('#d3').hide();
alert ('I should show #div2');
}
What could be the possible reason for this happening?
@Velibor Mrdak
ReplyDeleteHmmm...what version of PhoneGap are you using? If the add/remove causes the event to fire immediately we could have a bug.
@Simon
ReplyDeleteVer. 2.0.0 & 2.1.0 - same thing
I can post some sample code, but maybe there is not need for it, because you can create sample fns
test(){alert('ok');}
test1(){alert('ok1');}
and attach in onDeviceReady() {
document.addEventListener("backbutton", test, false);
} it works OK, but if you try later
document.removeEventListener("backbutton", test, false);
and
document.addEventListener("backbutton", test1, false);
it immediately fires "alert ok1".
To sum up If addEventListener more than once it is not working as expected (just to attach fn to listener) it launches test1() fn
I think that I was clear with explanation.
I found workaround with adding some extra code to fn and attaching listener only once, but it would be nice (if already have fns that exists in code) to attach as many listeners as I want depending on current situation.
@Velibor Mrdak
ReplyDeleteI am sorry, I just can't reproduce this.
I did not understand it? Reproduce what? Code? Should I upload index.html file?
ReplyDelete@Velibor Mrdak
ReplyDeleteYeah, if you could post your index.html file somewhere I will test it. I can't seem to reproduce the problem in my own code.
Hi Simon,
ReplyDeleteI am using cordova 2.2 and after overwriting the back button I want user to be able to still close the app if back button is pressed in the home page?
Any suggestions?
I used this: navigator.device.resetBackButton();
But it had no visible effect.
Thanks in advance.
@Akorede Ismael Olusola Enitan Jimoh
ReplyDeleteWell if you are over-riding the back button you can detect you are on the home page and call navigator.app.exitApp() to close your app. Alternatively you can remove the back button event listener when you are on the main page and then the default behaviour will be returned.
Thanks a lot Simon.
ReplyDeleteWorked.
I used the navigator.app.exitApp();
Thanks a lot once again for the quick reply.
Is there some way to do that:
ReplyDeleteIf user is on #home, EXIT, if is not, use navigator.app.backHistory()
@Joker
ReplyDeleteSure you can do that. You just have to keep track of the url you are currently on.
I have tried it with location, but it dont works with JquerMobile. It uses just ont file, for pages it uses hashs...
ReplyDelete@Joker
ReplyDeleteYes, and isn't the hash part of the url?
Simon I was using the cordova 2.1.0 and my backbutton override was working nice. After I upgrade to the 2.2.0 when I hit the backbutton my app closes like there is no override. When I click on the back button my callback function is not being called. Here is how I'm doing:
ReplyDeleteif (Ext.os.is('Android')) {
document.addEventListener("backbutton", Ext.bind(onBackKeyDown, this), false);
function onBackKeyDown(e) {
alert('Back Button');
e.preventDefault();
if ( Ext.Viewport.getActiveItem().xtype == 'panelmenu' ) {
navigator.app.exitApp();
} else {
this.getApplication().getHistory().add(Ext.create('Ext.app.Action', {
url: 'panelmenu'
}));
}}}
This code is inside the launch() function on app.js. I'm using sencha touch 2.
@Tio
ReplyDeleteWhat do you see in "adb logcat" when you click the back button? Also, you are closing the app when you detect you are on "panelmenu". Are you sure you're not running into that case?
Does this work on devices running on Honeycomb and higher with on screen navigation button? Some how it doesnt work for me.
ReplyDelete@Prakash
ReplyDeleteWorks fine for me. Remember to call the addEventListener after you get the deviceready event.
Hi
ReplyDeleteMy app is a javascript app and uses Sencha Touch 2.1 and Phonegap 2.5.
I have a problem with the device back button on Android: My app uses the device back button to navigate to the previous view. Now, if I press the back button twice really quickly, then my app stops working. I suspect that what happens is that I get a second onBackButton() event callback before the previous one is fully served, i.e. before my app is ready to handle another back button event.
I am basically using similar code as the example code above to catch the back button events in my app.
I wonder if anyone can help me a little...?
Cheers
Tommi
@Tommi Joutsiniemi
ReplyDeleteI haven't seen that type of behaviour but you could try guarding the code with a boolean. Set it to true when your back code is executing then false when you are done. Should ignore the double click.
Turned out this is a... feature in Sencha Touch.
ReplyDeleteThe pop() method of NavigationView class is asynchronous, so a simple boolean guard is not enough - I need a way to know if the previous pop() operation has finished, i.e. if another pop() is allowed to happen.
Anyway, I solved this with a "complex guard", basically I check if the previous pop() has actually been done before I allow another one.
Thank You