I have an app in which I have a WebView
where I display some websites. It works, clicking a link in the webpage goes to the next page in the website inside my app. But when I click the phone's back button, it takes me straight into my app. I want to go back to the previous page in the website instead. How can I do this?
Here is the code sample I'm using:
public class Webdisplay extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.getWindow().requestFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.webdisplay);
getWindow().setFeatureInt(Window.FEATURE_PROGRESS,
Window.PROGRESS_VISIBILITY_ON);
Toast loadingmess = Toast.makeText(this,
"Cargando El Diario de Hoy", Toast.LENGTH_SHORT);
loadingmess.show();
WebView myWebView;
myWebView = (WebView) findViewById(R.id.webview);
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.loadUrl("http://www.elsalvador.com");
myWebView.setWebViewClient(new WebViewClient());
myWebView.setInitialScale(1);
myWebView.getSettings().setBuiltInZoomControls(true);
myWebView.getSettings().setUseWideViewPort(true);
final Activity MyActivity = this;
myWebView.setWebChromeClient(new WebChromeClient()
{
public void onProgressChanged(WebView view, int progress)
{
MyActivity.setTitle("Loading...");
MyActivity.setProgress(progress * 100);
if(progress == 100)
MyActivity.setTitle(R.string.app_name);
}
});
}
}
I use something like this in my activities with WebViews:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (mWebView.canGoBack()) {
mWebView.goBack();
} else {
finish();
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}
Edit:
For this code to work, you need to add a field to the Activity
containing the WebView:
private WebView mWebView;
Initialize it in the onCreate()
method and you should be good to go.
mWebView = (WebView) findViewById(R.id.webView);
If using Android 2.2 and above (which is most devices now), the following code will get you what you want.
@Override
public void onBackPressed() {
if (webView.canGoBack()) {
webView.goBack();
} else {
super.onBackPressed();
}
}
android:noHistory="true"
attribute in the <activity>
you want, in the AndroidManifest.xml
return;
? It does in the training guide.
This is my solution. It works also in Fragment.
webView.setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
WebView webView = (WebView) v;
switch(keyCode) {
case KeyEvent.KEYCODE_BACK:
if (webView.canGoBack()) {
webView.goBack();
return true;
}
break;
}
}
return false;
}
});
WebView
has focus. If necessary, Issue webView.requestFocus()
(for example in the case of a Fragment
that is visible alongside the UI of its parent Activity
)
Full reference for next button and progress bar : put back and next button in webview
If you want to go to back page when click on phone's back button, use this:
@Override
public void onBackPressed() {
if (webView.canGoBack()) {
webView.goBack();
} else {
super.onBackPressed();
}
}
You can also create custom back button like this:
btnback.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (wv.canGoBack()) {
wv.goBack();
}
}
});
Focusing should also be checked in onBackPressed
@Override
public void onBackPressed() {
if (mWebview.isFocused() && mWebview.canGoBack()) {
mWebview.goBack();
} else {
super.onBackPressed();
finish();
}
}
Why not use onBackPressed()
?
@Override
public void onBackPressed() {
// super.onBackPressed(); Do not call me!
// Go to the previous web page.
}
In kotlin:
override fun onBackPressed() {
when {
webView.canGoBack() -> webView.goBack()
else -> super.onBackPressed()
}
}
webView - id of the webview component in xml, if using synthetic reference.
here is a code with confirm exit:
@Override
public void onBackPressed()
{
if(webView.canGoBack()){
webView.goBack();
}else{
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Exit!")
.setMessage("Are you sure you want to close?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setNegativeButton("No", null)
.show();
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Check if the key event was the Back button and if there's history
if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
myWebView.goBack();
return true;
}
// If it wasn't the Back key or there's no web page history, bubble up to the default
// system behavior (probably exit the activity)
return super.onKeyDown(keyCode, event);
}
The first answer by FoamyGuy is correct but I have some additions; low reputations cannot allow me to do comments. If for some reasons your page fails to load, ensure that you set a flag to take note of the failure and then check it on the onBackPressed override. Otherwise your canGoBack() will be forever executed without heading to the actual back activity if it was there:
//flag with class wide access
public boolean ploadFailFlag = false;
//your error handling override
@Override
public void onReceivedError(WebView view, WebResourceRequest req, WebResourceError rerr) {
onReceivedError(view, rerr.getErrorCode(), rerr.getDescription().toString(), req.getUrl().toString());
ploadFailFlag = true; //note this change
.....
.....
}
//finally to the answer to this question:
@Override
public void onBackPressed() {
if(checkinWebView.canGoBack()){
//if page load fails, go back for web view will not go back - no page to go to - yet overriding the super
if(ploadFailFlag){
super.onBackPressed();
}else {
checkinWebView.goBack();
}
}else {
Toast.makeText(getBaseContext(), "super:", Toast.LENGTH_LONG).show();
super.onBackPressed();
}
}
You can try this for webview in a fragment:
private lateinit var webView: WebView
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_name, container, false)
webView = root!!.findViewById(R.id.home_web_view)
var url: String = "http://yoururl.com"
webView.settings.javaScriptEnabled = true
webView.webViewClient = WebViewClient()
webView.loadUrl(url)
webView.canGoBack()
webView.setOnKeyListener{ v, keyCode, event ->
if(keyCode == KeyEvent.KEYCODE_BACK && event.action == MotionEvent.ACTION_UP
&& webView.canGoBack()){
webView.goBack()
return@setOnKeyListener true
}
false
}
return root
}
webView.canGoBack()
before setOnKeyListener
?
You should the following libraries on your class handle the onBackKeyPressed. canGoBack() checks whether the webview can reference to the previous page. If it is possible then use the goBack() function to reference the previous page (go back).
@Override
public void onBackPressed() {
if( mWebview.canGoBack()){
mWebview.goBack();
}else{
//Do something else. like trigger pop up. Add rate app or see more app
}
}
Here is the Kotlin solution:
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
if (event?.action != ACTION_UP || event.keyCode != KEYCODE_BACK) {
return super.onKeyUp(keyCode, event)
}
if (mWebView.canGoBack()) {
mWebView.goBack()
} else {
finish()
}
return true
}
If someone wants to handle backPressed for a webView inside a fragment, then he can use below code.
Copy below code into your Activity class (that contains a fragment YourFragmmentName) @Override
public void onBackPressed() {
List
Notes
Activity should be replaced with the actual Acitivity class you are using.
YourFragmentName should be replaced with the name of your Fragment.
Declare webView in YourFragmentName so that it can be accessed from within the function.
WebView mWebView;
mWebView = findViewById(R.id.webView);
@Override
public void onBackPressed() {
if (webView.canGoBack()) {
webView.goBack();
} else {
super.onBackPressed();
}
}
I think I'm a little late but according to the android documentation, you can have custom back navigation inside fragments done by the following piece of code.
requireActivity().onBackPressedDispatcher.addCallback(this) {
// Handle the back button event
if (binding.webView.canGoBack()){
binding.webView.goBack()
} else {
findNavController().popBackStack()
}
}
you can customize what to do when you the webView cant go back as per your needs.
Official Kotlin Way:
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
// Check if the key event was the Back button and if there's history
if (keyCode == KeyEvent.KEYCODE_BACK && myWebView.canGoBack()) {
myWebView.goBack()
return true
}
// If it wasn't the Back key or there's no web page history, bubble up to the default
// system behavior (probably exit the activity)
return super.onKeyDown(keyCode, event)
}
https://developer.android.com/guide/webapps/webview.html#NavigatingHistory
use this code to go back on page and when last page came then go out of activity
@Override
public void onBackPressed() {
super.onBackPressed();
Intent intent=new Intent(LiveImage.this,DashBoard.class);
startActivity(intent);
}
Success story sharing
finish()
putreturn super.onKeyDown(keyCode, event)
else
block