Skip to content

Instantly share code, notes, and snippets.

@avisper
Created July 27, 2020 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save avisper/62c2470e53baa07bf6f7f6f5ce123b13 to your computer and use it in GitHub Desktop.
Save avisper/62c2470e53baa07bf6f7f6f5ce123b13 to your computer and use it in GitHub Desktop.
MyCrashlyics some classes
interface IDbClient {
fun saveCrashReport(throwable: Throwable)
fun loadExceptions( ): List<ExceptionEntity>
}
class DbClient(context: Context) : IDbClient {
private var appDatabase: AppDatabase = create(context, false)
private var exceptionDAO: ExceptionDAO
init {
exceptionDAO = appDatabase.exceptionDao()
}
override fun loadExceptions( ): List<ExceptionEntity> {
return exceptionDAO.getAllExceptions()
}
override fun saveCrashReport(throwable: Throwable) {
val exceptionEntity = ExceptionEntity(CrashUtil.getStackTrace(throwable))
exceptionDAO.insertExceptions(exceptionEntity)
}
}
package com.avisper.mycrashlyticslib
import android.content.Context
interface IMyCrashlytics {
fun initialize(context: Context)
fun logException(throwable: Throwable)
fun report()
}
class MyCrashlytics {
companion object : IMyCrashlytics {
private var client: MyCrashlyticsClient? = null
private fun getClient(): MyCrashlyticsClient {
if (client == null) {
try {
throw Exception("Initialize MyCrashlytics : call MyCrashlytics.initialize(context)")
} catch (e: Exception) {
e.printStackTrace()
}
}
return client!!
}
override fun initialize(context: Context) {
client = MyCrashlyticsClient(context)
sendFirstTime()
}
// for caught exception
override fun logException(throwable: Throwable) {
getClient().saveCrashReport(throwable)
}
override fun report() {
getClient().report()
}
// Requirement:
// Send the reports to the server on the next application start
private fun sendFirstTime() {
getClient().report()
}
}
}
class MyCrashlyticsClient(private val context: Context) {
private val TAG = MyCrashlyticsClient::class.java.simpleName
private lateinit var dbClient: IDbClient
private lateinit var networkClient: INetworkClient
private val executor = Executors.newSingleThreadExecutor()
init {
setup()
sendFirstTime()
}
private fun setup() {
setUpExceptionHandler()
setUpDbClient()
setUpNetworkClient()
setupTimerHandler()
}
private fun setUpNetworkClient() {
networkClient = NetworkClient()
}
private fun setupTimerHandler() {
TimerController.register()
}
private fun setUpExceptionHandler() {
if (Thread.getDefaultUncaughtExceptionHandler() !is MyCrashlyticsExceptionHandler) {
Thread.setDefaultUncaughtExceptionHandler(MyCrashlyticsExceptionHandler())
}
}
private fun setUpDbClient() {
dbClient = DbClient(context)
}
// Requirement:
// Send the reports to the server on the next application start
private fun sendFirstTime() {
report()
}
fun saveCrashReport(throwable: Throwable) {
Log.e(TAG, throwable.toString())
dbClient.saveCrashReport(throwable)
}
fun report() {
executor.execute {
//load data from DB
val exceptions: List<ExceptionEntity> = dbClient.loadExceptions()
if (!exceptions.isNullOrEmpty()) {
//make a request
val request = RequestReportExceptions(exceptions)
//do report api call
val response = networkClient.report(request)
Log.v(TAG, "check the response")
//TODO delete all from db
} else {
Log.v(TAG, "the exceptions table is empty")
}
}
}
}
package com.avisper.mycrashlyticslib.data.network
import com.avisper.mycrashlyticslib.BuildConfig.BASE_URL
import com.avisper.mycrashlyticslib.data.network.request.RequestReportExceptions
import com.avisper.mycrashlyticslib.data.network.response.ResponseReportExceptions
import com.avisper.mycrashlyticslib.data.network.service.ApiService
import com.google.gson.Gson
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
interface INetworkClient {
fun report(request: RequestReportExceptions): Response<ResponseReportExceptions>
}
class NetworkClient : INetworkClient {
private var retrofit: Retrofit
private var apiService: ApiService
init {
retrofit = buildClient()
apiService = buildApiService()
}
private fun buildClient(): Retrofit {
val loggingInterceptor = HttpLoggingInterceptor()
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
val gson = Gson()
val client = OkHttpClient.Builder() //
.addInterceptor(loggingInterceptor) //
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.build()
return Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
}
private fun buildApiService(): ApiService {
val retrofit = buildClient()
return retrofit.create(ApiService::class.java)
}
override fun report(request: RequestReportExceptions): Response<ResponseReportExceptions> {
return apiService.report(request).execute()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment