Androidアプリのリリースバージョンをビルドする前に、すべてのデバッグログ呼び出しを削除するにはどうすればよいですか?


397

Googleによると、AndroidアプリをGoogle Playに公開する前に、「ソースコードのLogメソッドへの呼び出しを無効にする」必要があります。公開チェックリストのセクション3からの抜粋:

リリース用のアプリケーションをビルドする前に、ロギングを非アクティブにし、デバッグオプションを無効にしてください。ソースファイルのLogメソッドの呼び出しを削除することで、ロギングを非アクティブ化できます。

私のオープンソースプロジェクトは大きく、リリースするたびに手動で行うのは面倒です。さらに、ログ行の削除は、たとえば次のようにトリッキーになる可能性があります。

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

Log行をコメントにすると、条件が次の行に適用され、load()が呼び出されない可能性があります。そのような状況は、私がそれが存在するべきではないと判断できるほどまれなものですか?

それで、それを行うためのより良いソースコードレベルの方法はありますか?または、すべてのログ行を効率的かつ安全に削除するための巧妙なProGuard構文ですか?


2
+1は、これが出版物のチェックリストにあることを覚えていなかったためです。
RDS

51
ブロックされていない行をコメントアウトするには、「//」の代わりに「; //」を使用します。
2012年

これを元に戻すことができる必要がある場合は、sed 's_^\(\s*Log\.\)_;//'`date|tr -s \ -`'\1_g'代わりに使用することをお勧めします。
2012年

2
Dimitarが追加したリンクは機能しなくなります。代わりにsource.android.com/source/code-style.html#log-sparinglyが見つかりました。
JosephL 2013年

1
@mboy:主に最近のパフォーマンスのためと思われますが、古いAndroidバージョンでは、セキュリティ上の利点もあります。
Nicolas Raoul

回答:


488

はるかに簡単な解決策は、あちこちにあるすべてのifチェックを忘れて、ProGuardを使用して、Ant ターゲットを呼び出すときに、すべての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と使用しているAndroidプラットフォーム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!");
}

より高度な例については、Timberサンプルアプリをご覧ください。開発中にすべてのログステートメントがlogcatに送信され、本番環境ではデバッグステートメントは記録されませんが、エラーはCrashlyticsに通知されます。


59
そして、なぜそれがデフォルトのproguardファイルにないのですか?
RDS

10
+ rdsは、行が削除されるため、プロダクションスタックトレースの行番号がコード内の行番号と異なるためです。
ガイ

5
ログの呼び出しを削除すると、スタックトレースの行番号がシフトすることを確認できます。常に同期しているとは限りません(私はいくつかの簡単なテストを行いましたが、おそらくLog呼び出しで文字列を連結した場合、原因を正確に特定することはできません)。ログコールを簡単に削除できるため、問題のあるIMOに値します。
Tony Chan

5
@Fraggle ADTツールのproguard-android.txtから:「最適化を有効にする場合は、独自のプロジェクト構成ファイルに最適化フラグを含めることはできません。代わりに、「proguard-android-optimize。 txt "ファイルの代わりに、"#project.propertiesファイルから。
Raanan

3
エスピンチが下の答えで言ったように。「このアプローチの唯一の問題は、Log.d( "tag"、 "Processed:" + new ItemCounter(blabla)+ "items")を実行すると、このログメッセージがリリースバージョンに表示されない場合でも、 StringBuilderを使用してメッセージを作成しますが、作成にコストがかかる可能性があります。 "これは、Timberの場合にも当てはまりますか?
Chitrang 2016年

117

すべての良い答えですが、開発が終了したとき、すべてのLog呼び出しの周りにifステートメントを使用することも、外部ツールを使用することもしたくありませんでした。

したがって、私が使用している解決策は、android.util.Logクラスを自分のLogクラスに置き換えることです。

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

すべてのソースファイルで私がしなければならなかった唯一のことは、android.util.Logのインポートを自分のクラスで置き換えることでした。


143
このアプローチの唯一の問題は、Log.d( "tag"、 "Processed:" + new ItemCounter(blabla)+ "items")を実行すると、このログメッセージがリリースバージョンに表示されない場合でも、 StringBuilderはメッセージの作成に使用されますが、作成にはコストがかかる可能性があります。
espinchi

9
このソリューションには大きな問題があります。espinchiは氷山の一角に言及しました。問題は、それを呼び出すとLog.d("tag", someValue.toString());、someValueがnullでないことを確認することを忘れるのが非常に簡単であることNullPointerExceptionです。安全なソリューションを提案しますが、だまされます。私たちは私たちa private static boolean DEBUGそしてそれからif(DEBUG)Log.d(TAG, msg);
フィリップ2012

2
@espinchiあなたの懸念は、この回答で述べたように、すべてのロギングライブラリに適用するようだstackoverflow.com/a/15452492/433718(SLF4J、バックログ、...)。それらを使用することは推奨されていませんか?
OneWorld

1
@espinchiの最初のコメントで言及されているオーバーヘッドを最小限に抑える唯一の方法は、ロギングメソッドを変更して、の代わりに可変引数を受け入れることですString。完全なソリューションはここで説明されています。これには明らかに別の欠点があります。すべての呼び出しを編集する必要があります(1つのインポート行だけでなく)。
スタン

21
参考までに、Android StudioとGradleビルドシステムを使用static final boolean LOG = BuildConfig.DEBUGしている場合は、このファイルを使用でき、このファイルを変更する必要はありません。
ashishduh 2014年

61

ログを取るかどうかを示す静的なブール値をどこかに持つことをお勧めします:

クラスMyDebug {
  static final boolean LOG = true;
}

次に、コードにログインする場所を問わず、次のようにします。

if(MyDebug.LOG){
  if(条件)Log.i(...);
}

MyDebug.LOGを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 + ")");

1
私もそのようなアプローチに投票します。また、Googleの公式アプリ内課金サンプルでも使用されています。
LA_

4
条件を最初のパラメータとして渡すほうが冗長ではないでしょうか?
スニコラ2012

1
これは、各ログステートメントに追加のコードが必要ですが、最善の解決策のようです。行番号は保持されます(ProGuardアプローチの弱点)、ログメッセージを作成するコードは実行されません(ラッパークラスアプローチの弱点、そして明らかにログライブラリアプローチの弱点) 。@LA_に基づくGoogleのアプリ課金サンプルでのこのアプローチの使用は、私の考えもサポートしています。
OneWorld

2
@Snicolasラッパーを実装せずに、条件を最初のパラメーターとしてどのように渡すことができますか?さらに、パラメーターとして追加する場合、メソッドに入る前に、すべてのパラメーター、つまりメッセージ文字列も評価する必要があります。パラメータを作成する前に、条件をテストする必要があります。提案されたソリューションは、おそらく外部ツールが与えられていないので最良のものです。
type-a1pha 2013

2
バイナリコードとしては、これが一番です。ただし、このようなコーディングは、単純なデバッグログ出力のために多くの労力を費やします。コードの可読性が大幅に低下します。一部を獲得、一部を失うと思います...
Richard Le Mesurier

30

クリストファーの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コマンドを使用します)


1
Macで実行している場合は、Sedの-iの後に「」が必要です(これに従って)ありがとう。
Vishal 2012

私は、Proguardでそれを行うのにあまり運がなかったので、私が取り組んでいる何かのために最終的に使用するものになるかもしれないと感じています
Joe Plante

そして、最初の投稿で提案したように、ブラケットなしのwhileブランチの後にログがある場合はどうなりますか?
type-a1pha 2013

@ type-a1pha:このソリューションを採用する場合、ブラケットブロックを必須と見なす必要があります。
Nicolas Raoul

2
@NicolasRaoulセミコロンはこの問題を修正します(//;//
Alex Gittemeier 2013

18

最終的なバイナリからログ行を削除するのに多くの問題があったので、Android StudioとGradleでProguardを使用することについて、いくつかの精度を追加したいと思います。

assumenosideeffectsプロガード作品で作るためには、前提条件があります。

あなたの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ファイルでは、2つのフラグを使用して最適化が無効になっています。

-dontoptimize
-dontpreverify

proguard-android-optimize.txtファイルには、これらの行を追加していないので、今assumenosideeffects作業することができます。

次に、個人的には、私はSLF4Jを使用します。他の人に配布されるライブラリーを開発するときはなおさらです。利点は、デフォルトでは出力がないことです。また、インテグレーターがログ出力を必要とする場合は、Android用のLogbackを使用してログをアクティブ化できるため、ログをファイルまたはLogCatにリダイレクトできます。

最終的なライブラリからログを削除する必要がある場合は、Proguardファイルに追加します(proguard-android-optimize.txtもちろん、ファイルを有効にした後)。

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

これは、新しいジャックcompiler--では動作しませんstackoverflow.com/questions/37932114/...
fattire

これは私を助けました。両方のproguard-android-optimize.txtデフォルトProGuardのファイルとして、および-assumenosideeffectsカスタムProGuardのファイルには、必要とされました!私はR8シンカー(現在のデフォルト)とデフォルトのAndroidロギングを使用しています。
Jonik

10

Jake WhartonのTimberを使用することを強く勧めます

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

印刷する

タグを指定せずに「あなたのクラス/メッセージ」


2
材木はとても良いですが、すでに既存のプロジェクトがある場合-github.com/zserge/logを試すことができます。これはandroid.util.Logのドロップイン代替であり、Timberが持つ機能のほとんどを備えています。
zserge

zserge、あなたのログソリューションはよさそうです。たくさんの機能。TimberのようにLintルールを追加することを検討しましたか?
jk7 2017

8

私はGoogle IOサンプルアプリケーションのようにLogUtilsクラスを使用しました。BuildConfig.DEBUGは信頼できないため、BuildConfig.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");
  }
}

Build.DEBUG以前使用していたバグレポートの+1 。また、さまざまな「正しい」回避策をあきらめ、同様のスタイルのソリューションを使用しました。
Richard Le Mesurier

7

組み込みのandroid.util.Logの代わりにroboguiceのログ機能を使用することを検討します

それらの機能は、リリースビルドのデバッグログと詳細ログを自動的に無効にします。さらに、いくつかの便利な機能を無料で利用できます(たとえば、カスタマイズ可能なロギング動作、すべてのログの追加データなど)。

proguardを使用するのはかなり面倒な場合があり、そのための正当な理由がない限り、アプリケーションで構成してアプリケーションで動作させる問題を経験しません(ログを無効にすることは良いことではありません)。


難読化を使用できない場合の非常に優れたアプローチ....特にプロガードLOLのためのロボギースのブレイクのため
Snicolas

1
robojuiceのロギング機能の更新されたリンク:github.com/roboguice/roboguice/wiki/Logging-via-Ln
RenniePet

7

Android Studioユーザーに特に適用されるこのソリューションを投稿しています。私は最近Timberも発見し、次のようにしてアプリに正常にインポートしました:

ライブラリの最新バージョンをbuild.gradleに入れます。

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

次に、Android Studiosで、[編集]-> [検索]-> [パス内で置換...]に移動します。

入力するLog.e(TAG,か、ログメッセージを"Text to find"テキストボックスに定義しました。次に、それを置き換えるだけですTimber.e(

ここに画像の説明を入力してください

[検索]をクリックして、すべて置換します。

Android Studioはプロジェクト内のすべてのファイルを処理し、すべてのログを木材に置き換えます。

この方法で私が持っていた唯一の問題は、gradleが各Javaファイルのインポートで「Timber」を見つけられないため、その後100万のエラーメッセージが表示されることです。エラーをクリックするだけで、Android Studioが自動的に「木材」をJavaにインポートします。すべてのエラーファイルに対してこれを実行すると、gradleは再度コンパイルされます。

また、このコードをクラスのonCreateメソッドに配置する必要がありますApplication

    if (BuildConfig.DEBUG) {
        Timber.plant(new Timber.DebugTree());
    }

これにより、本番環境ではなく開発モードの場合にのみアプリのログが記録されます。またBuildConfig.RELEASE、リリースモードでのログインも可能です。


3
インポートに対して同じことを試してみて、[正規表現]ボックスがオンになっていることを確認してください。テキスト:import android\.util\.Log\;置換:import android\.util\.Log\;\nimport timber\.log\.Timber\;
クラークウィルソン

または、構造的検索を使用して、Chike Mgbemenaが彼の投稿で
Maksim

@MaksimTuraevあなたのリンクはもはや関係ありません。今はヘアスタイルのブログです。
Vadim Kotov

ポストのように見えますが(=削除されたどこにでもそれを見つけることができません。
マクシムTuraev

@MaksimTuraevここウェイバックマシンからのコピーですが、イメージが壊れている- web.archive.org/web/20161004161318/http://chikemgbemena.com/...
ヴァディムコトフ

6

android.util.Logごとに、ログを有効/無効にする方法が提供されます。

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

デフォルトでは、メソッドisLoggable(...)はfalseを返します。

adb shell setprop log.tag.MyAppTag DEBUG

これは、DEBUGレベルを超えるログを印刷できることを意味します。リファレンスandroid doc:

指定したタグのログが指定したレベルでログ可能かどうかを確認します。タグのデフォルトレベルは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);
    }
}

6

グローバル置換を(一度だけ)実行でき、その後いくつかのコーディング規則を保持する場合、Android フレームワークでよく使用されるパターンに従うことができます。

書く代わりに

Log.d(TAG, string1 + string2 + arg3.toString());

それを持っている

if (BuildConfig.DEBUG) Log.d(TAG, string1 + String.format("%.2f", arg2) + arg3.toString());

これで、proguardは、最適化されたリリースのDEXから、StringBuilderと、その途中で使用するすべての文字列とメソッドを削除できます。使用してproguard-android-optimize.txt、あなたはあなたのandroid.util.Logについて心配する必要はありませんproguard-rules.pro

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

Android Studio Gradleプラグインを使用すると、信頼性が非常に高くなるため、ストリッピングを制御するための追加の定数は必要ありません。BuildConfig.DEBUG


4

以下をproguard-rules.txtファイルに追加します

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

4

ここに画像の説明を入力してください

これは、私がAndroidプロジェクトで使用していたものです。

Android Studioでは、Ctrl + Shift + Fでプロジェクト全体を検索し(MacOではCommand + Shift + F)、Ctrl + Shift + Rで置き換える(MacOではCommand + Shift + R)と同様の操作を実行できます。


これは、Eclipseプロジェクトでの作業を開くようです。検索オプションは、Androidスタジオでも使用できません。
Simon

2
Android Studioでは、Ctrl + Shift + Fショートカットを使用して同様の検索を実行できます
Lins Louis

質問のサンプルコードは、これが信頼できない理由を説明しています。
Nicolas Raoul

ログに含まれるコマンドの削除で問題が発生する可能性があります。たとえば、chocolateLog.recipie();
Andrew S

Android Studio 2.1ではこのオプションが見つかりません。また、このトリックは、通常の検索/置換で一度に1つのファイルに使用できます。
VVB

3

私は非常に簡単な解決策を持っています。開発にはIntelliJを使用しているため、詳細は異なりますが、アイデアはすべてのIDEに適用されるはずです。

ソースツリーのルートを選択して右クリックし、「置換」を選択します。次に、すべての「ログ」を置き換えることを選択します。「// Log。」で。これにより、すべてのログステートメントが削除されます。後で元に戻すには、同じ置換を繰り返しますが、今回はすべての「// Log」を置換します。「ログ」と。

私にとっては素晴らしい作品です。「ダイアログ」などの事故を避けるために、大文字と小文字を区別して置換を設定することを忘れないでください。追加の保証のために、「ログ」で最初のステップを実行することもできます。検索する文字列として。

鮮やかさ。


2
質問の「ログ行をコメントする場合」の段落読んでください。
Nicolas Raoul

はい、はい。回答を閲覧した後、もっと頻繁に読み直す必要があります。そのようなケースがある場合、すべてのログを別のインターフェースの背後に置くなど、以前に提案されたような別のソリューションが必要になる場合があります。私の提案は、おそらくより良い人々がオーバーヘッド追加のログLIBSのを避けたい小さなチームやプロジェクト、のために、あなたはなど、うまく人とコードを知っている作品
kg_sYy

1
Log.dを; // Log.dで置き換えると、その "If"シナリオも処理されます。
Jasper

3

以下のようzsergeさんのコメントが示唆され、

材木はとても良いですが、すでに既存のプロジェクトがある場合-github.com/zserge/logを試すことができます。これはandroid.util.Logのドロップイン置換であり、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

そのコード行を各アクティビティ/フラグメントに配置する必要がありますか、それとも1か所に配置する必要がありますか?
Noah Ternullo

@NoahTernullo //派生アプリケーションファイル内。DefaultApplication.java
Youngjae

1

さまざまなログレベルのサポートを提供し、コードがライブデバイスで実行されているかエミュレータで実行されているかに応じてログレベルを自動的に変更することにより、上記のソリューションを改善しました。

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


}

1
前のソリューションと同じ問題。文字列パラメーターが高価な呼び出しを使用して構築されている場合でも、リソースは無駄になります。渡されたパラメーターを作成する前に、呼び出しのチェックを行う必要があります。
type-a1pha 2013

1

ProGuardは、リリースビルドでそれを行い、android.comからの朗報です。

http://developer.android.com/tools/help/proguard.html

ProGuardツールは、未使用のコードを削除し、クラス、フィールド、メソッドの名前を意味的にあいまいな名前に変更することで、コードを縮小、最適化、難読化します。その結果、リバースエンジニアリングが困難な、サイズの小さい.apkファイルが作成されます。ProGuardはアプリケーションのリバースエンジニアリングを困難にするため、アプリケーションにライセンスを付与する場合など、セキュリティに敏感な機能をアプリケーションが利用する場合は、ProGuardを使用することが重要です。

ProGuardはAndroidビルドシステムに統合されているため、手動で呼び出す必要はありません。ProGuardは、アプリケーションをリリースモードでビルドするときにのみ実行されるため、デバッグモードでアプリケーションをビルドするときに難読化されたコードを処理する必要はありません。ProGuardの実行は完全にオプションですが、強くお勧めします。

このドキュメントでは、ProGuardを有効にして構成する方法、およびリトレースツールを使用して難読化されたスタックトレースをデコードする方法について説明します


2
ただし、デフォルトではデバッグログは削除されないようです。だからクリストファーの答えはよく聞こえます。
Nicolas Raoul 2013年

0

私はLog.d(TAG、いくつかの文字列、しばしばString.format())を使用するのが好きです。

TAGは常にクラス名です

クラスのテキストでLog.d(TAG、-> Logd(を変換します

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

このように、リリースバージョンを作成する準備ができたら、MainClass.debugをfalseに設定します。


1
これを含む他のソリューションの問題点は、コードを保護したりコメントしたりすることであり、コードに残しておくことで、大量の文字列がビルドされる可能性があります。平均的なアプリでは問題ありませんが、最適化しようとすると問題になります。
Lassi Kinnunen

0

Linuxとsedでbashを使用してログを削除できます。

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

複数行のログで機能します。このソリューションでは、ログが本番コードに存在しないことを確認できます。


0

これは古い質問であることは承知していますが、なぜすべてのログ呼び出しをBoolean logCallWasHere = trueのようなものに置き換えなかったのですか。// ---ここに残りのログ

これにより、いつそれらを元に戻したいかがわかり、ifステートメントの呼び出しには影響しません:)


興味深いことに、そのような行はコンパイラ/オプティマイザによって無視されます。ただし、一部のメソッドには複数のログ呼び出しがあり、同じ変数を2回宣言できないため、変数名は一意である必要があります。
Nicolas Raoul

アクティビティの上部で変数を宣言し、この行からブール宣言を削除できます;)
masood elsad

0

なぜしないのですか

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

?追加のライブラリは不要で、プロジェクトを台無しにする傾向のあるプロガードルールもありません。Javaコンパイラは、リリースビルドを行うときに、この呼び出しのためにバイトコードを除外するだけです。


不便なのは、単に書くよりも冗長Log.d("tag","msg");であり、また、そのif(BuildConfig.DEBUG)部分を書くことを忘れやすいことです。
Nicolas Raoul

1
これに関する別の問題は、ストリングがパックされたリリースに残っていることです。
ストラヤ

0

追加のライブラリをいじったり、コードを手動で編集したりしたくない場合の解決策を次に示します。このJupyterノートブックを作成して、すべてのJavaファイルを調べ、すべてのログメッセージをコメント化しました。完璧ではありませんが、それは私のために仕事を成し遂げました。


0

私のやり方:

1)列選択モードを有効にする(alt + shift + insert)

2)1つのLog.d(TAG、 "text")を選択します。「ログ」の部分

3)次に、shift + ctrl + alt + jを実行します

4)左矢印をクリックします

5)shift + endを実行

6)削除を押します。

これにより、Javaファイル内のすべてのLOG呼び出しが一度に削除されます。


0

この単純な従来の方法を使用してみてください:

Ctrl+ Shift+R

取り替える

Log.e(

// Log.e(

それは質問で与えられたサンプルコードではうまく機能しません。
Nicolas Raoul

0

kotlinで簡単、いくつかのトップレベル関数を宣言するだけ

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

-1

最も簡単な方法。

使用する DebugLog

アプリがリリースされると、DebugLogによってすべてのログが無効になります。

https://github.com/MustafaFerhan/DebugLog


これは間違いです。これによりログがログに記録されないだけで、コードからログが削除されることはないため、ユーザーがコードをリバースエンジニアリングするのに役立つログが引き続き存在し、すべてのログの文字列をフォーマットするコストがかかります。
Glenn Maynard
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.