Android 诡异错误[日积月累计划]

综述

最近在学安卓,遇到过一些诡异的错误。因此开一贴,用来记录错误和错误的原因。

1、Execution failed for task ‘:app:kaptDebugKotlin’.

一般是使用room的时候造成的错误。具体可能是@annotation错误或者data class错误。
我这次遇到的是后一种:

@Entity(tableName = "scale_node_table")
data class ScaleNodeInfo(
        @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "Device ID") val devId : Int,
        @ColumnInfo(name="Bus ID") val busId : Int,
        @ColumnInfo(name="Product Name") val name:String,
        @ColumnInfo(name="Product Price") val price:BigDecimal,
        @ColumnInfo(name="Scale Factor") val factor:BigDecimal,
        @ColumnInfo(name="Scale Base") val base:Int
)

上面的代码在编译的时候不会提示任何错误。但是实际上Room不能直接存储BigDecimal格式数据。
建议更改成String格式,在使用的时候将其转换成BigDecimal。

@Entity(tableName = "scale_node_table")
data class ScaleNodeInfo(
        @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "Device ID") val devId : Int,
        @ColumnInfo(name="Bus ID") val busId : Int,
        @ColumnInfo(name="Product Name") val name:String,
        @ColumnInfo(name="Product Price") val price:String,
        @ColumnInfo(name="Scale Factor") val factor:String,
        @ColumnInfo(name="Scale Base") val base:Int
)

这个原因很难找。

2、@dimen错误

昨天遇到一个诡异的错误,navigation到一个页面却怎么也打不开。检查了源码和layout的xml文件。感觉没什么问题。后来发现,把margin用@dimen/设置的时候.dimen的一个取值本应该是“16dp”,错误写成了“16”.这当然有错误。但没有错误提示。
这个错误很隐蔽,有时候匪夷所思。其实类似的xml资源导致的错误还有很多。尤其是开启dataBinding之后。

3、ByteArray转String问题

下面是一段kotlin的小程序,可以在线测试

fun main() {
    val a:String = "John Henry "
    val a_BA = a.toByteArray()
    val aStr = a_BA.toString()
    val aStr2 = String(a_BA)
    println("a is:$aStr or $aStr2")
}

运行结果如下:

a is:[B@7adf9f5f or John Henry

这个错误其实最开始发生在我写的一段RSA加解密程序。核心代码如下:

package com.example.loginwithrsa.ui.navi

import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import android.util.Base64
import java.security.KeyPairGenerator
import javax.crypto.Cipher

class PswSecurity {
    private val keyPairGenerator : KeyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA,"AndroidKeyStore")
    private val cipherEncrypt = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256andMGF1Padding")
    private val cipherDecrypt = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256andMGF1Padding")
    private val charset = Charsets.UTF_8
    suspend fun createKeyPair(){
        /*try to find keystore*/

        /*create*/
        val keyDecrypt = KeyGenParameterSpec.Builder(
                "user_psw_key",
                KeyProperties.PURPOSE_DECRYPT)
                .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
                .build()
        keyPairGenerator.initialize(keyDecrypt)
        val keyPair = keyPairGenerator.generateKeyPair()

        cipherEncrypt.init(Cipher.ENCRYPT_MODE, keyPair.public)
        cipherDecrypt.init(Cipher.DECRYPT_MODE,keyPair.private)
    }
    suspend fun encrypt(msg:String): String {
        return try{
            val iv = cipherEncrypt.iv
            val secret = cipherEncrypt.doFinal(msg.toByteArray(charset))
            Base64.encodeToString(secret,Base64.DEFAULT)
        }catch (e:Throwable){
            throw Throwable("can not encrypt", e)
        }
    }
    suspend fun decrypt(secret:String): String {
        return try {
            val msg = cipherDecrypt.doFinal(Base64.decode(secret,Base64.DEFAULT))
            String(msg)
            //msg.toString()
        }catch(e :Throwable){
            throw Throwable("Can not decrypt", e)
        }
    }
}

请注意上面的公钥和私钥暂时没有保存起来,所以每次运行是会变的。
可以看到编码的时候可以直接将string用toByteArray转过去,但是这个过程是不可逆的。
在解码之后byteArray却不能直接用toString转变,而是用String(byteArray[])的形式来实现。
如果不这么做得到的结果是乱码。
那里错了?
看下面的纠正:

fun main() {
    val a:String = "John Henry "
    val a_BA = a.toByteArray()
    val aStr = a_BA.toString(Charsets.UTF_8)
    val aStr2 = String(a_BA)
    println("a is:$aStr or $aStr2")
}

再次运行就对了

a is:John Henry or John Henry

所以问题看似复杂,其实说起来也很简单。ByteArray到String相当于一对多。String有很多编码形式。
但反过来String内部带有自己的编码格式,所以知道反过来怎么编码。

>、后续陆续添加

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值