0

I want to override the behavior of back button in a WebView in Android so when an exact menu is open in the webpage (in the WebView), the back button should close the menu instead of going to previous page.

I know how to be able to send data from JavaScript to Android, but I am confused about how to use the callback data in if() blocks (which is not presented in the accepted answer of linked question):

Ok. The logic I used is something like these codes:

if ( isMenuOpen() ){
   closeMenu();
   return true;
}
else{
   //Let the back button do its default behavior
}

isMenuOpen() calls a JavaScript function to check if menu is open:

public void isMenuOpen(){
    webview.loadUrl="javascript:isMenuOpen()";
}

And this is my JavaScript function which passes the result into a Java function using JavaScriptInterface:

function isMenuOpen(){
    if ($(".menu").hasClass("open")){
        jInterface.resultFunction(true);
        }
    else{
        jInterface.resultFunction(false);
    }
}

And this is the final Java function which retrieves the data from JavaScript output:

@JavascriptInterface
public boolean resultFunction(boolean result){
    return result;
}

The problem is that isMenuOpen() is a void function which only calls a JavaScript function. How should I change the logic to get the final result in isMenuOpen()?

JorgeAmVF
  • 1,660
  • 3
  • 21
  • 32
Ali Sheikhpour
  • 10,475
  • 5
  • 41
  • 82

1 Answers1

0

You won't be able to create a synchronous method that calls into JavaScript and returns with the result. This is because the communication with JavaScript side is inherently async.

What you can do instead is handle your use case in an async way. When the back button is pressed, first pass control to the JS side and allow it to handle the event however it wants. If the JS side does not want to handle the event, it should pass the control back to the Java side by calling a JavascriptInterface function.

In code:

Java Side:

public class MainActivity extends AppCompatActivity {

    private WebView webview;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webview = findViewById(R.id.webview);
        webview.getSettings().setJavaScriptEnabled(true);
        webview.getSettings().setAllowFileAccessFromFileURLs(true);


        webview.addJavascriptInterface(this, "jInterface");

        webview.loadUrl("file:///android_asset/index.html");

    }

    @Override
    public void onBackPressed() {
        webview.loadUrl("javascript:onBackPressed()");
    }

    @JavascriptInterface
    public void onBackPressedWhenMenuClosed() {
        // This will be called on a JavaScript bridge thread, so we post a job to the UI thread.
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                MainActivity.super.onBackPressed();
            }
        });
    }

}

JavaScript side:

function onBackPressed() {
    if ($(".menu").hasClass("open")) {
        // Close the menu
    } else {
        jInterface.onBackPressedWhenMenuClosed();
    }
}
Janos Breuer
  • 480
  • 2
  • 6