Home > Software engineering >  ANR android to calculate cpf digit if it is valid
ANR android to calculate cpf digit if it is valid

Time:01-10

I'm getting ANR from play store in a method of calculating CPF and CNPJ digits, calculating valid CPF

fun isValidCPF(cpf: String?): Boolean {
            if (cpf == null || cpf.length != 11) return false
            if (cpf.trim { it <= ' ' } == "00000000000") {
                return false
            }
            val digit1 = calculateDigit(cpf.substring(0, 9), weightCPF)
            val digit2 = calculateDigit(cpf.substring(0, 9)   digit1, weightCPF)
            return cpf == cpf.substring(0, 9)   digit1.toString()   digit2.toString()
        }
private val weightCPF = intArrayOf(11, 10, 9, 8, 7, 6, 5, 4, 3, 2)
private fun calculateDigit(str: String, weightCPF: IntArray): Int {
            var sum = 0
            var index = str.length - 1
            var digit: Int
            while (index >= 0) {
                try {
                    digit = Integer.parseInt(str.substring(index, index   1))
                    sum  = digit * weightCPF[weightCPF.size - str.length   index]
                    index--
                } catch (ex: NumberFormatException) {
                    Timber.e(ex, "calculateDigit: %s", ex.message)
                }
            }
            sum = 11 - sum % 11
            return if (sum > 9) 0 else sum
        }

Does anyone know why i am getting this ANR? I can't reproduce the error

CodePudding user response:

You get an infinite loop when any of the characters isn't a digit:

while (index >= 0) {
    try {
        digit = Integer.parseInt(str.substring(index, index   1))
        sum  = digit * weightCPF[weightCPF.size - str.length   index]
        index--
    } catch (ex: NumberFormatException) {
        Timber.e(ex, "calculateDigit: %s", ex.message)
    }
}

If parseInt fails, it throws an exception and jumps to the catch block without ever decrementing index, so you just end up spinning on the same index value and its invalid character forever.

I don't know how you want to handle invalid characters, but if you just want to skip them, you could put the index-- outside the try/catch so it always runs every loop. If it should immediately fail, you could do an early return or throw an exception.


You also have an issue in your validation in isValidCPF:

if (cpf.trim { it <= ' ' } == "00000000000") {
    return false
}

This implies that you're expecting the the function might be passed non-digit values - just to check the digits aren't all zeroes, you're trimming some invalid chars (only the ones preceding ! in this table though). But that trim only happens for this check - the rest of your code still uses the original string. So when you do this:

val digit1 = calculateDigit(cpf.substring(0, 9), weightCPF)

If that trim was necessary to check the digits before, isn't it necessary now? What if it has leading non-digit characters? You're just taking the first 9, whatever they happen to be (which is probably how you're ending up with the infinite loop situation).

I don't know exactly what you're doing, but you might want to use something like val trimmed = cpf.trim { !it.isDigit() } or { it !in ['0'..'9']) }. Or maybe even something like val filtered = cpf.filter { it.isDigit() } to remove all non-digit chars, and then decide if you have enough to consider it valid and continue processing. Depends what you're doing of course! Just giving you some options.

CodePudding user response:

I presume "ANR" means "Application not responding" and CPF and CNPJ are some acronyms that no-one outside of Brazil has ever heard about and that we don't need to know about.

This ANR would happen if your while loop never terminates. This can only happen if there is an error. Luckily, you are logging the error, so check your logs to see what's gone wrong.

  • Related