三星Galaxy S4(SGS4)上的Android套接字问题

8
我们最近收到了关于三星Galaxy S4上我们的Android应用中音频无法播放的报告。在其他设备上,该应用程序正常运行。
使用MediaPlayer流式传输音频。使用Android Socket方法在本地保存。
Logcat中的警告是由以下原因引起的:
try {
    byte[] buffer = httpString.toString().getBytes();
    int readBytes = -1;
    Log.d(LOG_TAG, "writing to client");
    client.getOutputStream().write(buffer, 0, buffer.length);

    // Start streaming content.
    byte[] buff = new byte[1024 * 64];
    while (isRunning && (readBytes = data.read(buff, 0, buff.length)) != -1) {
        client.getOutputStream().write(buff, 0, readBytes);
    }
}

堆栈跟踪如下:
D/StreamProxy(3913): downloaded
D/StreamProxy(3913): downloading...
D/StreamProxy(3913): reading headers
D/StreamProxy(3913): headers done HTTP/1.0 200 OK
D/StreamProxy(3913): Content-Type: audio/mpeg
D/StreamProxy(3913): 
D/StreamProxy(3913): writing to client
W/StreamProxy(3913): Broken pipe.
W/StreamProxy(3913): java.net.SocketException: sendto failed: EPIPE (Broken pipe)
W/StreamProxy(3913):    at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:506)
W/StreamProxy(3913):    at libcore.io.IoBridge.sendto(IoBridge.java:475)
W/StreamProxy(3913):    at java.net.PlainSocketImpl.write(PlainSocketImpl.java:507)
W/StreamProxy(3913):    at java.net.PlainSocketImpl.access$100(PlainSocketImpl.java:46)
W/StreamProxy(3913):    at java.net.PlainSocketImpl$PlainSocketOutputStream.write(PlainSocketImpl.java:269)
W/StreamProxy(3913):    at com.gm.mobile.util.StreamProxy.processRequest(StreamProxy.java:234)
W/StreamProxy(3913):    at com.gm.mobile.util.StreamProxy.run(StreamProxy.java:123)
W/StreamProxy(3913):    at java.lang.Thread.run(Thread.java:856)
W/StreamProxy(3913): Caused by: libcore.io.ErrnoException: sendto failed: EPIPE (Broken pipe)
W/StreamProxy(3913):    at libcore.io.Posix.sendtoBytes(Native Method)
W/StreamProxy(3913):    at libcore.io.Posix.sendto(Posix.java:151)
W/StreamProxy(3913):    at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:177)
W/StreamProxy(3913):    at libcore.io.IoBridge.sendto(IoBridge.java:473)
W/StreamProxy(3913):    ... 6 more
E/(3913): client closing
D/StreamProxy(3913): Proxy interrupted. Shutting down.

当我注释掉代理代码时,流可以播放,但是它会开始播放一秒钟,然后缓冲2-3秒钟,之后才恢复播放。任何解决方案都将不胜感激。
我找到了类似的问题,但它们没有得到解决:
- Android : Socket - java.net.SocketException: sendto failed: EPIPE (Broken pipe) - Media Player socket exception in Samsung Grand

我一直遇到同样的问题,但还没有解决 :( - Nick
至少我不是唯一一个。你有比我更进一步吗?你能分享一些有助于解决问题的信息吗? - SteveEdson
很遗憾,我没有S4进行测试。除了S4之外,我在其他几个设备上也看到过这种情况,但是我还没有找到问题的根源。如果我有任何发现,我会在这里更新。 - Nick
你不一定需要在服务器上更改它。在从服务器收到请求后,您可以在将其发送回媒体播放器之前更改标头为任何您想要的内容。 - Nick
@Nick,很遗憾更改状态行没有任何效果。谢谢Arpit,我会尝试并报告结果。 - SteveEdson
显示剩余3条评论
2个回答

4
我终于找到了导致问题的原因。如预期,媒体播放器正在进行范围请求以查找id3信息。在其他手机上,只需将标头状态行设置为HTTP/1.0 206 OK即可防止媒体播放器执行这些范围请求。但是,由于某种奇怪的原因,在S4上不适用(感谢三星!)。
因此,要修复它,您只需要处理这些范围请求。在我的情况下,我只调用了一次socket.accept()。我将其更改为在run()函数中循环执行,只要isRunning为真,就会处理新请求。我的代码的简化版本如下...
public void run() {

    while (isRunning) {

        client = socket.accept();

        HttpResponse cloudResponse = startCloudRequest();
        sendDataToMediaPlayer(cloudResponse);

    }
}

希望这能帮到你。

你好。能否分享更多的代码?我只在某些歌曲上遇到了这个问题,似乎无法解决。 - frostymarvelous

0

Broken Pipe通常发生在对方关闭了与您的连接时。确保正确代理头部,然后在放入正文之前加入两个换行符。您向另一端提供的某些内容可能会导致套接字关闭...这只在S4上发生吗?您是否发送了内容长度?


是的,这只发生在Galaxy S4上,在数百个其他设备上没有问题。据我所知,内容长度为0,因为它是一个理论上永远不会结束的实时流。 - SteveEdson
我在头部发送内容长度。如果不这样做,媒体播放器将无法知道歌曲的长度,因此不会显示持续时间。最有可能发生这种情况(尽管我无法确认)是因为媒体播放器正在进行范围请求,之后没有得到正确的信息。然而,我不知道如何停止这个范围请求(在所有其他手机上发送http1.0可以解决问题)。我也在某些Note 2和LG Optimus G版本上看到了这种情况。 - Nick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接