In this article, we will build an application in Android to implement a logging utility class that is better than the default Log class of android. For that, we will be using Timber Library which is a small logger with an extensible API. As Android developers, we use a lot of log statements in our projects to generate outputs to test our application at different stages. Logs are of many types like Verbose, Debug, Warn, Info, Error. We use all sorts of Log statements in our application for finding errors and debugging. Once the application is ready to be released we need to remove all the log statements so that the generated APK doesn’t carry any additional application data. To tackle this problem we have several ways:
- Condition-based logging
- ProGuard
- Timber
Condition-based logging
Using this method we check the level for which the logger is enabled and then log a message to that level. We just have to create a boolean variable in our Application class to check for logging. Use this boolean condition before every log statement in the application and before releasing the application change it to isDebug = false. Below is the code snippet of the Application class.
Java
import android.app.Application; public class LogApplication extends Application { public static boolean checkDebug; @Override public void onCreate() { super .onCreate(); checkDebug = true ; } } |
Kotlin
import android.os.Bundle import androidx.appcompat.app.AppCompatActivity class MainActivity : AppCompatActivity() { var checkDebug = false override fun onCreate(savedInstanceState: Bundle?) { super .onCreate(savedInstanceState) setContentView(R.layout.activity_main) checkDebug = true } } |
ProGuard
ProGuard is used to get rid of unused codes. Here we can use it to remove the Log statements in the release build. Add the log methods that you want to strip in your release build in proguard-android-optimize.txt. Open this file from Gradle Scripts and add all the log statements that need to be removed while releasing. Below is the code snippet
-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(…);
}
Timber
This is where the Timber Logging library comes in to reduce the tedious task by automatically generating the tags and later removing the logs from the generated APKs. Let us discuss integrating Timber into our Android Project.
Step by Step Implementation
Step 1: Add Dependency
Timber is an open-source library made by Jake Wharton. To add its dependency open build.gradle file and add –
implementation ‘com.jakewharton.timber:timber:4.7.1’
and sync project.
Step 2: Make Application Class
We need to create a separate base class for the application so that the Timber library can be used in all the activities. To initialize timber as soon the app starts it should be best kept in the application class.
Java
import android.app.Application; import timber.log.Timber; public class MyTimber extends Application { @Override public void onCreate() { super .onCreate(); // initialize timber in application class Timber.plant( new Timber.DebugTree()); } } |
Kotlin
import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import timber.log.Timber import timber.log.Timber.DebugTree class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super .onCreate(savedInstanceState) setContentView(R.layout.activity_main) // initialize timber in application class Timber.plant(DebugTree()) } } |
After creating Application Class change the default application class in the AndroiManifest.xml file
XML
<? xml version = "1.0" encoding = "utf-8" ?> <application android:name = ".MyTimber" android:allowBackup = "true" android:icon = "@mipmap/ic_launcher" android:label = "@string/app_name" android:roundIcon = "@mipmap/ic_launcher_round" android:supportsRtl = "true" android:theme = "@style/Theme.TimberLogger" > < activity android:name = ".MainActivity" > < intent-filter > < action android:name = "android.intent.action.MAIN" /> < category android:name = "android.intent.category.LAUNCHER" /> </ intent-filter > </ activity > </ application > </ manifest > |
Step 3: Use Timber for Logging
Now we can use timber for logging in to all our android activities.
Java
import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import timber.log.Timber; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); Timber.i( "Timber logging is ready" ); } } |
Kotlin
import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import timber.log.Timber class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super .onCreate(savedInstanceState) setContentView(R.layout.activity_main) Timber.i( "Timber logging is ready" ); } } |