Home > Software design >  How to remove all log calls except in specific package with prodguard and R8?
How to remove all log calls except in specific package with prodguard and R8?

Time:01-02

I've configured my Android project to remove all logging in "release" mode like so:

build.gradle (app)

postprocessing {
    removeUnusedCode false
    obfuscate false
    optimizeCode true
    proguardFile 'proguard-rules.pro'
}

pro guard-rules.pro

-assumenosideeffects class android.util.Log { *; }

This indeed removes all Log.* calls from the app, but is there a way to keep logs in specific package? for instance:

// Remove all Log.* calls except in all files in package com.mylibrary

-assumenosideeffects class android.util.Log { *; } -except-in com.mylibrary.**

CodePudding user response:

I'm not familiar with such a conditional rule configuration with regards to assumenosideeffects.

However, if you're able to change the code of the specific package where you'd want to keep the logs on, then the following workaround might effectively emulate exactly what you want.

In proguard rule configuration list all the available shorthand methods, but omit the println and getStackTraceString methods:

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

Create a Log wrapper class, which re-implements various v/d/i/e/w methods using kept println and getStackTraceString methods:

package com.example;

import android.util.Log;

public class Logger {
    public static int w(String tag, String message) {
        return Log.println(Log.WARN, tag, message);
    }

    public static int w(String tag, String msg, Throwable tr) {
        return Log.println(Log.WARN, tag, msg   '\n'   Log.getStackTraceString(tr));
    }
}

Then in your code, keep calling Log.* methods for logs you'd want to remove but switch to Logger.* methods for logs you'd like to keep.

package com.example;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // this one will be removed
        Log.w("MainActivity", "in onCreate: removed");
        // this one will be kept
        Logger.w("MainActivity", "in onCreate: kept");
    }
}
  • Related