programing

안드로이드 앱의 릴리스 버전을 구축하기 전에 디버그 로깅 호출을 모두 제거하는 방법은 무엇입니까?

powerit 2023. 6. 2. 21:24
반응형

안드로이드 앱의 릴리스 버전을 구축하기 전에 디버그 로깅 호출을 모두 제거하는 방법은 무엇입니까?

Google에 따르면 Android 앱을 Google Play에 게시하기 전에 "소스 코드에 메서드를 기록하는 모든 호출을 비활성화"해야 합니다.간행물 점검표의 섹션 3에서 발췌:

릴리스할 응용 프로그램을 빌드하기 전에 로깅을 비활성화하고 디버깅 옵션을 비활성화해야 합니다.원본 파일에서 Log 메서드에 대한 호출을 제거하여 로깅을 비활성화할 수 있습니다.

제 오픈 소스 프로젝트는 규모가 크고 출시할 때마다 수동으로 하는 것이 고통스럽습니다.또한 로그 줄을 제거하는 것은 다음과 같이 어려울 수 있습니다.

if(condition)
  Log.d(LOG_TAG, "Something");
data.load();
data.show();

Log 라인에 주석을 달면 다음 라인에 조건이 적용되고 load()가 호출되지 않을 가능성이 높습니다.존재하지 않아야 한다고 결정할 수 있을 정도로 그러한 상황이 드문가요?

그렇다면, 그렇게 하는 더 나은 소스 코드 수준의 방법이 있을까요?아니면 모든 로그 라인을 효율적이지만 안전하게 제거할 수 있는 영리한 ProGuard 구문이 아닐까요?

훨씬 쉬운 해결책은 모든 것을 잊어버리는 것입니다.if모든 곳을 검사하고 ProGuard를 사용하여 모든 데이터를 제거합니다.Log.d()또는Log.v()가 개미를 때 호출합니다.release표적이 되는

이렇게 하면 일반 빌드에 대한 디버그 정보가 항상 출력되고 릴리스 빌드에 대한 코드를 변경할 필요가 없습니다.또한 ProGuard는 바이트 코드를 통해 여러 패스를 수행하여 원하지 않는 다른 문, 빈 블록을 제거할 수 있으며 필요한 경우 짧은 메서드를 자동으로 인라인화할 수 있습니다.

예를 들어 Android를 위한 매우 기본적인 ProGuard 구성은 다음과 같습니다.

-dontskipnonpubliclibraryclasses
-dontobfuscate
-forceprocessing
-optimizationpasses 5

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

그래서 당신은 그것을 파일에 저장한 다음, Ant에서 ProGuard를 호출하여 방금 컴파일된 JAR과 당신이 사용하고 있는 안드로이드 플랫폼 JAR을 전달합니다.

ProGuard 설명서의 예도 참조하십시오.


업데이트(4.5년 후):요즘 나는 Android 로깅을 위해 Timber를 사용했습니다.

더만 아니라 기본값보다 더 .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에 자동으로 보고되는 고급 예제는 Timber 샘플 앱을 참조하십시오.

모두 좋은 답변입니다. 하지만 개발이 완료되었을 때 모든 Log 호출에 대한 설명을 사용하거나 외부 도구를 사용하고 싶지 않았습니다.

그래서 제가 사용하고 있는 해결책은 안드로이드.util을 교체하는 것입니다.내 로그 클래스가 있는 로그 클래스:

public class Log {
    static final boolean LOG = BuildConfig.DEBUG;

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

모든 소스 파일에서 제가 해야 할 일은 rodroid.util의 Import를 교체하는 것이었습니다.내 클래스로 기록합니다.

기록 여부를 나타내는 정적 부울을 어딘가에 두는 것이 좋습니다.

클래스 MyDebug {}정적 최종 부울 LOG = true;}

그런 다음 코드를 로그인할 때마다 다음을 수행합니다.

if(MyDebug).LOG) {if (조건) Log.i(...);}

이제 MyDebug를 설정하면 됩니다.로그를 거짓으로 기록하면 컴파일러는 이러한 검사 내의 모든 코드를 제거합니다(정적 최종이므로 컴파일 시 코드가 사용되지 않음을 알 수 있습니다).

대규모 프로젝트의 경우 개별 파일에 부울을 설치하여 필요에 따라 로깅을 쉽게 활성화하거나 비활성화할 수 있습니다.예를 들어 창 관리자에 있는 다양한 로깅 상수는 다음과 같습니다.

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 + ")");

Christopher의 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 계층을 가져오거나 동등한 Windows 명령을 사용합니다.)

Proguard를 Android Studio 및 Gradle과 함께 사용하는 것에 대한 몇 가지 규정을 추가하고 싶습니다. 왜냐하면 최종 바이너리에서 로그 라인을 제거하는 데 많은 문제가 있었기 때문입니다.

만기위는서해를 만들기 .assumenosideeffects프로가드 작업에는 전제 조건이 있습니다.

그래들 파일에서, 당신은 다음의 용도를 지정해야 합니다.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 두 플래그로 됩니다: 일화는다두가플래로지비활다니.

-dontoptimize
-dontpreverify

proguard-android-optimize.txt파일에서 해당 행을 추가하지 않으므로 지금assumenosideeffects작동할 수 있습니다.

그리고 개인적으로 SLF4J를 사용하는데, 다른 사람들에게 배포되는 도서관을 개발할 때 더욱 그렇습니다.장점은 기본적으로 출력이 없다는 것입니다.또한 통합업체가 로그 출력을 원하는 경우 Android용 로그백을 사용하여 로그를 활성화하여 로그를 파일 또는 LogCat로 리디렉션할 수 있습니다.

라이브러리에서 해야 할 파일에 합니다(" "Proguard 파일"을후).proguard-android-optimize.txt물론 파일):

-assumenosideeffects class * implements org.slf4j.Logger {
    public *** trace(...);
    public *** debug(...);
    public *** info(...);
    public *** warn(...);
    public *** error(...);
}

제이크 와튼의 팀버를 사용하는 것을 강력히 추천합니다.

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

인쇄할

태그 지정 없이 "사용자 클래스 / 메시지"

Google IO 예제 응용 프로그램과 같이 LogUtils 클래스를 사용해 본 적이 있습니다.BuildConfig 대신 응용 프로그램별 DEBUG 상수를 사용하도록 수정했습니다.빌드 구성으로 인해 DEBUG가 발생했습니다.DEBUG를 신뢰할 수 없습니다.그리고 제 수업에는 다음과 같은 것들이 있습니다.

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

내장된 Android.util 대신 Roboguice의 로깅 기능을 사용하는 것을 고려하고 싶습니다.로그.

해당 기능은 릴리스 빌드에 대한 디버그 및 상세 로그를 자동으로 비활성화합니다.또한 사용자 정의 가능한 로깅 동작, 모든 로그에 대한 추가 데이터 등의 몇 가지 기능을 무료로 제공합니다.

proguard를 사용하는 것은 상당히 번거로울 수 있으며, 그럴 만한 충분한 이유가 없는 한 애플리케이션을 구성하고 작동시키는 번거로움을 겪지 않을 것입니다(로그를 비활성화하는 것은 좋은 일이 아닙니다).

Android Studio 사용자에게 특별히 적용되는 솔루션을 게시합니다.또한 최근에 Timber를 발견하고 다음 작업을 수행하여 성공적으로 앱으로 가져왔습니다.

최신 버전의 라이브러리를 build.gradle에 넣습니다.

compile 'com.jakewharton.timber:timber:4.1.1'

그런 다음 Android Studios에서 편집 -> 찾기 -> 경로에서 바꾸기...로 이동합니다.

에 입력Log.e(TAG,를 또는 한 경우도 ."Text to find"텍스트 상자그런 다음 그냥 다음으로 대체합니다.Timber.e(

여기에 이미지 설명 입력

찾기를 누른 다음 모두 바꾸기를 누릅니다.

이제 Android Studios가 프로젝트의 모든 파일을 검토하고 모든 로그를 Timbers로 대체합니다.

이 방법에서 유일하게 문제가 된 것은 Gradle이 각 Java 파일의 가져오기에서 "Timber"를 찾을 수 없기 때문에 이후에 백만 개의 오류 메시지가 표시된다는 것입니다.오류를 클릭하기만 하면 Android Studios가 자동으로 "Timber"를 Java로 가져옵니다.모든 오류 파일에 대해 작업을 완료하면 Gradle이 다시 컴파일됩니다.

이▁your에 넣어야 합니다.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와 StringBuilder가 사용하는 모든 문자열과 메서드를 최적화된 릴리스 DEX에서 제거할 수 있습니다.사용하다proguard-android-optimize.txtAndroid.dll에 대해 걱정할 필요가 없습니다.로그인합니다.proguard-rules.pro:

android {
  …
  buildTypes {
    release {
      minifyEnabled true
      proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
  }
}

Android Studio Gradle 플러그인을 사용하면BuildConfig.DEBUG상당히 신뢰할 수 있으므로 스트리핑을 제어하기 위해 추가 상수가 필요하지 않습니다.

Android.util 단위.로그는 로그를 활성화/비활성화하는 방법을 제공합니다.

public static native boolean isLoggable(String tag, int level);

기본적으로 Loggable(...) 메서드는 다음과 같이 장치에서 prop를 설정한 후에만 false를 반환합니다.

adb shell setprop log.tag.MyAppTag DEBUG

즉, DEBUG 레벨 이상의 로그를 출력할 수 있습니다.참조 안드로이드 문서:

지정된 태그에 대한 로그가 지정된 수준에서 로깅 가능한지 여부를 확인합니다.태그의 기본 수준은 INFO로 설정됩니다.즉, INFO를 포함한 모든 레벨이 기록됩니다.기록 방법에 전화를 걸기 전에 태그가 기록되어야 하는지 확인해야 합니다.시스템 속성 'setprop log.tag'를 설정하여 기본 수준을 변경할 수 있습니다.여기서 level은 VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT 또는 Suppress입니다.Suppress는 태그에 대한 모든 로깅을 해제합니다.'log.tag'가 포함된 local.prop 파일을 만들 수도 있습니다./data/local.prop에 배치합니다.

따라서 사용자 지정 로그 유틸리티를 사용할 수 있습니다.

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);
    }
}
  1. 에 가다Application->app->proguard-rules.pro 여기에 이미지 설명 입력

  2. 보호 규칙 내부에 아래 코드를 입력하십시오.프로의

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

특정 디버그 클래스를 제거할 수 있습니다. 디버그 유형 버그를 로그에 기록하려면

  1. build.gradle(app) ->android 일을 해라, 이 일을 하세요.

    buildTypes {
            debug{
                debuggable false
                minifyEnabled true
                shrinkResources true
                proguardFiles getDefaultProguardFile('proguard-android- 
                optimize.txt'), 'proguard-rules.pro'
            }
            release {
                debuggable false
                minifyEnabled true
                shrinkResources true
                proguardFiles getDefaultProguardFile('proguard-android- 
                optimize.txt'), 'proguard-rules.pro'
            }
        }
    
     lintOptions {
               checkReleaseBuilds false
               // Or, if you prefer, you can continue to check for errors in release builds,
               // but continue the build even when errors are found:
               abortOnError false
      }
    

보호 규칙에 다음을 추가합니다.txt 파일

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

아주 간단한 해결책이 있습니다.저는 IntelliJ를 개발에 사용하기 때문에 세부 사항은 다양하지만 아이디어는 모든 IDE에 적용되어야 합니다.

소스 트리의 루트를 선택하고 마우스 오른쪽 버튼을 클릭한 다음 "바꾸기"를 선택합니다.그런 다음 모든 "로그"를 "//로그"로 바꾸도록 선택합니다.이렇게 하면 모든 로그 문이 제거됩니다.나중에 다시 되돌리려면 동일한 바꾸기를 반복하지만 이번에는 모든 "//Log."를 "Log."로 바꿉니다.

저한테 딱 맞습니다."Dialog"와 같은 사고를 방지하려면 대소문자를 구분하여 교체를 설정해야 합니다.추가 확인을 위해 "로그"를 검색할 문자열로 사용하여 첫 번째 단계를 수행할 수도 있습니다.

대단하다.

즈세르게의 의견이 시사했듯이,

Timber는 매우 좋지만, 만약 당신이 이미 기존의 프로젝트를 가지고 있다면, 당신은 github.com/zserge/log 을 사용해 볼 수 있습니다.Android.util을 대체할 제품입니다.Log and는 Timber가 가진 대부분의 기능과 그 이상의 기능을 가지고 있습니다.

로그 라이브러리는 아래와 같은 간단한 로그 인쇄 스위치를 제공합니다.

또한 변경만 하면 됩니다.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

여기에 이미지 설명 입력

이것이 제가 안드로이드 프로젝트에서 하던 일입니다.

Android Studio에서는 전체 프로젝트에서 찾을 Ctrl+Shift+F(MacOS에서는 Command+Shift+F)와 바꿀 Ctrl+Shift+R(MacOS에서는 Command+Shift+R)로 유사한 작업을 수행할 수 있습니다.

프로덕션에 가기 전에 Kotlin 프로젝트에서 이 문제를 해결하는 방법은 다음과 같습니다.

buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

-assumenosideeffects class android.util.Log {
    public static boolean isLoggable(java.lang.String, int);
    public static int d(...);
    public static int w(...);
    public static int v(...);
    public static int i(...);
    public static int e(...);
}

코드가 활성 장치에서 실행되는지 에뮬레이터에서 실행되는지에 따라 다양한 로그 수준을 지원하고 로그 수준을 자동으로 변경하여 위의 솔루션을 개선했습니다.

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를 실행하는 것은 완전히 선택 사항이지만 강력하게 권장됩니다.

이 문서에서는 ProGuard를 활성화 및 구성하는 방법과 난독화된 스택 추적을 디코딩하는 재추적 도구를 사용하는 방법을 설명합니다.

ProGuard를 사용하는 대신 프로그래밍 방식을 사용하려는 경우 디버그용과 릴리스용 두 개의 인스턴스로 자신의 클래스를 만들어 두 가지 상황에서 기록할 항목을 선택할 수 있습니다.

따라서 릴리스에서 아무것도 기록하지 않으려면 아래 예와 같이 아무것도 하지 않는 Logger를 구현하기만 하면 됩니다.

import android.util.Log

sealed class Logger(defaultTag: String? = null) {
    protected val defaultTag: String = defaultTag ?: "[APP-DEBUG]"

    abstract fun log(string: String, tag: String = defaultTag)

    object LoggerDebug : Logger() {
        override fun log(string: String, tag: String) {
            Log.d(tag, string)
        }
    }

    object LoggerRelease : Logger() {
        override fun log(string: String, tag: String) {}
    }

    companion object {
        private val isDebugConfig = BuildConfig.DEBUG

        val instance: Logger by lazy {
            if(isDebugConfig)
            LoggerDebug
            else
                LoggerRelease
        }

    }
}

그런 다음 로거 클래스를 사용합니다.

class MainActivity : AppCompatActivity() {

private val logger = Logger.instance

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    logger.log("Activity launched...")
    ...
    myView.setOnClickListener {
        ...

        logger.log("My View clicked!", "View-click")
    }
}

업데이트 ==

더 나은 성능을 위해 문자열 연결을 방지하려면 디버그 구성에서만 호출될 람다를 사용하여 인라인 함수를 추가할 수 있습니다.

// Add this function to the Logger class.
inline fun commit(block: Logger.() -> Unit) {
    if(this is LoggerDebug)
        block.invoke(this)
}

그리고 나서:

 logger.commit {
     log("Logging without $myVar waste of resources"+ "My fancy concat")
 }

인라인 기능을 사용하고 있기 때문에 추가 객체 할당 및 가상 메서드 호출이 없습니다.

Log.d(TAG, 일부 문자열, 종종 문자열)를 사용합니다.형식().

태그는 항상 클래스 이름입니다.

Transform Log.d(TAG, --> Logd(클래스의 텍스트에서)

private void Logd(String str){
    if (MainClass.debug) Log.d(className, str);
}

이런 식으로 릴리스 버전을 만들 준비가 되면 MainClass.debug를 false로 설정합니다!

Linux 및 sed에서 bash를 사용하여 로그를 제거할 수 있습니다.

find . -name "*\.java" | xargs sed -ri ':a; s%Log\.[ivdwe].*\);%;%; ta; /Log\.[ivdwe]/ !b; N; ba'

여러 줄 로그에 사용할 수 있습니다.이 솔루션에서는 로그가 프로덕션 코드에 존재하지 않는다고 확신할 수 있습니다.

이것이 오래된 질문인 것은 알지만, 왜 모든 로그 호출을 부울 logCallWas와 같은 것으로 바꾸지 않았습니까?여기=true; //--로그의 나머지 부분

이것이 당신이 언제 그것들을 되돌리고 싶은지 알 수 있는 이유이며, 그것들은 당신의 if 스테이트먼트 통화에 영향을 미치지 않을 것입니다:)

그냥 하는 게 어때요?

if(BuildConfig.DEBUG)
  Log.d("tag","msg");

추가 라이브러리가 필요하지 않고 프로젝트를 망치는 프로가드 규칙이 없으며 Java 컴파일러는 릴리스 빌드 시 이 호출에 대한 바이트 코드를 생략합니다.

내 방식:

열 선택 모드 활성화(alt+shift+insert)

Log.d(TAG, "text"), 'Log' 부품 중 하나를 선택합니다.

그런 다음 shift + ctrl + alt + j를 수행합니다.

왼쪽 화살표 클릭

교대 근무를 하다

delete를 누릅니다.

Java 파일의 모든 LOG 호출을 한 번에 제거합니다.

코틀린으로 간편하고 몇 가지 최상위 기능만 선언할 수 있습니다.

val isDebug: Boolean
    get() = BuildConfig.DEBUG

fun logE(tag: String, message: String) {
    if (isDebug) Log.e(tag, message)
}

fun logD(tag: String, message: String) {
    if (isDebug) Log.d(tag, message)
}

프로젝트에서 아래의 접근 방식을 사용했습니다.

생성된 사용자 지정 로거 클래스:

public class LoggerData 
{
   
    public static void showLog(String type, Object object) {
        try {
            Log.d("loggerData:" + type + "-", "showLog: " + new Gson().toJson(object));
        } catch (Exception e) {
            Log.d("TAG", "showLog: " + e.getLocalizedMessage());
            Log.d("loggerData:" + type + "-", "showLog: " + object);
        }

    }

    public static void showLog(Object object) {
        
            try {
                Log.d("loggerData:" + "-", "showLog: +" + new Gson().toJson(object));
            } catch (Exception e) {
                Log.d("TAG", "showLog: " + e.getLocalizedMessage());
                Log.d("loggerData:" + "-", "showLog: " + object);
            }
        
    }
}

그런 다음 필요한 로그인 코드를 다음과 같이 사용합니다.

  LoggerData.showLog("Refreshed token: ", token);

릴리스 APK를 빌드하기 전에 LoggerData 클래스에서 로그를 한 위치만 비활성화합니다.

public class LoggerData {
    

    public static void showLog(String type, Object object) {
        try {
            //Log.d("loggerData:" + type + "-", "showLog: " + new Gson().toJson(object));
        } catch (Exception e) {
            //Log.d("TAG", "showLog: " + e.getLocalizedMessage());
            //Log.d("loggerData:" + type + "-", "showLog: " + object);
        }

    }

    public static void showLog(Object object) {
       
            try {
              //  Log.d("loggerData:" + "-", "showLog: +" + new Gson().toJson(object));
            } catch (Exception e) {
                //Log.d("TAG", "showLog: " + e.getLocalizedMessage());
                //Log.d("loggerData:" + "-", "showLog: " + object);
            }
        }
    }

그것이 당신에게도 도움이 되길 바랍니다.

다음은 Android 또는 로깅 API 전용이 아닌 간단한 Kotlin 솔루션입니다.

일부 도우미 개체 설정LoggingUtils:

object LoggingUtils {
  const val DEBUG_LOGGING_ENABLED = false

  /** Wraps log lines that should be removed from the prod binary. */
  inline fun debugLog(logBlock: () -> Unit) {
    if (DEBUG_LOGGING_ENABLED) logBlock()
  }
}

그런 다음 해당 방법으로 줄 바꿈:

fun handleRequest(req: Request) {
  debugLog { logger.atFinest().log("This is a high-volume debug log! %s", request) }

  // ...

  try {
    // ...
  } catch (e: Exception) {
    logger.atSevere().withCause(e).log("I want this to appear in prod logs!")
  }
}

그 이후로debugLog메서드가 다음과 같이 표시됩니다.inline그리고 변수.DEBUG_LOGGING_ENABLED로그 라인은 단순하게 포함되거나 컴파일 시 최적화됩니다.람다도 할당되지 않고 메서드 호출도 없습니다.

각 로그 라인을 포장하는 것보다 약간 더 깨끗하고 리팩터링하기 쉽습니다.if() {}개별적으로 명령문을 작성하고 로거를 위한 래퍼를 만드는 유혹적인 옵션은 컴파일러 및 로깅 서버 최적화, 부적절한 사용자 데이터 로깅 방지 보호 등의 측면에서 상당한 단점을 가질 수 있습니다.

가장 간단한 방법;

사용하다DebugLog

앱이 릴리스되면 DebugLog에 의해 모든 로그가 비활성화됩니다.

https://github.com/MustafaFerhan/DebugLog

추가 라이브러리를 사용하거나 코드를 수동으로 편집하지 않으려면 다음 방법을 사용합니다.저는 모든 자바 파일을 검토하고 모든 로그 메시지에 주석을 달기 위해 이 주피터 노트북을 만들었습니다.완벽하지는 않지만, 그것은 저에게 일을 해주었습니다.

언급URL : https://stackoverflow.com/questions/2446248/how-to-remove-all-debug-logging-calls-before-building-the-release-version-of-an

반응형