javaandroidcordovaphonegap

Cordova inAppBrowser Hide / Show in Java Android


I am working with Cordova and the inAppBrowser plugin for Android

https://github.com/apache/cordova-plugin-inappbrowser

I am trying to control the hardware back button for Android in Java file

InAppBrowserDialog.java

public void onBackPressed() {
    if (this.inAppBrowser == null) {
        this.dismiss();
    } else {
        if (this.inAppBrowser.hardwareBack() && this.inAppBrowser.canGoBack()) {
            // this.inAppBrowser.goBack();
        } else {
            // this.inAppBrowser.closeDialog();
        }
    }
}

I do not want it to "goBack" or "closeDialog", I want it to "hide", like you can call it on the Cordova Javascript side

https://github.com/apache/cordova-plugin-inappbrowser#inappbrowserhide

ref.hide();

Hide is ideal so I can call .show if I want without loading the entire page, which is what would happen if I just closed it.

I am looking for a Java command such as

 this.inAppBrowser.hide();

But I can't seem to find it.


Update

So the Java code linked to the Codrova .hide Javascript is here

https://github.com/apache/cordova-plugin-inappbrowser/blob/8bdbd18d1619e25cf8bdedadf6448ef40b21ea7c/src/android/InAppBrowser.java#L329-L341

        else if (action.equals("hide")) {
        this.cordova.getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (dialog != null && !cordova.getActivity().isFinishing()) {
                    dialog.hide();
                }
            }
        });
        PluginResult pluginResult = new PluginResult(PluginResult.Status.OK);
        pluginResult.setKeepCallback(true);
        this.callbackContext.sendPluginResult(pluginResult);
    }

I just can't figure out how to call this Java function from the Java back button function.


Update

WORKING VERSION provided by JensV

So I edited InAppBrowserDialog.java

I added

import org.apache.cordova.CordovaArgs;
import org.json.JSONArray;

And added inside the

public class InAppBrowserDialog extends Dialog {

the following

public void hideDialog() {
    CordovaArgs args = new CordovaArgs(new JSONArray());
    try {
        this.inAppBrowser.execute("hide", args, new FakeCallbackContext());
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

public void showDialog() {
    CordovaArgs args = new CordovaArgs(new JSONArray());
    try {
        this.inAppBrowser.execute("show", args, new FakeCallbackContext());
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

I then created a new java file in the same directory, called

FakeCallbackContext.java

And placed the following code inside

package org.apache.cordova.inappbrowser;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.PluginResult;

class FakeCallbackContext extends CallbackContext {

  public FakeCallbackContext() {
    super(null, null);
    
  }

  @Override
  public void sendPluginResult(PluginResult pluginResult) {
    // Do not send an actual result to the webview
    // Perhaps just log the result
  }
}

Solution

  • I had a look at the source code and confirmed that the plugin does not expose the dialog member which prevents you from directly interacting with it. One way is to expose it via reflection but that seems to hacky to me.

    What you can do is to emulate the JS function call directly in Java by calling execute on the plugin. In order for that to not have any unexpected issues, we need to provide a CordovaArgs and CallbackContext instance. CordovaArgs is easily faked, but the CallbackContext should not interact with the actual webview and attempt to call JS. So I created a wrapper which does nothing when called:

    package your.package.name
    
    import org.apache.cordova.CallbackContext;
    import org.apache.cordova.PluginResult;
    
    class FakeCallbackContext extends CallbackContext {
    
        public FakeCallbackContext() {
            super(null, null);
        }
    
        @Override
        public void sendPluginResult(PluginResult pluginResult) {
            // Do not send an actual result to the webview
            // Perhaps just log the result
        }
    }
    

    Then in order to call the methods from your code you can call execute as follows. I'm assuming that this.inAppBrowser is an instance of InAppBrowser:

    // ...
    
    import org.apache.cordova.CordovaArgs;
    import org.json.JSONArray;
    
    // ...
    
    
    void hideDialog() {
        CordovaArgs args = new CordovaArgs(new JSONArray());
        this.inAppBrowser.execute("hide", args, new FakeCallbackContext());
    }
    
    void showDialog() {
        CordovaArgs args = new CordovaArgs(new JSONArray());
        this.inAppBrowser.execute("show", args, new FakeCallbackContext());
    }
    

    Update
    Added the necessary imports. For reference, I was referring to the "Quick Fix" feature of Intellij / Android Studio. You can press Alt+Enter (Mac: + ) on a error in the source code (highlighted in red) to apply suggestions to fix that error. This includes and is not limited to missing imports.