La eliminación del registro con ProGuard no elimina las cadenas que se están registrando

Posible duplicado:
Eliminación de cadenas no utilizadas durante la optimización de ProGuard

Tengo una aplicación de Android con decenas de declaraciones de registro. Preferiría que no aparecieran en la versión de lanzamiento, así que usé Proguard con algo como esto en el archivo proguard.cfg :

 -assumenosideeffects class android.util.Log { public static *** d(...); } 

Pero el problema es que hay un montón de Log.d("something is " + something) , y aunque la Log.d() se está Log.d() del bytecode, las cadenas siguen ahí .

Por lo tanto, siguiendo esta respuesta, creé una clase simple de contenedor, algo en la línea de:

 public class MyLogger { public static void d(Object... msgs) { StringBuilder log = new StringBuilder(); for(Object msg : msgs) { log.append(msg.toString()); } Log.d(TAG, log.toString()); } } 

Luego proguard.cfg mi proguard.cfg :

 -assumenosideeffects class my.package.MyLogger { public static *** d(...); } 

Pero las cadenas todavía se encuentran en el bytecode generado!

Aparte de esto, estoy usando el proguard.cfg estándar proporcionado por el SDK de Android. ¿Estoy haciendo algo mal?


Edit : después de examinar el bytecode generado, vi que las cuerdas estaban allí, pero no estaban siendo añadidas una a otra, como yo pensaba. Se estaban almacenando en una matriz . ¿Por qué? Para pasarlos como parámetros variables a mi método. Parece que a ProGuard no le gusta eso, así que modifiqué mi clase de logger así:

 public static void d(Object a) { log(a); } public static void d(Object a, Object b) { log(a, b); } (... I had to put like seven d() methods ...) private static void log(Object... msgs) { (same as before) } 

Es feo, pero ahora las cadenas están en ninguna parte del bytecode.

¿Es esto algún tipo de error / limitación de ProGuard? ¿O es sólo que yo no entiendo cómo funciona?

Su solución con diferentes métodos para diferentes números de argumentos es probablemente la más conveniente. Un único método con un número variable de argumentos sería más agradable, pero la versión actual de ProGuard no es lo suficientemente inteligente como para eliminar todo el código no utilizado.

El compilador java compila un número variable de argumentos como un solo argumento de matriz. En el lado invocación, esto significa crear una matriz del tamaño correcto, rellenar los elementos y pasarlo al método. ProGuard ve que la matriz se está creando y luego se utiliza para almacenar elementos en ella. No se da cuenta (todavía) de que entonces no se utiliza para las operaciones útiles reales, con la invocación del método que se ha ido. Como resultado, se conservan la creación de matrices y la inicialización.

Es una buena práctica para comprobar el código procesado si usted está esperando alguna optimización en particular.

Proguard no me funciona, también, y no me gusta crear un contenedor alrededor de Log, así que he probado las siguientes soluciones:

Solución de trabajo

 final static boolean IsDebugging = false; 

Y en su código:

 if(IsDebugging) Log.i(TAG, "Debugging"); 

Considere que debe utilizar la palabra clave final para que IsDebugging se convierta en true o false en tiempo de compilación y las cadenas de registro no aparezcan en bytecode final.

NO TRABAJA (IsDebugMode)

  public static boolean IsDebugMode(Context context) { PackageManager pm = context.getPackageManager(); PackageInfo pi; try { pi = pm.getPackageInfo(context.getPackageName(),0); } catch (NameNotFoundException e) { return false; } return (pi.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; } 

Y en mi código:

  boolean IsDebugging = Utils.IsDebugMode(this); if(IsDebugging) Log.i(TAG, "Debugging"); 

La solución anterior no imprime ningún registro en Logcat pero la cadena de registro se compilan y existen en bytecode final que es incorrecto.

La otra solución fue:

NO FUNCIONA (BuildConfid.DEBUG)

  if(BuildConfig.DEBUG) Log.i(TAG, "Debugging"); 

Esto es lo mismo que la solución IsDebugMode. No imprime nada, pero las cadenas están en bytecode final. Malo de nuevo

  • ProGuard: ¿duplicado definición de biblioteca clase?
  • El tamaño de la pila se vuelve negativo después de la instrucción
  • * Vs ** vs *** en Proguard?
  • ¿Cómo configurar Proguard usando Gradle?
  • Proguard con Crashlytics
  • TransformClassesAndResourcesWithProguardForRelease FALLA
  • Proguard retrace la confusión de salida
  • Proguard para ofuscar el código de Android con la biblioteca DNSJava
  • ¿Cómo configurar PROGUARD para el procesador Jackson JSON?
  • Android, javamail y proguard
  • "No se puede encontrar la clase referenciada" con Proguard y Kotlin
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.