ExoPlayer播放指定MP3流失败,求解析IllegalArgumentException错误
ExoPlayer播放MP3流链接错误解析
问题背景
使用ExoPlayer播放MP3流链接 https://go_fm.streampartner.nl/live?type=.mp3 时,出现流加载失败的异常。
错误核心原因
从错误日志的根异常可以定位问题:
java.lang.IllegalArgumentException: toASCII输入无效:go_fm.streampartner.nl Caused by: 输入不符合STD 3 ASCII规则。line: 0. preContext: . postContext: o_fm
问题出在域名 go_fm.streampartner.nl 中的下划线 _。根据**STD 3 ASCII(RFC 1123)**规范,域名的每个标签(点分隔的部分)只能包含字母、数字和连字符 -,下划线 _ 属于非法字符。
Android系统的IDN.toASCII方法会严格验证域名格式,当建立TLS连接时,SNI(Server Name Indication)需要将域名转换为ASCII格式,此时非法的下划线会触发验证失败,导致TLS连接无法建立,最终ExoPlayer加载流时抛出异常。
解决方案
1. 更换合法域名(推荐)
联系流服务提供商,将包含下划线的域名修改为符合RFC 1123规范的域名,例如将 go_fm 改为 go-fm。
2. 自定义HttpDataSource绕过验证(临时方案)
如果无法更换域名,可以自定义ExoPlayer的HttpDataSource,修改域名处理逻辑或禁用SNI验证。示例代码如下:
// 自定义OkHttpClient,跳过SNI的严格域名验证 OkHttpClient okHttpClient = new OkHttpClient.Builder() .sslSocketFactory(new SSLSocketFactory() { @Override public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException { // 忽略原host的下划线问题,直接使用socket连接 return socket; } @Override public String[] getDefaultCipherSuites() { return new String[0]; } @Override public String[] getSupportedCipherSuites() { return new String[0]; } @Override public Socket createSocket() throws IOException { return new Socket(); } }, (X509TrustManager) TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()).getTrustManagers()[0]) .build(); // 配置ExoPlayer使用自定义的HttpDataSource DefaultHttpDataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory() .setOkHttpClient(okHttpClient); // 初始化ExoPlayer时使用该dataSourceFactory ExoPlayer player = new ExoPlayer.Builder(context) .setMediaSourceFactory(new DefaultMediaSourceFactory(dataSourceFactory)) .build();
注意:该方案会降低TLS连接的安全性,仅作为临时替代方案使用。
完整错误日志
2024-04-16 17:16:03.298 8130-8228 LoadTask com.familiekoning.radionedplus E 加载流时出现意外异常 java.lang.IllegalArgumentException: toASCII输入无效:go_fm.streampartner.nl at java.net.IDN.toASCII(IDN.java:115) at javax.net.ssl.SNIHostName.(SNIHostName.java:99) at com.android.org.conscrypt.Platform.getSSLParameters(Platform.java:192) at com.android.org.conscrypt.ConscryptEngine.getSSLParameters(ConscryptEngine.java:525) at com.android.org.conscrypt.ConscryptEngineSocket.getSSLParameters(ConscryptEngineSocket.java:186) at com.android.okhttp.internal.Platform.configureTlsExtensions(Platform.java:121) at com.android.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:191) at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:153) at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:116) at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:186) at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128) at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97) at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289) at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:131) at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:90) at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:30) at androidx.media3.datasource.DefaultHttpDataSource.makeConnection(DefaultHttpDataSource.java:678) at androidx.media3.datasource.DefaultHttpDataSource.makeConnection(DefaultHttpDataSource.java:575) at androidx.media3.datasource.DefaultHttpDataSource.open(DefaultHttpDataSource.java:399) at androidx.media3.datasource.DefaultDataSource.open(DefaultDataSource.java:275) at androidx.media3.datasource.StatsDataSource.open(StatsDataSource.java:86) at androidx.media3.exoplayer.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:1029) at androidx.media3.exoplayer.upstream.Loader$LoadTask.run(Loader.java:421) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644) at java.lang.Thread.run(Thread.java:1012) Caused by: 输入不符合STD 3 ASCII规则。line: 0. preContext: . postContext: o_fm at android.icu.impl.IDNA2003.convertToASCII(IDNA2003.java:218) at android.icu.impl.IDNA2003.convertIDNToASCII(IDNA2003.java:276) at android.icu.text.IDNA.convertIDNToASCII(IDNA.java:654) at com.android.icu.text.ExtendedIDNA.convertIDNToASCII(ExtendedIDNA.java:50) at java.net.IDN.toASCII(IDNA.java:108) ... 27 more 2024-04-16 17:16:03.322 8130-8168 ExoPlayerImplInternal com.familiekoning.radionedplus E 播放错误 androidx.media3.exoplayer.ExoPlaybackException: 源错误 at androidx.media3.exoplayer.ExoPlayerImplInternal.handleIoException(ExoPlayerImplInternal.java:717) at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:693) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loopOnce(Looper.java:205) at android.os.Looper.loop(Looper.java:294) at android.os.HandlerThread.run(HandlerThread.java:67) Caused by: androidx.media3.exoplayer.upstream.Loader$UnexpectedLoaderException: Unexpected IllegalArgumentException: Invalid input to toASCII: go_fm.streampartner.nl at androidx.media3.exoplayer.upstream.Loader$LoadTask.run(Loader.java:442) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644) at java.lang.Thread.run(Thread.java:1012) Caused by: java.lang.IllegalArgumentException: Invalid input to toASCII: go_fm.streampartner.nl at java.net.IDN.toASCII(IDN.java:115) at javax.net.ssl.SNIHostName.(SNIHostName.java:99) at com.android.org.conscrypt.Platform.getSSLParameters(Platform.java:192) at com.android.org.conscrypt.ConscryptEngine.getSSLParameters(ConscryptEngine.java:525) at com.android.org.conscrypt.ConscryptEngineSocket.getSSLParameters(ConscryptEngineSocket.java:186) at com.android.okhttp.internal.Platform.configureTlsExtensions(Platform.java:121) at com.android.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:191) at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:153) at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:116) at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:186) at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128) at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97) at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289) at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:131) at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:90) at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:30) at androidx.media3.datasource.DefaultHttpDataSource.makeConnection(DefaultHttpDataSource.java:678) at androidx.media3.datasource.DefaultHttpDataSource.makeConnection(DefaultHttpDataSource.java:575) at androidx.media3.datasource.DefaultHttpDataSource.open(DefaultHttpDataSource.java:399) at androidx.media3.datasource.DefaultDataSource.open(DefaultDataSource.java:275) at androidx.media3.datasource.StatsDataSource.open(StatsDataSource.java:86) at androidx.media3.exoplayer.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:1029) at androidx.media3.exoplayer.upstream.Loader$LoadTask.run(Loader.java:421) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644) at java.lang.Thread.run(Thread.java:1012) Caused by: 输入不符合STD 3 ASCII规则。line: 0. preContext: . postContext: o_fm at android.icu.impl.IDNA2003.convertToASCII(IDNA2003.java:218) at android.icu.impl.IDNA2003.convertIDNToASCII(IDNA2003.java:276) at android.icu.text.IDNA.convertIDNToASCII(IDNA.java:654) at com.android.icu.text.ExtendedIDNA.convertIDNToASCII(ExtendedIDNA.java:50) at java.net.IDN.toASCII(IDNA.java:108)
内容的提问来源于stack exchange,提问作者Patrick Koning
相关产品推荐
相关产品推荐

