Upgrade to Kotlin 1.5 (#1397)
* build: upgrade Kotlin to 1.5.0 and Hilt to 2.35.1 Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * all: address kotlin.time.seconds deprecation Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * autofill-parser/openpgp-ktx: require Kotlin 1.5 Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * all: address string method deprecations Signed-off-by: Harsh Shandilya <me@msfjarvis.dev> * build: disable NewApi lint Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
parent
d3bc28c1c3
commit
4880e1db27
16 changed files with 43 additions and 38 deletions
|
@ -35,6 +35,11 @@ android {
|
||||||
isAbortOnError = true
|
isAbortOnError = true
|
||||||
isCheckReleaseBuilds = false
|
isCheckReleaseBuilds = false
|
||||||
disable("MissingTranslation", "PluralsCandidate", "ImpliedQuantity")
|
disable("MissingTranslation", "PluralsCandidate", "ImpliedQuantity")
|
||||||
|
// Kotlin 1.5 + AGP 4.1.3 trip up NewApi for Kotlin intrinsics like forEach
|
||||||
|
// This can be fixed by either switching to AGP 4.2.0-rc1, or disabling it
|
||||||
|
// outright.
|
||||||
|
// https://issuetracker.google.com/issues/185418482
|
||||||
|
disable("NewApi")
|
||||||
}
|
}
|
||||||
|
|
||||||
flavorDimensions("free")
|
flavorDimensions("free")
|
||||||
|
|
|
@ -27,8 +27,8 @@ import dev.msfjarvis.aps.util.settings.PreferenceKeys
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlin.time.Duration
|
||||||
import kotlin.time.ExperimentalTime
|
import kotlin.time.ExperimentalTime
|
||||||
import kotlin.time.seconds
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.collect
|
import kotlinx.coroutines.flow.collect
|
||||||
|
@ -121,7 +121,7 @@ class DecryptActivity : BasePgpActivity(), OpenPgpServiceConnection.OnBound {
|
||||||
@OptIn(ExperimentalTime::class)
|
@OptIn(ExperimentalTime::class)
|
||||||
private fun startAutoDismissTimer() {
|
private fun startAutoDismissTimer() {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
delay(60.seconds)
|
delay(Duration.seconds(60))
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,8 +60,8 @@ object RandomPhonemesGenerator {
|
||||||
|
|
||||||
private class Element(str: String, val flags: Int) {
|
private class Element(str: String, val flags: Int) {
|
||||||
|
|
||||||
val upperCase = str.toUpperCase(Locale.ROOT)
|
val upperCase = str.uppercase(Locale.ROOT)
|
||||||
val lowerCase = str.toLowerCase(Locale.ROOT)
|
val lowerCase = str.lowercase(Locale.ROOT)
|
||||||
val length = str.length
|
val length = str.length
|
||||||
val isAmbiguous = str.any { it in PasswordGenerator.AMBIGUOUS_STR }
|
val isAmbiguous = str.any { it in PasswordGenerator.AMBIGUOUS_STR }
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,10 +101,16 @@ class PasswordBuilder(ctx: Context) {
|
||||||
val candidate = wordBank.secureRandomElement()
|
val candidate = wordBank.secureRandomElement()
|
||||||
val s =
|
val s =
|
||||||
when (capsType) {
|
when (capsType) {
|
||||||
CapsType.UPPERCASE -> candidate.toUpperCase(Locale.getDefault())
|
CapsType.UPPERCASE -> candidate.uppercase(Locale.getDefault())
|
||||||
CapsType.Sentence -> if (i == 0) candidate.capitalize(Locale.getDefault()) else candidate
|
CapsType.Sentence ->
|
||||||
CapsType.TitleCase -> candidate.capitalize(Locale.getDefault())
|
if (i == 0)
|
||||||
CapsType.lowercase -> candidate.toLowerCase(Locale.getDefault())
|
candidate.replaceFirstChar {
|
||||||
|
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString()
|
||||||
|
}
|
||||||
|
else candidate
|
||||||
|
CapsType.TitleCase ->
|
||||||
|
candidate.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
|
||||||
|
CapsType.lowercase -> candidate.lowercase(Locale.getDefault())
|
||||||
CapsType.As_iS -> candidate
|
CapsType.As_iS -> candidate
|
||||||
}
|
}
|
||||||
password.append(s)
|
password.append(s)
|
||||||
|
|
|
@ -442,8 +442,7 @@ open class SearchableRepositoryAdapter<T : RecyclerView.ViewHolder>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final override fun getPopupText(position: Int): String {
|
final override fun getPopupText(position: Int): String {
|
||||||
return getItem(position).name[0].toString().toUpperCase(Locale.getDefault())
|
return getItem(position).name[0].toString().uppercase(Locale.getDefault())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
- Updated `androidx.annotation` to 1.1.0 and `androidx.autofill` to `1.2.0-alpha01`.
|
- Updated `androidx.annotation` to 1.1.0 and `androidx.autofill` to `1.2.0-alpha01`.
|
||||||
|
|
||||||
|
- The library now requires Kotlin 1.5.0 configured with `kotlinOptions.languageVersion = "1.5"`.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fix build warning from undeclared unsigned type use.
|
- Fix build warning from undeclared unsigned type use.
|
||||||
|
|
|
@ -39,19 +39,16 @@ internal class FormField(
|
||||||
HintConstants.AUTOFILL_HINT_USERNAME,
|
HintConstants.AUTOFILL_HINT_USERNAME,
|
||||||
HintConstants.AUTOFILL_HINT_NEW_USERNAME,
|
HintConstants.AUTOFILL_HINT_NEW_USERNAME,
|
||||||
)
|
)
|
||||||
|
|
||||||
private val HINTS_NEW_PASSWORD =
|
private val HINTS_NEW_PASSWORD =
|
||||||
listOf(
|
listOf(
|
||||||
HintConstants.AUTOFILL_HINT_NEW_PASSWORD,
|
HintConstants.AUTOFILL_HINT_NEW_PASSWORD,
|
||||||
)
|
)
|
||||||
|
|
||||||
private val HINTS_PASSWORD =
|
private val HINTS_PASSWORD =
|
||||||
HINTS_NEW_PASSWORD +
|
HINTS_NEW_PASSWORD +
|
||||||
listOf(
|
listOf(
|
||||||
HintConstants.AUTOFILL_HINT_PASSWORD,
|
HintConstants.AUTOFILL_HINT_PASSWORD,
|
||||||
HintConstants.AUTOFILL_HINT_WIFI_PASSWORD,
|
HintConstants.AUTOFILL_HINT_WIFI_PASSWORD,
|
||||||
)
|
)
|
||||||
|
|
||||||
private val HINTS_OTP =
|
private val HINTS_OTP =
|
||||||
listOf(
|
listOf(
|
||||||
HintConstants.AUTOFILL_HINT_SMS_OTP,
|
HintConstants.AUTOFILL_HINT_SMS_OTP,
|
||||||
|
@ -70,7 +67,6 @@ internal class FormField(
|
||||||
HintConstants.AUTOFILL_HINT_PHONE,
|
HintConstants.AUTOFILL_HINT_PHONE,
|
||||||
HintConstants.AUTOFILL_HINT_PHONE_NUMBER,
|
HintConstants.AUTOFILL_HINT_PHONE_NUMBER,
|
||||||
)
|
)
|
||||||
|
|
||||||
private val ANDROID_TEXT_FIELD_CLASS_NAMES =
|
private val ANDROID_TEXT_FIELD_CLASS_NAMES =
|
||||||
listOf(
|
listOf(
|
||||||
"android.widget.EditText",
|
"android.widget.EditText",
|
||||||
|
@ -79,9 +75,7 @@ internal class FormField(
|
||||||
"android.support.v7.widget.AppCompatEditText",
|
"android.support.v7.widget.AppCompatEditText",
|
||||||
"com.google.android.material.textfield.TextInputEditText",
|
"com.google.android.material.textfield.TextInputEditText",
|
||||||
)
|
)
|
||||||
|
|
||||||
private const val ANDROID_WEB_VIEW_CLASS_NAME = "android.webkit.WebView"
|
private const val ANDROID_WEB_VIEW_CLASS_NAME = "android.webkit.WebView"
|
||||||
|
|
||||||
private fun isPasswordInputType(inputType: Int): Boolean {
|
private fun isPasswordInputType(inputType: Int): Boolean {
|
||||||
val typeClass = inputType and InputType.TYPE_MASK_CLASS
|
val typeClass = inputType and InputType.TYPE_MASK_CLASS
|
||||||
val typeVariation = inputType and InputType.TYPE_MASK_VARIATION
|
val typeVariation = inputType and InputType.TYPE_MASK_VARIATION
|
||||||
|
@ -117,7 +111,6 @@ internal class FormField(
|
||||||
(HTML_INPUT_FIELD_TYPES_USERNAME + HTML_INPUT_FIELD_TYPES_PASSWORD + HTML_INPUT_FIELD_TYPES_OTP).toSet().toList()
|
(HTML_INPUT_FIELD_TYPES_USERNAME + HTML_INPUT_FIELD_TYPES_PASSWORD + HTML_INPUT_FIELD_TYPES_OTP).toSet().toList()
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O) private fun isSupportedHint(hint: String) = hint in HINTS_FILLABLE
|
@RequiresApi(Build.VERSION_CODES.O) private fun isSupportedHint(hint: String) = hint in HINTS_FILLABLE
|
||||||
|
|
||||||
private val EXCLUDED_TERMS =
|
private val EXCLUDED_TERMS =
|
||||||
listOf(
|
listOf(
|
||||||
"url_bar", // Chrome/Edge/Firefox address bar
|
"url_bar", // Chrome/Edge/Firefox address bar
|
||||||
|
@ -158,14 +151,13 @@ internal class FormField(
|
||||||
|
|
||||||
private val List<String>.anyMatchesFieldInfo
|
private val List<String>.anyMatchesFieldInfo
|
||||||
get() = any { fieldId.contains(it) || hint.contains(it) || htmlName.contains(it) }
|
get() = any { fieldId.contains(it) || hint.contains(it) || htmlName.contains(it) }
|
||||||
|
|
||||||
val autofillId: AutofillId = node.autofillId!!
|
val autofillId: AutofillId = node.autofillId!!
|
||||||
|
|
||||||
// Information for heuristics and exclusion rules based only on the current field
|
// Information for heuristics and exclusion rules based only on the current field
|
||||||
private val htmlId = node.htmlInfo?.attributes?.firstOrNull { it.first == "id" }?.second
|
private val htmlId = node.htmlInfo?.attributes?.firstOrNull { it.first == "id" }?.second
|
||||||
private val resourceId = node.idEntry
|
private val resourceId = node.idEntry
|
||||||
private val fieldId = (htmlId ?: resourceId ?: "").toLowerCase(Locale.US)
|
private val fieldId = (htmlId ?: resourceId ?: "").lowercase(Locale.US)
|
||||||
private val hint = node.hint?.toLowerCase(Locale.US) ?: ""
|
private val hint = node.hint?.lowercase(Locale.US) ?: ""
|
||||||
private val className: String? = node.className
|
private val className: String? = node.className
|
||||||
private val inputType = node.inputType
|
private val inputType = node.inputType
|
||||||
|
|
||||||
|
@ -186,10 +178,9 @@ internal class FormField(
|
||||||
private val htmlTag = node.htmlInfo?.tag
|
private val htmlTag = node.htmlInfo?.tag
|
||||||
private val htmlAttributes: Map<String, String> =
|
private val htmlAttributes: Map<String, String> =
|
||||||
node.htmlInfo?.attributes?.filter { it.first != null && it.second != null }?.associate {
|
node.htmlInfo?.attributes?.filter { it.first != null && it.second != null }?.associate {
|
||||||
Pair(it.first.toLowerCase(Locale.US), it.second.toLowerCase(Locale.US))
|
Pair(it.first.lowercase(Locale.US), it.second.lowercase(Locale.US))
|
||||||
}
|
}
|
||||||
?: emptyMap()
|
?: emptyMap()
|
||||||
|
|
||||||
private val htmlAttributesDebug = htmlAttributes.entries.joinToString { "${it.key}=${it.value}" }
|
private val htmlAttributesDebug = htmlAttributes.entries.joinToString { "${it.key}=${it.value}" }
|
||||||
private val htmlInputType = htmlAttributes["type"]
|
private val htmlInputType = htmlAttributes["type"]
|
||||||
private val htmlName = htmlAttributes["name"] ?: ""
|
private val htmlName = htmlAttributes["name"] ?: ""
|
||||||
|
@ -204,7 +195,6 @@ internal class FormField(
|
||||||
// HTML fields with non-fillable types (such as submit buttons) should be excluded here
|
// HTML fields with non-fillable types (such as submit buttons) should be excluded here
|
||||||
private val isAndroidTextField = !isHtmlField && className in ANDROID_TEXT_FIELD_CLASS_NAMES
|
private val isAndroidTextField = !isHtmlField && className in ANDROID_TEXT_FIELD_CLASS_NAMES
|
||||||
private val isAndroidPasswordField = isAndroidTextField && hasPasswordInputType
|
private val isAndroidPasswordField = isAndroidTextField && hasPasswordInputType
|
||||||
|
|
||||||
private val isTextField = isAndroidTextField || isHtmlTextField
|
private val isTextField = isAndroidTextField || isHtmlTextField
|
||||||
|
|
||||||
// Autofill hint detection for native fields
|
// Autofill hint detection for native fields
|
||||||
|
|
|
@ -144,7 +144,7 @@ internal class PublicSuffixListData(private val rules: ByteArray, private val ex
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
val WILDCARD_LABEL = byteArrayOf('*'.toByte())
|
val WILDCARD_LABEL = byteArrayOf('*'.code.toByte())
|
||||||
val PREVAILING_RULE = listOf("*")
|
val PREVAILING_RULE = listOf("*")
|
||||||
val EMPTY_RULE = listOf<String>()
|
val EMPTY_RULE = listOf<String>()
|
||||||
const val EXCEPTION_MARKER = '!'
|
const val EXCEPTION_MARKER = '!'
|
||||||
|
|
|
@ -42,7 +42,7 @@ internal fun ByteArray.binarySearch(labels: List<ByteArray>, labelIndex: Int): S
|
||||||
val byte0 =
|
val byte0 =
|
||||||
if (expectDot) {
|
if (expectDot) {
|
||||||
expectDot = false
|
expectDot = false
|
||||||
'.'.toByte()
|
'.'.code.toByte()
|
||||||
} else {
|
} else {
|
||||||
labels[currentLabelIndex][currentLabelByteIndex] and BITMASK
|
labels[currentLabelIndex][currentLabelByteIndex] and BITMASK
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ internal fun ByteArray.binarySearch(labels: List<ByteArray>, labelIndex: Int): S
|
||||||
/** Search for a '\n' that marks the start of a value. Don't go back past the start of the array. */
|
/** Search for a '\n' that marks the start of a value. Don't go back past the start of the array. */
|
||||||
private fun ByteArray.findStartOfLineFromIndex(start: Int): Int {
|
private fun ByteArray.findStartOfLineFromIndex(start: Int): Int {
|
||||||
var index = start
|
var index = start
|
||||||
while (index > -1 && this[index] != '\n'.toByte()) {
|
while (index > -1 && this[index] != '\n'.code.toByte()) {
|
||||||
index--
|
index--
|
||||||
}
|
}
|
||||||
index++
|
index++
|
||||||
|
@ -119,7 +119,7 @@ private fun ByteArray.findStartOfLineFromIndex(start: Int): Int {
|
||||||
/** Search for a '\n' that marks the end of a value. */
|
/** Search for a '\n' that marks the end of a value. */
|
||||||
private fun ByteArray.findEndOfLineFromIndex(start: Int): Int {
|
private fun ByteArray.findEndOfLineFromIndex(start: Int): Int {
|
||||||
var end = 1
|
var end = 1
|
||||||
while (this[start + end] != '\n'.toByte()) {
|
while (this[start + end] != '\n'.code.toByte()) {
|
||||||
end++
|
end++
|
||||||
}
|
}
|
||||||
return end
|
return end
|
||||||
|
|
|
@ -41,8 +41,8 @@ dependencies {
|
||||||
implementation("org.jetbrains.kotlinx:binary-compatibility-validator:0.5.0")
|
implementation("org.jetbrains.kotlinx:binary-compatibility-validator:0.5.0")
|
||||||
implementation("org.jetbrains.dokka:dokka-gradle-plugin:1.4.30")
|
implementation("org.jetbrains.dokka:dokka-gradle-plugin:1.4.30")
|
||||||
implementation("de.undercouch:gradle-download-task:4.1.1")
|
implementation("de.undercouch:gradle-download-task:4.1.1")
|
||||||
implementation("com.google.dagger:hilt-android-gradle-plugin:2.34.1-beta")
|
implementation("com.google.dagger:hilt-android-gradle-plugin:2.35.1")
|
||||||
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.32")
|
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.0")
|
||||||
implementation("com.ncorti.ktfmt.gradle:plugin:0.5.0")
|
implementation("com.ncorti.ktfmt.gradle:plugin:0.5.0")
|
||||||
implementation("com.vanniktech:gradle-maven-publish-plugin:0.13.0")
|
implementation("com.vanniktech:gradle-maven-publish-plugin:0.13.0")
|
||||||
implementation("com.vdurmont:semver4j:3.1.0")
|
implementation("com.vdurmont:semver4j:3.1.0")
|
||||||
|
|
|
@ -36,6 +36,7 @@ internal fun Project.configureForAllProjects() {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
jcenter {
|
jcenter {
|
||||||
content {
|
content {
|
||||||
// https://github.com/zhanghai/AndroidFastScroll/issues/35
|
// https://github.com/zhanghai/AndroidFastScroll/issues/35
|
||||||
|
@ -57,7 +58,7 @@ internal fun Project.configureForAllProjects() {
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||||
freeCompilerArgs = freeCompilerArgs + additionalCompilerArgs
|
freeCompilerArgs = freeCompilerArgs + additionalCompilerArgs
|
||||||
languageVersion = "1.4"
|
languageVersion = "1.5"
|
||||||
useIR = true
|
useIR = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ import dev.msfjarvis.aps.util.time.UserClock
|
||||||
import dev.msfjarvis.aps.util.totp.Otp
|
import dev.msfjarvis.aps.util.totp.Otp
|
||||||
import dev.msfjarvis.aps.util.totp.TotpFinder
|
import dev.msfjarvis.aps.util.totp.TotpFinder
|
||||||
import kotlin.collections.set
|
import kotlin.collections.set
|
||||||
|
import kotlin.time.Duration
|
||||||
import kotlin.time.ExperimentalTime
|
import kotlin.time.ExperimentalTime
|
||||||
import kotlin.time.seconds
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
@ -84,10 +84,10 @@ constructor(
|
||||||
scope.launch {
|
scope.launch {
|
||||||
updateTotp(clock.millis())
|
updateTotp(clock.millis())
|
||||||
val remainingTime = totpPeriod - (System.currentTimeMillis() % totpPeriod)
|
val remainingTime = totpPeriod - (System.currentTimeMillis() % totpPeriod)
|
||||||
delay(remainingTime.seconds)
|
delay(Duration.seconds(remainingTime))
|
||||||
repeat(Int.MAX_VALUE) {
|
repeat(Int.MAX_VALUE) {
|
||||||
updateTotp(clock.millis())
|
updateTotp(clock.millis())
|
||||||
delay(totpPeriod.seconds)
|
delay(Duration.seconds(totpPeriod))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ internal object Otp {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun calculateCode(secret: String, counter: Long, algorithm: String, digits: String) = runCatching {
|
fun calculateCode(secret: String, counter: Long, algorithm: String, digits: String) = runCatching {
|
||||||
val algo = "Hmac${algorithm.toUpperCase(Locale.ROOT)}"
|
val algo = "Hmac${algorithm.uppercase(Locale.ROOT)}"
|
||||||
val decodedSecret = BASE_32.decode(secret)
|
val decodedSecret = BASE_32.decode(secret)
|
||||||
val secretKey = SecretKeySpec(decodedSecret, algo)
|
val secretKey = SecretKeySpec(decodedSecret, algo)
|
||||||
val digest =
|
val digest =
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# Centralized versions for dependencies that share versions
|
# Centralized versions for dependencies that share versions
|
||||||
[versions]
|
[versions]
|
||||||
androidx_test = "1.4.0-alpha05"
|
androidx_test = "1.4.0-alpha05"
|
||||||
coroutines = "1.4.3"
|
coroutines = "1.5.0-RC"
|
||||||
hilt = "2.34.1-beta"
|
hilt = "2.35.1"
|
||||||
kotlin = "1.4.32"
|
kotlin = "1.5.0"
|
||||||
lifecycle = "2.4.0-alpha01"
|
lifecycle = "2.4.0-alpha01"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
### [Unreleased]
|
### [Unreleased]
|
||||||
|
|
||||||
|
- The library now requires Kotlin 1.5.0 configured with `kotlinOptions.languageVersion = "1.5"`.
|
||||||
|
|
||||||
### [3.0.0] - 2021-04-10
|
### [3.0.0] - 2021-04-10
|
||||||
- Relicence under Apache 2.0
|
- Relicence under Apache 2.0
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ public object OpenPgpUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun convertKeyIdToHex32bit(keyId: Long): String {
|
private fun convertKeyIdToHex32bit(keyId: Long): String {
|
||||||
var hexString = java.lang.Long.toHexString(keyId and 0xffffffffL).toLowerCase(Locale.ENGLISH)
|
var hexString = java.lang.Long.toHexString(keyId and 0xffffffffL).lowercase(Locale.ENGLISH)
|
||||||
while (hexString.length < 8) {
|
while (hexString.length < 8) {
|
||||||
hexString = "0$hexString"
|
hexString = "0$hexString"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue