/* * * * Copyright © 2023-2025 by Navi Technologies Limited * * All rights reserved. Strictly confidential * */ package com.navi.alfred.demo import android.app.Activity import android.app.Application import android.os.Bundle import android.util.Log import com.github.anrwatchdog.ANRWatchDog import com.navi.alfred.AlfredConfig import com.navi.alfred.AlfredManager import com.navi.alfred.demo.activity.MainActivity import com.navi.alfred.demo.activity.SWWActivity import com.navi.alfred.utils.AlfredConstants import com.navi.alfred.utils.log import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch class AlfredDemoApplication : Application(), Application.ActivityLifecycleCallbacks { private var appForegroundCounter: Int = 0 override fun onCreate() { super.onCreate() registerActivityLifecycleCallbacks(this) val alfredConfig = AlfredConfig( "Alfred Demo App", "1020", "4.9.9", "qa", "oMv77fgpBg9NFGom0Psizbf7lbrdBVJz", ) AlfredManager.init(alfredConfig, this, 27, "Critical Journey") CoroutineScope(Dispatchers.IO).launch { try { AlfredManager.getAlfredCruiseInfo( cruiseApiSuccessful = { response -> Log.d( "Alfred", "Alfred - getAlfredCruiseInfo cruiseApiSuccessful h response = $response", ) } ) } catch (e: Exception) { e.log() } } // Dumping anr data to click stream ANRWatchDog() .setIgnoreDebugger(true) .setReportMainThreadOnly() .setANRListener { if (it.cause?.stackTrace.isNullOrEmpty()) { return@setANRListener } val className = it.cause?.stackTrace?.get(0)?.className.orEmpty() val anrEventProperties = mutableMapOf( "SCREEN_NAME" to ("Alfred Demo App"), "METHOD_NAME" to it.cause?.stackTrace?.get(0)?.methodName.orEmpty(), "LINE_NUMBER" to it.cause?.stackTrace?.get(0)?.lineNumber.toString(), "APP_IN_FOREGROUND" to isAppInForeground().toString(), ) anrEventProperties["STACK_TRACE"] = it.cause?.stackTrace?.get(0).toString() AlfredManager.handleAnrEvent(anrEventProperties) } .start() // Crash Reporting to backend val defaultHandler = Thread.getDefaultUncaughtExceptionHandler() Thread.setDefaultUncaughtExceptionHandler { thread, exception -> if (exception.stackTrace.isNullOrEmpty()) { defaultHandler?.uncaughtException(thread, exception) return@setDefaultUncaughtExceptionHandler } try { val crashEventProperties = mutableMapOf( "SCREEN_NAME" to ("Alfred Demo App"), "METHOD_NAME" to exception.stackTrace[0]?.methodName.orEmpty(), "LINE_NUMBER" to exception.stackTrace[0]?.lineNumber.toString(), "APP_IN_FOREGROUND" to isAppInForeground().toString(), ) exception.stackTrace[0]?.let { stackTraceElement -> crashEventProperties["STACK_TRACE"] = stackTraceElement.toString() } AlfredManager.handleCrashEvent(crashEventProperties) } finally { defaultHandler?.uncaughtException(thread, exception) } } } override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {} override fun onActivityStarted(activity: Activity) { appForegroundCounter++ } override fun onActivityResumed(activity: Activity) { if (appForegroundCounter > 0) { alfredOnActivityResumed(activity) } } override fun onActivityPaused(activity: Activity) {} override fun onActivityStopped(activity: Activity) { appForegroundCounter-- if (appForegroundCounter == 0) { AlfredManager.stopRecording() } } override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {} override fun onActivityDestroyed(activity: Activity) {} private fun alfredOnActivityResumed(activity: Activity) { val screenName: String? val moduleName: String? when (activity) { is MainActivity -> { screenName = "NaviApp_HomePage_Lands" moduleName = "Demo App" } is SWWActivity -> { screenName = "NaviApp_HomePage_Lands" moduleName = "Demo App" } else -> { screenName = AlfredConstants.THIRD_PARTY_SCREEN moduleName = AlfredConstants.THIRD_PARTY_MODULE } } try { AlfredManager.onActivityResumed( activity = activity, screenName = screenName, moduleName = moduleName, applicationContext = applicationContext, ) } catch (e: Exception) { e.log() } } private fun isAppInForeground(): Boolean { return appForegroundCounter >= 1 } }