Как удалить все вызовы журнала отладки перед публикацией приложения в Google Play? [закрытый]
согласно Google, я должен"деактивировать все вызовы методов журнала в исходном коде " перед публикацией моего приложения для Android. Выдержка из раздела 5 публикации контрольный список:
перед созданием приложения для выпуска убедитесь, что вы отключили ведение журнала и отключили опцию отладки. Вы можете отключить ведение журнала, удалив вызовы методов журнала в исходных файлах.
мой проект с открытым исходным кодом большая и это боль, чтобы сделать это вручную каждый раз, когда я выпускаю. Кроме того, удаление строки журнала потенциально сложно, например:
if(condition)
Log.d(LOG_TAG, "Something");
data.load();
data.show();
Если я комментирую строку журнала, то условие применяется к следующей строке, и скорее всего load() не вызывается. Достаточно ли редки такие ситуации, чтобы я мог решить, что его не должно быть?
Это официальный контрольный список, поэтому я думаю, что многие люди делают это на регулярной основе.
Итак, как эффективно, но безопасно удалить весь журнал линии?
21 ответов
Я нахожу гораздо более простое решение-забыть все if
проверяет повсюду и просто использует должны быть чтобы удалить любой Log.d()
или Log.v()
метод вызывает, когда мы вызываем нашего муравья release
цель.
таким образом, у нас всегда есть отладочная информация, выводимая для обычных сборок, и нам не нужно вносить изменения в код для сборок выпуска. ProGuard также может выполнять несколько проходов по байт-коду для удаления других нежелательных операторов, пустых блоков и может автоматически встроенные короткие методы, где это необходимо.
например, вот очень простая конфигурация ProGuard для Android:
-dontskipnonpubliclibraryclasses
-dontobfuscate
-forceprocessing
-optimizationpasses 5
-keep class * extends android.app.Activity
-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** v(...);
}
таким образом, вы сохраните это в файл, а затем вызовите ProGuard из Ant, передав только что скомпилированную банку и банку платформы Android, которую вы используете.
см. также примеры в руководстве ProGuard.
обновление (4.5 лет): сегодня я Лесной для ведения журнала Android.
не только это немного лучше, чем по умолчанию Log
реализация-тег журнала устанавливается автоматически, и легко регистрировать форматированные строки и исключения, но вы также можете указать различные поведения ведения журнала во время выполнения.
в этом примере операторы ведения журнала будут записываться только в logcat в отладочных сборках моего приложения:
древесина настроена в моем Application
onCreate()
метод:
if (BuildConfig.DEBUG) {
Timber.plant(new Timber.DebugTree());
}
тогда в любом другом месте моего кода я могу легко войти:
Timber.d("Downloading URL: %s", url);
try {
// ...
} catch (IOException ioe) {
Timber.e(ioe, "Bad things happened!");
}
посмотреть образец древесины приложение для более продвинутого примера, где все операторы журнала отправляются в logcat во время разработки и в производстве не регистрируются операторы отладки, но ошибки молча сообщаются Crashlytics.
все хорошие ответы, но когда я закончил свою разработку, я не хотел ни использовать операторы if вокруг всех вызовов журнала, ни использовать внешние инструменты.
поэтому решение, которое я использую, - это заменить android.утиль.Класс журнала с моим собственным классом журнала:
public class Log {
static final boolean LOG = false;
public static void i(String tag, String string) {
if (LOG) android.util.Log.i(tag, string);
}
public static void e(String tag, String string) {
if (LOG) android.util.Log.e(tag, string);
}
public static void d(String tag, String string) {
if (LOG) android.util.Log.d(tag, string);
}
public static void v(String tag, String string) {
if (LOG) android.util.Log.v(tag, string);
}
public static void w(String tag, String string) {
if (LOG) android.util.Log.w(tag, string);
}
}
единственное, что мне нужно было сделать во всех исходных файлах, это заменить импорт android.утиль.Войдите в мой собственный класс.
Я предлагаю иметь статическое логическое значение, указывающее, следует ли регистрировать:
class MyDebug { static final boolean LOG = true; }
тогда везде, где вы хотите войти в свой код, просто сделайте это:
if (MyDebug.LOG) { if (condition) Log.i(...); }
теперь, когда вы устанавливаете MyDebug.Войдите в false, компилятор удалит весь код внутри таких проверок (поскольку это статический финал, он знает во время компиляции, что код не используется.)
для больших проектов, вы можете начать иметь логические значения в отдельных файлах, чтобы иметь возможность легко включить или отключить ведение журнала там по мере необходимости. Например, это различные константы ведения журнала, которые мы имеем в оконном менеджере:
static final String TAG = "WindowManager";
static final boolean DEBUG = false;
static final boolean DEBUG_FOCUS = false;
static final boolean DEBUG_ANIM = false;
static final boolean DEBUG_LAYOUT = false;
static final boolean DEBUG_RESIZE = false;
static final boolean DEBUG_LAYERS = false;
static final boolean DEBUG_INPUT = false;
static final boolean DEBUG_INPUT_METHOD = false;
static final boolean DEBUG_VISIBILITY = false;
static final boolean DEBUG_WINDOW_MOVEMENT = false;
static final boolean DEBUG_ORIENTATION = false;
static final boolean DEBUG_APP_TRANSITIONS = false;
static final boolean DEBUG_STARTING_WINDOW = false;
static final boolean DEBUG_REORDER = false;
static final boolean DEBUG_WALLPAPER = false;
static final boolean SHOW_TRANSACTIONS = false;
static final boolean HIDE_STACK_CRAWLS = true;
static final boolean MEASURE_LATENCY = false;
С соответствующим кодом:
if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
TAG, "Adding window " + window + " at "
+ (i+1) + " of " + mWindows.size() + " (after " + pos + ")");
решение Кристофера Proguard является лучшим, но если по какой-либо причине вам не нравится Proguard, вот очень низкотехнологичное решение:
комментарий журналы:
find . -name "*\.java" | xargs grep -l 'Log\.' | xargs sed -i 's/Log\./;\/\/ Log\./g'
раскомментировать журналы:
find . -name "*\.java" | xargs grep -l 'Log\.' | xargs sed -i 's/;\/\/ Log\./Log\./g'
ограничение заключается в том, что ваши инструкции ведения журнала не должны охватывать несколько строк.
(выполните эти строки в оболочке UNIX в корне вашего проекта. При использовании Windows получите слой UNIX или используйте эквивалентные окна команды)
Я хотел бы добавить некоторые уточнения об использовании Proguard с Android Studio и gradle, так как у меня было много проблем с удалением строк журнала из окончательного двоичного файла.
для того чтобы assumenosideeffects
В Proguard работает, есть необходимое условие.
в вашем файле gradle вы должны указать использование proguard-android-optimize.txt
как файл по умолчанию.
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
// With the file below, it does not work!
//proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
на самом деле, по умолчанию proguard-android.txt
file, оптимизация отключена с помощью двух флаги:
-dontoptimize
-dontpreverify
на proguard-android-optimize.txt
файл не добавляет эти строки, так что теперь assumenosideeffects
может работать.
потом, лично я использую SLF4J, тем более, когда я разрабатываю некоторые библиотеки, которые распространяются на другие. Преимущество в том, что по умолчанию нет выхода. И если интегратор хочет некоторые выходы журнала, он может использовать Logback для Android и активировать журналы, поэтому журналы могут быть перенаправлены в файл или LogCat.
если мне действительно нужно зачищать журналы из окончательной библиотеки, затем я добавляю в свой файл Proguard (после включения конечно):
-assumenosideeffects class * implements org.slf4j.Logger {
public *** trace(...);
public *** debug(...);
public *** info(...);
public *** warn(...);
public *** error(...);
}
я использовал LogUtils класс, как в примере приложения Google IO. Я изменил это, чтобы использовать конкретную константу отладки приложения вместо BuildConfig.Отладка, потому что BuildConfig.Отладка ненадежна. Затем в моих классах у меня есть следующее.
import static my.app.util.LogUtils.makeLogTag;
import static my.app.util.LogUtils.LOGV;
public class MyActivity extends FragmentActivity {
private static final String TAG = makeLogTag(MyActivity.class);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LOGV(TAG, "my message");
}
}
Я бы рассмотрел использование roboguice ведение объекта вместо встроенного android.утиль.Log
их средство автоматически отключает отладочные и подробные журналы для сборок выпуска. Кроме того, вы получаете отличные функции бесплатно (например, настраиваемое поведение ведения журнала, дополнительные данные для каждого журнала и многое другое)
использование proguard может быть довольно хлопот, и я бы не стал проходить через проблемы настройки и создания его работа С приложение, если у вас нет веской причины для этого (отключение журналов не является хорошим)
я настоятельно рекомендую использовать древесину от Джейка Уортон
https://github.com/JakeWharton/timber
это решает вашу проблему с включением / отключением плюс добавляет класс тегов автоматически
просто
public class MyApp extends Application {
public void onCreate() {
super.onCreate();
//Timber
if (BuildConfig.DEBUG) {
Timber.plant(new DebugTree());
}
...
журналы будут использоваться только в отладочной версии, а затем использовать
Timber.d("lol");
или
Timber.i("lol says %s","lol");
печати
"ваш класс / msg" без specyfing тега
на android.утиль.Log предоставляет способ включить / отключить log:
public static native boolean isLoggable(String tag, int level);
по умолчанию метод isLoggable(...) возвращает false, только после того, как вы setprop в устройстве нравится это:
adb shell setprop log.tag.MyAppTag DEBUG
это означает, что любой журнал выше уровня отладки может быть распечатан. Ссылка на Android док:
проверяет, является ли журнал для указанного тега loggable на указанном уровне. По умолчанию установлен уровень любого тега к информации. Это означает, что любой уровень выше и включая информацию будет отяжелевший. Перед вызовом метода ведения журнала необходимо проверить чтобы увидеть, должен ли ваш тег регистрироваться. Можно изменить уровень по умолчанию установив системное свойство: 'setprop log.метка. ' Где level-это VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT или ПОДАВЛЯТЬ. SUPPRESS отключит все ведение журнала для вашего тега. Вы можете также создайте локальный.prop файл, который со следующим в нем: - журнал.метка.= 'и поместите это в / data / local.прислонить.
поэтому мы могли бы использовать пользовательский журнал util:
public final class Dlog
{
public static void v(String tag, String msg)
{
if (Log.isLoggable(tag, Log.VERBOSE))
Log.v(tag, msg);
}
public static void d(String tag, String msg)
{
if (Log.isLoggable(tag, Log.DEBUG))
Log.d(tag, msg);
}
public static void i(String tag, String msg)
{
if (Log.isLoggable(tag, Log.INFO))
Log.i(tag, msg);
}
public static void w(String tag, String msg)
{
if (Log.isLoggable(tag, Log.WARN))
Log.w(tag, msg);
}
public static void e(String tag, String msg)
{
if (Log.isLoggable(tag, Log.ERROR))
Log.e(tag, msg);
}
}
я публикую это решение, которое применяется специально для пользователей Android Studio. Я также недавно обнаружил древесину и успешно импортировал ее в свое приложение, выполнив следующие действия:
поместите последнюю версию библиотеки в свою сборку.Gradle в:
compile 'com.jakewharton.timber:timber:4.1.1'
затем в Android Studios перейдите в меню Правка - > найти - > заменить в пути...
тип Log.e(TAG,
или, Однако, вы определили свои сообщения журнала в "Text to find"
текстовое поле. Тогда вы просто замените его с Timber.e(
Нажмите кнопку Найти, а затем заменить все.
Android Studios теперь будет проходить через все ваши файлы в вашем проекте и заменить все журналы с бревнами.
единственная проблема, которую я имел с этим методом, заключается в том, что gradle придумывает миллион сообщений об ошибках после этого, потому что он не может найти "древесину" в импорте для каждого из ваших файлов java. Просто нажмите на ошибки и Android Studios будет автоматически импортируйте "древесину" в свой java. После того, как вы сделали это для всех ваших файлов ошибок, gradle будет компилироваться снова.
Вам также нужно поместить этот фрагмент кода в свой onCreate
метод Application
класс:
if (BuildConfig.DEBUG) {
Timber.plant(new Timber.DebugTree());
}
это приведет к регистрации приложения только тогда, когда вы находитесь в режиме разработки не в производстве. Вы также можете иметь BuildConfig.RELEASE
для входа в режим выхода.
если вы можете запустить глобальную замену (один раз), и после этого сохранить некоторое соглашение о кодировании, вы можете следовать шаблону, часто используемому в Android рамки.
вместо того, чтобы писать
Log.d(TAG, string1 + string2 + arg3.toString());
это как
if (BuildConfig.DEBUG) Log.d(TAG, string1 + String.format("%.2f", arg2) + arg3.toString());
теперь proguard может удалить StringBuilder и все строки и методы, которые он использует в пути, из оптимизированного выпуска DEX. Использовать proguard-android-optimize.txt
и вам не нужно беспокоиться о android.утиль.Log в вашей proguard-rules.pro
:
android {
…
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
в студии плагин Gradle в Android, в BuildConfig.DEBUG
довольно надежно, поэтому вам не нужны дополнительные константы для того чтобы контролировать обнажать.
Это то, что я использовал для своих проектов android..
В Android Studio мы можем сделать аналогичную операцию, Ctrl + Shift+F, чтобы найти из всего проекта (Command+Shift+F в MacOs) и Ctrl+Shift+R, чтобы заменить ((Command+Shift+R в MacOs))
У меня есть очень простое решение. Я использую IntelliJ для разработки, поэтому детали различаются, но идея должна применяться во всех IDE.
Я выбираю корень моего исходного дерева, щелкните правой кнопкой мыши и выберите "заменить". Затем я выбираю заменить все " Log." с бревнами.". Это удаляет все инструкции журнала. Чтобы вернуть их позже, я повторяю ту же замену, но на этот раз, как заменить все "//Log." с бревнами.".
отлично работает для меня. Просто не забудьте установить replace как case чувствительна, чтобы избежать несчастных случаев, таких как "диалог.". Для дополнительной гарантии, вы также можете сделать первый шаг с " Лог.- как строка для поиска.
блестящая.
As комментарий zserge предложил
древесина очень хорошая, но если у вас уже есть существующий проект - вы можете попробовать github.com/zserge/log - ... Это выпадающая замена для android.утиль.Журнал и имеет большинство функций, которые имеет древесина и даже больше.
его Библиотека журнала обеспечивает простой переключатель включения / выключения печати журнала, как показано ниже.
кроме того,только требует замены import
строки, и ничего на Log.d(...);
заявление.
if (!BuildConfig.DEBUG)
Log.usePrinter(Log.ANDROID, false); // from now on Log.d etc do nothing and is likely to be optimized with JIT
я улучшил решение выше, предоставив поддержку для разных уровней журнала и изменив уровни журнала автоматически в зависимости от того, выполняется ли код на живом устройстве или на эмуляторе.
public class Log {
final static int WARN = 1;
final static int INFO = 2;
final static int DEBUG = 3;
final static int VERB = 4;
static int LOG_LEVEL;
static
{
if ("google_sdk".equals(Build.PRODUCT) || "sdk".equals(Build.PRODUCT)) {
LOG_LEVEL = VERB;
} else {
LOG_LEVEL = INFO;
}
}
/**
*Error
*/
public static void e(String tag, String string)
{
android.util.Log.e(tag, string);
}
/**
* Warn
*/
public static void w(String tag, String string)
{
android.util.Log.w(tag, string);
}
/**
* Info
*/
public static void i(String tag, String string)
{
if(LOG_LEVEL >= INFO)
{
android.util.Log.i(tag, string);
}
}
/**
* Debug
*/
public static void d(String tag, String string)
{
if(LOG_LEVEL >= DEBUG)
{
android.util.Log.d(tag, string);
}
}
/**
* Verbose
*/
public static void v(String tag, String string)
{
if(LOG_LEVEL >= VERB)
{
android.util.Log.v(tag, string);
}
}
}
ProGuard сделает это за вас на вашей версии сборки и теперь хорошие новости от android.com:
http://developer.android.com/tools/help/proguard.html
инструмент ProGuard сжимает, оптимизирует и запутывает ваш код, удаляя неиспользуемый код и переименовывая классы, поля и методы с семантически неясными именами. В результате получается меньший размер .apk-файл, который сложнее перепроектировать. Потому что ProGuard делает ваше приложение сложнее для обратного проектирования важно использовать его, когда приложение использует функции, чувствительные к безопасности, например, при лицензировании приложений.
ProGuard интегрирован в систему сборки Android, поэтому вам не нужно вызывать его вручную. ProGuard запускается только при построении приложения в режиме выпуска, поэтому вам не придется иметь дело с запутанным кодом при построении приложения в режиме отладки. Запуск ProGuard полностью необязателен, но настоятельно рекомендуемый.
этот документ описывает, как включить и настроить ProGuard, а также использовать инструмент retrace для декодирования запутанных трассировок стека
добавьте в свой proguard-правила.txt
-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** w(...);
public static *** v(...);
public static *** i(...);
}
Мне нравится использовать Log.d (тег, некоторая строка, часто строка.формат.))(
тег всегда является именем класса
Преобразование Журнала.d (тег, -- > Logd (в тексте вашего класса
private void Logd(String str){
if (MainClass.debug) Log.d(className, str);
}
таким образом, когда вы будете готовы сделать версию выпуска, установите MainClass.отладка в false!
журналы могут быть удалены с помощью bash в linux и sed:
find . -name "*\.java" | xargs sed -ri ':a; s%Log\.[ivdwe].*\);%;%; ta; /Log\.[ivdwe]/ !b; N; ba'
работает для многострочных журналы. В этом решении вы можете быть уверены, что журналы отсутствуют в производственном коде.
Я знаю, что это старый вопрос, но почему вы не заменили все свои вызовы журнала чем - то вроде Boolean logCallWasHere=true; / / - - - остальная часть вашего журнала здесь
вот почему вы будете знать, когда вы хотите вернуть их, и они не повлияют на ваш вызов оператора if:)
самый простой способ;
использовать DebugLog
все журналы отключаются DebugLog при выпуске приложения.