Apache Commons Codec与Android:找不到方法

54

今天我尝试在我的Android应用程序中包含apache.commons.codec包,但无法运行。Android找不到org.apache.commons.codec.binary.*方法,并在DDMS中输出以下错误。

01-12 08:41:48.161: ERROR/dalvikvm(457): 无法找到 org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString 方法,它被 com.dqminh.app.util.Util.sendRequest 方法引用

01-12 08:41:48.161: WARN/dalvikvm(457): VFY: 无法解析静态方法10146: Lorg/apache/commons/codec/binary/Base64;.encodeBase64URLSafeString ([B)Ljava/lang/String;

01-12 08:41:48.161: WARN/dalvikvm(457): VFY: 在 0x0004 处拒绝操作码 0x71

如何解决这个问题?非常感谢。


3
你是否已经成功使用apache.commons.codec中的任何类?这个问题仅仅是针对该类还是你认为所有的类都不能用?请简明扼要回答。 - David Webb
11个回答

65

我在开发中使用Android时遇到了类似的问题,这与我正在开发的OAuth库有关。

尽管我已将apache.commons.codec包含在类路径中,但从Android中获得的信息是找不到特定方法(encodeBase64String)。

检查Java文档,两种方法都声称仅适用于1.4及更高版本,因此我的猜测是Android已经包含一个旧版本的commons.codec,其中确实未定义这些方法。

我的解决方案是使用旧的方法,就像这样:

String encodedString = new String(Base64.encodeBase64('string to encode'));

您想要使用的方法与普通方法不同,因为它将 + 和 / 替换为 url 安全值 - 和 _。因此,您可能需要使用类似以下内容的内容:

String encodedString = new String(Base64.encodeBase64('string to encode'));
String safeString = encodedString.replace('+','-').replace('/','_');

我已经为此苦苦挣扎了两天!只是一个问题,如果我要替换+和-,我该如何解码?如果原始编码字符串(在替换之前)已经包含+和-怎么办? - jax
我猜这没关系,你可以像上面的例子一样做。 - Pablo Fernandez

18

你不必使用Apache Commons,而在Android上,你可以使用android.util.Base64代替。


4
有用,但需要API 8级(2.2.x)以上。 - Anton I. Sipos
2
如果您正在使用依赖于Commons-Codec的库,则此方法无法正常工作。 - William
11
请注意,您需要使用Base64.encode("foobar".getBytes(), Base64.Base64.NO_WRAP);才能获得与Apache Commons库完全相同的结果。参见:https://dev59.com/B2Mm5IYBdhLWcg3wDrpR - Dylan Watson
@DylanWatson:非常感谢!!!我没有设置“NO_WRAP”,这导致了 Android-Java 和我正在编程的“桌面”Java 应用程序之间通信中的问题。谢谢!! - Martin Pfeffer

13

我遇到了完全相同的问题。于是我开始浏览Android源代码,结果发现Pablo Fernandez关于Android有一个org.apache.commons.code.binary实现的猜测是正确的。然而,它使用的是apache commons 1.2版本,而不是1.4甚至1.5版本。你可以在Android 源代码中亲自查看。

需要注意的是,这个问题已经是一个重复的帖子


“Source” 的链接已经失效了,您能修复一下吗? - Michel Ayres

11


5

我解决相同问题的方法是将有问题的类org.apache.commons.codec.binary.Base64.java重命名为org.apache.commons.codec.binary.ApacheBase64.java。我使用Eclipse的 refactor-rename 功能完成这个操作。

这样,最新和最好的 Apache 解决方案得以保留和使用,当我的应用程序最终从 Android 1.6 的低端设备转移到更高级别设备时,就不会意外地出现问题。

请注意,我已经将整个 Apache Commons 源代码树设置为一个单独的 Eclipse Java 项目,与我的 Android 项目并列。我的 Android 项目使用了许多 Apache Commons 类,但由于上述问题而在 Base64 上失败了...


我在使用哈希时遇到了完全相同的问题,但我通过类似的方式解决了它(实际上我重构了整个编解码库的包名称)。 - tstaylor7

3
请注意,此答案是由Dylan Watson在上面的评论中提供的:

请注意,您需要使用Base64.encode("foobar".getBytes(), Base64.Base64.NO_WRAP); 才能获得与apache commons库完全相同的结果。请参见:stackoverflow.com/questions/17912119

经过数小时的尝试,这个答案是唯一有效的,可以使我的Android应用程序与Java“桌面”应用程序进行通信。

以下是一些源代码,也许它会帮助其他人:

桌面应用程序的代码:

   private static String convertToBase64(String s) {
        byte[] bytes = new byte[0];
        try {
            bytes = (s.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return DatatypeConverter.printBase64Binary(bytes);
    }

这个代码片段用于Android应用程序

 public static String convertToBase64(String password) {

        byte[] bPwd = new byte[0];
        try {
            bPwd = (password.getBytes("UTF-8"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            password = new String(Base64.encode(bPwd, Base64.NO_WRAP), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return password;
    }

帮了我很多。特别是在使用aws签名生成java类“SignedRequestsHelper”来签署使用“org.apache.commons.codec.binary.Base64”的url时。但在android中,我们必须使用“android.util.Base64”。不得不用“signature = new String(Base64.encode(rawHmac, Base64.NO_WRAP), "UTF-8");”替换“Base64 encoder = new Base64(); signature = new String(encoder.encode(rawHmac));”才能使其正常工作。详细的评论是为了帮助未来的求助者。希望它能帮到其他人。谢谢..... - Ashiq

2
您可以在Gradle依赖项下导入以下库。
dependencies {
    implementation "commons-codec:commons-codec:1.11"
}

它将会起作用。


0

虽然这是一个老问题,但我最近在编译API Level 23时遇到了这个问题,并找到了另一种解决方案:使用guava项目。

// Encoding
String encodedString = BaseEncoding.base64().encode(text.getBytes(UTF_8));
System.out.println("encodedString: " + encodedString);

// Decoding
byte[] decodedString = BaseEncoding.base64().decode(encodedString);
System.out.println("decodedString: " + new String(decodedString, UTF_8));

我使用的是guava库(18.0),升级过程非常顺利。代码按预期工作。

在这里找到了解决方案:https://memorynotfound.com/encode-decode-base64-string-using-native-java/


0

你是否包含了 Apache Commons 项目库,例如

org.apache.commons:commons-compress
org.apache.commons:commons-email
org.apache.commons:commons-io
org.apache.commons:commons-lang3
org.apache.commons:commons-parent
org.apache.commons:commons-pool2

commons-codec 的 GAV 是

commons-codec:commons-codec 

但它的包名是

org.apache.commons.codec

这个包名会与Apache Commons项目库发生冲突,请尝试更改commons-codec的包名,然后将其生成为jar文件或导入已更改包名的源代码;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接