0

I thought it was a very easy problem... but I haven't solved for quite some time. For now, pressing back button will turn off the app. I want to go back by pressing the back button. Fragment containing the webview. HomeFragment.java

public class HomeFragment extends Fragment {
    WebView webView;

    public HomeFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_home, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        webView = view.findViewById(R.id.home_webview);
        String url = "https://galaxyhub.kr/starcitizen";
        webView.loadUrl(url);
        webView.getSettings().setJavaScriptEnabled(true);

        final ProgressDialog dialog = ProgressDialog.show(getActivity(),"", "Loading", true);
        webView.setWebViewClient(new WebViewClient(){
            @Override
            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
                Toast.makeText(getActivity(), "URL ERROR", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                dialog.show();
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                dialog.dismiss();
            }

        });
    }
}

I heard that I should also write in the MainActivity. I'll post it right away if needed.

package com.example.starcitizen.fragment;

import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

import androidx.activity.OnBackPressedCallback;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.example.starcitizen.R;


/**
 * A simple {@link Fragment} subclass.
 */
public class HomeFragment extends Fragment {
    WebView webView;

    OnBackPressedCallback callback = new OnBackPressedCallback(true) {
        @Override
        public void handleOnBackPressed() {
            if (webView.canGoBack()) {
                webView.goBack();
            } else {
                //use this if you need to call the Activity
                //backpress for default back action
                requireActivity().onBackPressed();
            }
        }
    };
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_home, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        webView = view.findViewById(R.id.home_webview);
        String url = "https://galaxyhub.kr/starcitizen";
        webView.loadUrl(url);
        webView.getSettings().setJavaScriptEnabled(true);

        final ProgressDialog dialog = ProgressDialog.show(getActivity(),"", "Loading",
                true);
        webView.setWebViewClient(new WebViewClient(){
            @Override
            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
                Toast.makeText(getActivity(), "URL ERROR", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                dialog.show();
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                dialog.dismiss();
            }

        });
    }
}

Now this code is running!

jiwon
  • 13
  • 4
  • i think the problem is fragment being reload when you go to any activity and come back to Homefragment – Arul Nov 19 '19 at 08:18
  • You need 2 things: 1) add the `HomeFragment` to the backstack when you replace it in the container. 2) add an `OnBackPressDispatcher` in your fragment, to handle the back button if the webview con go back – MatPag Nov 19 '19 at 08:24
  • Does this answer your question? [How to go back to previous page if back button is pressed in WebView?](https://stackoverflow.com/questions/6077141/how-to-go-back-to-previous-page-if-back-button-is-pressed-in-webview) – Subham Naik Nov 19 '19 at 08:27

1 Answers1

1

Add the fragment to the back stack if you need to navigate back from your fragment when the WebView can't go back more.

getSupportFragmentManager().beginTransaction()
  .replace(R.id.fragment_container, fragment)
  .addToBackStack(null)
  .commit();

Then in your fragment:

public class HomeFragment extends Fragment {

    private WebView webView;

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        OnBackPressedCallback callback = new OnBackPressedCallback(true) {
            @Override
            public void handleOnBackPressed() {
                if (webView.canGoBack()) {
                    webView.goBack();
                } else {
                    //use this if you need to call the Activity
                    //backpress for default back action
                    requireActivity().onBackPressed();
                }
            }
        };
        requireActivity().getOnBackPressedDispatcher()
             .addCallback(getViewLifecycleOwner(), callback);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        webView = view.findViewById(R.id.home_webview);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.setWebViewClient(new WebViewClient() {
            //callbacks omitted...
        });
        String url = "https://galaxyhub.kr/starcitizen";
        //call this after WebViewClient setup
        webView.loadUrl(url);
    }
}

Remember that Activity on onBackPressed will be called before the one added in the Fragment.

More info on back press handling here: https://developer.android.com/guide/navigation/navigation-custom-back#java

For this to work use at least:

androidx.fragment:fragment:1.1.0

MatPag
  • 41,742
  • 14
  • 105
  • 114
  • 1
    using pretty new `getOnBackPressedDispatcher`, +1, thanks for info about new feature :) – snachmsm Nov 19 '19 at 08:59
  • Thank you! Your article was helpful! I've posted some code to fix and run, but is there anything I don't need? – jiwon Nov 19 '19 at 10:18
  • You are fine with the updated code you posted. Just move `webView.loadUrl(url);` as list line of the `onViewCreated` method or at least after you call `setWebViewClient` otherwise you could miss the first page event – MatPag Nov 19 '19 at 10:40
  • This does create infinite loop as activity tries once again to invoke this handler – V-master Jul 27 '20 at 09:58
  • @V-master Have you tried to move the callback register to `onViewCreated` or `onAttach` instead of onCreate? The callback should be disabled automatically when finish is called because you are passing the lifecycle – MatPag Jul 27 '20 at 10:03
  • I have it in onViewCreated, and I don't think callback is disabled yet, as i wanted the activity to remove this view on back press, yet it cant as i handle back pressed. My resolution is to add `callback.isEnabled = view.canGoBack()` in `onPageFinished` – V-master Jul 27 '20 at 10:13
  • Try with `onAttach` or you can disable it manually as you did – MatPag Jul 27 '20 at 10:16