Added latest alfred changes from super app repo (#9)

This commit is contained in:
Girish Suragani
2023-09-08 12:54:25 +05:30
committed by Shivam Goyal
parent 029f88c8d4
commit c2be31c426
28 changed files with 834 additions and 764 deletions

View File

@@ -1,6 +1,6 @@
/*
*
* * Copyright © 2022-2023 by Navi Technologies Limited
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
@@ -12,7 +12,9 @@ import android.provider.Settings
import android.text.TextUtils
import com.navi.alfred.utils.AlfredConstants
import com.navi.alfred.utils.getCarrierName
import com.navi.alfred.utils.getNetworkType
import java.util.*
data class AlfredConfig(
private var appVersionCode: String = "",
private var appVersionName: String = "",
@@ -40,23 +42,22 @@ 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<String>? = null,
var batteryPercentageBeforeEventStart: Float? = null,
private var disableScreenList: List<String>? = null,
private var maskingEnabledScreenList: List<String>? = null,
private var disableModuleList: List<String>? = null,
private var snapshotPerSecond: Int = 1,
private var enableAlfred: Boolean = false,
private var disableDialogScreenShot: Boolean = false,
private var zipFileName: String? = null,
private var disableAlfredLogs: Boolean = true
) {
fun getDeviceId(): String = Settings.System.getString(
AlfredManager.applicationContext.contentResolver, Settings.Secure.ANDROID_ID
)
fun getDeviceId(): String =
Settings.System.getString(
AlfredManager.applicationContext.contentResolver,
Settings.Secure.ANDROID_ID
)
fun setEventStartRecordingTime(setToNext: Boolean? = false) {
if (setToNext == true) {
@@ -133,7 +134,7 @@ data class AlfredConfig(
fun getNetworkCarrier(): String? = getCarrierName(AlfredManager.applicationContext)
fun getNetworkType(): String = com.navi.alfred.utils.getNetworkType(AlfredManager.applicationContext)
fun getNetworkType(): String = getNetworkType(AlfredManager.applicationContext)
fun getBatteryPercentage(): Float =
com.navi.alfred.utils.getBatteryPercentage(AlfredManager.applicationContext)
@@ -173,12 +174,15 @@ data class AlfredConfig(
this.batteryPercentageBeforeEventStart = getBatteryPercentage()
}
fun getCpuUsage(): Float = getCpuUsage()
fun getCpuUsage(): Float = com.navi.alfred.utils.getCpuUsage()
fun getMemoryUsage(): Float = getMemoryUsage()
fun getMemoryUsage(): Float = com.navi.alfred.utils.getMemoryUsage()
fun getStorageUsage(): Float {
val (totalSize, freeSize) = com.navi.alfred.utils.getStorageUsage(context = AlfredManager.applicationContext)
val (totalSize, freeSize) =
com.navi.alfred.utils.getStorageUsage(
context = AlfredManager.applicationContext
)
return (totalSize - freeSize).toFloat()
}
@@ -186,6 +190,10 @@ data class AlfredConfig(
this.disableScreenList = disableScreenList
}
fun setMaskingEnabledScreenList(maskingEnabledScreenList: List<String>) {
this.maskingEnabledScreenList = maskingEnabledScreenList
}
fun setDisableModuleList(disableModuleList: List<String>) {
this.disableModuleList = disableModuleList
}
@@ -212,6 +220,8 @@ data class AlfredConfig(
fun getDisableScreenList(): List<String>? = this.disableScreenList
fun getMaskingEnabledScreenList(): List<String>? = this.maskingEnabledScreenList
fun setCpuEnableStatus(status: Boolean) {
this.cpuEnableStatus = status
}
@@ -227,25 +237,11 @@ data class AlfredConfig(
fun setApiMetricsEnableStatus(status: Boolean) {
this.metricsApiEnableStatus = status
}
fun getMetricsApiEnableStatus(): Boolean = this.metricsApiEnableStatus
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<String>?) {
this.enabledApiPath = enabledApiPath
}
fun getEnabledApiPath():Set<String>? = this.enabledApiPath?.toSet()
fun setDisableDialogScreenShot(status: Boolean){
this.disableDialogScreenShot=status
fun setDisableDialogScreenShot(status: Boolean) {
this.disableDialogScreenShot = status
}
fun getDisableDialogScreenShot(): Boolean {

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/*
*
* * Copyright © 2022-2023 by Navi Technologies Limited
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
@@ -18,14 +18,22 @@ import com.navi.alfred.db.model.ScreenShotPathHelper
import com.navi.alfred.db.model.ZipDetailsHelper
@Database(
entities = [AnalyticsEvent::class, ScreenShotPathHelper::class, ZipDetailsHelper::class, ApiMetricHelper::class],
entities =
[
AnalyticsEvent::class,
ScreenShotPathHelper::class,
ZipDetailsHelper::class,
ApiMetricHelper::class
],
version = 3,
exportSchema = true
)
abstract class AlfredDatabase : RoomDatabase() {
abstract fun analyticsDao(): AnalyticsDAO
abstract fun screenShotDao(): ScreenShotDao
abstract fun zipDetailsDao(): ZipDetailsDao
abstract fun apiMetricDao(): ApiMetricDao
}

View File

@@ -21,11 +21,11 @@ object AlfredDatabaseHelper {
INSTANCE
}
val instance =
Room.databaseBuilder(context, AlfredDatabase::class.java, EVENT_DB_NAME).fallbackToDestructiveMigration()
Room.databaseBuilder(context, AlfredDatabase::class.java, EVENT_DB_NAME)
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
instance
}
}
}

View File

@@ -18,8 +18,7 @@ import com.navi.alfred.db.model.ZipDetailsHelper
@Dao
interface AnalyticsDAO {
@Insert
fun insertEvent(event: AnalyticsEvent)
@Insert fun insertEvent(event: AnalyticsEvent)
@Query("SELECT * FROM AnalyticsEvent ORDER BY time ASC LIMIT :thresholdValue")
fun fetchEvents(thresholdValue: Int): List<AnalyticsEvent>
@@ -27,9 +26,7 @@ interface AnalyticsDAO {
@Query("DELETE FROM AnalyticsEvent WHERE eventId IN (:idList)")
fun deleteEvents(idList: List<Int>)
@Query("SELECT count(*) FROM AnalyticsEvent")
fun getEventCount(): Int
@Query("SELECT count(*) FROM AnalyticsEvent") fun getEventCount(): Int
}
@Dao
@@ -47,37 +44,30 @@ interface ScreenShotDao {
@Query("DELETE FROM ScreenShotPathHelper WHERE id IN (:idList)")
fun deleteScreenShot(idList: List<Int>)
@Query("DELETE FROM ScreenShotPathHelper")
fun deleteAllScreenShot()
@Query("DELETE FROM ScreenShotPathHelper") fun deleteAllScreenShot()
@Query("SELECT count(*) FROM ScreenShotPathHelper")
fun getScreenShotCount(): Int
@Query("SELECT count(*) FROM ScreenShotPathHelper") fun getScreenShotCount(): Int
}
@Dao
interface ZipDetailsDao{
interface ZipDetailsDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(data: ZipDetailsHelper)
@Insert(onConflict = OnConflictStrategy.REPLACE) fun insert(data: ZipDetailsHelper)
@Query("SELECT count(*) FROM ZipDetailsHelper")
fun getZipFilesDetailsCount(): Int
@Query("SELECT count(*) FROM ZipDetailsHelper") fun getZipFilesDetailsCount(): Int
@Query("SELECT * FROM ZipDetailsHelper ORDER BY sessionStartRecordingTime")
fun fetchAllZipFilesDetails(): List<ZipDetailsHelper>
@Query("DELETE FROM ZipDetailsHelper WHERE id = :id")
fun deleteZipFileDetail(id: Int)
@Query("DELETE FROM ZipDetailsHelper WHERE id = :id") fun deleteZipFileDetail(id: Int)
}
@Dao
interface ApiMetricDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(data: ApiMetricHelper)
@Insert(onConflict = OnConflictStrategy.REPLACE) fun insert(data: ApiMetricHelper)
@Query("SELECT count(*) FROM ApiMetricHelper")
fun getApiMetricCount(): Int
@Query("SELECT count(*) FROM ApiMetricHelper") fun getApiMetricCount(): Int
@Query("SELECT * FROM ApiMetricHelper ORDER BY time ASC LIMIT :thresholdValue")
fun fetchApiMetric(thresholdValue: Int): List<ApiMetricHelper>

View File

@@ -1,6 +1,6 @@
/*
*
* * Copyright © 2022-2023 by Navi Technologies Limited
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
@@ -16,8 +16,7 @@ data class AnalyticsEvent(
@ColumnInfo(name = "time") val time: Long?,
@ColumnInfo(name = "details") val details: String?
) {
@PrimaryKey(autoGenerate = true)
var eventId: Int = 0
@PrimaryKey(autoGenerate = true) var eventId: Int = 0
}
@Entity
@@ -25,8 +24,7 @@ data class ScreenShotPathHelper(
@ColumnInfo(name = "time") val time: Long?,
@ColumnInfo(name = "screenShotPath") val screenShotPath: String?
) {
@PrimaryKey(autoGenerate = true)
var id: Int = 0
@PrimaryKey(autoGenerate = true) var id: Int = 0
}
@Entity
@@ -37,8 +35,7 @@ data class ZipDetailsHelper(
@ColumnInfo(name = "eventStartRecordingTime") val eventStartRecordingTime: Long,
@ColumnInfo(name = "zipFileName") val zipFileName: String
) {
@PrimaryKey(autoGenerate = true)
var id: Int = 0
@PrimaryKey(autoGenerate = true) var id: Int = 0
}
@Entity
@@ -46,8 +43,7 @@ data class ApiMetricHelper(
@ColumnInfo(name = "time") val time: Long?,
@ColumnInfo(name = "metric") val metric: String?
) {
@PrimaryKey(autoGenerate = true)
var id: Int = 0
@PrimaryKey(autoGenerate = true) var id: Int = 0
}
class Converter {
@@ -61,8 +57,4 @@ class Converter {
fun toDeviceAttributes(data: String): DeviceAttributes {
return Gson().fromJson(data, DeviceAttributes::class.java)
}
}

View File

@@ -1,3 +1,10 @@
/*
*
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.alfred.deserializer
import com.google.gson.JsonDeserializationContext
@@ -8,11 +15,13 @@ import java.lang.reflect.Type
class AnalyticsDataDeserializer : JsonDeserializer<AnalyticsRequest> {
override fun deserialize(
json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?
json: JsonElement?,
typeOfT: Type?,
context: JsonDeserializationContext?
): AnalyticsRequest? {
json?.let {
return context?.deserialize(json, AnalyticsRequest::class.java)
}
return null
}
}
}

View File

@@ -1,3 +1,10 @@
/*
*
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.alfred.deserializer
import com.google.gson.JsonDeserializationContext
@@ -8,11 +15,13 @@ import java.lang.reflect.Type
class MetricsDataDeserializer : JsonDeserializer<EventMetricRequest> {
override fun deserialize(
json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?
json: JsonElement?,
typeOfT: Type?,
context: JsonDeserializationContext?
): EventMetricRequest? {
json?.let {
return context?.deserialize(json, EventMetricRequest::class.java)
}
return null
}
}
}

View File

@@ -1,3 +1,10 @@
/*
*
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.alfred.deserializer
import com.google.gson.JsonDeserializationContext
@@ -9,11 +16,13 @@ import java.lang.reflect.Type
class SessionDataDeserializer : JsonDeserializer<SessionRequest> {
override fun deserialize(
json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?
json: JsonElement?,
typeOfT: Type?,
context: JsonDeserializationContext?
): SessionRequest? {
json?.let {
return context?.deserialize(json, EventMetricRequest::class.java)
}
return null
}
}
}

View File

@@ -1,6 +1,6 @@
/*
*
* * Copyright © 2019-2023 by Navi Technologies Limited
* * Copyright © 2021-2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
@@ -10,18 +10,15 @@ package com.navi.alfred.dispatcher
import com.navi.alfred.worker.AnalyticsTask
import com.navi.alfred.worker.AnalyticsTaskProcessor
/**
* handles task of putting events into DB and syncing data with backend
*/
/** handles task of putting events into DB and syncing data with backend */
object AlfredDispatcher {
private val taskProcessor: AnalyticsTaskProcessor = AnalyticsTaskProcessor()
fun addTaskToQueue(task: AnalyticsTask) {
taskProcessor.addTask(task)
}
/**
* Executes task in a different thread than the Queue
*/
/** Executes task in a different thread than the Queue */
fun executeInNewThread(task: AnalyticsTask) {
taskProcessor.executeInNewThread(task)
}

View File

@@ -1,13 +1,16 @@
/*
*
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
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 ErrorMessage(var statusCode: Int? = null, var message: String? = null)
data class WorkManagerFailureInputData(
var alfredSessionId: String? = "",
@@ -15,4 +18,4 @@ data class WorkManagerFailureInputData(
var eventStartRecordingTime: Long = 0L,
var screenShots: List<ScreenShotPathHelper> = emptyList(),
val id: UUID
)
)

View File

@@ -1,3 +1,10 @@
/*
*
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.alfred.model
import com.google.gson.annotations.SerializedName
@@ -16,5 +23,3 @@ data class MetricAttribute(
@SerializedName("module_name") val moduleName: String? = null,
@SerializedName("attributes") val attributes: HashMap<String, Any>? = null
)

View File

@@ -1,3 +1,10 @@
/*
*
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.alfred.model
import com.google.gson.annotations.SerializedName
@@ -21,32 +28,43 @@ data class EventAttribute(
data class SessionRequest(
@SerializedName("base_attributes") val base_attribute: BaseAttribute,
@SerializedName("session_upload_event_attributes") val session_upload_event_attributes: SessionEventAttribute
@SerializedName("session_upload_event_attributes")
val session_upload_event_attributes: SessionEventAttribute
)
data class BaseAttribute(
@SerializedName("app_version_code") val appVersionCode: String = AlfredManager.config.getAppVersionCode(),
@SerializedName("app_version_name") val appVersionName: String? = AlfredManager.config.getAppVersionName(),
@SerializedName("client_ts") val clientTs: Long? = AlfredManager.config.getEventStartRecordingTime(),
@SerializedName("app_version_code")
val appVersionCode: String = AlfredManager.config.getAppVersionCode(),
@SerializedName("app_version_name")
val appVersionName: String? = AlfredManager.config.getAppVersionName(),
@SerializedName("client_ts")
val clientTs: Long? = AlfredManager.config.getEventStartRecordingTime(),
@SerializedName("device_id") val deviceId: String? = AlfredManager.config.getDeviceId(),
@SerializedName("device_model") val deviceModel: String? = AlfredManager.config.getDeviceModel(),
@SerializedName("device_manufacturer") val deviceManufacturer: String? = AlfredManager.config.getManufacturer(),
@SerializedName("device_model")
val deviceModel: String? = AlfredManager.config.getDeviceModel(),
@SerializedName("device_manufacturer")
val deviceManufacturer: String? = AlfredManager.config.getManufacturer(),
@SerializedName("app_os") val appOs: String? = AlfredManager.config.getOs(),
@SerializedName("os_version") val osVersion: String? = AlfredManager.config.getOsVersion(),
@SerializedName("latitude") val latitude: Double? = AlfredManager.config.getLatitude(),
@SerializedName("longitude") val longitude: Double? = AlfredManager.config.getLongitude(),
@SerializedName("customer_id") val customerId: String? = AlfredManager.config.getUserId(),
@SerializedName("up_time") val upTime: Long? = null,
@SerializedName("carrier_name") val carrierName: String? = AlfredManager.config.getNetworkCarrier(),
@SerializedName("carrier_name")
val carrierName: String? = AlfredManager.config.getNetworkCarrier(),
@SerializedName("parent_session_id") val parentSessionId: String? = null,
@SerializedName("event_timestamp") val eventTimeStamp: Long? = AlfredManager.config.getEventTimeStamp(),
@SerializedName("session_id") val sessionId: String? = AlfredManager.config.getAlfredSessionId(),
@SerializedName("session_time_stamp") val sessionTimeStamp: Long? = AlfredManager.config.getSessionStartRecordingTime(),
@SerializedName("event_timestamp")
val eventTimeStamp: Long? = AlfredManager.config.getEventTimeStamp(),
@SerializedName("session_id")
val sessionId: String? = AlfredManager.config.getAlfredSessionId(),
@SerializedName("session_time_stamp")
val sessionTimeStamp: Long? = AlfredManager.config.getSessionStartRecordingTime(),
)
data class SessionEventAttribute(
@SerializedName("event_id") val eventId: String? = AlfredManager.config.getAlfredEventId(),
@SerializedName("beginning_device_attributes") val beginningDeviceAttributes: DeviceAttributes? = null,
@SerializedName("beginning_device_attributes")
val beginningDeviceAttributes: DeviceAttributes? = null,
@SerializedName("end_device_attributes") val endDeviceAttributes: DeviceAttributes? = null
)
@@ -55,4 +73,4 @@ data class DeviceAttributes(
@SerializedName("cpu") val cpu: Float? = null,
@SerializedName("storage") val storage: Float? = null,
@SerializedName("memory") val memory: Float? = null,
)
)

View File

@@ -18,7 +18,8 @@ import retrofit2.Response
class AlfredNetworkRepository {
suspend fun sendEvents(
url: String, analyticsRequest: AnalyticsRequest
url: String,
analyticsRequest: AnalyticsRequest
): Response<Unit> {
return AlfredRetrofitProvider.getApiService()
.sendEvents(url, "application/json", ALFRED, analyticsRequest)
@@ -28,37 +29,34 @@ class AlfredNetworkRepository {
return AlfredRetrofitProvider.getApiService().getPreSignedUrl(sessionId, ALFRED)
}
suspend fun sendSession(
url: String,
sessionRequest: SessionRequest
): Response<Unit> {
suspend fun sendSession(url: String, sessionRequest: SessionRequest): Response<Unit> {
return AlfredRetrofitProvider.getApiService()
.sendSession(url, "application/json", ALFRED, sessionRequest)
}
suspend fun uploadZipToS3(
preSignedUrl: String, request: RequestBody
): Response<Unit> {
suspend fun uploadZipToS3(preSignedUrl: String, request: RequestBody): Response<Unit> {
return AlfredRetrofitProvider.getApiService().uploadToS3(preSignedUrl, request, ALFRED)
}
suspend fun eventMetric(
url: String, metricRequestBody: EventMetricRequest
): Response<Unit> {
suspend fun eventMetric(url: String, metricRequestBody: EventMetricRequest): Response<Unit> {
return AlfredRetrofitProvider.getApiService()
.sendMetric(url, ALFRED, "application/json", metricRequestBody)
}
suspend fun cruiseConfig(
url: String, appVersionName: String, osVersionCode: String, deviceId: String
url: String,
appVersionName: String,
osVersionCode: String,
deviceId: String
): Response<CruiseResponse> {
return AlfredRetrofitProvider.getApiService().getCruiseConfig(
return AlfredRetrofitProvider.getApiService()
.getCruiseConfig(
url,
ALFRED,
ALFRED,
contentType = "application/json",
appVersionName = appVersionName,
osVersion = osVersionCode,
deviceId = deviceId
)
}
}
}

View File

@@ -12,10 +12,10 @@ 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.handleException
@@ -34,64 +34,79 @@ 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 = try {
chain.proceed(request).newBuilder().build()
} catch (e: Exception) {
val errorMessage = handleException(e)
// A mocked response in case of n/w exception
Response.Builder().request(request).protocol(Protocol.HTTP_2)
.code(errorMessage.statusCode.orZero())
.body(ResponseBody.create("application/json".toMediaTypeOrNull(), "{}"))
.message(errorMessage.message.orEmpty()).build()
}
val response =
try {
chain.proceed(request).newBuilder().build()
} catch (e: Exception) {
val errorMessage = handleException(e)
// A mocked response in case of n/w exception
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(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))
.alwaysReadResponseBody(false).build()
)
}
addInterceptor(headerInterceptor)
connectionPool(ConnectionPool(0, 5, TimeUnit.MINUTES))
.protocols(listOf(Protocol.HTTP_1_1))
}.build()
okHttpClient =
OkHttpClient.Builder()
.apply {
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))
.alwaysReadResponseBody(false)
.build()
)
}
addInterceptor(headerInterceptor)
connectionPool(ConnectionPool(0, 5, TimeUnit.MINUTES))
.protocols(listOf(Protocol.HTTP_1_1))
}
.build()
apiService = getRetrofit().create(AlfredRetrofitService::class.java)
}
private fun getRetrofit(): Retrofit {
val baseUrl = if (AlfredManager.config.isQa()) {
BASE_URL_QA
} else if (AlfredManager.config.isProd()) {
BASE_URL_PROD
} else {
BASE_URL_DEBUG
}
val providesDeserializer = GsonBuilder().registerTypeAdapter(
AnalyticsRequest::class.java,
AnalyticsDataDeserializer()
).registerTypeAdapter(SessionRequest::class.java, SessionDataDeserializer())
.registerTypeAdapter(EventMetricRequest::class.java, MetricsDataDeserializer()).create()
return Retrofit.Builder().baseUrl(baseUrl)
val baseUrl =
if (AlfredManager.config.isQa()) {
BASE_URL_QA
} else if (AlfredManager.config.isProd()) {
BASE_URL_PROD
} else {
BASE_URL_DEBUG
}
val providesDeserializer =
GsonBuilder()
.registerTypeAdapter(
com.navi.alfred.model.AnalyticsRequest::class.java,
AnalyticsDataDeserializer()
)
.registerTypeAdapter(SessionRequest::class.java, SessionDataDeserializer())
.registerTypeAdapter(EventMetricRequest::class.java, MetricsDataDeserializer())
.create()
return Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(providesDeserializer))
.client(okHttpClient).build()
.client(okHttpClient)
.build()
}
fun getApiService(): AlfredRetrofitService {
return apiService
}
private fun loggingInterceptor() = HttpLoggingInterceptor().apply {
setLevel(HttpLoggingInterceptor.Level.BODY)
}
private fun loggingInterceptor() =
HttpLoggingInterceptor().apply { setLevel(HttpLoggingInterceptor.Level.BODY) }
}

View File

@@ -69,4 +69,4 @@ interface AlfredRetrofitService {
@Header(DEVICE_ID) deviceId: String,
@Header(CONTENT_TYPE) contentType: String,
): Response<CruiseResponse>
}
}

View File

@@ -1,13 +1,22 @@
/*
*
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.alfred.network.model
import com.google.gson.annotations.SerializedName
data class CruiseResponse(
@SerializedName("data") val data: List<CruiseConfig>, @SerializedName("status") val status: Int
@SerializedName("data") val data: List<CruiseConfig>,
@SerializedName("status") val status: Int
)
data class CruiseConfig(
@SerializedName("_id") val id: String, @SerializedName("_source") val source: Source
@SerializedName("_id") val id: String,
@SerializedName("_source") val source: Source
)
data class Source(
@@ -26,7 +35,8 @@ data class RecordingsConfig(
@SerializedName("video_quality") val videoQuality: String? = null,
@SerializedName("video_recording_policy") val videoRecordingPolicy: String? = null,
@SerializedName("disable_screens") val disableScreens: List<String>? = null,
@SerializedName("disable_modules") val disableModules: List<String>? = null
@SerializedName("disable_modules") val disableModules: List<String>? = null,
@SerializedName("masked_enabled_screens") val maskingEnabledScreens: List<String>? = null
)
data class OsConfig(
@@ -37,11 +47,8 @@ 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<String>? = 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,
@SerializedName("enable") val enable: Boolean? = null
)
)

View File

@@ -48,8 +48,6 @@ 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"
@@ -68,12 +66,9 @@ object AlfredConstants {
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 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 SENSITIVE_VIEW_TAG = "sensitive_view"
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"
}

View File

@@ -1,3 +1,10 @@
/*
*
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.alfred.utils
object ApiConstants {
@@ -10,4 +17,4 @@ object ApiConstants {
const val API_CODE_UNKNOWN_HOST = 21
const val API_CODE_CONNECT_EXCEPTION = 22
const val API_CODE_SOCKET = 26
}
}

View File

@@ -1,5 +1,13 @@
/*
*
* * Copyright © 2021-2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.alfred.utils
fun Int?.orZero() = this ?: 0
fun Boolean?.orFalse() = this ?: false
fun Boolean?.orFalse() = this ?: false
fun Int?.orZero() = this ?: 0

View File

@@ -1,6 +1,6 @@
/*
*
* * Copyright © 2022-2023 by Navi Technologies Limited
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
@@ -11,12 +11,10 @@ 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)) {
@@ -31,29 +29,9 @@ fun handleException(e: Throwable): ErrorMessage {
errorMessage.statusCode = ApiConstants.API_WRONG_ERROR_RESPONSE
} else if (e is SocketException) {
errorMessage.statusCode = ApiConstants.API_CODE_SOCKET
}
else {
} 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
}

View File

@@ -1,6 +1,6 @@
/*
*
* * Copyright © 2022-2023 by Navi Technologies Limited
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/

View File

@@ -1,6 +1,6 @@
/*
*
* * Copyright © 2022-2023 by Navi Technologies Limited
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
@@ -19,25 +19,26 @@ import android.os.StatFs
import android.telephony.TelephonyManager
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
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.SENSITIVE_VIEW_TAG
import com.navi.alfred.utils.AlfredConstants.UNDERSCORE
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.io.*
import java.lang.Math.subtractExact
import java.util.*
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
import kotlin.math.abs
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
suspend fun captureScreen(
v: View,
@@ -53,11 +54,39 @@ suspend fun captureScreen(
return null
}
if (canvas != null && bmp != null) {
withContext(Dispatchers.Main) {
try {
v.draw(canvas)
} catch (e: Exception) {
e.log()
if (isMaskingEnabled(screenName) || (v.tag == SENSITIVE_VIEW_TAG)) {
val maskedViewsList = findViewWithTagRecursive(v, SENSITIVE_VIEW_TAG, mutableListOf())
withContext(Dispatchers.Main) {
try {
if (maskedViewsList.isEmpty()) {
v.draw(canvas)
} else {
val alphaList = mutableListOf<Pair<View, Float>>()
for (maskedView in maskedViewsList) {
alphaList.add(Pair(maskedView, maskedView.alpha))
maskedView.alpha = 0.0f
}
v.draw(canvas)
for (alphaView in alphaList) {
val view = alphaView.first
view.alpha = alphaView.second
}
alphaList.clear()
}
} catch (e: Exception) {
e.log()
}
}
} else {
withContext(Dispatchers.Main) {
try {
v.draw(canvas)
} catch (e: Exception) {
e.log()
}
}
}
insertScreenShotPathInDb(scope, context, bmp, bottomSheetFlow)
@@ -65,6 +94,19 @@ suspend fun captureScreen(
return bmp
}
fun findViewWithTagRecursive(view: View, tag: String, maskedViews: MutableList<View>): List<View> {
if (view.tag == tag) {
maskedViews.add(view)
}
if (view is ViewGroup) {
for (i in 0 until view.childCount) {
val childView = view.getChildAt(i)
findViewWithTagRecursive(childView, tag, maskedViews)
}
}
return maskedViews
}
fun combineScreenshots(
backgroundScreenshot: Bitmap?,
@@ -74,29 +116,26 @@ fun combineScreenshots(
moduleName: String? = null,
scope: CoroutineScope
): Bitmap? {
if (backgroundScreenshot == null || bottomSheetScreenshot == null || isScreenDisabled(
screenName, moduleName
)
if (
backgroundScreenshot == null ||
bottomSheetScreenshot == null ||
isScreenDisabled(screenName, moduleName)
) {
return null
}
var screenWidth = Resources.getSystem().displayMetrics.widthPixels / 2
var screenHeight = Resources.getSystem().displayMetrics.heightPixels / 2
if (!isResolutionEven(screenWidth)) {
screenWidth += 1
}
if (!isResolutionEven(screenHeight)) {
if (!isResolutionEven(screenWidth, screenHeight)) {
screenHeight += 1
screenWidth += 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())) {
if (!isResolutionEven(bottomSheetLeft.toInt(), bottomSheetTop.toInt())) {
bottomSheetLeft = (bottomSheetLeft.toInt() + 1).toFloat()
}
if (!isResolutionEven(bottomSheetTop.toInt())) {
bottomSheetTop = (bottomSheetTop.toInt() + 1).toFloat()
}
canvas.drawBitmap(bottomSheetScreenshot, bottomSheetLeft, bottomSheetTop, null)
@@ -105,7 +144,10 @@ fun combineScreenshots(
}
fun insertScreenShotPathInDb(
scope: CoroutineScope, context: Context, bitmap: Bitmap?, bottomSheetFlow: Boolean? = false
scope: CoroutineScope,
context: Context,
bitmap: Bitmap?,
bottomSheetFlow: Boolean? = false
) {
scope.launch(Dispatchers.IO) {
try {
@@ -113,23 +155,22 @@ fun insertScreenShotPathInDb(
val fileName = System.currentTimeMillis().toString() + IMAGE_FILE_EXTENSION
val path = fileDir.path.plus("/").plus(fileName)
val imageUrl = File(path)
val fos = FileOutputStream(
imageUrl
)
val videoQuality: Int = when (AlfredManager.config.getVideoQuality()) {
VideoQuality.HIGH.name -> {
10
val fos = FileOutputStream(imageUrl)
val videoQuality: Int =
when (AlfredManager.config.getVideoQuality()) {
VideoQuality.HIGH.name -> {
10
}
VideoQuality.LOW.name -> {
6
}
VideoQuality.MEDIUM.name -> {
8
}
else -> {
10
}
}
VideoQuality.LOW.name -> {
6
}
VideoQuality.MEDIUM.name -> {
8
}
else -> {
10
}
}
bitmap?.compress(CompressFormat.JPEG, videoQuality, fos)
fos.flush()
fos.close()
@@ -138,9 +179,7 @@ fun insertScreenShotPathInDb(
val screenShotDao = db.screenShotDao()
try {
screenShotDao.insertScreenShotPath(
ScreenShotPathHelper(
System.currentTimeMillis(), path
)
ScreenShotPathHelper(System.currentTimeMillis(), path)
)
ScreenShotStorageHelper.addImage(path)
} catch (e: Exception) {
@@ -149,16 +188,13 @@ fun insertScreenShotPathInDb(
}
} catch (e: Exception) {
e.log()
} catch (e: IOException) {
e.log()
}
}
}
fun captureScreenshotOfCustomView(
view: View
): Bitmap? {
fun captureScreenshotOfCustomView(view: View): Bitmap? {
view.draw(Canvas())
val bitmapForCanvas = createBitmapForView(view)
try {
@@ -173,10 +209,8 @@ fun createBitmapForView(view: View): Pair<Canvas, Bitmap>? {
var width = view.width / 2
var height = view.height / 2
if (width > 0 && height > 0) {
if (!isResolutionEven(width)) {
if (!isResolutionEven(width, height)) {
width += 1
}
if (!isResolutionEven(height)) {
height += 1
}
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
@@ -187,13 +221,11 @@ fun createBitmapForView(view: View): Pair<Canvas, Bitmap>? {
return null
}
fun zip(_files: ArrayList<String>, zipFilePath: String?): Boolean? {
val buffer = 1000
try {
zipFilePath?.let { path ->
if (File(path).exists())
return true
if (File(path).exists()) return true
else {
File(path)
}
@@ -235,13 +267,15 @@ fun clearScreenShot(path: List<ScreenShotPathHelper>) {
}
fun isScreenDisabled(screenName: String? = null, moduleName: String? = null): Boolean {
if (moduleName != null && AlfredManager.config.getDisableModuleList()
?.contains(moduleName) == true
if (
moduleName != null &&
AlfredManager.config.getDisableModuleList()?.contains(moduleName) == true
) {
return true
} else {
if (screenName != null && AlfredManager.config.getDisableScreenList()
?.contains(screenName) == true
if (
screenName != null &&
AlfredManager.config.getDisableScreenList()?.contains(screenName) == true
) {
return true
}
@@ -249,6 +283,13 @@ fun isScreenDisabled(screenName: String? = null, moduleName: String? = null): Bo
return false
}
fun isMaskingEnabled(screenName: String? = null): Boolean {
if (AlfredManager.config.getMaskingEnabledScreenList()?.contains(screenName) == true) {
return true
}
return false
}
fun checkFileExists(fileName: String, context: Context): File? {
val file = File(context.filesDir, fileName)
return if (file.exists()) {
@@ -259,24 +300,26 @@ fun checkFileExists(fileName: String, context: Context): File? {
}
fun getTouchEvent(
currentTouchEvent: MotionEvent?, previousTouchEvent: NaviMotionEvent?
currentTouchEvent: MotionEvent?,
previousTouchEvent: NaviMotionEvent?
): Pair<String, HashMap<String, String>> {
val properties = HashMap<String, String>()
val pointerIndex = currentTouchEvent?.actionIndex ?: 0
val eventName = if (difference(currentTouchEvent?.getX(pointerIndex), previousTouchEvent?.positionX) && difference(
currentTouchEvent?.getY(pointerIndex), previousTouchEvent?.positionY
)
) {
properties[AlfredConstants.START_X] = previousTouchEvent?.positionX.toString()
properties[AlfredConstants.START_Y] = previousTouchEvent?.positionY.toString()
AlfredConstants.TOUCH_EVENT
} else {
properties[AlfredConstants.START_X] = previousTouchEvent?.positionX.toString()
properties[AlfredConstants.START_Y] = previousTouchEvent?.positionY.toString()
properties[AlfredConstants.END_X] = currentTouchEvent?.rawX.toString()
properties[AlfredConstants.END_Y] = currentTouchEvent?.rawY.toString()
AlfredConstants.SCROLL_EVENT
}
val eventName =
if (
difference(currentTouchEvent?.getX(pointerIndex), previousTouchEvent?.positionX) &&
difference(currentTouchEvent?.getY(pointerIndex), previousTouchEvent?.positionY)
) {
properties[AlfredConstants.START_X] = previousTouchEvent?.positionX.toString()
properties[AlfredConstants.START_Y] = previousTouchEvent?.positionY.toString()
AlfredConstants.TOUCH_EVENT
} else {
properties[AlfredConstants.START_X] = previousTouchEvent?.positionX.toString()
properties[AlfredConstants.START_Y] = previousTouchEvent?.positionY.toString()
properties[AlfredConstants.END_X] = currentTouchEvent?.rawX.toString()
properties[AlfredConstants.END_Y] = currentTouchEvent?.rawY.toString()
AlfredConstants.SCROLL_EVENT
}
return Pair(eventName, properties)
}
@@ -298,8 +341,20 @@ fun getNetworkType(context: Context): String {
val mTelephonyManager =
context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
return when (mTelephonyManager.networkType) {
TelephonyManager.NETWORK_TYPE_GPRS, TelephonyManager.NETWORK_TYPE_EDGE, TelephonyManager.NETWORK_TYPE_CDMA, TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyManager.NETWORK_TYPE_IDEN -> "2G"
TelephonyManager.NETWORK_TYPE_UMTS, TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyManager.NETWORK_TYPE_HSDPA, TelephonyManager.NETWORK_TYPE_HSUPA, TelephonyManager.NETWORK_TYPE_HSPA, TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyManager.NETWORK_TYPE_HSPAP -> "3G"
TelephonyManager.NETWORK_TYPE_GPRS,
TelephonyManager.NETWORK_TYPE_EDGE,
TelephonyManager.NETWORK_TYPE_CDMA,
TelephonyManager.NETWORK_TYPE_1xRTT,
TelephonyManager.NETWORK_TYPE_IDEN -> "2G"
TelephonyManager.NETWORK_TYPE_UMTS,
TelephonyManager.NETWORK_TYPE_EVDO_0,
TelephonyManager.NETWORK_TYPE_EVDO_A,
TelephonyManager.NETWORK_TYPE_HSDPA,
TelephonyManager.NETWORK_TYPE_HSUPA,
TelephonyManager.NETWORK_TYPE_HSPA,
TelephonyManager.NETWORK_TYPE_EVDO_B,
TelephonyManager.NETWORK_TYPE_EHRPD,
TelephonyManager.NETWORK_TYPE_HSPAP -> "3G"
TelephonyManager.NETWORK_TYPE_LTE -> "4G"
TelephonyManager.NETWORK_TYPE_NR -> "5G"
else -> "Unknown" + UNDERSCORE + mTelephonyManager.networkType
@@ -312,9 +367,10 @@ fun getNetworkType(context: Context): String {
fun getCarrierName(context: Context): String? {
return try {
(context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager).networkOperatorName
(context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager)
.networkOperatorName
} catch (e: Exception) {
e.log()
e.log()
null
}
}
@@ -347,7 +403,6 @@ fun getCpuUsage(): Float {
}
reader.close()
return cpuUsage
}
fun getStorageUsage(context: Context): Pair<Long, Long> {
@@ -362,7 +417,9 @@ fun getStorageUsage(context: Context): Pair<Long, Long> {
}
enum class VideoQuality {
LOW, HIGH, MEDIUM
LOW,
HIGH,
MEDIUM
}
private fun Any.tag(): String {
@@ -386,8 +443,8 @@ fun isNetworkAvailable(context: Context): Boolean {
return connectivityManager?.activeNetworkInfo?.isConnected.orFalse()
}
private fun isResolutionEven(size: Int): Boolean {
return size.mod(2) == 0
private fun isResolutionEven(width: Int, height: Int): Boolean {
return width.mod(2) == 0 && height.mod(2) == 0
}
fun recordException(e: Throwable) {

View File

@@ -1,6 +1,6 @@
/*
*
* * Copyright © 2022-2023 by Navi Technologies Limited
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
@@ -16,12 +16,11 @@ import com.navi.alfred.dispatcher.AlfredDispatcher
import com.navi.alfred.utils.AlfredConstants
import java.util.concurrent.atomic.AtomicInteger
class AddEventTask(
private val event: AnalyticsEvent,
private val context: Context
) : AnalyticsTask {
class AddEventTask(private val event: AnalyticsEvent, private val context: Context) :
AnalyticsTask {
companion object {
private var eventCount: AtomicInteger = AtomicInteger(0)
fun resetEventCount() {
eventCount = AtomicInteger(0)
}

View File

@@ -1,3 +1,10 @@
/*
*
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.alfred.worker
import android.content.Context
@@ -9,12 +16,11 @@ import com.navi.alfred.dispatcher.AlfredDispatcher
import com.navi.alfred.utils.AlfredConstants
import java.util.concurrent.atomic.AtomicInteger
class AddMetricTask(
private val event: ApiMetricHelper, private val context: Context
) : AnalyticsTask {
class AddMetricTask(private val event: ApiMetricHelper, private val context: Context) :
AnalyticsTask {
companion object {
private var eventCount: AtomicInteger = AtomicInteger(0)
fun resetEventCount() {
eventCount = AtomicInteger(0)
}

View File

@@ -1,6 +1,6 @@
/*
*
* * Copyright © 2019-2023 by Navi Technologies Limited
* * Copyright © 2021-2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
@@ -10,8 +10,7 @@ package com.navi.alfred.worker
import androidx.annotation.WorkerThread
interface AnalyticsTask {
@WorkerThread
fun execute(): Boolean
@WorkerThread fun execute(): Boolean
fun getTaskName(): String
}

View File

@@ -1,16 +1,16 @@
/*
*
* * Copyright © 2019-2023 by Navi Technologies Limited
* * Copyright © 2021-2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.alfred.worker
import kotlinx.coroutines.asCoroutineDispatcher
import java.util.concurrent.BlockingDeque
import java.util.concurrent.Executors
import java.util.concurrent.LinkedBlockingDeque
import kotlinx.coroutines.asCoroutineDispatcher
class AnalyticsTaskProcessor {
private val taskQueue: BlockingDeque<AnalyticsTask> = LinkedBlockingDeque<AnalyticsTask>()
@@ -18,6 +18,7 @@ class AnalyticsTaskProcessor {
private val singleThreadExecutorForSync = Executors.newSingleThreadExecutor()
private var active: AnalyticsTask? = null
private var isSyncEventTaskExecuted: Boolean = true
fun addTask(task: AnalyticsTask?) {
if (task != null) {
taskQueue.add(task)

View File

@@ -1,3 +1,10 @@
/*
*
* * Copyright © 2023 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
package com.navi.alfred.worker
import android.content.Context
@@ -14,43 +21,53 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.lang.reflect.Type
class UploadFileWorker(context: Context, workerParams: WorkerParameters) :
CoroutineWorker(context, workerParams) {
class UploadFileWorker(
context: Context, workerParams: WorkerParameters
) : CoroutineWorker(context, workerParams) {
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
val alfredSessionId = inputData.getString(AlfredConstants.ALFRED_SESSION_ID)
val sessionStartRecordingTime =
inputData.getLong(AlfredConstants.SESSION_START_RECORDING_TIME, 0L)
val eventStartRecordingTime =
inputData.getLong(AlfredConstants.EVENT_START_RECORDING_TIME, 0L)
val screenShotList = inputData.getString(AlfredConstants.SCREENSHOT_LIST)
val listType: Type = object : TypeToken<List<ScreenShotPathHelper?>?>() {}.type
val screenShots: List<ScreenShotPathHelper> =
Gson().fromJson(screenShotList.toString(), listType)
val zipFileName =
alfredSessionId + sessionStartRecordingTime + AlfredConstants.WORKER_ZIP_FILENAME_ENDPOINT
workFailureData.add(
WorkManagerFailureInputData(
alfredSessionId = alfredSessionId,
sessionStartRecordingTime,
eventStartRecordingTime,
screenShots,
id
override suspend fun doWork(): Result =
withContext(Dispatchers.IO) {
val alfredSessionId = inputData.getString(AlfredConstants.ALFRED_SESSION_ID)
val sessionStartRecordingTime =
inputData.getLong(AlfredConstants.SESSION_START_RECORDING_TIME, 0L)
val eventStartRecordingTime =
inputData.getLong(AlfredConstants.EVENT_START_RECORDING_TIME, 0L)
val screenShotList = inputData.getString(AlfredConstants.SCREENSHOT_LIST)
val listType: Type = object : TypeToken<List<ScreenShotPathHelper?>?>() {}.type
val screenShots: List<ScreenShotPathHelper> =
Gson().fromJson(screenShotList.toString(), listType)
val zipFileName =
alfredSessionId +
sessionStartRecordingTime +
AlfredConstants.WORKER_ZIP_FILENAME_ENDPOINT
workFailureData.add(
WorkManagerFailureInputData(
alfredSessionId = alfredSessionId,
sessionStartRecordingTime,
eventStartRecordingTime,
screenShots,
id
)
)
)
try {
if (alfredSessionId == null || sessionStartRecordingTime == 0L || eventStartRecordingTime == 0L) {
Result.failure()
} else {
AlfredManager.toZipForWorkManager(screenShots, zipFileName,sessionStartRecordingTime,alfredSessionId, eventStartRecordingTime)
Result.success()
try {
if (
alfredSessionId == null ||
sessionStartRecordingTime == 0L ||
eventStartRecordingTime == 0L
) {
Result.failure()
} else {
AlfredManager.toZipForWorkManager(
screenShots,
zipFileName,
sessionStartRecordingTime,
alfredSessionId,
eventStartRecordingTime
)
Result.success()
}
} catch (e: Exception) {
e.printStackTrace()
Result.retry()
}
} catch (e: Exception) {
e.printStackTrace()
Result.retry()
}
}
}