Eliminar cadenas no utilizadas durante la optimización de ProGuard

Incluyo esta configuración de ProGuard para quitar declaraciones de registro de depuración cuando lanzo una aplicación de Android:

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

Esto funciona como se esperaba: puedo ver en los registros de ProGuard y en la salida del registro de Android llamadas como Log.d("This is a debug statement"); son removidos.

Sin embargo, si descompilo la aplicación en esta etapa, aún puedo ver todos los literales de String que se utilizaron, es decir, This is a debug statement en este ejemplo.

¿Hay alguna forma de eliminar también cada String que ya no se necesita del bytecode?

ProGuard puede eliminar argumentos constantes simples (cadenas, enteros, etc.). Entonces, en este caso, el código y la constante de cadena deberían desaparecer por completo:

 Log.d("This is a debug statement"); 

Sin embargo, es posible que haya observado el problema con algún código como este:

 Log.d("The answer is "+answer); 

Después de la comstackción, esto en realidad corresponde a:

 Log.d(new StringBuilder().append("The answer is ").append(answer).toString()); 

ProGuard versión 4.6 puede simplificar esto a algo así como:

 new StringBuilder().append("The answer is ").append(answer).toString(); 

Por lo tanto, el registro se ha ido, pero el paso de optimización todavía deja un poco de pelusa. Es sorprendentemente complicado simplificar esto sin un conocimiento más profundo sobre la clase StringBuilder. En lo que respecta a ProGuard, podría decir:

 new DatabaseBuilder().setup("MyDatabase").initialize(table).close(); 

Para un humano, el código de StringBuilder obviamente puede eliminarse, pero el código de DatabaseBuilder probablemente no pueda. ProGuard requiere un análisis de escape y algunas otras técnicas, que aún no están en esta versión.

En cuanto a una solución: puede crear métodos de depuración adicionales que toman argumentos simples, y deje que ProGuard los elimine:

 MyLog.d("The answer is ", answer); 

Alternativamente, puede probar el prefijo de cada instrucción de depuración con una condición que ProGuard pueda evaluar posteriormente como falsa. Esta opción puede ser un poco más intrincada, requiriendo alguna opción adicional de efectos secundarios en un método de inicialización para el indicador de depuración.

así es como lo hacemos – usando la tarea de la ant

        

Como no tengo suficiente representante para comentar directamente la respuesta de la tarea ant, aquí algunas correcciones ya que resulta muy útil en combinación con un servidor CI como Jenkins que puede ejecutarlo para una comstackción de lanzamiento:

          

Los ‘.’ después de que se debe escapar el registro y un ‘.’ dentro de los corchetes se dirige a cualquier statement de registro, no solo a los espacios en blanco como ‘\ s *’.

Como no tengo mucha experiencia con RegEx, espero que esto ayude a algunas personas en la misma situación para que funcione esta ant (por ejemplo, en Jenkins).

Si desea admitir llamadas de registro de línea múltiple, puede usar esta expresión regular en su lugar:

 (android\.util\.)*Log\.@([ewidv]|wtf)\s*\([\S\s]*?\)\s*; 

Debería poder usar esto dentro de una tarea ant replaceregexp como esta:

        

Nota: esto rodea las llamadas de Log con if(false){ y } para preservar la llamada original, tanto para referencia como para conservar números de línea cuando se inspeccionan los archivos de comstackción intermedios, permitiendo que el comstackdor java quite las llamadas durante la comstackción.

Si prefiere eliminar completamente las llamadas de registro, puede hacerlo así:

        

También podría aplicar la expresión regular como un filtro dentro de una tarea como esta: