I find a better and cleaner way to disable and manage Fabric.
In my application I use slf4j-api
, a log API used a lot in web development. With this API you can create appender, so I decided to create a Fabric Appender and use this appender only when the app run.
How to
Install slf4j
with Logback
Set your build.gradle
dependencies {
...
// Log
compile 'com.github.tony19:logback-android-core:1.1.1-6'
compile 'com.github.tony19:logback-android-classic:1.1.1-6'
compile 'org.slf4j:slf4j-api:1.7.21'
}
Add src/main/assets/logback.xml
<configuration>
<appender name="FABRIC" class="path/to/your/FabricAppender" />
<appender name="LOGCAT" class="ch.qos.logback.classic.android.LogcatAppender">
<tagEncoder>
<pattern>%logger{0}</pattern>
</tagEncoder>
<encoder>
<pattern>[PUP] %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="LOGCAT" />
<appender-ref ref="FABRIC" />
</root>
By default Logback
has a customize appender working with Logback
. You can comment the FABRIC
part we will be explain later.
Add src/androidTest/assets/logback.xml
<configuration>
<appender name="LOGCAT" class="ch.qos.logback.classic.android.LogcatAppender">
<tagEncoder>
<pattern>%logger{0}</pattern>
</tagEncoder>
<encoder>
<pattern>[PUP] %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="LOGCAT" />
</root>
</configuration>
You don't want to have Fabric appender here! because you want your instrumented test running only with Logcat
Use Logback
Now you can easily log using the powerful API of slf4j
like below
class MainActivity : AppCompatActivity() {
private val log = LoggerFactory.getLogger(javaClass)!! // Call your logger in each class with this line
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
log.info("Activity start")
// ...
} }
Set Fabric for Logback
Create in your project FabricAppender.kt
package your.package.log
import android.content.Context
import ch.qos.logback.classic.Level
import ch.qos.logback.classic.spi.ILoggingEvent
import ch.qos.logback.classic.spi.ThrowableProxy
import ch.qos.logback.core.UnsynchronizedAppenderBase
import com.crashlytics.android.Crashlytics
import com.crashlytics.android.answers.Answers
import com.crashlytics.android.answers.CustomEvent
import io.fabric.sdk.android.Fabric
class FabricAppender : UnsynchronizedAppenderBase<ILoggingEvent>() {
companion object {
private var isFabricInit = false
fun init(context: Context) {
Fabric.with(context, Crashlytics(), Answers())
isFabricInit = true
}
}
override fun append(event: ILoggingEvent) {
if (isFabricInit.not()) return
when (event.level.levelInt) {
Level.ERROR_INT -> {
val throwable = (event.throwableProxy as ThrowableProxy).throwable
if (throwable != null) {
Crashlytics.logException(throwable)
} else {
Crashlytics.log(event.message.replace(": {}", ""))
}
}
}
}
}
This appender will send exception to Crashlytics
every time you call log.error("Something wrong happen!!")
. As you can see, you can fully customized the appender.
Init the appender when application start
class MainActivity : AppCompatActivity() {
private val log = LoggerFactory.getLogger(javaClass)!! // Call your logger in each class with this line
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
FabricAppender.init(this) // Init before the first log
log.info("Activity start")
// ...
} }
Finally
Now your fabric will be totally isolated to your code by using the slf4j
API, and will be not use during your instrumented test yataaa!!! You can find other appender on internet (send to ELK, file, etc.)