How to configure proguard for javascript interface?

Ikky picture Ikky · Jul 13, 2013 · Viewed 13.3k times · Source

I have a implemented a Webview which takes use of JavascriptInterface. It's working fine when not obfuscating, but at once Proguard is active, it does not work. I've looked here at other answers, but i still can't get it working.

Some of the WebView class:

public class Activity_Webview {
private WebView webView;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        webView = (WebView) findViewById(R.id.webview);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.addJavascriptInterface(new JavaScriptInterface (), "HTMLOUT");
        webView.setWebViewClient(mWebViewClient);
    }

    public class JavaScriptInterface implements NonObfuscateable{
        @JavascriptInterface
        public void processHTML(String html) {
        handleFinishFromWebView(html);
    }
}

What i've tried in Proguard:

-keep public class * implements com.project.NonObfuscateable
-keepclassmembers class * implements NonObfuscateable {
    public void processHTML(java.lang.String);
}

I've also tried this (when not implementing NonObfuscateable interface:

-keep public class com.project.Activity_Webview.JavaScriptInterface
-keep public class * implements com.project.Activity_Webview.JavaScriptInterface
-keepclassmembers class * implements com.project.Activity_Webview.JavaScriptInterface {
    <fields>;
    <methods>;
}

Does anybody have an idea of what could be wrong? Thanks in advance

Answer

Eric Lafortune picture Eric Lafortune · Jul 14, 2013

Both your configurations could have worked if they hadn't contained typos:

  • ProGuard requires fully qualified names:

    NonObfuscateable -> com.project.NonObfuscateable

  • Compiled classes use '$' as a separator for inner classes:

    com.project.Activity_Webview.JavaScriptInterface -> com.project.Activity_Webview$JavaScriptInterface

In the console log, ProGuard prints out notes about such suspected typos.

A more general solution for keeping annotated Javascript interface methods:

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