30

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

1
  • Don't know why I use default proguard-rule.pro file (it seems not set anything) in Android Studio 4.1.2 and everything goes right after the build with minifyEnabled=true. Commented Mar 10, 2021 at 7:20

4 Answers 4

50

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>;
}
Sign up to request clarification or add additional context in comments.

1 Comment

With newer ProGuard we should use -keepclassmembers,allowoptimization, right?
5

If you're using obfuscation, in addition to Eric Lafortune's answer you also need:

-keepattributes JavascriptInterface

http://proguard.sourceforge.net/manual/usage.html#obfuscationoptions

1 Comment

Indeed, according to a statement by @Eric Lafortune on a bug report, "ProGuard is currently agnostic about the meaning of any annotations". That's unfortunate… sourceforge.net/p/proguard/bugs/491
4

In my case work only code:

proguard.cfg:

-dontwarn

-keepattributes Signature
-keepattributes SetJavaScriptEnabled
-keepattributes JavascriptInterface
-keepattributes InlinedApi
-keepattributes SourceFile,LineNumberTable
-keepattributes *Annotation*

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

-keep public class **.*$MyJavascriptInteface
-keep public class **.*$JavaScriptInterface

Java code:

@SuppressLint("SetJavaScriptEnabled")
public class ActivityWebView extends Activity {
    ...
    webView.getSettings().setJavaScriptEnabled(true);
    webView.addJavascriptInterface(new MyJavascriptInterface(MyActivity.this), "MyJSI");

    ....

    public class MyJavaScriptInterface {

        Context context;

        MyJavascriptInterface(Context context) {
        this.context = context;
        }

        @JavascriptInterface
        @SuppressWarnings("unused")
        public void myjavascriptfunction() {
            ...
        }

    }
    ...
}

Comments

0

This is the only thing that worked for me:

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

According to the proguard docs, things like -keepattributes JavascriptInterface aren't supposed to do anything at all, as JavascriptInterface is not in the list of attributes recognized by proguard.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.