java - Android mediaPlayer渐进式下载 "Connection Reset By Peer"

标签 java android http media spark-java

我在使用 android MediaPlayer 时遇到了问题,我首先在播放之前将整首歌曲缓存到内存中,然后我决定从用 SparkJava 编写的 api 流式传输这首歌曲。所以现在如果我试图寻找加载点它工作得很好,否则它就会停止。并在 API 服务器中生成此内容:

    org.eclipse.jetty.io.EofException
at org.eclipse.jetty.io.ChannelEndPoint.flush(ChannelEndPoint.java:286)
at org.eclipse.jetty.io.WriteFlusher.flush(WriteFlusher.java:393)
at org.eclipse.jetty.io.WriteFlusher.completeWrite(WriteFlusher.java:349)
at org.eclipse.jetty.io.ChannelEndPoint$3.run(ChannelEndPoint.java:133)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:295)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: java.io.IOException: Connection reset by peer
at java.base/sun.nio.ch.SocketDispatcher.write0(Native Method)
at java.base/sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:54)
at java.base/sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:113)
at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:79)
at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:50)
at java.base/sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:484)
at org.eclipse.jetty.io.ChannelEndPoint.flush(ChannelEndPoint.java:264)

这是 API 部分使用的代码:

public static Object postAudioResponse(Request request, Response response) {
    try ( OutputStream os = response.raw().getOutputStream(); BufferedOutputStream bos = new BufferedOutputStream(os))
    {
        File mp3 = new File("C:\\FTPServer\\" + request.queryParams("dir"));
        String range = request.headers("Range");
        if (range == null) {
            response.status(200);
            byte[] bytes = Files.readAllBytes(java.nio.file.Paths.get("C:\\FTPServer\\" + request.queryParams("dir")));
            response.header("Content-Type", "audio/mpeg");
            response.header("Content-Length", String.valueOf(bytes.length));
            System.out.println(response.raw().toString());
            HttpServletResponse raw = response.raw();
            raw.getOutputStream().write(bytes);
            raw.getOutputStream().flush();
            raw.getOutputStream().close();
            return raw;
        }
        int[] fromTo = fromTo(mp3, range);
        int length = fromTo[1] - fromTo[0] + 1;
        response.status(206);
        response.raw().setContentType("audio/mpeg");
        response.header("Accept-Ranges", "bytes");
        response.header("Content-Range", contentRangeByteString(fromTo));
        response.header("Content-Length", String.valueOf(length));
        final RandomAccessFile raf = new RandomAccessFile(mp3, "r");
        raf.seek(fromTo[0]);
        writeAudioToOS(length, raf, bos);
        raf.close();
        bos.flush();
        bos.close();
        return response.raw();
    } catch (IOException e) {
        e.printStackTrace();
        response.header("Content-Type", "application/json");
        return gson.toJson(new StandardResponse(StatusResponse.ERROR, e.toString()));
    }
}

这是我的 API HTTP 响应(字符串格式)

HTTP/1.1 206 
Date: Wed, 04 Mar 2020 19:39:45 GMT
Content-Type: audio/mpeg
Accept-Ranges: bytes
Content-Range: bytes 4767443-4775635/8897707
Content-Length: 8193

我尝试了多种方法,更改 header ,多次验证 header ,尝试了 ExoPlayer,我什至检查了 HTTP 部分的 Android 源代码,它似乎是正确的。

Android 代码:

mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(Api.getSongSource(songName));
mediaPlayer.prepareAsync();

注意:异常发生在我发送内容在特定范围内的新 HTTP 响应之前。 谢谢。

* UPD *

我在第一个答案中解决了这个问题。

最佳答案

我通过执行以下操作修复了上述错误

*客户端 我没有使用android原生SDK中的mediaPlayer,而是使用ExoMedia(这是ExoPlayer的接口(interface),但与mediaPlayer具有相同的功能)

*服务器端

使用 ExoMedia 后,我开始注意到一些事情,当我寻找尚未加载的点时,它从该部分播放了一小部分时间, 也许 50 毫秒,所以我开始挖掘并发现了以下内容。

当服务器收到带有Range的请求时,服务器会查找来自,然后发送带有数据[From, From + Chunk]的响应。 p>

我的 block 等于8192,在增加 block 部分后,我可以注意到这首歌的播放时间更长。因此,不要发送 [From, From + Chunk] 并等待 ExoMedia 请求下一部分。

我发送了整个[歌曲的起始、结束]。这解决了我的错误。 .

关于java - Android mediaPlayer渐进式下载 "Connection Reset By Peer",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60533644/

相关文章:

javascript - 如何从 Node 响应对象获取请求 URL?

java - 为分散的日历项目选择数据库类型

java - 使用 java 8 流处理空属性并使用 lambda 表达式进行排序

java - 如何在 Java 中管理多个自定义异常

javascript - 在成功登录后运行 HTTP post

http - 仅将一个文件夹重定向到 HTTPS,将所有其他文件夹重定向到 HTTP

java - 如何使用另一个 JLabel 控制 Java Swing JLabel

java - 从字符串中提取多个子字符串(例如 "B#####",其中 # 是所有可能的数字) - Java - Android

android - 如何在 android sqlite 中更新具有列值更改的特定行

android - 在 setSdclangVars() 上的 soong-cc-config 测试中构建 Android msm-3.18 内核失败