Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ android.enableJetifier=true
kotlin.code.style=official

# SDK version property
SDK_VERSION_NAME=2.8.2
SDK_VERSION_NAME=2.8.3
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import cloud.mindbox.mobile_sdk.logger.MindboxLogger
import cloud.mindbox.mobile_sdk.pushes.MindboxPushService
import cloud.mindbox.mobile_sdk.pushes.PushServiceHandler
import cloud.mindbox.mobile_sdk.utils.ExceptionHandler

/**
* An object to use when choosing push provider in Mindbox.initPushServices or Mindbox.init.
* Represents FCM
* */
object MindboxFirebase : MindboxPushService {

override val tag: String = "FCM"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import cloud.mindbox.mobile_sdk.logger.MindboxLogger
import cloud.mindbox.mobile_sdk.pushes.MindboxPushService
import cloud.mindbox.mobile_sdk.pushes.PushServiceHandler
import cloud.mindbox.mobile_sdk.utils.ExceptionHandler

/**
* An object to use when choosing push provider in Mindbox.initPushServices or Mindbox.init.
* Represents HCM
* */
object MindboxHuawei : MindboxPushService {

override val tag: String = "HCM"
Expand Down
16 changes: 16 additions & 0 deletions sdk/src/main/java/cloud/mindbox/mobile_sdk/Extensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ import androidx.annotation.IdRes
import cloud.mindbox.mobile_sdk.inapp.domain.models.InAppType
import cloud.mindbox.mobile_sdk.logger.MindboxLoggerImpl
import cloud.mindbox.mobile_sdk.utils.LoggingExceptionHandler
import com.android.volley.VolleyError
import com.android.volley.toolbox.HttpHeaderParser
import org.threeten.bp.Instant
import org.threeten.bp.LocalDateTime
import org.threeten.bp.ZoneOffset
import org.threeten.bp.ZonedDateTime
import org.threeten.bp.format.DateTimeFormatter
import java.nio.charset.Charset
import java.util.Queue
import kotlin.math.roundToInt

Expand Down Expand Up @@ -182,4 +185,17 @@ internal fun PackageManager.getPackageInfoCompat(context: Context, flags: Int):
} else {
getPackageInfo(context.packageName, flags)
}
}

internal fun VolleyError.getErrorResponseBodyData(): String {
return this.networkResponse?.data
?.takeIf { it.isNotEmpty() }
?.toString(
Charset.forName(
HttpHeaderParser.parseCharset(
this.networkResponse?.headers ?: emptyMap()
)
)
)
?: ""
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package cloud.mindbox.mobile_sdk

/**
* An error thrown during initialization in case validation of initialization fails
* */
class InitializeMindboxException(message: String) : Exception(message)
3 changes: 3 additions & 0 deletions sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,9 @@ object Mindbox : MindboxLog {
* Creates and deliveries event of "Push delivered". Recommended call this method from
* background thread.
*
* Use this method only if you have custom push handling you don't use [Mindbox.handleRemoteMessage].
* You must not call it otherwise.
*
* @param context used to initialize the main tools
* @param uniqKey - unique identifier of push notification
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package cloud.mindbox.mobile_sdk.abtests

interface CustomerAbMixer {
internal interface CustomerAbMixer {
fun stringModulusHash(identifier: String, salt: String): Int
}
Empty file.
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package cloud.mindbox.mobile_sdk.inapp.data.validators

import com.google.gson.JsonParser

internal class JsonValidator : Validator<String?> {

override fun isValid(item: String?): Boolean {
if (item.isNullOrBlank()) return false
val jsonRegex = "^\\s*(\\{.*\\}|\\[.*])\\s*$"
return item.trim().matches(jsonRegex.toRegex())

return runCatching {
JsonParser.parseString(item).let { it.isJsonObject || it.isJsonArray }
}.getOrElse { false }
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
package cloud.mindbox.mobile_sdk.inapp.domain

import cloud.mindbox.mobile_sdk.getErrorResponseBodyData
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.InAppContentFetcher
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.managers.InAppChoosingManager
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.repositories.InAppGeoRepository
import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.repositories.InAppSegmentationRepository
import cloud.mindbox.mobile_sdk.inapp.domain.models.*
import cloud.mindbox.mobile_sdk.logger.MindboxLoggerImpl
import cloud.mindbox.mobile_sdk.logger.mindboxLogD
import cloud.mindbox.mobile_sdk.logger.mindboxLogI
import cloud.mindbox.mobile_sdk.logger.mindboxLogW
import cloud.mindbox.mobile_sdk.models.InAppEventType
import com.android.volley.VolleyError
import kotlinx.coroutines.*

internal class InAppChoosingManagerImpl(
private val inAppGeoRepository: InAppGeoRepository,
private val inAppSegmentationRepository: InAppSegmentationRepository,
private val inAppContentFetcher: InAppContentFetcher
) :
InAppChoosingManager {
) : InAppChoosingManager {

companion object {
private const val RESPONSE_STATUS_CUSTOMER_SEGMENTS_REQUIRE_CUSTOMER =
"CheckCustomerSegments requires customer"
}
override suspend fun chooseInAppToShow(
inApps: List<InApp>,
triggerEvent: InAppEventType,
Expand Down Expand Up @@ -66,11 +73,7 @@ internal class InAppChoosingManagerImpl(
inAppSegmentationRepository.setCustomerSegmentationStatus(
CustomerSegmentationFetchStatus.SEGMENTATION_FETCH_ERROR
)
MindboxLoggerImpl.e(
this,
"Error fetching customer segmentations",
throwable
)
handleCustomerSegmentationErrorLog(throwable)
}

else -> {
Expand Down Expand Up @@ -124,6 +127,19 @@ internal class InAppChoosingManagerImpl(
)
}

private fun handleCustomerSegmentationErrorLog(error: CustomerSegmentationError) {
val volleyError = error.cause as? VolleyError
volleyError?.let { error ->
if ((error.networkResponse?.statusCode == 400) && (error.getErrorResponseBodyData()
.contains(RESPONSE_STATUS_CUSTOMER_SEGMENTS_REQUIRE_CUSTOMER))
) {
mindboxLogI("Cannot check customer segment. It's a new customer")
return
}
}
mindboxLogW("Error fetching customer segmentations", error)
}

private class TargetingDataWrapper(
override val triggerEventName: String,
override val operationBody: String? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ internal class GeoError(volleyError: VolleyError) : Exception(volleyError)
internal class ProductSegmentationError(volleyError: VolleyError) :
Exception(volleyError)

internal class InAppContentFetchingError(error: GlideException?) : Exception(error)
internal class InAppContentFetchingError(error: GlideException?) : Exception(error)
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import cloud.mindbox.mobile_sdk.monitoring.domain.interfaces.MonitoringRepositor
import com.android.volley.VolleyLog
import kotlinx.coroutines.*
import org.threeten.bp.Instant

/**
* An interface for internal sdk work only. Do not implement or use it.
* */
interface MindboxLogger {

fun i(parent: Any, message: String)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import com.android.volley.DefaultRetryPolicy
import com.android.volley.DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
import com.android.volley.Request
import com.android.volley.VolleyError
import com.android.volley.toolbox.StringRequest
import com.google.gson.Gson
import kotlinx.coroutines.*
import org.json.JSONException
Expand Down Expand Up @@ -409,17 +408,18 @@ internal class GatewayManager(private val mindboxServiceGenerator: MindboxServic
}
}


suspend fun fetchMobileConfig(configuration: Configuration): String {
return suspendCoroutine { continuation ->
mindboxServiceGenerator.addToRequestQueue(
StringRequest(
Request.Method.GET,
getConfigUrl(configuration),
{ response ->
continuation.resume(response)
MindboxRequest(
methodType = Request.Method.GET,
fullUrl = getConfigUrl(configuration),
configuration = configuration,
jsonRequest = null,
listener = { response ->
continuation.resume(response.toString())
},
{ error ->
errorsListener = { error ->
continuation.resumeWithException(error)
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package cloud.mindbox.mobile_sdk.models

import com.google.gson.Gson
import com.google.gson.annotations.JsonAdapter

/**
* A class for representing Mindbox error.
* Used in operations.
* */
sealed class MindboxError(open val statusCode: Int?) {

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter

class MindboxErrorAdapter : TypeAdapter<MindboxError?>() {
internal class MindboxErrorAdapter : TypeAdapter<MindboxError?>() {

private val gson by lazy { Gson() }

Expand Down
54 changes: 31 additions & 23 deletions sdk/src/main/java/cloud/mindbox/mobile_sdk/models/Requests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package cloud.mindbox.mobile_sdk.models

import android.os.Build
import cloud.mindbox.mobile_sdk.BuildConfig
import cloud.mindbox.mobile_sdk.logger.MindboxLoggerImpl
import cloud.mindbox.mobile_sdk.getErrorResponseBodyData
import cloud.mindbox.mobile_sdk.logger.mindboxLogI
import cloud.mindbox.mobile_sdk.logger.mindboxLogW
import cloud.mindbox.mobile_sdk.utils.LoggingExceptionHandler
import com.android.volley.NetworkResponse
import com.android.volley.ParseError
Expand Down Expand Up @@ -108,25 +110,16 @@ internal data class MindboxRequest(
//Logging error responses
override fun parseNetworkError(volleyError: VolleyError): VolleyError {
LoggingExceptionHandler.runCatching {
MindboxLoggerImpl.e(
this,
"<--- Error ${volleyError.networkResponse?.statusCode} $fullUrl TimeMls:${volleyError.networkTimeMs}; ",
)
try {
volleyError.networkResponse?.allHeaders?.joinToString (
val json = volleyError.getErrorResponseBodyData()

logResponseResult(volleyError, json)

volleyError.networkResponse?.allHeaders?.joinToString(
separator = System.getProperty("line.separator") ?: "\n"
) { header ->
"${header.name}: ${header.value}"
}?.let { MindboxLoggerImpl.d(this, it) }

val json = String(
volleyError.networkResponse?.data ?: ByteArray(0),
Charset.forName(
HttpHeaderParser.parseCharset(
volleyError.networkResponse?.headers ?: emptyMap()
)
)
)
}?.let { mindboxLogI(it) }

logBodyResponse(json)
} catch (e: Exception) {
Expand All @@ -142,32 +135,47 @@ internal data class MindboxRequest(

private fun logResponse(response: NetworkResponse?) {
LoggingExceptionHandler.runCatching {
MindboxLoggerImpl.d(this, "<--- ${response?.statusCode} $fullUrl")
mindboxLogI("<--- ${response?.statusCode} $fullUrl")

response?.allHeaders?.joinToString (
response?.allHeaders?.joinToString(
separator = System.getProperty("line.separator") ?: "\n"
) { header ->
"${header.name}: ${header.value}"
}?.let { MindboxLoggerImpl.d(this, it) }
}?.let { mindboxLogI(it) }
}
}

private fun logBodyResponse(json: String?) {
LoggingExceptionHandler.runCatching {
MindboxLoggerImpl.d(this, "$json")
mindboxLogI("$json")
}
}

private fun logError(e: Exception) {
LoggingExceptionHandler.runCatching {
MindboxLoggerImpl.d(this, e.message ?: "Empty message")
MindboxLoggerImpl.d(this, e.stackTraceToString())
mindboxLogW(e.message ?: "Empty message")
mindboxLogW(e.stackTraceToString())
}
}

private fun logEndResponse() {
LoggingExceptionHandler.runCatching {
MindboxLoggerImpl.d(this, "<--- End of response")
mindboxLogI("<--- End of response")
}
}

private fun logResponseResult(volleyError: VolleyError?, json: String?) {
LoggingExceptionHandler.runCatching {
val logMessage = buildString {
append("<--- ")
append(if (json?.contains("\"status\": \"Success\"") == true) "Success" else "Error")
append(" ${volleyError?.networkResponse?.statusCode} $fullUrl TimeMls:${volleyError?.networkTimeMs}; ")
}
if (json?.contains("{\"status\": \"Success\"}") == true) {
mindboxLogI(logMessage)
} else {
mindboxLogW(logMessage)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package cloud.mindbox.mobile_sdk.models

import com.google.gson.annotations.SerializedName

/**
* A class to hold validation message if validation error occurs
* */
data class ValidationMessage(
@SerializedName("message") val message: String? = null,
@SerializedName("location") val location: String? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import cloud.mindbox.mobile_sdk.models.MindboxRequest
import cloud.mindbox.mobile_sdk.utils.LoggingExceptionHandler
import com.android.volley.RequestQueue
import com.android.volley.VolleyLog
import com.android.volley.toolbox.StringRequest
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine

Expand All @@ -29,11 +28,6 @@ internal class MindboxServiceGenerator(private val requestQueue: RequestQueue) {
}
}

internal fun addToRequestQueue(request: StringRequest) {
requestQueue.add(request)
// TODO change StringRequest to MindboxRequest or log here
}

internal fun addToRequestQueue(request: MindboxRequest) = LoggingExceptionHandler.runCatching {
requestQueue.let { requestQueue ->
requestQueue.add(request)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package cloud.mindbox.mobile_sdk.pushes

import cloud.mindbox.mobile_sdk.logger.MindboxLogger
import cloud.mindbox.mobile_sdk.utils.ExceptionHandler

/**
* An interface for internal sdk work only. Do not implement it
* */
interface MindboxPushService {

val tag: String
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package cloud.mindbox.mobile_sdk.pushes

import com.google.gson.annotations.SerializedName

/**
* A class representing mindbox push action in [RemoteMessage]
* * You can use it as a model to store data from mindbox
* * with your custom push notification implementation.
* */
data class PushAction(
@SerializedName("uniqueKey") val uniqueKey: String?,
@SerializedName("text") val text: String?,
Expand Down
Loading