521 lines
19 KiB
Kotlin
521 lines
19 KiB
Kotlin
/*
|
|
*
|
|
* * Copyright © 2021-2023 by Navi Technologies Limited
|
|
* * All rights reserved. Strictly confidential
|
|
*
|
|
*/
|
|
|
|
package com.navi.base.utils
|
|
|
|
import android.content.ComponentName
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.content.pm.PackageManager
|
|
import android.net.ConnectivityManager
|
|
import android.net.NetworkCapabilities
|
|
import android.net.Uri
|
|
import android.os.Build
|
|
import android.provider.Settings
|
|
import com.navi.base.sharedpref.CommonPrefConstants
|
|
import com.navi.base.sharedpref.CommonPrefConstants.ALFRED_DIALOG_SCREENSHOT
|
|
import com.navi.base.sharedpref.CommonPrefConstants.UPDATED_BASE_URL
|
|
import com.navi.base.sharedpref.CommonPrefConstants.UPDATED_PULSE_BASE_URL
|
|
import com.navi.base.sharedpref.CommonPrefConstants.UPDATED_VERSION_CODE
|
|
import com.navi.base.sharedpref.PreferenceManager
|
|
import java.util.Locale
|
|
|
|
object BaseUtils {
|
|
fun getDeviceId(applicationContext: Context): String {
|
|
return Settings.System.getString(
|
|
applicationContext.contentResolver,
|
|
Settings.Secure.ANDROID_ID
|
|
)
|
|
}
|
|
|
|
fun getDefaultLocale(): String {
|
|
try {
|
|
return Locale.getDefault().toString()
|
|
} catch (_: Exception) {}
|
|
|
|
return ""
|
|
}
|
|
|
|
fun isUserLoggedIn(): Boolean {
|
|
val sessionToken =
|
|
PreferenceManager.getSecureString(CommonPrefConstants.SESSION_TOKEN)
|
|
?: run { PreferenceManager.getStringPreference(CommonPrefConstants.SESSION_TOKEN) }
|
|
return !sessionToken.isNullOrBlank()
|
|
}
|
|
|
|
fun getSessionToken(): String? {
|
|
return PreferenceManager.getSecureString(CommonPrefConstants.SESSION_TOKEN)
|
|
?: run { PreferenceManager.getStringPreference(CommonPrefConstants.SESSION_TOKEN) }
|
|
}
|
|
|
|
fun saveSessionToken(sessionToken: String) {
|
|
PreferenceManager.saveStringSecurely(CommonPrefConstants.SESSION_TOKEN, sessionToken)
|
|
}
|
|
|
|
fun getRefreshToken(): String? {
|
|
return PreferenceManager.getSecureString(CommonPrefConstants.REFRESH_TOKEN)
|
|
?: run { PreferenceManager.getStringPreference(CommonPrefConstants.REFRESH_TOKEN) }
|
|
}
|
|
|
|
fun saveRefreshToken(refreshToken: String) {
|
|
PreferenceManager.saveStringSecurely(CommonPrefConstants.REFRESH_TOKEN, refreshToken)
|
|
}
|
|
|
|
fun getPhoneNumber(): String? {
|
|
return PreferenceManager.getSecureString(CommonPrefConstants.PHONE_NUMBER)
|
|
?: run { PreferenceManager.getStringPreference(CommonPrefConstants.PHONE_NUMBER) }
|
|
}
|
|
|
|
fun getEmail(): String? {
|
|
return PreferenceManager.getSecureString(CommonPrefConstants.EMAIL)
|
|
?: run { PreferenceManager.getStringPreference(CommonPrefConstants.EMAIL) }
|
|
}
|
|
|
|
fun savePhoneNumber(phoneNumber: String) {
|
|
PreferenceManager.saveStringSecurely(CommonPrefConstants.PHONE_NUMBER, phoneNumber)
|
|
}
|
|
|
|
fun saveEmail(email: String) {
|
|
PreferenceManager.saveStringSecurely(CommonPrefConstants.EMAIL, email)
|
|
}
|
|
|
|
fun isNetworkAvailable(context: Context): Boolean {
|
|
val connectivityManager =
|
|
context.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
val network = connectivityManager?.activeNetwork ?: return false
|
|
val activeNetwork = connectivityManager.getNetworkCapabilities(network) ?: return false
|
|
return when {
|
|
activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
|
|
activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
|
|
else -> false
|
|
}
|
|
} else {
|
|
return connectivityManager?.activeNetworkInfo?.isConnected.orFalse()
|
|
}
|
|
}
|
|
|
|
fun isFirebaseTokenRefreshed(): Boolean {
|
|
return PreferenceManager.getBooleanPreferenceApp(
|
|
CommonPrefConstants.IS_FIREBASE_TOKEN_REFRESHED
|
|
)
|
|
}
|
|
|
|
fun setFirebaseTokenRefreshed(value: Boolean) {
|
|
PreferenceManager.setBooleanPreferenceApp(
|
|
CommonPrefConstants.IS_FIREBASE_TOKEN_REFRESHED,
|
|
value
|
|
)
|
|
}
|
|
|
|
fun getPhoneNumberWithCountryCode(): String? {
|
|
var phoneNumber = getPhoneNumber()
|
|
if (phoneNumber?.contains("+91").orFalse().not()) {
|
|
phoneNumber = "+91 ".plus(phoneNumber)
|
|
}
|
|
return phoneNumber
|
|
}
|
|
|
|
fun getDigioExceptionReasonForAadhaarOtp(errorCode: Int?): String {
|
|
return when (errorCode) {
|
|
1001 -> "Invalid Input"
|
|
1002 -> "Init not called yet."
|
|
1003 -> "User Cancelled"
|
|
1004 -> "Internal Error, Try after some time"
|
|
1005 -> "Internet not connected"
|
|
1006 -> "Server Error, Try after some time"
|
|
1007 -> "Error from UIDAI"
|
|
1008 -> "Authentication Failed"
|
|
else -> "Reason Unknown"
|
|
}
|
|
}
|
|
|
|
fun getHyperVergeReasonForSelfieVerification(errorCode: Int?): String {
|
|
return when (errorCode) {
|
|
2 -> "INTERNAL_SDK_ERROR"
|
|
3 -> "OPERATION_CANCELLED_BY_USER_ERROR"
|
|
4 -> "PERMISSIONS_NOT_GRANTED_ERROR"
|
|
5 -> "HARDWARE_ERROR"
|
|
6 -> "INPUT_ERROR"
|
|
7 -> "QR_PARSER_ERROR"
|
|
8 -> "LOCATION_PERMISSION_NOT_AVAILABLE_ERROR"
|
|
11 -> "INITIALIZATION_ERROR"
|
|
12 -> "NETWORK_ERROR"
|
|
14 -> "INTERNAL_SERVER_ERROR"
|
|
15 -> "SSL_CONNECT_ERROR"
|
|
16 -> "ACTIVE_SESSION_ERROR"
|
|
17 -> "TRANSACTION_ID_EMPTY"
|
|
18 -> "SIGNATURE_FAILED_ERROR"
|
|
22 -> "FACE_DETECTION_ERROR"
|
|
23 -> "BLURRY_FACE_DETECTION_ERROR"
|
|
31 -> "INSTRUCTION_ERROR"
|
|
32 -> "QR_SCANNER_ERROR"
|
|
33 -> "GPS_ACCESS_DENIED"
|
|
else -> "REASON_UNKNOWN"
|
|
}
|
|
}
|
|
|
|
fun getFinarkeinEventDescription(eventCode: String?): String {
|
|
return when (eventCode) {
|
|
"OPEN" -> "User has opened Anubhav journey"
|
|
"ERROR" -> "Recoverable error occurred in the Anubhav flow"
|
|
"UNKNOWN" -> "Event is not handled by Anubhab SDK"
|
|
"EXIT" -> "User has exited without completing journey"
|
|
"FIP_SELECTED" -> "User selected a FIP in the Anubhav flow"
|
|
"AA_SELECTED" -> "When AA is auto-selected based on User/FIU preference"
|
|
"AA_OTP_SENT" -> "When AA has triggered the verification OTP to User"
|
|
"AA_OTP_FAILED" -> "When AA is unable to send OTP to User"
|
|
"AA_OTP_INVALID" -> "Enter OTP is invalid"
|
|
"AA_OTP_VERIFIED" -> "When OPT is verified successfully"
|
|
"AA_UNREACHABLE" -> "When AA is not reachable"
|
|
"FIP_RENDERED" -> "When FIP list is successfully displayed to User"
|
|
"ACCOUNT_DISCOVERED" -> "When User account(s) is discovered in the FIP"
|
|
"ACCOUNT_NOT_DISCOVERED" -> "When User account(s) is not discovered in the FIP"
|
|
"ACCOUNT_LINKED" -> "When User links account successfully"
|
|
"MOBILE_CHANGE" -> "When User changed mobile number for Account discovery"
|
|
"MOBILE_VERIFIED" -> "When User's new mobile number is verified using OTP"
|
|
"CONSENT_GRANTED" -> "When User grants consent successfully"
|
|
"CONSENT_REJECTED" ->
|
|
"When User rejects consent i.e. does not proceed with FIP selection"
|
|
"ALTERNATIVE_CHOSEN" -> "When User selects alternative mechanism instead of AA"
|
|
"DATA_REQUESTED" -> "When data is requested from AA"
|
|
"DATA_RECEIVED" -> "When data is received from AA"
|
|
"DATA_VALID" -> "When received data is valid as per set rules"
|
|
"DATA_INVALID" -> "When received data is invalid as per set rules"
|
|
"FIP_ERROR" -> "When FIP sends an error"
|
|
"AA_ERROR" -> "When AA sends an error"
|
|
else -> "Reason Unknown"
|
|
}
|
|
}
|
|
|
|
fun hasMultipleDots(originalText: String): Boolean {
|
|
var count = 0
|
|
for (i in originalText.indices) {
|
|
if (originalText[i] == '.') {
|
|
count++
|
|
}
|
|
}
|
|
return count > 1
|
|
}
|
|
|
|
fun cleanDecimalString(decimalString: String): String {
|
|
if (decimalString.contains('.')) {
|
|
var decimalValue = decimalString
|
|
decimalValue = stripTrailingCharacters(decimalValue, '0')
|
|
decimalValue = stripTrailingCharacters(decimalValue, '.')
|
|
return decimalValue
|
|
}
|
|
return decimalString
|
|
}
|
|
|
|
fun stripTrailingCharacters(str: String, char: Char): String {
|
|
val sb: StringBuilder = StringBuilder(str)
|
|
while (sb.length > 0 && sb[sb.length - 1] == char) {
|
|
sb.setLength(sb.length - 1)
|
|
}
|
|
return sb.toString()
|
|
}
|
|
|
|
fun isWholeNumber(number: Double): Boolean {
|
|
return number.toInt().toDouble() == number
|
|
}
|
|
|
|
fun getDigitsCountAfterDecimal(input: String): Int {
|
|
var count = 0
|
|
val decimalIndex = input.indexOf(".")
|
|
if (decimalIndex >= 0 && decimalIndex < input.length - 1) {
|
|
val decimalPart = input.substring(decimalIndex + 1)
|
|
count = decimalPart.length
|
|
}
|
|
return count
|
|
}
|
|
|
|
fun numberToWords(amount: String, isWholeNumber: Boolean): String {
|
|
if (isWholeNumber) {
|
|
return numberToWords(amount)
|
|
} else {
|
|
val splitValues = amount.split(".")
|
|
if (splitValues.size > 1) {
|
|
val result = splitValues[0]
|
|
var decimalValue = splitValues[1]
|
|
if (decimalValue.length == 1) {
|
|
decimalValue += "0"
|
|
}
|
|
return numberToWords(result)
|
|
.plus(" and ")
|
|
.plus(numberToWords(decimalValue, "paise", "paise").lowercase())
|
|
} else {
|
|
return numberToWords(splitValues[0])
|
|
}
|
|
}
|
|
}
|
|
|
|
fun numberToWords(
|
|
amount: String,
|
|
unitSingular: String = "rupee",
|
|
unitPlural: String = "rupees"
|
|
): String {
|
|
try {
|
|
val number = amount.toDouble().toInt().toString()
|
|
if (number == "0") return "Zero $unitPlural"
|
|
|
|
if (number.length <= 9) {
|
|
var numberInStringFormat = number.reversed()
|
|
var numberInWords = ""
|
|
while (numberInStringFormat.length < 9) {
|
|
numberInStringFormat = numberInStringFormat.plus("0")
|
|
}
|
|
numberInStringFormat = numberInStringFormat.reversed()
|
|
while (numberInStringFormat.isNotEmpty()) {
|
|
if (numberInStringFormat.length > 7) {
|
|
val leftMostTwoDigits = numberInStringFormat.take(2).toInt()
|
|
if (leftMostTwoDigits != 0) {
|
|
numberInWords =
|
|
numberInWords
|
|
.plus(twoDigitNumberToWords(leftMostTwoDigits))
|
|
.plus(" crore ")
|
|
}
|
|
} else if (numberInStringFormat.length > 5) {
|
|
val leftMostTwoDigits = numberInStringFormat.take(2).toInt()
|
|
if (leftMostTwoDigits != 0) {
|
|
numberInWords =
|
|
numberInWords
|
|
.plus(twoDigitNumberToWords(leftMostTwoDigits))
|
|
.plus(" lakh ")
|
|
}
|
|
} else if (numberInStringFormat.length > 3) {
|
|
val leftMostTwoDigits = numberInStringFormat.take(2).toInt()
|
|
if (leftMostTwoDigits != 0) {
|
|
numberInWords =
|
|
numberInWords
|
|
.plus(twoDigitNumberToWords(leftMostTwoDigits))
|
|
.plus(" thousand ")
|
|
}
|
|
} else if (numberInStringFormat.length > 2) {
|
|
val leftMostDigit = numberInStringFormat.take(1).toInt()
|
|
if (leftMostDigit != 0) {
|
|
numberInWords =
|
|
numberInWords
|
|
.plus(twoDigitNumberToWords(leftMostDigit))
|
|
.plus(" hundred ")
|
|
}
|
|
} else {
|
|
val lastDigits = numberInStringFormat.toInt()
|
|
if (lastDigits != 0) {
|
|
numberInWords = numberInWords.plus(twoDigitNumberToWords(lastDigits))
|
|
}
|
|
}
|
|
if (numberInStringFormat.length > 3) {
|
|
numberInStringFormat = numberInStringFormat.drop(2)
|
|
} else if (numberInStringFormat.length > 2) {
|
|
numberInStringFormat = numberInStringFormat.drop(1)
|
|
} else {
|
|
numberInStringFormat = ""
|
|
}
|
|
}
|
|
numberInWords = numberInWords.trim().replaceFirstChar { it.uppercase() }
|
|
if (numberInWords == "One") {
|
|
numberInWords = numberInWords.plus(" $unitSingular")
|
|
} else {
|
|
numberInWords = numberInWords.plus(" $unitPlural")
|
|
}
|
|
return numberInWords
|
|
} else {
|
|
return EMPTY
|
|
}
|
|
} catch (_: Exception) {}
|
|
return EMPTY
|
|
}
|
|
|
|
private fun twoDigitNumberToWords(num: Int): String {
|
|
when (num) {
|
|
0 -> return "zero"
|
|
1 -> return "one"
|
|
2 -> return "two"
|
|
3 -> return "three"
|
|
4 -> return "four"
|
|
5 -> return "five"
|
|
6 -> return "six"
|
|
7 -> return "seven"
|
|
8 -> return "eight"
|
|
9 -> return "nine"
|
|
10 -> return "ten"
|
|
11 -> return "eleven"
|
|
12 -> return "twelve"
|
|
13 -> return "thirteen"
|
|
14 -> return "fourteen"
|
|
15 -> return "fifteen"
|
|
16 -> return "sixteen"
|
|
17 -> return "seventeen"
|
|
18 -> return "eighteen"
|
|
19 -> return "nineteen"
|
|
20 -> return "twenty"
|
|
30 -> return "thirty"
|
|
40 -> return "forty"
|
|
50 -> return "fifty"
|
|
60 -> return "sixty"
|
|
70 -> return "seventy"
|
|
80 -> return "eighty"
|
|
90 -> return "ninety"
|
|
}
|
|
|
|
if (num in 21..99) {
|
|
val tens = twoDigitNumberToWords((num / 10) * 10)
|
|
val ones = twoDigitNumberToWords(num % 10)
|
|
return tens.plus(SPACE).plus(ones)
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
fun cacheDirUri(context: Context, fileName: String): String {
|
|
return "file://${context.externalCacheDir?.path}/$fileName"
|
|
}
|
|
|
|
fun getUpdatedBaseUrl(): String? =
|
|
PreferenceManager.getStringPreferenceApp(key = UPDATED_BASE_URL)
|
|
|
|
fun getUpdatedPulseBaseUrl(): String? =
|
|
PreferenceManager.getStringPreferenceApp(key = UPDATED_PULSE_BASE_URL)
|
|
|
|
fun getAlfredDialogDisabledStatus(): String? =
|
|
PreferenceManager.getStringPreferenceApp(key = ALFRED_DIALOG_SCREENSHOT)
|
|
|
|
fun saveBaseUrlsAndRestart(
|
|
updatedBaseUrl: String?,
|
|
updatedPulseBaseUrl: String?,
|
|
context: Context?
|
|
) {
|
|
val updateBaseUrl =
|
|
checkDiffAndSaveDataInSharedPreference(
|
|
sharedPrefKey = UPDATED_BASE_URL,
|
|
updatedValue = updatedBaseUrl
|
|
)
|
|
|
|
val updatePulseBaseUrl =
|
|
checkDiffAndSaveDataInSharedPreference(
|
|
sharedPrefKey = UPDATED_PULSE_BASE_URL,
|
|
updatedValue = updatedPulseBaseUrl
|
|
)
|
|
|
|
if (updateBaseUrl || updatePulseBaseUrl) {
|
|
triggerAppRestart(context = context)
|
|
}
|
|
}
|
|
|
|
fun checkDiffAndSaveDataInSharedPreference(
|
|
sharedPrefKey: String,
|
|
updatedValue: String?
|
|
): Boolean {
|
|
if (updatedValue.isNullOrEmpty()) {
|
|
return false
|
|
}
|
|
val currentValue = PreferenceManager.getStringPreferenceApp(key = sharedPrefKey)
|
|
if (updatedValue != currentValue) {
|
|
PreferenceManager.saveStringPreferenceAppOnMainThread(
|
|
key = sharedPrefKey,
|
|
value = updatedValue
|
|
)
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
fun triggerAppRestart(context: Context?) {
|
|
val packageManager: PackageManager? = context?.packageManager
|
|
val intent: Intent? = packageManager?.getLaunchIntentForPackage(context.packageName)
|
|
val componentName: ComponentName? = intent?.component
|
|
val mainIntent = Intent.makeRestartActivityTask(componentName)
|
|
context?.startActivity(mainIntent)
|
|
try {
|
|
Runtime.getRuntime().exit(0)
|
|
} catch (e: Exception) {}
|
|
}
|
|
|
|
/**
|
|
* This function formats the entered digits in a group of 5 For ex: any phone number will be
|
|
* formatted as: 12345 67890
|
|
*/
|
|
fun phoneFormat(value: String): String {
|
|
var tempValue = value
|
|
tempValue = tempValue.replace(SPACE, EMPTY)
|
|
var result = EMPTY
|
|
val partition = 5
|
|
val start = 0
|
|
val end = 10
|
|
for ((digitCount, i) in tempValue.indices.withIndex()) {
|
|
if (digitCount == partition && i > start && i < end) {
|
|
result = "$result "
|
|
}
|
|
result += tempValue[i].toString()
|
|
}
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* This function formats the entered amount with commas For ex: 1000000 will be formatted as
|
|
* 10,00,000
|
|
*/
|
|
fun moneyFormat(value: String): String {
|
|
var tempValue = value.toDoubleWithSafe().toLong().toString()
|
|
var result = EMPTY
|
|
tempValue = tempValue.replace(COMMA, EMPTY)
|
|
if (tempValue.isEmpty()) return result
|
|
val lastDigit = tempValue[tempValue.length - 1]
|
|
val len = tempValue.length - 1
|
|
var nDigits = 0
|
|
for (i in len - 1 downTo 0) {
|
|
result = tempValue[i].toString() + result
|
|
nDigits++
|
|
if (nDigits % 2 == 0 && i > 0) {
|
|
result = ",$result"
|
|
}
|
|
}
|
|
return result + lastDigit
|
|
}
|
|
|
|
fun saveUpdatedBaseUrlAndRestart(updatedBaseUrl: String?, context: Context?) {
|
|
val updateBaseUrl =
|
|
checkDiffAndSaveDataInSharedPreference(
|
|
sharedPrefKey = UPDATED_BASE_URL,
|
|
updatedValue = updatedBaseUrl
|
|
)
|
|
if (updateBaseUrl) {
|
|
triggerAppRestart(context = context)
|
|
}
|
|
}
|
|
|
|
fun saveUpdatedVersionCodeAndRestart(updatedVersionCode: String?, context: Context?) {
|
|
val updatedVersionCode =
|
|
checkDiffAndSaveDataInSharedPreference(
|
|
sharedPrefKey = UPDATED_VERSION_CODE,
|
|
updatedValue = updatedVersionCode
|
|
)
|
|
if (updatedVersionCode) {
|
|
triggerAppRestart(context = context)
|
|
}
|
|
}
|
|
|
|
fun getDebugVersionCode(): String? =
|
|
PreferenceManager.getStringPreferenceApp(key = UPDATED_VERSION_CODE)
|
|
|
|
fun getVersionSDKInt() = Build.VERSION.SDK_INT
|
|
|
|
fun isUpiAppAvailable(context: Context?): Boolean {
|
|
if (context == null) {
|
|
return false
|
|
}
|
|
val upiIntent = Intent(Intent.ACTION_VIEW, Uri.parse(UPI_APP_INTENT_URL))
|
|
val pm = context.packageManager
|
|
pm?.let {
|
|
val upiActivities = it.queryIntentActivities(upiIntent, 0)
|
|
return (upiActivities.isNotEmpty())
|
|
}
|
|
return false
|
|
}
|
|
}
|