Apache Commons Codec with Android: could not find method
Asked Answered
J

11

56

Today I tried including the apache.commons.codec package in my Android application and couldn't get it running. Android could not find method ord.apache.commons.codec.binary.* and output the following errors in DDMS

01-12 08:41:48.161: ERROR/dalvikvm(457): Could not find method org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString, referenced from method com.dqminh.app.util.Util.sendRequest

01-12 08:41:48.161: WARN/dalvikvm(457): VFY: unable to resolve static method 10146: Lorg/apache/commons/codec/binary/Base64;.encodeBase64URLSafeString ([B)Ljava/lang/String;

01-12 08:41:48.161: WARN/dalvikvm(457): VFY: rejecting opcode 0x71 at 0x0004

Any clue on how to solve this problem ? Thanks a lot.

Joellenjoelly answered 12/1, 2010 at 8:55 Comment(1)
Have you got any of the Classes in apache.commons.codec working? So is it a peculiar problem with just this class or do you think none of the classes are available?Ovoid
S
65

I had a similar problem while using android with an OAuth library I'm developing.

I also got from android that, although I had included apache.commons.codec in the classpath, a particular method (encodeBase64String) was not found.

Checking the javadocs, both methods claim to be 1.4 and greater only, so my guess is that android already includes an older version of commons.codec where these methods are indeed undefined.

My solution was to use an older method, like this:

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

The method you want to use is different since it replaces + and / with url-safe values - and _. So you probably might use something like:

String encodedString = new String(Base64.encodeBase64('string to encode'));
String safeString = encodedString.replace('+','-').replace('/','_');
Skat answered 28/3, 2010 at 16:10 Comment(2)
I have been struggling with this for two days now! Just a question though, if I were to replace the + and - how would I go about decoding? What if the original encoded string (before the replacement) already contained + and -Vortex
I guess it doesn't matter, you would do just the same as the example aboveSkat
T
18

You don't have to use apache commons, on android you can use android.util.Base64 instead.

Treasury answered 7/7, 2012 at 7:39 Comment(4)
Useful, but requires API level 8 (2.2.x).Comatulid
Doesn't work if you are using a library that depends on Commons-Codec.Perlite
Be aware that you need to use Base64.encode("foobar".getBytes(), Base64.Base64.NO_WRAP); to get exactly the same result as the apache commons library. See: stackoverflow.com/questions/17912119Aroma
@DylanWatson: Thank you so much!!! I didn't set the "NO_WRAP" and that caused the issue in the communication of android-java and the "desktop" java-app I'm programming. Thanks!!Centum
B
13

I experienced the exact same problem. So i started browsing the android source code, and as it turns out Pablo Fernandez's guess about Android having an implementation of org.apache.commons.code.binary is correct. However, its version 1.2 of the apache commons, not version 1.4 or even 1.5. You can see for your self in the android source.

as a note this is question is a duplicate of this post

Bumbling answered 5/5, 2011 at 18:10 Comment(1)
The link for "Source" is broken. Could you fix that?Heteromerous
F
11

You can use the following function:

private static String encodeBase64URLSafeString(byte[] binaryData) {

        return android.util.Base64.encodeToString(binaryData, Base64.URL_SAFE);

    }

source + listing of other possible flags: http://developer.android.com/reference/android/util/Base64.html

Farouche answered 18/5, 2015 at 15:19 Comment(0)
Y
5

You could simply copy this code bit from the apache library (it is pretty isolated) http://www.java2s.com/Open-Source/Android/Blog-Twitter/twitspeak/org/apache/commons/codec/binary/Base64.java.htm

Edit: Updated link from the Wayback Machine as the original is gone: http://web.archive.org/web/20130610025148/http://www.java2s.com/Open-Source/Android/Blog-Twitter/twitspeak/org/apache/commons/codec/binary/Base64.java.htm

Yet answered 9/11, 2011 at 1:58 Comment(0)
P
5

My solution to the same problem was to rename the problematic class org.apache.commons.codec.binary.Base64.java into org.apache.commons.codec.binary.ApacheBase64.java. I did it using Eclipse refactor-rename.

That way, the latest and greatest apache solution is preserved and used, and there is no chance for accidental problem recurrence when my app is eventually being lifted from android 1.6 lowest denominator.

Note I had the entire apache commons source tree already set as separate Eclipse java project, next to my Android project. My Android project used many of Apache Commons classes, but failed on Base64 because of above described problems...

Pickard answered 27/11, 2011 at 16:44 Comment(1)
I had the exact same issue with Hash, and was able to resolve it in a similar way (I actually refactored the package names for the entire Codec library).Gangplank
C
3

Please note that this answer was made by Dylan Watson in the comments above:

Be aware that you need to use Base64.encode("foobar".getBytes(), Base64.Base64.NO_WRAP); to get exactly the same result as the apache commons library. See: stackoverflow.com/questions/17912119

This answer was the only which worked after hours of trying to communicate my android app with a java "desktop" app.

So here is some source code, maybe it will help others:

Code from the desktop applet:

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

This snippet is used in the android app:

 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;
    }
Centum answered 3/4, 2015 at 1:55 Comment(1)
Helped me a lot. Specially when using aws signature generating java class "SignedRequestsHelper" to sign url which uses "org.apache.commons.codec.binary.Base64". But in android we have to use "android.util.Base64" Had to replace "Base64 encoder = new Base64(); signature = new String(encoder.encode(rawHmac));" with "signature = new String(Base64.encode(rawHmac, Base64.NO_WRAP), "UTF-8");" to make it work. Elaborated comment is for future help seekers. May it help others. Thanks.....Kingbolt
B
3

You can simply import the following library under Gradle dependency

dependencies {
    implementation "commons-codec:commons-codec:1.11"
}

It will work

Boldface answered 30/7, 2021 at 4:42 Comment(0)
M
0

did you include apache commons project lib,like

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

the commons-codec 's GAV is

commons-codec:commons-codec 

but it's package name is

org.apache.commons.codec

this package name will be conflict with apache commons project libs,try to change the package name of commons-codec,then generate it as a jar or import the source code had changed the package name;

Mcdevitt answered 23/12, 2016 at 5:12 Comment(0)
J
0

Knowing that this is an old question, but I faced this problem recently when compiling for API Level 23, and found another solution for the problem: use guava project.

// 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));

The guava library (18.0) was the version that I've used, and the change was smooth. The code works as expected.

Solution found in here: https://memorynotfound.com/encode-decode-base64-string-using-native-java/

Jobholder answered 7/2, 2018 at 9:23 Comment(0)
X
-1

This works for me:

import org.apache.commons.codec.binary.Base64;

/**
 * This is used to get the base64 from the bytes
 *
 * @param rawBytes the raw bytes
 * @return the base64 encoded string
 */
public static String getBase64String(byte[] rawBytes) {
    String base64Str = "";
    if (rawBytes!= null) {
        base64Str= new String(Base64.encodeBase64(rawBytes));
    }
    return base64Str;
}

public static byte[] getBase64DecodedString(String base64EncodedStr) {
    byte[] base64Bytes = Base64.decodeBase64(base64EncodedStr.getBytes());
    return bitmap;
}
Xanthate answered 17/7, 2018 at 21:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.