diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index e1eea1d..7e340a7 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 9f71c83..773fe0f 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,3 @@
-
diff --git a/navi-alfred/src/main/java/com/navi/alfred/AlfredConfig.kt b/navi-alfred/src/main/java/com/navi/alfred/AlfredConfig.kt
index 4dac4b7..35c62bf 100644
--- a/navi-alfred/src/main/java/com/navi/alfred/AlfredConfig.kt
+++ b/navi-alfred/src/main/java/com/navi/alfred/AlfredConfig.kt
@@ -10,7 +10,8 @@ package com.navi.alfred
import android.os.Build
import android.provider.Settings
import android.text.TextUtils
-import com.navi.alfred.utils.*
+import com.navi.alfred.utils.AlfredConstants
+import com.navi.alfred.utils.getCarrierName
import java.util.*
data class AlfredConfig(
private var appVersionCode: String = "",
@@ -39,13 +40,17 @@ data class AlfredConfig(
private var cpuEnableStatus: Boolean = false,
private var memoryEnableStatus: Boolean = false,
private var metricsApiEnableStatus: Boolean = false,
+ private var apiResponseEnableStatus:Boolean=false,
+ private var apiRequestEnableStatus:Boolean=false,
+ private var enabledApiPath: List? = null,
var batteryPercentageBeforeEventStart: Float? = null,
private var disableScreenList: List? = null,
private var disableModuleList: List? = null,
private var snapshotPerSecond: Int = 1,
private var enableAlfred: Boolean = false,
- private var firebaseControlledCruise: Boolean = false,
- private var disableChucker:Boolean=true
+ private var disableDialogScreenShot: Boolean = false,
+ private var zipFileName: String? = null,
+ private var disableAlfredLogs: Boolean = true
) {
@@ -96,11 +101,6 @@ data class AlfredConfig(
fun setAlfredStatus(enable: Boolean) {
this.enableAlfred = enable
}
- fun getFirebaseControlledCruise(): Boolean = this.firebaseControlledCruise
-
- fun setFirebaseControlledCruise(firebaseControlledCruise: Boolean) {
- this.firebaseControlledCruise = firebaseControlledCruise
- }
fun setEnableRecordingStatus(enableRecording: Boolean) {
this.enableRecording = enableRecording
@@ -133,10 +133,10 @@ data class AlfredConfig(
fun getNetworkCarrier(): String? = getCarrierName(AlfredManager.applicationContext)
- fun getNetworkType(): String = getNetworkType(AlfredManager.applicationContext)
+ fun getNetworkType(): String = com.navi.alfred.utils.getNetworkType(AlfredManager.applicationContext)
fun getBatteryPercentage(): Float =
- getBatteryPercentageForDevice(AlfredManager.applicationContext)
+ com.navi.alfred.utils.getBatteryPercentage(AlfredManager.applicationContext)
fun getUserId(): String? = userId
@@ -173,12 +173,12 @@ data class AlfredConfig(
this.batteryPercentageBeforeEventStart = getBatteryPercentage()
}
- fun getCpuUsage(): Float = getCpuUsageForDevice()
+ fun getCpuUsage(): Float = getCpuUsage()
- fun getMemoryUsage(): Float = getMemoryUsageForDevice()
+ fun getMemoryUsage(): Float = getMemoryUsage()
fun getStorageUsage(): Float {
- val (totalSize, freeSize) = getStorageUsageForDevice(context = AlfredManager.applicationContext)
+ val (totalSize, freeSize) = com.navi.alfred.utils.getStorageUsage(context = AlfredManager.applicationContext)
return (totalSize - freeSize).toFloat()
}
@@ -229,5 +229,38 @@ data class AlfredConfig(
}
fun getMetricsApiEnableStatus(): Boolean = this.metricsApiEnableStatus
- fun getDisableChuckerStatus(): Boolean = this.disableChucker
+ fun setApiResponseEnableStatus(status: Boolean) {
+ this.apiResponseEnableStatus = status
+ }
+ fun getApiResponseEnableStatus(): Boolean = this.apiResponseEnableStatus
+
+ fun setApiRequestEnableStatus(status: Boolean) {
+ this.apiRequestEnableStatus = status
+ }
+ fun getApiRequestEnableStatus(): Boolean = this.apiRequestEnableStatus
+
+ fun setEnabledApiPath(enabledApiPath: List?) {
+ this.enabledApiPath = enabledApiPath
+ }
+ fun getEnabledApiPath():Set? = this.enabledApiPath?.toSet()
+
+ fun setDisableDialogScreenShot(status: Boolean){
+ this.disableDialogScreenShot=status
+ }
+
+ fun getDisableDialogScreenShot(): Boolean {
+ return this.disableDialogScreenShot
+ }
+
+ fun setZipFileName(zipFileName: String) {
+ this.zipFileName = zipFileName
+ }
+
+ fun getZipFileName(): String? = this.zipFileName
+
+ fun clearZipFileName() {
+ this.zipFileName = ""
+ }
+
+ fun getDisableAlfredLogsStatus(): Boolean = this.disableAlfredLogs
}
diff --git a/navi-alfred/src/main/java/com/navi/alfred/AlfredManager.kt b/navi-alfred/src/main/java/com/navi/alfred/AlfredManager.kt
index f1ef8ad..ab8e383 100644
--- a/navi-alfred/src/main/java/com/navi/alfred/AlfredManager.kt
+++ b/navi-alfred/src/main/java/com/navi/alfred/AlfredManager.kt
@@ -11,6 +11,7 @@ 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
@@ -20,7 +21,6 @@ import androidx.annotation.WorkerThread
import androidx.work.*
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
-import com.navi.alfred.utils.ScreenShotStorageHelper
import com.navi.alfred.db.AlfredDatabase
import com.navi.alfred.db.AlfredDatabaseHelper
import com.navi.alfred.db.dao.ApiMetricDao
@@ -31,15 +31,38 @@ import com.navi.alfred.db.model.ApiMetricHelper
import com.navi.alfred.db.model.ScreenShotPathHelper
import com.navi.alfred.db.model.ZipDetailsHelper
import com.navi.alfred.dispatcher.AlfredDispatcher
-import com.navi.alfred.model.*
+import com.navi.alfred.model.AnalyticsRequest
+import com.navi.alfred.model.BaseAttribute
+import com.navi.alfred.model.DeviceAttributes
+import com.navi.alfred.model.EventAttribute
+import com.navi.alfred.model.EventMetricRequest
+import com.navi.alfred.model.MetricAttribute
+import com.navi.alfred.model.NaviMotionEvent
+import com.navi.alfred.model.SessionEventAttribute
+import com.navi.alfred.model.SessionRequest
+import com.navi.alfred.model.WorkManagerFailureInputData
import com.navi.alfred.network.AlfredNetworkRepository
import com.navi.alfred.network.AlfredRetrofitProvider
import com.navi.alfred.network.model.CruiseResponse
-import com.navi.alfred.utils.*
+import com.navi.alfred.utils.AlfredConstants
+import com.navi.alfred.utils.AlfredConstants.ALFRED
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.THIRD_PARTY_MODULE
+import com.navi.alfred.utils.AlfredConstants.X_TARGET
import com.navi.alfred.utils.AlfredConstants.ZIP_FILE_EXTENSION
+import com.navi.alfred.utils.ScreenShotStorageHelper
+import com.navi.alfred.utils.captureScreen
+import com.navi.alfred.utils.captureScreenshotOfCustomView
+import com.navi.alfred.utils.checkFileExists
+import com.navi.alfred.utils.clearScreenShot
+import com.navi.alfred.utils.combineScreenshots
+import com.navi.alfred.utils.createBitmapForView
+import com.navi.alfred.utils.getTouchEvent
+import com.navi.alfred.utils.insertScreenShotPathInDb
+import com.navi.alfred.utils.log
+import com.navi.alfred.utils.zip
import com.navi.alfred.worker.AddEventTask
import com.navi.alfred.worker.AddMetricTask
import com.navi.alfred.worker.UploadFileWorker
@@ -50,7 +73,6 @@ import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.Request
import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.Response
-import okio.Buffer
import java.io.File
import java.lang.reflect.Type
import java.util.*
@@ -63,7 +85,7 @@ object AlfredManager {
lateinit var config: AlfredConfig
lateinit var applicationContext: Context
private var previousTouchEvent: NaviMotionEvent = NaviMotionEvent()
- private val mutex = Mutex()
+ val mutex = Mutex()
private val coroutineDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
private val repository = AlfredNetworkRepository()
private val completableJob = Job()
@@ -75,7 +97,6 @@ object AlfredManager {
private const val imageThreshHoldValue: Int = 60
private const val imageSecondThreshHoldValue: Int = 100
private var screenShotCaptureDelay: Long = 1000L
- private var isAppInBackground: Boolean = false
private var hasRecordingStarted: Boolean = false
var dialog: Dialog? = null
private var timer: Timer? = null
@@ -83,23 +104,22 @@ object AlfredManager {
private var viewLayoutDelay: Long = 1000
private var currentScreenName: String? = null
private var currentModuleName: String? = null
- private var sessionIdForCrash: String? = null
- private var sessionStartRecordingTimeForCrash: Long? = null
- private var eventStartRecordingTimeForCrash: Long? = null
+ val workFailureData: MutableList = mutableListOf()
+ private var retryCount: Int = 0
private lateinit var zipFileDetails: List
- private val exceptionHandler = CoroutineExceptionHandler { _, exception ->
+ private val exceptionHandler = CoroutineExceptionHandler { _, _ ->
}
private val coroutineScope = CoroutineScope(Dispatchers.IO + completableJob + exceptionHandler)
fun init(config: AlfredConfig, context: Context) {
- this.config = config
- this.applicationContext = context
+ AlfredManager.config = config
+ applicationContext = context
AlfredRetrofitProvider.init(applicationContext)
startSyncEvents(context)
alfredDataBase = AlfredDatabaseHelper.getAnalyticsDatabase(applicationContext)
- this.screenShotDao = alfredDataBase.screenShotDao()
- this.zipDetailsDao = alfredDataBase.zipDetailsDao()
- this.apiMetricDao = alfredDataBase.apiMetricDao()
+ screenShotDao = alfredDataBase.screenShotDao()
+ zipDetailsDao = alfredDataBase.zipDetailsDao()
+ apiMetricDao = alfredDataBase.apiMetricDao()
}
fun startRecording(
@@ -188,15 +208,16 @@ object AlfredManager {
}
private suspend fun checkToStartZipUpload() {
- val zipFileName =
- config.getAlfredSessionId() + config.getSessionStartRecordingTime().toString()
- if (checkFileExists(
- zipFileName, applicationContext
- ) != null
- ) {
- if (!hasUploadFlowStarted) {
- hasUploadFlowStarted = true
- getPreSignedUrl(zipFileName)
+ val zipFileName = config.getZipFileName().toString()
+ if (zipFileName.isNotEmpty()) {
+ if (checkFileExists(
+ zipFileName, applicationContext
+ ) != null
+ ) {
+ if (!hasUploadFlowStarted) {
+ hasUploadFlowStarted = true
+ getPreSignedUrl(zipFileName)
+ }
}
}
}
@@ -209,6 +230,9 @@ object AlfredManager {
rootBmp: Bitmap? = null,
moduleName: String? = null
) {
+ if(config.getDisableDialogScreenShot()){
+ return
+ }
val bottomSheetView = dialog?.window?.decorView?.rootView
if (bottomSheetView != null) {
val bottomSheetCanvasForBitmap = createBitmapForView(bottomSheetView)
@@ -249,16 +273,17 @@ object AlfredManager {
private fun checkDbBeforeStartRecording() {
coroutineScope.launch(Dispatchers.IO) {
if (screenShotDao.getScreenShotCount() > 0) {
- clearScreenShot(screenShotDao.fetchAllScreenShotsPath())
screenShotDao.deleteAllScreenShot()
}
if (zipDetailsDao.getZipFilesDetailsCount() > 0) {
zipFileDetails = zipDetailsDao.fetchAllZipFilesDetails()
zipFileDetails.forEachIndexed { index, DumpZipDetailsHelper ->
- val zipFileName =
- DumpZipDetailsHelper.alfredSessionId + DumpZipDetailsHelper.sessionStartRecordingTime.toString()
- if (checkFileExists(fileName = zipFileName, applicationContext) != null) {
- getPreSignedUrl(zipFileName, true, index)
+ if (checkFileExists(
+ fileName = DumpZipDetailsHelper.zipFileName,
+ applicationContext
+ ) != null
+ ) {
+ getPreSignedUrl(DumpZipDetailsHelper.zipFileName, true, index)
} else {
zipDetailsDao.deleteZipFileDetail(DumpZipDetailsHelper.id)
}
@@ -287,8 +312,12 @@ object AlfredManager {
config.getDeviceId()
)
if (response.isSuccessful && response.code() == CODE_API_SUCCESS) {
- response.body()?.let { cruiseResponse ->
- setCruiseConfig(cruiseResponse)
+ try {
+ response.body()?.let { cruiseResponse ->
+ setCruiseConfig(cruiseResponse)
+ }
+ } catch (e: Exception) {
+ e.log()
}
}
}
@@ -334,6 +363,15 @@ object AlfredManager {
metricsConfig.disableApiPerformance?.let { api_monitor_status ->
config.setApiMetricsEnableStatus(!api_monitor_status)
}
+ metricsConfig.disableApiRequest?.let { api_request_status ->
+ config.setApiRequestEnableStatus(!api_request_status)
+ }
+ metricsConfig.disableApiResponse?.let { api_response_status ->
+ config.setApiResponseEnableStatus(!api_response_status)
+ }
+ metricsConfig.enabledApiPaths.let {enabled_api_path ->
+ config.setEnabledApiPath(enabled_api_path)
+ }
}
}
}
@@ -341,35 +379,98 @@ object AlfredManager {
}
private suspend fun getPreSignedUrl(
- zipFileName: String, dumpFlow: Boolean = false, index: Int? = null
+ zipFileName: String,
+ dumpFlow: Boolean = false,
+ index: Int? = null,
+ workManagerFlow: Boolean? = false,
+ alfredSessionId: String? = null,
+ eventStartRecordingTime: Long? = null,
+ sessionStartRecordingTime: Long? = null
) {
- config.setAlfredEventId()
- val bucketKey = config.getAlfredEventId().plus(ZIP_FILE_EXTENSION)
- val response = repository.getPreSignedUrl(bucketKey)
- if (response.isSuccessful && response.code() == CODE_API_SUCCESS) {
- checkFileExists(
- zipFileName, applicationContext
- )?.let { file ->
- response.body()?.data?.let { uploadFile(file, it, dumpFlow, index) }
- }
- } else {
- if (!dumpFlow) {
- hasUploadFlowStarted = false
- config.getEventStartRecordingTime()?.let { eventStartRecordingTime ->
- insertZipDetailsToDbForDumpingLater(
- config.getAlfredSessionId(),
- config.getSessionStartRecordingTime(),
- eventStartRecordingTime
- )
+ mutex.withLock {
+ config.setAlfredEventId()
+ val bucketKey = config.getAlfredEventId().plus(ZIP_FILE_EXTENSION)
+ val response = repository.getPreSignedUrl(bucketKey)
+ if (response.isSuccessful && response.code() == CODE_API_SUCCESS) {
+ if (workManagerFlow == true) {
+ retryCount = 0
+ }
+ checkFileExists(
+ zipFileName, applicationContext
+ )?.let { file ->
+ response.body()?.data?.let { url ->
+ uploadFile(
+ file,
+ url,
+ dumpFlow,
+ index,
+ zipFileName,
+ workManagerFlow = workManagerFlow,
+ alfredSessionId = alfredSessionId,
+ eventStartRecordingTime = eventStartRecordingTime,
+ sessionStartRecordingTime = sessionStartRecordingTime
+ )
+ }
+ }
+ } else {
+ if (!dumpFlow) {
+ hasUploadFlowStarted = false
+ config.getEventStartRecordingTime()?.let { eventStartRecordingTime ->
+ insertZipDetailsToDbForDumpingLater(
+ config.getAlfredSessionId(),
+ config.getSessionStartRecordingTime(),
+ eventStartRecordingTime,
+ zipFileName
+ )
+ }
+ config.setEventStartRecordingTime(true)
+ }
+ if (workManagerFlow == true) {
+ uploadWorkManagerFailedZip(zipFileName)
+ } else {
}
- config.setEventStartRecordingTime(true)
}
}
}
+ private fun uploadWorkManagerFailedZip(zipFileName: String) {
+ retryCount +=1
+ if (workFailureData.size > 0) {
+ val inputData = workFailureData[0]
+ WorkManager.getInstance(applicationContext).cancelWorkById(inputData.id)
+ if (retryCount <= 3) {
+ val requestData = Data.Builder()
+ .putString(AlfredConstants.ALFRED_SESSION_ID, inputData.alfredSessionId)
+ .putLong(
+ AlfredConstants.SESSION_START_RECORDING_TIME,
+ inputData.sessionStartRecordingTime
+ ).putLong(
+ AlfredConstants.EVENT_START_RECORDING_TIME,
+ inputData.eventStartRecordingTime
+ ).putString(
+ AlfredConstants.SCREENSHOT_LIST,
+ Gson().toJson(inputData.screenShots)
+ )
+ .build()
+ buildWorkManager(requestData)
+ } else {
+ insertZipDetailsToDbForDumpingLater(
+ inputData.alfredSessionId.toString(),
+ inputData.sessionStartRecordingTime,
+ inputData.eventStartRecordingTime,
+ zipFileName
+ )
+ }
+ workFailureData.removeAt(0)
+ }
+ }
+
private fun checkAndInitiateFileUploadWorkManager() {
val screenShotList = screenShotDao.fetchAllScreenShotsPath()
screenShotDao.deleteAllScreenShot()
+ ScreenShotStorageHelper.clearAll()
+ hasRecordingStarted = false
+ config.clearZipFileName()
val requestData = Data.Builder()
.putString(AlfredConstants.ALFRED_SESSION_ID, config.getAlfredSessionId())
.putLong(
@@ -380,6 +481,10 @@ object AlfredManager {
config.getEventStartRecordingTime() ?: 0L
).putString(AlfredConstants.SCREENSHOT_LIST, Gson().toJson(screenShotList))
.build()
+ buildWorkManager(requestData)
+ }
+
+ private fun buildWorkManager(requestData: Data) {
val constraints = Constraints.Builder().setRequiresBatteryNotLow(false)
.setRequiredNetworkType(NetworkType.CONNECTED).build()
val uniqueWorkName = "YOUR_UNIQUE_WORK_NAME"
@@ -391,7 +496,7 @@ object AlfredManager {
.setInputData(requestData)
.build()
WorkManager.getInstance(applicationContext)
- .beginUniqueWork(uniqueWorkName, ExistingWorkPolicy.REPLACE, uniqueWorkRequest)
+ .beginUniqueWork(uniqueWorkName, ExistingWorkPolicy.KEEP, uniqueWorkRequest)
.enqueue()
} else {
val workRequest = OneTimeWorkRequestBuilder()
@@ -404,7 +509,15 @@ object AlfredManager {
}
private suspend fun uploadFile(
- uploadFile: File, url: String, dumpFlow: Boolean = false, index: Int? = null
+ uploadFile: File,
+ url: String,
+ dumpFlow: Boolean = false,
+ index: Int? = null,
+ zipFileName: String,
+ workManagerFlow: Boolean? = false,
+ alfredSessionId: String? = null,
+ eventStartRecordingTime: Long? = null,
+ sessionStartRecordingTime: Long? = null
) {
val requestBody = uploadFile.asRequestBody("application/zip".toMediaTypeOrNull())
val uploadResponse = repository.uploadZipToS3(
@@ -412,18 +525,30 @@ object AlfredManager {
)
if (uploadResponse.isSuccessful && uploadResponse.code() == CODE_API_SUCCESS) {
uploadFile.delete()
- sendAlfredSessionEvent(dumpFlow, index)
+ if (workManagerFlow == true) {
+ retryCount = 0
+ }
+ sendAlfredSessionEvent(
+ dumpFlow, index,
+ alfredSessionId = alfredSessionId,
+ eventStartRecordingTime = eventStartRecordingTime,
+ sessionStartRecordingTime = sessionStartRecordingTime
+ )
} else {
if (!dumpFlow) {
config.getEventStartRecordingTime()?.let { eventStartRecordingTime ->
insertZipDetailsToDbForDumpingLater(
config.getAlfredSessionId(),
config.getSessionStartRecordingTime(),
- eventStartRecordingTime
+ eventStartRecordingTime,
+ zipFileName
)
}
config.setEventStartRecordingTime(true)
}
+ if (workManagerFlow == true) {
+ uploadWorkManagerFailedZip(zipFileName)
+ }
}
if (!dumpFlow) {
hasUploadFlowStarted = false
@@ -434,42 +559,24 @@ object AlfredManager {
alfredSessionId: String,
sessionStartRecordingTime: Long,
eventStartRecordingTime: Long,
- screenShotList: String? = null
+ zipFileName: String
) {
zipDetailsDao.insert(
data = ZipDetailsHelper(
alfredSessionId = alfredSessionId,
sessionStartRecordingTime = sessionStartRecordingTime,
eventStartRecordingTime = eventStartRecordingTime,
- screenShotList = screenShotList
+ zipFileName = zipFileName
)
)
}
- private fun deleteScreenShot() {
+ private fun deleteScreenShot(imagePathList: List) {
try {
- val screenShotPathList: List =
- if (screenShotDao.getScreenShotCount() >= imageThreshHoldValue) {
- screenShotDao.fetchScreenShotsPath(imageThreshHoldValue)
- } else {
- screenShotDao.fetchAllScreenShotsPath()
- }
- if (clearScreenShot(screenShotPathList)) {
- try {
- if (isAppInBackground) {
- ScreenShotStorageHelper.clearAll()
- screenShotDao.deleteAllScreenShot()
- isAppInBackground = false
- hasRecordingStarted = false
- } else {
- val idList = screenShotPathList.map { it.id }
- screenShotDao.deleteScreenShot(idList)
- ScreenShotStorageHelper.deleteKItems(idList.size)
- }
- } catch (e: Exception) {
- e.log()
- }
- }
+ clearScreenShot(imagePathList)
+ val idList = imagePathList.map { it.id }
+ screenShotDao.deleteScreenShot(idList)
+ ScreenShotStorageHelper.deleteKItems(idList.size)
} catch (e: Exception) {
e.log()
}
@@ -496,7 +603,7 @@ object AlfredManager {
AlfredConstants.DEFAULT_INGEST_METRIC_URL,
metricRequestBody = request
)
- return if (response.isSuccessful && response.code() == CODE_API_SUCCESS) {
+ return if ((response.isSuccessful && response.code() == CODE_API_SUCCESS) or (response.code() == CODE_API_BAD_REQUEST)) {
apiMetricDao.deleteApiMetric(metricEventList.map { it.id })
true
} else {
@@ -531,6 +638,31 @@ object AlfredManager {
}
}
+ fun handleScreenTransitionEvent(
+ currentScreenName: String?, previousScreenName: String?, screenTransitionDuration: Long
+ ) {
+ if (config.getAlfredStatus() && config.getMetricsApiEnableStatus()) {
+ val screenTransitionAttributes: HashMap = hashMapOf()
+ screenTransitionAttributes.apply {
+ this[AlfredConstants.CURRENT_SCREEN_NAME] = currentScreenName.orEmpty()
+ this[AlfredConstants.PREVIOUS_SCREEN_NAME] = previousScreenName.orEmpty()
+ this[AlfredConstants.LOAD_TIME] = screenTransitionDuration
+ }
+ coroutineDispatcher.executor.execute {
+ val screenTransitionEvent = buildAppPerformanceEvent(
+ eventName = AlfredConstants.SCREEN_TRANSITION_METRICS,
+ attribute = screenTransitionAttributes,
+ eventType = AlfredConstants.SCREEN_TRANSITION_METRICS
+ )
+ AlfredDispatcher.addTaskToQueue(
+ AddMetricTask(
+ screenTransitionEvent, applicationContext
+ )
+ )
+ }
+ }
+ }
+
suspend fun sendEventsToServer(
applicationContext: Context
@@ -557,7 +689,7 @@ object AlfredManager {
val response = repository.sendEvents(
config.getPostUrl(), request
)
- return if (response.isSuccessful && response.code() == CODE_API_SUCCESS) {
+ return if ((response.isSuccessful && response.code() == CODE_API_SUCCESS) or (response.code() == CODE_API_BAD_REQUEST)) {
analyticsDao.deleteEvents(analyticsEvents.map { it.eventId })
true
} else {
@@ -578,7 +710,12 @@ object AlfredManager {
return false
}
- private fun sendAlfredSessionEvent(dumpFlow: Boolean = false, index: Int? = null) {
+ private fun sendAlfredSessionEvent(
+ dumpFlow: Boolean = false, index: Int? = null,
+ alfredSessionId: String? = null,
+ eventStartRecordingTime: Long? = null,
+ sessionStartRecordingTime: Long? = null
+ ) {
var request: SessionRequest? = null
if (dumpFlow) {
var clientTs: Long? = null
@@ -590,9 +727,9 @@ object AlfredManager {
sessionTimeStamp = zipFileDetail.sessionStartRecordingTime
sessionId = zipFileDetail.alfredSessionId
} else {
- clientTs = eventStartRecordingTimeForCrash
- sessionTimeStamp = sessionStartRecordingTimeForCrash
- sessionId = sessionIdForCrash
+ clientTs = eventStartRecordingTime
+ sessionTimeStamp = sessionStartRecordingTime
+ sessionId = alfredSessionId
}
request = SessionRequest(
base_attribute = BaseAttribute(
@@ -633,6 +770,13 @@ object AlfredManager {
if (!dumpFlow) {
config.setEventStartRecordingTime(true)
handleDeviceAttributes()
+ } else {
+ index?.let { index ->
+ zipDetailsDao.deleteZipFileDetail(zipFileDetails[index].id)
+ }
+ if(workFailureData.size>0){
+ workFailureData.removeAt(0)
+ }
}
}
}
@@ -669,8 +813,19 @@ object AlfredManager {
} else {
null
}
+ var url= request.url.toString().split("?").first()
+ request.header(ALFRED)?.let {pathParam ->
+ if(url.contains(pathParam)){
+ url=url.replace(pathParam,"Path_Param_Value")
+ request.header(X_TARGET)?.let {xTarget ->
+ url=xTarget.plus(url)
+ }
+ }
+ }
+ Log.d("ALFREDAPI","URL$url")
+ Log.d("ALFREDAPI","RESPONSE BODY${response.message}")
val attributes = hashMapOf().apply {
- this[AlfredConstants.URL] = request.url.toString()
+ this[AlfredConstants.URL] = url
this[AlfredConstants.METHOD] = request.method
this[AlfredConstants.RESPONSE_CODE] = response.code
this[AlfredConstants.ERROR_MESSAGE] = errorMessage.toString()
@@ -680,6 +835,22 @@ object AlfredManager {
this[AlfredConstants.DURATION_IN_MS] = duration.toDouble()
this[AlfredConstants.BYTES_RECEIVED] = byteReceived
this[AlfredConstants.BYTES_SENT] = byteSent
+ if (config.getApiResponseEnableStatus()) {
+ if (response.code != CODE_API_SUCCESS || config.getEnabledApiPath()
+ ?.contains(url) == true
+ ) {
+ Log.d("ALFREDAPI","response${response.body.toString()}")
+ this[AlfredConstants.RESPONSE_BODY] = response.body.toString()
+ }
+ }
+ if (config.getApiRequestEnableStatus()) {
+ if (response.code != CODE_API_SUCCESS || config.getEnabledApiPath()
+ ?.contains(url) == true
+ ) {
+ Log.d("ALFREDAPI","request${request.body.toString()}")
+ this[AlfredConstants.REQUEST_BODY] = request.body.toString()
+ }
+ }
}
val appPerformanceEvent = buildAppPerformanceEvent(
AlfredConstants.API_METRIC_EVENT_NAME, API_METRICS, attributes
@@ -693,18 +864,12 @@ object AlfredManager {
}
}
-
fun stopRecording(appBackgroundView: View) {
- isAppInBackground = true
hasRecordingStarted = false
screenShotTimer?.cancel()
- if (config.getFirebaseControlledCruise()) {
- deleteScreenShot()
- } else {
- if (config.getAlfredStatus() && config.getEnableRecordingStatus()) {
- if (ScreenShotStorageHelper.images.size > 0) {
- startAnrCrashZipUpload(appBackgroundView)
- }
+ if (config.getAlfredStatus() && config.getEnableRecordingStatus()) {
+ if (ScreenShotStorageHelper.images.size > 0) {
+ startAnrCrashZipUpload(appBackgroundView)
}
}
}
@@ -717,9 +882,6 @@ object AlfredManager {
eventStartRecordingTime: Long? = null,
index: Int? = null
) {
- sessionIdForCrash = alfredSessionId
- sessionStartRecordingTimeForCrash = sessionStartRecordingTime
- eventStartRecordingTimeForCrash = eventStartRecordingTime
val fileList = ArrayList()
imagePathList.forEach { screenShotPathHelper ->
screenShotPathHelper.screenShotPath?.let { screenShotPath ->
@@ -731,15 +893,25 @@ object AlfredManager {
val zipFilePath = applicationContext.filesDir.path + "/" + zipFileName
if (zip(fileList, zipFilePath) == true) {
clearScreenShot(imagePathList)
- getPreSignedUrl(zipFileName, true, index = index)
+ getPreSignedUrl(
+ zipFileName,
+ index = index,
+ workManagerFlow = true,
+ dumpFlow = true,
+ alfredSessionId = alfredSessionId,
+ eventStartRecordingTime = eventStartRecordingTime,
+ sessionStartRecordingTime = sessionStartRecordingTime
+ )
}
}
private fun toZip(
imagePathList: List
) {
+ val zipFileName = config.getAlfredSessionId() + UUID.randomUUID().toString()
+ config.setZipFileName(zipFileName)
val zipFilePath: String =
- applicationContext.filesDir.path + "/" + config.getAlfredSessionId() + config.getSessionStartRecordingTime()
+ applicationContext.filesDir.path + "/" + zipFileName
val fileList = ArrayList()
imagePathList.forEach { screenShotPathHelper ->
screenShotPathHelper.screenShotPath?.let { screenShotPath ->
@@ -749,12 +921,11 @@ object AlfredManager {
}
}
if (zip(fileList, zipFilePath) == true) {
- deleteScreenShot()
+ deleteScreenShot(imagePathList)
config.setNextEventStartRecordingTime()
}
}
-
fun handleTouchEvent(
currentTouchEvent: MotionEvent?,
screenName: String? = null,
@@ -807,46 +978,22 @@ object AlfredManager {
}
}
- fun handleScreenTransitionEvent(
- currentScreenName: String?, previousScreenName: String?, screenTransitionDuration: Long
- ) {
- if (config.getAlfredStatus() && config.getMetricsApiEnableStatus()) {
- val screenTransitionAttributes: HashMap = hashMapOf()
- screenTransitionAttributes.apply {
- this[AlfredConstants.CURRENT_SCREEN_NAME] = currentScreenName.orEmpty()
- this[AlfredConstants.PREVIOUS_SCREEN_NAME] = previousScreenName.orEmpty()
- this[AlfredConstants.LOAD_TIME] = screenTransitionDuration
- }
- coroutineDispatcher.executor.execute {
- val screenTransitionEvent = buildAppPerformanceEvent(
- eventName = AlfredConstants.SCREEN_TRANSITION_METRICS,
- attribute = screenTransitionAttributes,
- eventType = AlfredConstants.SCREEN_TRANSITION_METRICS
- )
- AlfredDispatcher.addTaskToQueue(
- AddMetricTask(
- screenTransitionEvent, applicationContext
- )
- )
- }
- }
- }
-
fun handleAnrEvent(
anrEventProperties: Map, anrView: View, screenName: String? = null
) {
startAnrCrashZipUpload(anrView)
- coroutineDispatcher.executor.execute {
- val event = buildEvent(
- AlfredConstants.ANR_EVENT, anrEventProperties as HashMap,
- screenName = screenName,
- moduleName = currentModuleName
- )
- AlfredDispatcher.addTaskToQueue(AddEventTask(event, this.applicationContext))
+ if (config.getAlfredSessionId().isNotEmpty()) {
+ coroutineDispatcher.executor.execute {
+ val event = buildEvent(
+ AlfredConstants.ANR_EVENT, anrEventProperties as HashMap,
+ screenName = screenName,
+ moduleName = currentModuleName
+ )
+ AlfredDispatcher.addTaskToQueue(AddEventTask(event, applicationContext))
+ }
}
}
-
fun handleSWWEvent(
screenName: String? = null, swwEventProperties: Map
) {
@@ -871,14 +1018,16 @@ object AlfredManager {
screenName: String? = null
) {
startAnrCrashZipUpload(crashView)
- coroutineDispatcher.executor.execute {
- val event = buildEvent(
- AlfredConstants.CRASH_ANALYTICS_EVENT,
- crashEventProperties as HashMap,
- screenName = screenName,
- moduleName = currentModuleName
- )
- AlfredDispatcher.addTaskToQueue(AddEventTask(event, applicationContext))
+ if (config.getAlfredSessionId().isNotEmpty()) {
+ coroutineDispatcher.executor.execute {
+ val event = buildEvent(
+ AlfredConstants.CRASH_ANALYTICS_EVENT,
+ crashEventProperties as HashMap,
+ screenName = screenName,
+ moduleName = currentModuleName
+ )
+ AlfredDispatcher.addTaskToQueue(AddEventTask(event, applicationContext))
+ }
}
}
diff --git a/navi-alfred/src/main/java/com/navi/alfred/db/AlfredDatabase.kt b/navi-alfred/src/main/java/com/navi/alfred/db/AlfredDatabase.kt
index 9f6b06a..1678581 100644
--- a/navi-alfred/src/main/java/com/navi/alfred/db/AlfredDatabase.kt
+++ b/navi-alfred/src/main/java/com/navi/alfred/db/AlfredDatabase.kt
@@ -19,7 +19,7 @@ import com.navi.alfred.db.model.ZipDetailsHelper
@Database(
entities = [AnalyticsEvent::class, ScreenShotPathHelper::class, ZipDetailsHelper::class, ApiMetricHelper::class],
- version = 2,
+ version = 3,
exportSchema = true
)
diff --git a/navi-alfred/src/main/java/com/navi/alfred/db/model/AlfredEntity.kt b/navi-alfred/src/main/java/com/navi/alfred/db/model/AlfredEntity.kt
index e4f5a99..2001a8b 100644
--- a/navi-alfred/src/main/java/com/navi/alfred/db/model/AlfredEntity.kt
+++ b/navi-alfred/src/main/java/com/navi/alfred/db/model/AlfredEntity.kt
@@ -35,7 +35,7 @@ data class ZipDetailsHelper(
@ColumnInfo(name = "alfredSessionId") val alfredSessionId: String,
@ColumnInfo(name = "sessionStartRecordingTime") val sessionStartRecordingTime: Long,
@ColumnInfo(name = "eventStartRecordingTime") val eventStartRecordingTime: Long,
- @ColumnInfo(name = "screenShotList") val screenShotList: String?
+ @ColumnInfo(name = "zipFileName") val zipFileName: String
) {
@PrimaryKey(autoGenerate = true)
var id: Int = 0
diff --git a/navi-alfred/src/main/java/com/navi/alfred/model/ErrorMessage.kt b/navi-alfred/src/main/java/com/navi/alfred/model/ErrorMessage.kt
new file mode 100644
index 0000000..c6fa755
--- /dev/null
+++ b/navi-alfred/src/main/java/com/navi/alfred/model/ErrorMessage.kt
@@ -0,0 +1,18 @@
+package com.navi.alfred.model
+
+import com.navi.alfred.db.model.ScreenShotPathHelper
+import java.util.*
+
+
+data class ErrorMessage(
+ var statusCode: Int? = null,
+ var message: String? = null
+)
+
+data class WorkManagerFailureInputData(
+ var alfredSessionId: String? = "",
+ var sessionStartRecordingTime: Long = 0L,
+ var eventStartRecordingTime: Long = 0L,
+ var screenShots: List = emptyList(),
+ val id: UUID
+)
\ No newline at end of file
diff --git a/navi-alfred/src/main/java/com/navi/alfred/network/AlfredNetworkRepository.kt b/navi-alfred/src/main/java/com/navi/alfred/network/AlfredNetworkRepository.kt
index b66c439..904ae9a 100644
--- a/navi-alfred/src/main/java/com/navi/alfred/network/AlfredNetworkRepository.kt
+++ b/navi-alfred/src/main/java/com/navi/alfred/network/AlfredNetworkRepository.kt
@@ -7,6 +7,7 @@
package com.navi.alfred.network
+import com.navi.alfred.model.AnalyticsRequest
import com.navi.alfred.model.EventMetricRequest
import com.navi.alfred.model.SessionRequest
import com.navi.alfred.network.model.CruiseResponse
@@ -17,7 +18,7 @@ import retrofit2.Response
class AlfredNetworkRepository {
suspend fun sendEvents(
- url: String, analyticsRequest: com.navi.alfred.model.AnalyticsRequest
+ url: String, analyticsRequest: AnalyticsRequest
): Response {
return AlfredRetrofitProvider.getApiService()
.sendEvents(url, "application/json", ALFRED, analyticsRequest)
diff --git a/navi-alfred/src/main/java/com/navi/alfred/network/AlfredRetrofitProvider.kt b/navi-alfred/src/main/java/com/navi/alfred/network/AlfredRetrofitProvider.kt
index 1c2971d..80842be 100644
--- a/navi-alfred/src/main/java/com/navi/alfred/network/AlfredRetrofitProvider.kt
+++ b/navi-alfred/src/main/java/com/navi/alfred/network/AlfredRetrofitProvider.kt
@@ -12,21 +12,19 @@ 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.deserializer.AnalyticsDataDeserializer
import com.navi.alfred.deserializer.MetricsDataDeserializer
import com.navi.alfred.deserializer.SessionDataDeserializer
+import com.navi.alfred.model.AnalyticsRequest
import com.navi.alfred.model.EventMetricRequest
import com.navi.alfred.model.SessionRequest
-import com.navi.alfred.utils.AlfredConstants.API_FAILURE
-import com.navi.alfred.utils.AlfredConstants.API_FAILURE_CODE
-import okhttp3.Interceptor
-import okhttp3.OkHttpClient
-import okhttp3.Response
+import com.navi.alfred.utils.handleException
+import com.navi.alfred.utils.orZero
+import okhttp3.*
+import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
-import java.io.IOException
import java.util.concurrent.TimeUnit
object AlfredRetrofitProvider {
@@ -36,26 +34,28 @@ object AlfredRetrofitProvider {
private lateinit var apiService: AlfredRetrofitService
private lateinit var okHttpClient: OkHttpClient
+
private val headerInterceptor: Interceptor
get() = Interceptor { chain ->
val request = chain.request()
- val response: Response = try {
+ val response = try {
chain.proceed(request).newBuilder().build()
- } catch (e: IOException) {
+ } catch (e: Exception) {
+ val errorMessage = handleException(e)
// A mocked response in case of n/w exception
- Response.Builder()
- .request(request)
- .code(API_FAILURE_CODE)
- .message(API_FAILURE)
- .build()
+ Response.Builder().request(request).protocol(Protocol.HTTP_2)
+ .code(errorMessage.statusCode.orZero())
+ .body(ResponseBody.create("application/json".toMediaTypeOrNull(), "{}"))
+ .message(errorMessage.message.orEmpty()).build()
}
response
}
+
fun init(context: Context) {
okHttpClient = OkHttpClient.Builder().apply {
- connectTimeout(20, TimeUnit.SECONDS).readTimeout(20, TimeUnit.SECONDS)
- if (BuildConfig.DEBUG && !AlfredManager.config.getDisableChuckerStatus()) {
+ connectTimeout(30, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).writeTimeout(30,TimeUnit.SECONDS)
+ if (BuildConfig.DEBUG && !AlfredManager.config.getDisableAlfredLogsStatus()) {
addInterceptor(loggingInterceptor())
addInterceptor(
ChuckerInterceptor.Builder(context).collector(ChuckerCollector(context))
@@ -63,6 +63,8 @@ object AlfredRetrofitProvider {
)
}
addInterceptor(headerInterceptor)
+ connectionPool(ConnectionPool(0, 5, TimeUnit.MINUTES))
+ .protocols(listOf(Protocol.HTTP_1_1))
}.build()
apiService = getRetrofit().create(AlfredRetrofitService::class.java)
}
@@ -76,7 +78,7 @@ object AlfredRetrofitProvider {
BASE_URL_DEBUG
}
val providesDeserializer = GsonBuilder().registerTypeAdapter(
- com.navi.alfred.model.AnalyticsRequest::class.java,
+ AnalyticsRequest::class.java,
AnalyticsDataDeserializer()
).registerTypeAdapter(SessionRequest::class.java, SessionDataDeserializer())
.registerTypeAdapter(EventMetricRequest::class.java, MetricsDataDeserializer()).create()
diff --git a/navi-alfred/src/main/java/com/navi/alfred/network/AlfredRetrofitService.kt b/navi-alfred/src/main/java/com/navi/alfred/network/AlfredRetrofitService.kt
index 9b82778..7dc8ee3 100644
--- a/navi-alfred/src/main/java/com/navi/alfred/network/AlfredRetrofitService.kt
+++ b/navi-alfred/src/main/java/com/navi/alfred/network/AlfredRetrofitService.kt
@@ -7,6 +7,7 @@
package com.navi.alfred.network
+import com.navi.alfred.model.AnalyticsRequest
import com.navi.alfred.model.EventMetricRequest
import com.navi.alfred.model.SessionRequest
import com.navi.alfred.network.model.CruiseResponse
@@ -27,7 +28,7 @@ interface AlfredRetrofitService {
@Url url: String,
@Header(CONTENT_TYPE) contentType: String,
@Header(X_TARGET) target: String,
- @Body analyticsRequest: com.navi.alfred.model.AnalyticsRequest
+ @Body analyticsRequest: AnalyticsRequest
): Response
@GET("ingest/session/pre-sign/{sessionId}")
diff --git a/navi-alfred/src/main/java/com/navi/alfred/network/model/CruiseResponse.kt b/navi-alfred/src/main/java/com/navi/alfred/network/model/CruiseResponse.kt
index 6bade16..ee995f8 100644
--- a/navi-alfred/src/main/java/com/navi/alfred/network/model/CruiseResponse.kt
+++ b/navi-alfred/src/main/java/com/navi/alfred/network/model/CruiseResponse.kt
@@ -37,6 +37,9 @@ data class OsConfig(
data class MetricsConfig(
@SerializedName("disable_api_performance") val disableApiPerformance: Boolean? = null,
+ @SerializedName("disable_api_response") val disableApiResponse: Boolean? = null,
+ @SerializedName("enabled_api_paths") val enabledApiPaths: List? = null,
+ @SerializedName("disable_api_request") val disableApiRequest: Boolean? = null,
@SerializedName("disable_cpu_monitoring") val disableCpuMonitoring: Boolean? = null,
@SerializedName("disable_memory_monitoring") val disableMemoryMonitoring: Boolean? = null,
@SerializedName("disable_remote_logging") val disableRemoteLogging: Boolean? = null,
diff --git a/navi-alfred/src/main/java/com/navi/alfred/utils/AlfredConstants.kt b/navi-alfred/src/main/java/com/navi/alfred/utils/AlfredConstants.kt
index 7a412c5..93e7e4c 100644
--- a/navi-alfred/src/main/java/com/navi/alfred/utils/AlfredConstants.kt
+++ b/navi-alfred/src/main/java/com/navi/alfred/utils/AlfredConstants.kt
@@ -9,6 +9,7 @@ package com.navi.alfred.utils
object AlfredConstants {
const val CODE_API_SUCCESS = 200
+ const val CODE_API_BAD_REQUEST = 400
const val UNDERSCORE = "_"
const val ADD_EVENT_TASK = "AddEventTask"
const val ADD_API_METRIC_TASK = "AddMetricTask"
@@ -24,8 +25,6 @@ object AlfredConstants {
const val QA = "qa"
const val TOUCH_EVENT = "TOUCH_EVENT"
const val SCROLL_EVENT = "SCROLL_EVENT"
- const val SCREEN_WIDTH = "SCREEN_WIDTH"
- const val SCREEN_HEIGHT = "SCREEN_HEIGHT"
const val START_X = "START_X"
const val START_Y = "START_Y"
const val END_X = "END_X"
@@ -37,7 +36,6 @@ object AlfredConstants {
const val ALFRED_SESSION_ID = "ALFRED_SESSION_ID"
const val API_METRIC_EVENT_NAME = "API_METRIC_EVENT"
const val API_METRICS = "API_METRICS"
- const val SCREEN_TRANSITION_METRICS = "SCREEN_TRANSITION_METRICS"
const val SESSION_START_RECORDING_TIME = "SESSION_START_RECORDING_TIME"
const val EVENT_START_RECORDING_TIME = "EVENT_START_RECORDING_TIME"
const val URL = "url"
@@ -50,6 +48,8 @@ object AlfredConstants {
const val DURATION_IN_MS = "duration_in_ms"
const val BYTES_RECEIVED = "bytes_received"
const val BYTES_SENT = "bytes_sent"
+ const val RESPONSE_BODY = "response_body"
+ const val REQUEST_BODY = "request_body"
const val ALFRED = "ALFRED"
const val CONTENT_TYPE = "Content-Type"
const val X_TARGET = "X-Target"
@@ -65,15 +65,15 @@ object AlfredConstants {
const val REASON = "REASON"
const val CODE = "CODE"
const val STATUS_CODE = "STATUS_CODE"
- const val EVENT_DB_NAME = "navi-analytics"
- const val ZIP_FILE_EXTENSION = ".zip"
- const val IMAGE_FILE_EXTENSION = ".jpeg"
- const val SYNC_EVENT_TASK = "SyncEventTask"
+ const val WORKER_ZIP_FILENAME_ENDPOINT = "WORKER_ZIP_FILENAME_ENDPOINT"
+ const val DISABLE_ALFRED_LOGS = "DISABLE_ALFRED_LOGS"
+ const val DISABLE_CDN_LOGS = "DISABLE_CDN_LOGS"
const val CURRENT_SCREEN_NAME = "current_screen_name"
const val PREVIOUS_SCREEN_NAME = "previous_screen_name"
const val LOAD_TIME = "load_time_in_ms"
- const val DISABLE_CHUCKER = "DISABLE_CHUCKER"
- const val API_FAILURE = "API_FAILURE"
- const val API_FAILURE_CODE = 300
-
+ const val SCREEN_TRANSITION_METRICS = "SCREEN_TRANSITION_METRICS"
+ const val ZIP_FILE_EXTENSION = ".zip"
+ const val SYNC_EVENT_TASK = "SyncEventTask"
+ const val IMAGE_FILE_EXTENSION = ".jpeg"
+ const val EVENT_DB_NAME = "navi-analytics"
}
diff --git a/navi-alfred/src/main/java/com/navi/alfred/utils/AlfredHelper.kt b/navi-alfred/src/main/java/com/navi/alfred/utils/AlfredHelper.kt
deleted file mode 100644
index c7f2584..0000000
--- a/navi-alfred/src/main/java/com/navi/alfred/utils/AlfredHelper.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.navi.alfred.utils
-
-import com.google.firebase.crashlytics.FirebaseCrashlytics
-
-object AlfredHelper {
-
- fun recordException(e: Throwable) {
- FirebaseCrashlytics.getInstance().recordException(e)
- }
-}
\ No newline at end of file
diff --git a/navi-alfred/src/main/java/com/navi/alfred/utils/ApiConstants.kt b/navi-alfred/src/main/java/com/navi/alfred/utils/ApiConstants.kt
new file mode 100644
index 0000000..03bc444
--- /dev/null
+++ b/navi-alfred/src/main/java/com/navi/alfred/utils/ApiConstants.kt
@@ -0,0 +1,13 @@
+package com.navi.alfred.utils
+
+object ApiConstants {
+ const val API_CONNECT_TIMEOUT_VALUE = 20L
+ const val API_SUCCESS_CODE = 200
+ const val API_CODE_ERROR = 20
+ const val NO_INTERNET = 23
+ const val API_CODE_SOCKET_TIMEOUT = 24
+ const val API_WRONG_ERROR_RESPONSE = 25
+ const val API_CODE_UNKNOWN_HOST = 21
+ const val API_CODE_CONNECT_EXCEPTION = 22
+ const val API_CODE_SOCKET = 26
+}
\ No newline at end of file
diff --git a/navi-alfred/src/main/java/com/navi/alfred/utils/Ext.kt b/navi-alfred/src/main/java/com/navi/alfred/utils/Ext.kt
new file mode 100644
index 0000000..f6fdec8
--- /dev/null
+++ b/navi-alfred/src/main/java/com/navi/alfred/utils/Ext.kt
@@ -0,0 +1,5 @@
+package com.navi.alfred.utils
+
+fun Int?.orZero() = this ?: 0
+
+fun Boolean?.orFalse() = this ?: false
\ No newline at end of file
diff --git a/navi-alfred/src/main/java/com/navi/alfred/utils/NetworkUtils.kt b/navi-alfred/src/main/java/com/navi/alfred/utils/NetworkUtils.kt
new file mode 100644
index 0000000..7313e49
--- /dev/null
+++ b/navi-alfred/src/main/java/com/navi/alfred/utils/NetworkUtils.kt
@@ -0,0 +1,59 @@
+/*
+ *
+ * * Copyright © 2022-2023 by Navi Technologies Limited
+ * * All rights reserved. Strictly confidential
+ *
+ */
+
+package com.navi.alfred.utils
+
+import com.google.gson.JsonParseException
+import com.navi.alfred.AlfredManager
+import com.navi.alfred.model.ErrorMessage
+import java.net.ConnectException
+import java.net.NetworkInterface
+import java.net.SocketException
+import java.net.SocketTimeoutException
+import java.net.UnknownHostException
+
+
+fun handleException(e: Throwable): ErrorMessage {
+ val errorMessage = ErrorMessage()
+ if (!isNetworkAvailable(AlfredManager.applicationContext)) {
+ errorMessage.statusCode = ApiConstants.NO_INTERNET
+ } else if (e is ConnectException) {
+ errorMessage.statusCode = ApiConstants.API_CODE_CONNECT_EXCEPTION
+ } else if (e is UnknownHostException) {
+ errorMessage.statusCode = ApiConstants.API_CODE_UNKNOWN_HOST
+ } else if (e is SocketTimeoutException) {
+ errorMessage.statusCode = ApiConstants.API_CODE_SOCKET_TIMEOUT
+ } else if (e is JsonParseException) {
+ errorMessage.statusCode = ApiConstants.API_WRONG_ERROR_RESPONSE
+ } else if (e is SocketException) {
+ errorMessage.statusCode = ApiConstants.API_CODE_SOCKET
+ }
+ else {
+ errorMessage.statusCode = ApiConstants.API_CODE_ERROR
+ }
+ errorMessage.message = e.message.toString()
+ return errorMessage
+}
+
+fun getIPAddress(): String? {
+ try {
+ val networkInterfaces = NetworkInterface.getNetworkInterfaces()
+ while (networkInterfaces.hasMoreElements()) {
+ val networkInterface = networkInterfaces.nextElement()
+ val inetAddresses = networkInterface.inetAddresses
+ while (inetAddresses.hasMoreElements()) {
+ val inetAddress = inetAddresses.nextElement()
+ if (!inetAddress.isLoopbackAddress && !inetAddress.isLinkLocalAddress && inetAddress.isSiteLocalAddress) {
+ return inetAddress.hostAddress
+ }
+ }
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ return null
+}
\ No newline at end of file
diff --git a/navi-alfred/src/main/java/com/navi/alfred/utils/Utils.kt b/navi-alfred/src/main/java/com/navi/alfred/utils/Utils.kt
index 0fb6b88..e1ad44c 100644
--- a/navi-alfred/src/main/java/com/navi/alfred/utils/Utils.kt
+++ b/navi-alfred/src/main/java/com/navi/alfred/utils/Utils.kt
@@ -19,12 +19,13 @@ import android.os.StatFs
import android.telephony.TelephonyManager
import android.view.MotionEvent
import android.view.View
-import com.navi.alfred.utils.ScreenShotStorageHelper
+import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.navi.alfred.AlfredManager
import com.navi.alfred.db.AlfredDatabaseHelper
import com.navi.alfred.db.model.ScreenShotPathHelper
import com.navi.alfred.model.NaviMotionEvent
import com.navi.alfred.utils.AlfredConstants.IMAGE_FILE_EXTENSION
+import com.navi.alfred.utils.AlfredConstants.UNDERSCORE
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -34,7 +35,6 @@ import java.io.*
import java.lang.Math.subtractExact
import java.util.*
import java.util.zip.ZipEntry
-import java.util.zip.ZipFile
import java.util.zip.ZipOutputStream
import kotlin.math.abs
@@ -82,17 +82,21 @@ fun combineScreenshots(
}
var screenWidth = Resources.getSystem().displayMetrics.widthPixels / 2
var screenHeight = Resources.getSystem().displayMetrics.heightPixels / 2
- if (!isResolutionEven(screenWidth, screenHeight)) {
- screenHeight += 1
+ if (!isResolutionEven(screenWidth)) {
screenWidth += 1
}
+ if (!isResolutionEven(screenHeight)) {
+ screenHeight += 1
+ }
val combinedBitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888)
val canvas = Canvas(combinedBitmap)
canvas.drawBitmap(backgroundScreenshot, 0f, 0f, null)
var bottomSheetLeft = (screenWidth - bottomSheetScreenshot.width) / 2f
var bottomSheetTop = screenHeight - bottomSheetScreenshot.height.toFloat()
- if (!isResolutionEven(bottomSheetLeft.toInt(), bottomSheetTop.toInt())) {
+ if (!isResolutionEven(bottomSheetLeft.toInt())) {
bottomSheetLeft = (bottomSheetLeft.toInt() + 1).toFloat()
+ }
+ if (!isResolutionEven(bottomSheetTop.toInt())) {
bottomSheetTop = (bottomSheetTop.toInt() + 1).toFloat()
}
canvas.drawBitmap(bottomSheetScreenshot, bottomSheetLeft, bottomSheetTop, null)
@@ -169,8 +173,10 @@ fun createBitmapForView(view: View): Pair