异常信息
Fatal Exception: java.nio.charset.IllegalCharsetNameException: java.nio.charset.CharsetICU[UTF-8]
at java.nio.charset.Charset.checkCharsetName(Charset.java:201)
at java.nio.charset.Charset.forName(Charset.java:295)
at java.net.URLEncoder.encode(URLEncoder.java:57)
at cn.itmob.demo.MainActivity.displayTerms(MainActivity.java:2)
at android.view.View.performClick(View.java:4796)
at android.view.View$PerformClick.run(View.java:19889)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:947)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:742)
解决方法
因为在 Android 6(Android Marshmallow)和之前的版本中 JDK 的 Charset.toString()
方法的返回值是 java.nio.charset.CharsetICU[UTF-8]
,它作为编码名称肯定是不对的。应该使用 Charset.name()
方法。
例如在 Java 或 Kotlin 代码中使用编码时使用了 toString()
方法获取编码名称:
URLEncoder.encode(json, StandardCharsets.UTF_8.toString());
应该使用 name() 方法:
URLEncoder.encode(json, StandardCharsets.UTF_8.name())
异常相关的源码
如下是不同 Android 版本中 Charset
的 toString()
方法 JDK 源码:
Android 6(Android Marshmallow)
https://android.googlesource.com/platform/libcore/+/refs/heads/marshmallow-release/luni/src/main/java/java/nio/charset/Charset.java
/**
* Gets a string representation of this charset. Usually this contains the
* canonical name of the charset.
*
* @return a string representation of this charset.
*/
@Override
public final String toString() {
return getClass().getName() + "[" + this.canonicalName + "]";
}
Android 7(Android Nougat)
https://android.googlesource.com/platform/libcore/+/refs/heads/nougat-release/ojluni/src/main/java/java/nio/charset/Charset.java
/**
* Returns a string describing this charset. </p>
*
* @return A string describing this charset
*/
public final String toString() {
return name();
}
所有Android 7之后的版本不存在这个问题,但是使用时还是应该用 name()
方法避免出现问题。