You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中Apache Commons Codecs Base64方法不存在异常求助

解决Android Activity中Apache Commons Base64与系统类冲突的问题

你遇到的问题核心是类名冲突:Android SDK从API Level 8开始提供了java.util.Base64类,而你引入的Apache Commons Codec库也有一个同名的org.apache.commons.codec.binary.Base64类。在Android Activity中,类加载机制优先使用了系统自带的java.util.Base64,但这个类并没有Apache库中的encodeBase64String()、decodeBase64()这些方法,所以才会提示“目标方法不存在”。而普通Java类环境中(比如JDK 7及以下)没有自带的java.util.Base64,所以只会调用你导入的Apache版本,运行正常。

下面给你三种可行的解决方案:

方案1:使用完全限定类名显式指定Apache的Base64

在所有调用Base64方法的地方,直接写出完整的类路径,强制使用Apache库的实现,避免类加载混淆。修改后的代码片段如下:

public String getSaltedHash(String password) throws Exception {
    byte[] salt = SecureRandom.getInstance("SHA1PRNG").generateSeed(saltLen);
    // 显式使用Apache的Base64
    return org.apache.commons.codec.binary.Base64.encodeBase64String(salt) + "$" + hash(password, salt);
}

public boolean check(String password, String stored) throws Exception {
    String[] saltAndPass = stored.split("\\$");
    if (saltAndPass.length != 2) {
        throw new IllegalStateException(
            "The stored password have the form 'salt$hash'");
    }
    // 显式使用Apache的Base64解码
    String hashOfInput = hash(password, org.apache.commons.codec.binary.Base64.decodeBase64(saltAndPass[0]));
    return hashOfInput.equals(saltAndPass[1]);
}

private String hash(String password, byte[] salt) throws Exception {
    if (password == null || password.length() == 0)
        throw new IllegalArgumentException("Empty passwords are not supported.");
    SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    SecretKey key = f.generateSecret(new PBEKeySpec(
        password.toCharArray(), salt, iterations, desiredKeyLen)
    );
    // 显式使用Apache的Base64编码
    return org.apache.commons.codec.binary.Base64.encodeBase64String(key.getEncoded());
}

方案2:静态导入Apache Base64的具体方法

如果你觉得全类名太冗长,可以通过静态导入指定要使用的Apache库方法,这样代码里直接写方法名即可:

// 替换原来的import语句,改为静态导入
import static org.apache.commons.codec.binary.Base64.encodeBase64String;
import static org.apache.commons.codec.binary.Base64.decodeBase64;

// 后续代码可以保持和原来一样,直接调用encodeBase64String和decodeBase64
public String getSaltedHash(String password) throws Exception {
    byte[] salt = SecureRandom.getInstance("SHA1PRNG").generateSeed(saltLen);
    return encodeBase64String(salt) + "$" + hash(password, salt);
}

方案3:改用Android自带的Base64实现

如果不想依赖Apache Commons库,可以直接替换成Android系统自带的java.util.Base64,它提供了类似的功能,只是方法名和参数略有不同:

修改后的代码片段:

// 替换Apache的import为系统的Base64
import java.util.Base64;

public String getSaltedHash(String password) throws Exception {
    byte[] salt = SecureRandom.getInstance("SHA1PRNG").generateSeed(saltLen);
    // 使用Android系统Base64编码,指定DEFAULT模式
    return Base64.encodeToString(salt, Base64.DEFAULT) + "$" + hash(password, salt);
}

public boolean check(String password, String stored) throws Exception {
    String[] saltAndPass = stored.split("\\$");
    if (saltAndPass.length != 2) {
        throw new IllegalStateException(
            "The stored password have the form 'salt$hash'");
    }
    // 使用Android系统Base64解码
    String hashOfInput = hash(password, Base64.decode(saltAndPass[0], Base64.DEFAULT));
    return hashOfInput.equals(saltAndPass[1]);
}

private String hash(String password, byte[] salt) throws Exception {
    if (password == null || password.length() == 0)
        throw new IllegalArgumentException("Empty passwords are not supported.");
    SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    SecretKey key = f.generateSecret(new PBEKeySpec(
        password.toCharArray(), salt, iterations, desiredKeyLen)
    );
    // 使用Android系统Base64编码
    return Base64.encodeToString(key.getEncoded(), Base64.DEFAULT);
}

这个方案的好处是不需要额外引入第三方库,更符合Android的生态环境,也避免了类名冲突的问题。

内容的提问来源于stack exchange,提问作者Leotrim Vojvoda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:19:42