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:
committed by
Shivam Goyal
parent
b25968983a
commit
d417719cbf
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
213
app/src/main/java/com/alfred/demo/MainApplication.kt
Normal file
213
app/src/main/java/com/alfred/demo/MainApplication.kt
Normal 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")
|
||||
}
|
||||
}
|
||||
23
app/src/main/java/com/alfred/demo/activity/DemoActivity.kt
Normal file
23
app/src/main/java/com/alfred/demo/activity/DemoActivity.kt
Normal 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)
|
||||
}
|
||||
}
|
||||
32
app/src/main/java/com/alfred/demo/activity/MainActivity.kt
Normal file
32
app/src/main/java/com/alfred/demo/activity/MainActivity.kt
Normal 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)
|
||||
}
|
||||
}
|
||||
11
app/src/main/res/layout/activity_demo.xml
Normal file
11
app/src/main/res/layout/activity_demo.xml
Normal 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>
|
||||
20
app/src/main/res/layout/activity_main.xml
Normal file
20
app/src/main/res/layout/activity_main.xml
Normal 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>
|
||||
20
app/src/main/res/layout/anr_screen.xml
Normal file
20
app/src/main/res/layout/anr_screen.xml
Normal 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>
|
||||
21
app/src/main/res/layout/app_background_screen.xml
Normal file
21
app/src/main/res/layout/app_background_screen.xml
Normal 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>
|
||||
20
app/src/main/res/layout/crash_screen.xml
Normal file
20
app/src/main/res/layout/crash_screen.xml
Normal 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>
|
||||
36
app/src/main/res/layout/third_party_screen.xml
Normal file
36
app/src/main/res/layout/third_party_screen.xml
Normal 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>
|
||||
@@ -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>
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {}
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user