¿Cómo configurar Proguard para la interfaz de JavaScript?

He implementado una vista web que utiliza JavascriptInterface. Funciona bien cuando no se ofusca, pero a la vez Proguard está activo, no funciona. He visto aquí otras respuestas, pero todavía no puedo hacer que funcione.

Algunas de las clases de WebView:

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); } } 

Lo que probé en Proguard :

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

También probé esto (cuando no estoy implementando la interfaz no ofuscable :

 -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 { ; ; } 

¿Alguien tiene una idea de lo que podría estar mal? Gracias por adelantado

Ambas configuraciones podrían haber funcionado si no hubieran contenido errores tipográficos:

  • ProGuard requiere nombres completamente calificados:

    NonObfuscateable -> com.project.NonObfuscateable

  • Las clases comstackdas usan ‘$’ como un separador para las clases internas:

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

En el registro de la consola, ProGuard imprime notas sobre dichos errores tipográficos.

Una solución más general para mantener métodos de interfaz de JavaScript anotados:

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

En mi caso, solo código de trabajo:

proguard.cfg:

 -dontwarn -keepattributes Signature -keepattributes SetJavaScriptEnabled -keepattributes JavascriptInterface -keepattributes InlinedApi -keepattributes SourceFile,LineNumberTable -keepattributes *Annotation* -keepclassmembers class * { @android.webkit.JavascriptInterface ; } -keepclassmembers class * { @android.webkit.JavascriptInterface ; } -keepclassmembers class **.*$MyJavascriptInterface { *; } -keepclassmembers class **.*$JavaScriptInterface { *; } -keep public class **.*$MyJavascriptInteface -keep public class **.*$JavaScriptInterface 

Código Java:

 @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() { ... } } ... } 

Si usa ofuscación, además de la respuesta de Eric Lafortune, también necesita:

 -keepattributes JavascriptInterface 

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