Added methods for integration Alfred SDK in navi super app (#13)

Co-authored-by: Sayed Owais Ali <sayed.owais@navi.com>
This commit is contained in:
Girish Suragani
2023-10-18 13:47:21 +05:30
committed by Shivam Goyal
parent b25968983a
commit d417719cbf
21 changed files with 500 additions and 26 deletions

View File

@@ -43,6 +43,8 @@ dependencies {
implementation 'com.google.android.material:material:1.8.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0'
implementation 'com.google.code.gson:gson:2.8.9'
implementation project(path: ':navi-alfred')
implementation "com.github.anrwatchdog:anrwatchdog:1.4.0"
testImplementation "junit:junit:4.13.2"
androidTestImplementation "androidx.test.ext:junit:1.1.4"

View File

@@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">
<application
android:name=".MainApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
@@ -10,19 +11,23 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AlfredAndroid"
android:theme="@style/Theme.AppCompat.Light"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:name=".activity.MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.AlfredAndroid">
android:theme="@style/Theme.AppCompat.Light">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activity.DemoActivity"
android:exported="true"
android:theme="@style/Theme.AppCompat.Light" />
</application>
</manifest>

View File

@@ -0,0 +1,213 @@
package com.alfred.demo
import android.app.Activity
import android.app.Application
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import androidx.appcompat.widget.AppCompatTextView
import com.alfred.demo.activity.DemoActivity
import com.alfred.demo.activity.MainActivity
import com.navi.alfred.AlfredConfig
import com.navi.alfred.AlfredManager
import com.navi.alfred.utils.AlfredConstants
import com.navi.alfred.utils.log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import com.github.anrwatchdog.ANRWatchDog
import com.navi.alfred.callbacks.NetworkCallback
import com.navi.alfred.model.ErrorMessage
import com.navi.alfred.network.AlfredRetrofitProvider
import okhttp3.Request
import okhttp3.Response
class MainApplication : Application(), Application.ActivityLifecycleCallbacks, NetworkCallback {
private var appForegroundCounter: Int = 0
override fun onCreate() {
super.onCreate()
registerActivityLifecycleCallbacks(this)
val alfredConfig = AlfredConfig(
"Alfred Demo App",
"1",
"1.0.0",
"qa",
"oMv77fgpBg9NFGom0Psizbf7lbrdBVJz"
)
AlfredManager.init(alfredConfig, this)
getAlfredCruiseInfo()
// 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()
)
if (AlfredManager.config.getAlfredStatus() && AlfredManager.config.getAnrEnableStatus()) {
anrEventProperties["STACK_TRACE"] = it.cause?.stackTrace?.get(0).toString()
val anrView =
LayoutInflater.from(applicationContext).inflate(R.layout.anr_screen, null)
AlfredManager.measureInflatedView(anrView)
AlfredManager.handleAnrEvent(anrEventProperties, anrView)
}
}.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()
)
if (AlfredManager.config.getAlfredStatus() && AlfredManager.config.getCrashEnableStatus()) {
exception.stackTrace[0]?.let { stackTraceElement ->
crashEventProperties["STACK_TRACE"] = stackTraceElement.toString()
}
val crashView =
LayoutInflater.from(applicationContext).inflate(R.layout.crash_screen, null)
AlfredManager.measureInflatedView(crashView)
AlfredManager.handleCrashEvent(crashEventProperties, crashView.rootView)
}
} 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) {
startAlfredRecording(activity)
}
}
override fun onActivityPaused(activity: Activity) {
}
override fun onActivityStopped(activity: Activity) {
appForegroundCounter--
if (appForegroundCounter == 0) {
if (AlfredManager.config.getAlfredStatus() && AlfredManager.config.getEnableRecordingStatus()) {
val appBackgroundView =
LayoutInflater.from(this)
.inflate(R.layout.app_background_screen, null)
AlfredManager.measureInflatedView(appBackgroundView)
AlfredManager.stopRecording(appBackgroundView)
}
}
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
}
override fun onActivityDestroyed(activity: Activity) {
}
private fun startAlfredRecording(activity: Activity) {
if (AlfredManager.config.getAlfredStatus() && AlfredManager.config.getEnableRecordingStatus()) {
var screenName: kotlin.String? = null
var moduleName: kotlin.String? = null
var thirdPartyScreenView: View? = null
when (activity) {
is MainActivity -> {
screenName = "MainActivity"
moduleName = "Demo App"
}
is DemoActivity -> {
screenName = "DemoActivity"
moduleName = "Demo App"
}
else -> {
screenName = AlfredConstants.THIRD_PARTY_SCREEN
moduleName = AlfredConstants.THIRD_PARTY_MODULE
thirdPartyScreenView = LayoutInflater.from(applicationContext)
.inflate(R.layout.third_party_screen, null)
AlfredManager.measureInflatedView(thirdPartyScreenView)
thirdPartyScreenView.findViewById<AppCompatTextView>(R.id.tv_third_party_name).text =
"${activity.localClassName}"
}
}
try {
AlfredManager.startRecording(
activity.applicationContext,
activity.window.decorView.rootView,
screenName,
moduleName,
thirdPartyScreenView,
onSessionIdGenerated = { sessionId ->
Log.d("Alfred", "Alfred Session ID: $sessionId")
}
)
} catch (e: Exception) {
e.log()
}
}
}
private fun isAppInForeground(): Boolean {
return appForegroundCounter >= 1
}
private fun getAlfredCruiseInfo() {
Log.d("Alfred", "Alfred - getAlfredCruiseInfo started")
CoroutineScope(Dispatchers.IO).launch {
try {
Log.d(
"Alfred",
"Alfred - getAlfredCruiseInfo started inside try thread = ${Thread.currentThread().name}"
)
AlfredManager.getCruiseConfig(cruiseApiSuccessful = { response ->
AlfredRetrofitProvider.setNetworkCallback(this@MainApplication)
Log.d(
"Alfred",
"Alfred - getAlfredCruiseInfo cruiseApiSuccessful h response = $response"
)
})
} catch (e: Exception) {
Log.d("Alfred", "Alfred - getAlfredCruiseInfo catch e = $e")
e.log()
}
}
}
override fun onNetworkRequest(request: okhttp3.Request?) {
Log.d("Alfred", "Alfred - onNetworkRequest request = $request")
}
override fun onNetworkSuccess(response: Response?) {
Log.d("Alfred", "Alfred - onNetworkSuccess response = $response")
}
override fun onNetworkFailure(
exception: Exception,
errorMessage: ErrorMessage,
request: Request
) {
Log.d("Alfred", "Alfred - onNetworkFailure exception = $exception request = $request")
}
}

View File

@@ -0,0 +1,23 @@
package com.alfred.demo.activity
import android.os.Bundle
import android.view.MotionEvent
import androidx.appcompat.app.AppCompatActivity
import com.alfred.demo.R
import com.navi.alfred.AlfredManager
class DemoActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_demo)
}
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
AlfredManager.handleTouchEvent(
ev,
screenName = "Demo Activity",
moduleName = "Alfred Demo App",
)
return super.dispatchTouchEvent(ev)
}
}

View File

@@ -0,0 +1,32 @@
package com.alfred.demo.activity
import android.content.Intent
import android.os.Bundle
import android.view.MotionEvent
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import com.alfred.demo.R
import com.navi.alfred.AlfredManager
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<Button>(R.id.button)
button.setOnClickListener {
val intent = Intent(this, DemoActivity::class.java)
startActivity(intent)
}
}
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
AlfredManager.handleTouchEvent(
ev,
screenName = "Main Activity",
moduleName = "Alfred Demo App",
)
return super.dispatchTouchEvent(ev)
}
}

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="Alfred Demo!" />
</LinearLayout>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:gravity="center"
android:text="Alfred Demo" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Open Demo Activity" />
</LinearLayout>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_anr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/anr"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_app_background"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_background"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
<TextView
android:id="@+id/tv_crash"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/crash"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_third_party"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/third_party_screen"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_third_party_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="10sp"
android:gravity="center"
android:lines="3"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_third_party"
tools:text="@string/third_party_screen" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,3 +1,7 @@
<resources>
<string name="app_name">Alfred Android</string>
<string name="crash">Crash Occurred</string>
<string name="anr">Anr Occurred</string>
<string name="app_background">App In Background</string>
<string name="third_party_screen">Third Party Screen</string>
</resources>

View File

@@ -5,7 +5,7 @@ plugins {
id 'maven-publish'
}
def VERSION_NAME = "v1.0.2"
def VERSION_NAME = "v1.0.3"
android {
namespace 'com.navi.alfred'

View File

@@ -7,19 +7,24 @@
package com.navi.alfred
import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.util.Log
import android.view.KeyEvent.ACTION_DOWN
import android.view.KeyEvent.ACTION_UP
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.annotation.WorkerThread
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.work.*
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.navi.alfred.callbacks.NetworkCallback
import com.navi.alfred.db.AlfredDatabase
import com.navi.alfred.db.AlfredDatabaseHelper
import com.navi.alfred.db.dao.ApiMetricDao
@@ -47,6 +52,7 @@ import com.navi.alfred.utils.AlfredConstants
import com.navi.alfred.utils.AlfredConstants.API_METRICS
import com.navi.alfred.utils.AlfredConstants.CODE_API_BAD_REQUEST
import com.navi.alfred.utils.AlfredConstants.CODE_API_SUCCESS
import com.navi.alfred.utils.AlfredConstants.FRAGMENT_SCREEN_NAME
import com.navi.alfred.utils.AlfredConstants.THIRD_PARTY_MODULE
import com.navi.alfred.utils.AlfredConstants.ZIP_FILE_EXTENSION
import com.navi.alfred.utils.AlfredConstants.INCREMENT_OF_ONE_MINUTE
@@ -115,6 +121,7 @@ object AlfredManager {
private val exceptionHandler = CoroutineExceptionHandler { _, _ -> }
private val coroutineScope = CoroutineScope(Dispatchers.IO + completableJob + exceptionHandler)
private var retryCount: Int = 0
private var currentActivity: WeakReference<Activity>? = null
fun init(config: AlfredConfig, context: Context) {
this.config = config
@@ -132,14 +139,18 @@ object AlfredManager {
view: View,
screenName: String? = null,
moduleName: String,
thirdPartyScreenView: View? = null
thirdPartyScreenView: View? = null,
activity: Activity? = null,
onSessionIdGenerated: (sessionId: String) -> Unit
) {
currentActivity = WeakReference(activity)
if (config.getEnableRecordingStatus().not()) {
return
}
if (!hasRecordingStarted) {
checkDbBeforeStartRecording()
config.setAlfredSessionId()
onSessionIdGenerated(config.getAlfredSessionId())
config.setSessionStartRecordingTime()
config.setEventStartRecordingTime()
handleDeviceAttributes()
@@ -322,11 +333,12 @@ object AlfredManager {
view.layout(0, 0, view.measuredWidth, view.measuredHeight)
}
fun getAlfredCruiseInfo(cruiseApiSuccessful: () -> Unit) {
fun getAlfredCruiseInfo(cruiseApiSuccessful: (response: CruiseResponse) -> Unit) {
CoroutineScope(Dispatchers.IO).launch {
try {
getCruiseConfig(cruiseApiSuccessful = {
cruiseApiSuccessful()
getCruiseConfig(cruiseApiSuccessful = {response ->
Log.d("Alfred","getAlfredCruiseInfo cruiseApiSuccessfulresponse = $response")
cruiseApiSuccessful(response)
})
} catch (e: Exception) {
e.log()
@@ -334,7 +346,7 @@ object AlfredManager {
}
}
suspend fun getCruiseConfig(cruiseApiSuccessful: () -> Unit) {
suspend fun getCruiseConfig(cruiseApiSuccessful: (response: CruiseResponse) -> Unit) {
val response =
repository.cruiseConfig(
AlfredConstants.DEFAULT_CRUISE_CONFIG_URL,
@@ -348,7 +360,7 @@ object AlfredManager {
try {
response.body()?.let { cruiseResponse ->
setCruiseConfig(cruiseResponse)
cruiseApiSuccessful()
cruiseApiSuccessful(cruiseResponse)
}
} catch (e: Exception) {
e.log()
@@ -637,6 +649,7 @@ object AlfredManager {
val response =
repository.eventMetric(
AlfredConstants.DEFAULT_INGEST_METRIC_URL,
config.getApiKey(),
metricRequestBody = request
)
return if (
@@ -982,8 +995,7 @@ object AlfredManager {
fun handleAnrEvent(
anrEventProperties: Map<String, String>,
anrView: View,
screenName: String? = null
anrView: View
) {
startAnrCrashZipUpload(anrView)
if (config.getAlfredSessionId().isNotEmpty()) {
@@ -992,7 +1004,7 @@ object AlfredManager {
buildEvent(
AlfredConstants.ANR_EVENT,
anrEventProperties as HashMap<String, String>,
screenName = screenName,
screenName = currentScreenName,
moduleName = currentModuleName
)
AlfredDispatcher.addTaskToQueue(AddEventTask(event, this.applicationContext))
@@ -1000,7 +1012,7 @@ object AlfredManager {
}
}
fun handleSWWEvent(screenName: String? = null, swwEventProperties: Map<String, String>) {
fun handleSWWEvent(swwEventProperties: Map<String, String>) {
if (config.getAlfredStatus() && config.getEnableRecordingStatus()) {
if (config.getAlfredSessionId().isNotEmpty()) {
coroutineDispatcher.executor.execute {
@@ -1008,7 +1020,7 @@ object AlfredManager {
buildEvent(
AlfredConstants.ERROR_LOG,
swwEventProperties as HashMap<String, String>,
screenName = screenName,
screenName = currentScreenName,
moduleName = currentModuleName
)
AlfredDispatcher.addTaskToQueue(AddEventTask(event, applicationContext))
@@ -1019,8 +1031,7 @@ object AlfredManager {
fun handleCrashEvent(
crashEventProperties: Map<String, String>,
crashView: View,
screenName: String? = null
crashView: View
) {
startAnrCrashZipUpload(crashView)
if (config.getAlfredSessionId().isNotEmpty()) {
@@ -1029,7 +1040,7 @@ object AlfredManager {
buildEvent(
AlfredConstants.CRASH_ANALYTICS_EVENT,
crashEventProperties as HashMap<String, String>,
screenName = screenName,
screenName = currentScreenName,
moduleName = currentModuleName
)
AlfredDispatcher.addTaskToQueue(AddEventTask(event, applicationContext))
@@ -1053,7 +1064,8 @@ object AlfredManager {
attributes = properties,
sessionId = config.getAlfredSessionId(),
screenName = screenName,
moduleName = moduleName
moduleName = moduleName,
fragmentList = getFragmentList()
)
return AnalyticsEvent(timeStamp, Gson().toJson(eventData))
}
@@ -1073,7 +1085,8 @@ object AlfredManager {
sessionId = config.getAlfredSessionId(),
attributes = attribute,
screenName = currentScreenName,
moduleName = currentModuleName
moduleName = currentModuleName,
fragmentList = getFragmentList()
)
return ApiMetricHelper(timeStamp, Gson().toJson(metricData))
}
@@ -1085,4 +1098,34 @@ object AlfredManager {
fun getCurrentScreenName(): String? {
return currentScreenName
}
private fun getFragmentList(): List<String> {
val activity = currentActivity?.get()
try {
val fragmentList = mutableListOf<String>()
if (activity is FragmentActivity) {
val fragments = activity.supportFragmentManager.fragments
fragments.forEach { fragment ->
if (!fragment.isHidden) {
val fragmentName = getFragmentName(fragment)
fragmentName?.let { fragmentList.add(it) }
}
}
}
return fragmentList
} catch (e: Exception) {
e.log()
}
return emptyList()
}
private fun getFragmentName(fragment: Fragment): String? {
fragment.arguments?.let { bundle ->
if (bundle.containsKey(FRAGMENT_SCREEN_NAME)) {
return bundle.getString(FRAGMENT_SCREEN_NAME).toString()
}
}
return null
}
}

View File

@@ -0,0 +1,11 @@
package com.navi.alfred.callbacks
import com.navi.alfred.model.ErrorMessage
import okhttp3.Request
import okhttp3.Response
interface NetworkCallback {
fun onNetworkRequest(request: Request?) {}
fun onNetworkSuccess(response: Response?) {}
fun onNetworkFailure(exception: Exception, errorMessage: ErrorMessage, request: Request) {}
}

View File

@@ -21,5 +21,6 @@ data class MetricAttribute(
@SerializedName("event_type") val eventType: String? = null,
@SerializedName("screen_name") val screenName: String? = null,
@SerializedName("module_name") val moduleName: String? = null,
@SerializedName("attributes") val attributes: HashMap<String, Any>? = null
@SerializedName("attributes") val attributes: HashMap<String, Any>? = null,
@SerializedName("fragment_list") val fragmentList: List<String>? = null
)

View File

@@ -23,7 +23,8 @@ data class EventAttribute(
@SerializedName("event_type") val eventType: String? = null,
@SerializedName("attributes") val attributes: Map<String, String>? = null,
@SerializedName("session_id") val sessionId: String? = null,
@SerializedName("module_name") val moduleName: String? = null
@SerializedName("module_name") val moduleName: String? = null,
@SerializedName("fragment_list") val fragmentList: List<String>? = null
)
data class SessionRequest(

View File

@@ -39,9 +39,9 @@ class AlfredNetworkRepository {
return AlfredRetrofitProvider.getApiService().uploadToS3(preSignedUrl, request, ALFRED)
}
suspend fun eventMetric(url: String, metricRequestBody: EventMetricRequest): Response<Unit> {
suspend fun eventMetric(url: String, apiKey: String, metricRequestBody: EventMetricRequest): Response<Unit> {
return AlfredRetrofitProvider.getApiService()
.sendMetric(url, ALFRED, "application/json", metricRequestBody)
.sendMetric(url, ALFRED, apiKey, "application/json", metricRequestBody)
}
suspend fun cruiseConfig(

View File

@@ -7,11 +7,13 @@
package com.navi.alfred.network
import android.content.Context
import android.util.Log
import com.chuckerteam.chucker.api.ChuckerCollector
import com.chuckerteam.chucker.api.ChuckerInterceptor
import com.google.gson.GsonBuilder
import com.navi.alfred.AlfredManager
import com.navi.alfred.BuildConfig
import com.navi.alfred.callbacks.NetworkCallback
import com.navi.alfred.deserializer.AnalyticsDataDeserializer
import com.navi.alfred.deserializer.MetricsDataDeserializer
import com.navi.alfred.deserializer.SessionDataDeserializer
@@ -32,15 +34,18 @@ object AlfredRetrofitProvider {
private const val BASE_URL_QA = "https://qa-alfred-ingester.np.navi-sa.in/"
private lateinit var apiService: AlfredRetrofitService
private lateinit var okHttpClient: OkHttpClient
private var callback: NetworkCallback? = null
private val headerInterceptor: Interceptor
get() = Interceptor { chain ->
val request = chain.request()
callback?.onNetworkRequest(request)
val response =
try {
chain.proceed(request).newBuilder().build()
} catch (e: Exception) {
val errorMessage = handleException(e)
callback?.onNetworkFailure(e, errorMessage, request)
// A mocked response in case of n/w exception
Response.Builder()
.request(request)
@@ -106,6 +111,10 @@ object AlfredRetrofitProvider {
return apiService
}
fun setNetworkCallback(callback: NetworkCallback) {
this.callback = callback
}
private fun loggingInterceptor() =
HttpLoggingInterceptor().apply { setLevel(HttpLoggingInterceptor.Level.BODY) }
}

View File

@@ -61,6 +61,7 @@ interface AlfredRetrofitService {
suspend fun sendMetric(
@Url url: String,
@Header(X_TARGET) target: String,
@Header(X_API_KEY) apiKey: String,
@Header(CONTENT_TYPE) contentType: String,
@Body metricRequestBody: EventMetricRequest
): Response<Unit>

View File

@@ -17,7 +17,7 @@ object AlfredConstants {
const val DEFAULT_SEND_EVENT_POST_URL = "/v2/ingest/event"
const val DEFAULT_SEND_SESSION_POST_URL = "/v2/ingest/session"
const val DEFAULT_CRUISE_CONFIG_URL = "/v2/cruise"
const val DEFAULT_INGEST_METRIC_URL = "/ingest/metrics"
const val DEFAULT_INGEST_METRIC_URL = "/v2/ingest/metrics"
const val TIMER_THREAD_NAME = "SyncTimer"
const val DEFAULT_INITIAL_DELAY = 5000L
const val DEFAULT_EVENT_DELAY_IN_SECONDS = 30
@@ -74,4 +74,5 @@ object AlfredConstants {
const val IMAGE_FILE_EXTENSION = ".jpeg"
const val SYNC_EVENT_TASK = "SyncEventTask"
const val INCREMENT_OF_ONE_MINUTE = 60000L
const val FRAGMENT_SCREEN_NAME = "fragmentScreenName"
}