others-how to solve `java.lang.NoSuchMethodError: No static method encodeBase64URLSafeString` that caused by conflict between imported library and our environment?
1. Purpose
In this post, I will try to solve the following error when trying to access the encodeBase64URLSafeString
method in commons-codec:
2022-07-03 10:47:34.181 22021-22583/? E/AndroidRuntime: FATAL EXCEPTION: Thread-20
Process: com.bswen.app, PID: 22021
java.lang.NoSuchMethodError: No static method encodeBase64URLSafeString([B)Ljava/lang/String; in class Lorg/apache/commons/codec/binary/Base64; or its super classes (declaration of 'org.apache.commons.codec.binary.Base64' appears in /system/framework/org.apache.http.legacy.boot.jar)
at com.bswen.app3.ui.misc.GoogleSigninActivity.a(SourceFile:31)
at com.bswen.app3.ui.misc.GoogleSigninActivity$b$a.run(SourceFile:1)
at java.lang.Thread.run(Thread.java:764)
The code that caused the above problem:
byte[] rawMessageBytes = buffer.toByteArray();
String encodedEmail = Base64.encodeBase64URLSafeString(rawMessageBytes);
The problem occurred because there is a conflict between commons-codec and org.apache.http.legacy.boot.jar in android system. They both have the class named org.apache.commons.codec.binary.Base64
, but they have different versions.
2. Solution
2.1 Solution #1
Because it can not find the method, so we can just create one:
private static String encodeBase64URLSafeString(byte[] binaryData) {
return android.util.Base64.encodeToString(binaryData, Base64.URL_SAFE);
}
2.2 Solution #2
Or we can use jarjar
tool to transplant the commons-codec library to a custom library for us.
Jar Jar Links is a utility that makes it easy to repackage Java libraries and embed them into your own distribution. This is useful for two reasons: You can easily ship a single jar file with no external dependencies.
To simplify ,jarjar allow us to change the package of an existing library to a customized package name, then we can avoid the conflication problem when importing library to our project.
To use jarjar, we first need to create a rules.txt
,which tells jarjar how to change the library:
Create a rules.txt as follows:
rule pattern result
zap pattern
rule org.apache.commons.codec.** com.bswen.codec.@1
The above rule tells jarjar to change the package name of commons-codec library from org.apache.commons.codec
to our customized name com.bswen.codec
then create new jar with jarjar
java -jar jarjar-1.4.jar process ./rules.txt commons-codec-1.6.jar bswen-codec-1.6.jar
then you get this:
➜ commons_codec ll
total 5448
-rw-r--r--@ 1 bswen staff 1.2M Jul 8 21:26 commons-codec-1.6-bin.zip
-rw-r--r--@ 1 bswen staff 227K Jul 8 21:29 commons-codec-1.6.jar
-rw-r--r--@ 1 bswen staff 118K Jul 8 21:24 jarjar-1.4.jar
-rw-r--r-- 1 bswen staff 225K Jul 8 21:38 bswen-codec-1.6.jar
-rw-r--r-- 1 bswen staff 88B Jul 8 21:38 rules.txt
check the packages inside the jar:
➜ commons_codec java -jar jarjar-1.4.jar strings bswen-codec-1.6.jar
com.bswen.codec.net.Utils
44: "Invalid URL encoding: not a valid digit (radix 16): "
com.bswen.codec.net.URLCodec
103: "UTF-8"
179: "Invalid URL encoding: "
312: "Objects of type "
312: " cannot be URL encoded"
337: "Objects of type "
337: " cannot be URL decoded"
com.bswen.codec.net.RFC1522Codec
"?="
"=?"
88: "=?"
95: "?="
118: "=?"
118: "?="
119: "RFC 1522 violation: malformed encoded content"
125: "RFC 1522 violation: charset token not found"
129: "RFC 1522 violation: charset not specified"
134: "RFC 1522 violation: encoding token not found"
138: "This codec cannot decode "
138: " encoded content"
com.bswen.codec.net.QuotedPrintableCodec
96: "UTF-8"
190: "Invalid quoted-printable encoding"
324: "Objects of type "
324: " cannot be quoted-printable encoded"
349: "Objects of type "
349: " cannot be quoted-printable decoded"
com.bswen.codec.net.QCodec
...
You can see that the package name has been successfully changed to com.bswen.codec...
, then we can just import the new pacakge com.bswen.codec
and use it to do base64 encoding and decoding.
3. Summary
In this post, I demonstrated how to solve the java.lang.NoSuchMethodError when trying to import a library into our project , the problem is caused by the confliction between the imported library and our runtime environment, to solve this problem, we can create the missing method or just transplant the library into our customized package . That’s it, thanks for your reading.