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
相关产品推荐
相关产品推荐

