Nakket
Nakket

Reputation: 620

How to get access to CordovaActivity appView from cordova plugin in android?

I have created a cordova plugin for android which handles the received push notification. When the push received, I'd like to send a javascript to the current webView of the cordova app like below:

appView.sendJavascript("some javascript");

But the problem is from the activity created as cordova plugin, I cannot get access to the appView of current webView in cordova app.

I'm really appreciate it if anyone can guide me how to access to the current webView of cordova pp.

Upvotes: 2

Views: 3247

Answers (1)

Alon Amir
Alon Amir

Reputation: 5025

You can use reflection.

Code answer:

Put the below static field and initialiser under your class:

private static Field appViewField;
static {
    try {
        Class<?> cdvActivityClass = CordovaActivity.class;
        Field wvField = cdvActivityClass.getDeclaredField("appView");
        wvField.setAccessible(true);
        appViewField = wvField;
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }
}

Then, under the "execute" method:

try {
    final CordovaWebView webView = (CordovaWebView) appViewField.get(cordova.getActivity());
    Handler mainHandler = new Handler(cordova.getActivity().getMainLooper());
    final Looper myLooper = Looper.myLooper();
    mainHandler.post(new Runnable() {
        @Override
        public void run() {
            // Finally do whatever you want with 'appView', for example:
            webView.clearCache();
            new Handler(myLooper).post(new Runnable() {
                @Override
                public void run() {
                    callbackContext.success();
                }
            });
        }
    });

} catch (Throwable e) {
    callbackContext.error(e.getMessage());
}

Details:

Using reflection, we store the protected appView field declaration of CordovaActivity.class in our plugin class, to be accessed later when needed.

Since the field is not accessible to us because it's protected, we must manually set it as accessible by calling setAccessible(true);

The reason we use use a different thread rather our plugin's thread which is called "JavaBridge", is that the appView field is stored on the thread of MainLooper, thus we must access it using the MainLooper, and when we're finished with it, call cordova's callbackContext success/error methods only under the "JavaBridge" thread again.

Upvotes: 1

Related Questions