Search code examples
androidwebviewproguardobfuscation

Android WebView Javascript calls not working with Proguard


I've been facing a problem that seem very common in Android. My Webview with a custom Javascript interface is not working when the application is in release mode. I am unable to call JS code from Java.

I feel that the problem is linked to proguard, as the Webview works normally in release mode as soon as I set the "minifyEnabled" to "false".

My proguard mappings are looking like this, I'm not sure if this is alright:

com.company.app.jsBridge.BaseJavascriptInterface -> 
com.company.app.jsBridge.BaseJavascriptInterface:
    java.util.Map mCallbacks -> a
    java.util.Map mHandlers -> b
    com.company.app.jsBridge.BridgeWebView mWebView -> c
    29:29:void send(java.lang.String,java.lang.String,java.lang.String):0:0 -> send
    ...

I have already browsed through Stackoverflow related questions such as these, and a few others:

Proguard stops Javascript in WebView from working How to configure proguard for javascript interface? Proguard mess Javascript Interface functions when targeting SDK in Android Manifest above 17

I tried applying the answers of these questions and my proguard file now looks like this:

-keepattributes JavascriptInterface
-keepattributes *Annotation*

-keepclassmembers class * {
   @android.webkit.JavascriptInterface <methods>;
}

-keepclassmembers class com.company.app.jsBridge.BaseJavascriptInterface {
   public *;
}

-keep public class com.company.app.jsBridge.BaseJavascriptInterface

And my interface:

package com.company.app.jsBridge;


public abstract class BaseJavascriptInterface {

    // Callbacks to execute after successful JS calls
    private final Map<String, IOnBridgeCallback> mCallbacks;

    // Handler methods that will be available to the JS
    private final Map<String, IBridgeHandler> mHandlers;

    private BridgeWebView mWebView;

    public BaseJavascriptInterface(Map<String, IOnBridgeCallback> callbacks, Map<String, IBridgeHandler> handlers, BridgeWebView webView) {
        mCallbacks = callbacks;
        mHandlers = handlers;
        mWebView = webView;
    }

    @JavascriptInterface
    public String send(String handlerName, String data) {
        //
    }
}

Other things that I have tried:

  • Running on both an emulator and a physical device, as I read that emulators could have a different behaviour with proguard
  • Using the @Keep annotation on the Javascript interface

Does anybody know what is wrong with my config or if I'm not looking at the right place ? Thanks


Solution

  • I ended up finding the solution by myself with the help of this post : Proguard issue while using GSON

    I needed to preserve both the Javascript Interface in Proguard like I did before, as well as the classes that I used for JSON communication between Java and JS. Gson was unable to properly serialize the data because the models were not preserved.