Разбирали мы как-то одно приложение. Было оно обфусцировано, и чёрт бы ногу там сломал. Но помогла нам такая вещь: в коде встречались логи. Просто строчки вида
Да даже если не рассматривать возможность реверс-инжиниринга, писание логов может неплохо затормозить приложение, так что в релизной версии их быть не должно. Этого можно добиться несколькими способами.
После этого надо не забывать перед релизом выставлять
Способ рабочий, но есть пара минусов: во-первых, реверс-инжиниринг мы так не затрудним, а во-вторых, при каждом вызове лога будет выполняться какая-то лишняя проверка.
Соответственно, если есть обертка над стандартным логом, нужно забанить и её.
И еще должна быть такая строчка, иначе ничего не выйдет:
Для корректной обработки правила тут должно быть любое число не меньше 1.
Log.i(TAG, "Do something")
. И по ним логику работы приложения можно было худо-бедно проследить.Да даже если не рассматривать возможность реверс-инжиниринга, писание логов может неплохо затормозить приложение, так что в релизной версии их быть не должно. Этого можно добиться несколькими способами.
Решение в лоб
Первый и очевидный — написать свою обёртку вида:public class Log { private static boolean logEnabled = true; public static void i(String tag, String string) { if (logEnabled) android.util.Log.i(tag, string); } public static void e(String tag, String string) { if (logEnabled) android.util.Log.e(tag, string); } public static void d(String tag, String string) { if (logEnabled) android.util.Log.d(tag, string); } public static void v(String tag, String string) { if (logEnabled) android.util.Log.v(tag, string); } public static void w(String tag, String string) { if (logEnabled) android.util.Log.w(tag, string); } }
logEnabled=false
, и все будет хорошо.Способ рабочий, но есть пара минусов: во-первых, реверс-инжиниринг мы так не затрудним, а во-вторых, при каждом вызове лога будет выполняться какая-то лишняя проверка.
Решение получше
Можно дописать несколько строчек в конфиге Proguard:-assumenosideeffects class android.util.Log { public static *** v(...); public static *** d(...); public static *** i(...); public static *** w(...); public static *** e(...); }
И еще должна быть такая строчка, иначе ничего не выйдет:
-optimizationpasses 1
P.S.
И ещё небольшой оффтопик. Когда собирается внутренняя сборка для тестеров, логи из неё вырезать не нужно. Для таких целей бывает полезно держать два конфига Proguard (скажем, proguard-test.cfg и proguard-release.cfg). А чтобы избежать полного дублирования, можно использовать такую конструкцию:-include proguard-test.cfg // правила, необходимые только для релиза
4 комментария:
Дарья, тут, похоже, должна использоваться одна и та же переменная:
ENABLE_LOCATION = true;
...
if (logEnabled)
Ещё вопрос: допустим, мы логируем так:
logger.d(someString+someString);
Как я понимаю, даже если logEnabled==false, конкатенация строк всё равно выполнится, т.е. это ещё небольшой overhead.
ENABLE_LOCATION случайно затесалась, она тут совершенно лишняя. Спасибо за замечание.
"Способ рабочий, но есть пара минусов: во-первых, реверс-инжиниринг мы так не затрудним, а во-вторых, при каждом вызове лога будет выполняться какая-то лишняя проверка."
А разве javac не удалит такие участки кода? Насколько мне известно он весьма неплохо справляется с dead-code elimination, т.о. в итоговый байткод эти if'ы просто напросто не попадут если logEnabled константно выставлен в false.
Да, может и удалит. Хоть я бы и не стала на него надеяться.
Отправить комментарий