在Android应用中灵活启用/禁用日志记录

时间:2012-07-22 17:08:07

标签: java android

出于性能方面的考虑,有些人建议使用以下方法,例如

public class MyActivity extends Activity {  

 private static final String TAG = "MyApp";  
 private static final boolean D = true;

 @Override  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if(D) Log.e(TAG, "MyActivity.onCreate debug message");  }

但是在处理大型项目时这是非精明的,因为在调试时,您需要为debug标志更新许多文件,有没有更好的方法?

6 个答案:

答案 0 :(得分:6)

您可以在BuildConfig中检查DEBUG布尔值:

if (BuildConfig.DEBUG) {
    // Do what you need
}

否则,您可以拥有一个调试变量,但是将其保存在每个活动中,在Application类中声明它,并在需要时检查它的值。

如果您对该变量的目的是用于日志记录,最好将您的日志包装到另一个类中,该类检查DEBUG变量:

public class LogUtils {
    public static void LOGD(final String tag, String message) {
        if (BuildConfig.DEBUG) {
            Log.d(tag, message);
        }
    }

    public static void LOGV(final String tag, String message) {
        if (BuildConfig.DEBUG) {
            Log.v(tag, message);
        }
    }

    public static void LOGI(final String tag, String message) {
        if (BuildConfig.DEBUG) {
            Log.i(tag, message);
        }
    }

    public static void LOGW(final String tag, String message) {
        if (BuildConfig.DEBUG) {
            Log.w(tag, message);
        }
    }

    public static void LOGE(final String tag, String message) {
        if (BuildConfig.DEBUG) {
            Log.e(tag, message);
        }
    }

}

然后,对此类进行日志调用:

LogUtils.LOGD(TAG, "MyActivity.onCreate debug message");

答案 1 :(得分:4)

我强烈推荐Google员工在其开源应用程序中开发的内容。在其他原因中,请记住BuildConfig,并检查指定标记的日志是否可以使用isLoggable在指定级别进行记录。这对我的项目来说是必须的。

/*
 * Copyright 2012 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.android.apps.iosched.util;

import com.google.android.apps.iosched.BuildConfig;

import android.util.Log;

/**
 * Helper methods that make logging more consistent throughout the app.
 */
public class LogUtils {
    private static final String LOG_PREFIX = "iosched_";
    private static final int LOG_PREFIX_LENGTH = LOG_PREFIX.length();
    private static final int MAX_LOG_TAG_LENGTH = 23;

    public static String makeLogTag(String str) {
        if (str.length() > MAX_LOG_TAG_LENGTH - LOG_PREFIX_LENGTH) {
            return LOG_PREFIX + str.substring(0, MAX_LOG_TAG_LENGTH - LOG_PREFIX_LENGTH - 1);
        }

        return LOG_PREFIX + str;
    }

    /**
     * WARNING: Don't use this when obfuscating class names with Proguard!
     */
    public static String makeLogTag(Class cls) {
        return makeLogTag(cls.getSimpleName());
    }

    public static void LOGD(final String tag, String message) {
        if (Log.isLoggable(tag, Log.DEBUG)) {
            Log.d(tag, message);
        }
    }

    public static void LOGD(final String tag, String message, Throwable cause) {
        if (Log.isLoggable(tag, Log.DEBUG)) {
            Log.d(tag, message, cause);
        }
    }

    public static void LOGV(final String tag, String message) {
        //noinspection PointlessBooleanExpression,ConstantConditions
        if (BuildConfig.DEBUG && Log.isLoggable(tag, Log.VERBOSE)) {
            Log.v(tag, message);
        }
    }

    public static void LOGV(final String tag, String message, Throwable cause) {
        //noinspection PointlessBooleanExpression,ConstantConditions
        if (BuildConfig.DEBUG && Log.isLoggable(tag, Log.VERBOSE)) {
            Log.v(tag, message, cause);
        }
    }

    public static void LOGI(final String tag, String message) {
        Log.i(tag, message);
    }

    public static void LOGI(final String tag, String message, Throwable cause) {
        Log.i(tag, message, cause);
    }

    public static void LOGW(final String tag, String message) {
        Log.w(tag, message);
    }

    public static void LOGW(final String tag, String message, Throwable cause) {
        Log.w(tag, message, cause);
    }

    public static void LOGE(final String tag, String message) {
        Log.e(tag, message);
    }

    public static void LOGE(final String tag, String message, Throwable cause) {
        Log.e(tag, message, cause);
    }

    private LogUtils() {
    }
}

答案 2 :(得分:3)

另一个解决方案是this某个相关问题的答案之一。您可以像这样覆盖Log类:

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

这样,每次使用日志时都不需要if语句。只需更改重写的Log类中的布尔值即可。当您准备发布时,可以使用ProGuard之类的工具去除对Log的所有引用以获得性能。

答案 3 :(得分:2)

使用ProGuard删除Log.v和Log.d消息

使用ProGuard的替代方法是使用Disable LogCat Output COMPLETELY in release Android app?删除最终版本的应用程序。

基本上,在app\proguard-rules.pro文件中,定义要删除的android.util.Log类的方法。对proguard-rules.pro文件的以下添加将导致在构建时删除v(详细)和d(调试)方法:

# This tell Proguard to assume Log.v and Log.d have no side effects (even
# though they do since they write to the logs) and thus can be removed
# during optimization:
-assumenosideeffects class android.util.Log {
    public static int v(...);
    public static int d(...);
}

这样可以避免在整个代码中使用if (BuildConfig.DEBUG)样式检查。

另见:{{3}}

答案 4 :(得分:1)

我写了一个LogWrapper类很简单,看起来像这样:

public class LogWrapper {
    private static final String DEBUG_TAG = "some-tag"
    private static boolean logsEnabled;

    public static void e(String msg) {
      if (logsEnabled) {      
        Log.e(DEBUG_TAG, msg);
      }
    }

    // other Log methods
}

您可以使用它而不是Log类,在一个地方根据需要修改布尔变量。希望这会有所帮助。

答案 5 :(得分:1)

我最近遇到了同样的问题,我不认为用Proguard剥离课程是禁用日志的好主意。所以我最终为标准的Android Log类编写了一个简单的替代品

https://github.com/zserge/log

它允许您控制日志级别。它还为你提供了很多糖#34;用于记录多个值,用于记录标记甚至更多,并且在Maven Central / JCenter上只提供了200行代码。