Có một giải pháp cho vấn đề này trong Android 4.4 nhưng nó yêu cầu sử dụng Apache HttpClient. Điều này dựa trên khả năng cung cấp trình phân tích cú pháp phản hồi tùy chỉnh vào công cụ Apache Http có thể thay đổi ICY 200 OK thành HTTP/1.0 200 OK. Này được dựa trên ý tưởng chung được trình bày trong:
http://hc.apache.org/httpcomponents-client-4.2.x/tutorial/html/advanced.html
Tôi đã sử dụng thành công sau mã.
public class IcyClientConnection extends DefaultClientConnection{
@Override
protected HttpMessageParser createResponseParser(SessionInputBuffer buffer,
HttpResponseFactory responseFactory, HttpParams params) {
return new IcyHttpResponseParser(
buffer,
new BasicLineParser(),
responseFactory,
params);
}
}
public class IcyClientConnectionOperator extends DefaultClientConnectionOperator {
public IcyClientConnectionOperator(SchemeRegistry schemes) {
super(schemes);
}
@Override
public OperatedClientConnection createConnection() {
return new IcyClientConnection();
}
}
public class IcyClientConnManager extends SingleClientConnManager {
public IcyClientConnManager(HttpParams params, SchemeRegistry schreg) {
super(params, schreg);
}
@Override
protected ClientConnectionOperator createConnectionOperator(
SchemeRegistry schreg) {
return new IcyClientConnectionOperator(schreg);
}
}
Bây giờ bạn phải mở rộng trình phân tích cú pháp được sử dụng theo mặc định và thêm mã sẽ thay đổi phát lại máy chủ sai để sửa lỗi. Mã thông thường sẽ chặn trên hasProtocolVersion
.
public class IcyHttpResponseParser extends DefaultResponseParser{
private CharArrayBuffer icyLineBuf;
private int icyMaxGarbageLines = 1000;
private final HttpResponseFactory icyResponseFactory;
public IcyHttpResponseParser(SessionInputBuffer buffer, LineParser parser,
HttpResponseFactory responseFactory, HttpParams params) {
super(buffer, parser, responseFactory, params);
this.icyLineBuf = new CharArrayBuffer(128);
icyResponseFactory = responseFactory;
}
@Override
protected HttpMessage parseHead(SessionInputBuffer sessionBuffer)
throws IOException, HttpException {
int count = 0;
ParserCursor cursor = null;
do {
// clear the buffer
this.icyLineBuf.clear();
final int i = sessionBuffer.readLine(this.icyLineBuf);
//look for ICY and change to HTTP to provide compatibility with non standard shoutcast servers
String tmp = icyLineBuf.substring(0, this.icyLineBuf.length());
if(tmp.contains("ICY ")){
tmp = tmp.replace("ICY", "HTTP/1.0");
}
//copy
this.icyLineBuf = new CharArrayBuffer(128);
System.arraycopy(tmp.toCharArray(), 0, icyLineBuf.buffer(), 0, tmp.length());
icyLineBuf.setLength(tmp.length());
if (i == -1 && count == 0) {
// The server just dropped connection on us
throw new NoHttpResponseException("The target server failed to respond");
}
cursor = new ParserCursor(0, this.icyLineBuf.length());
if (lineParser.hasProtocolVersion(this.icyLineBuf, cursor)) {
// Got one
break;
} else if (i == -1 || count >= this.icyMaxGarbageLines) {
// Giving up
throw new ProtocolException("The server failed to respond with a " +
"valid HTTP response");
}
//if (this.log.isDebugEnabled()) {
// this.log.debug("Garbage in response: " + this.lineBuf.toString());
// }
count++;
} while(true);
//create the status line from the status string
final StatusLine statusline = lineParser.parseStatusLine(this.icyLineBuf, cursor);
return this.icyResponseFactory.newHttpResponse(statusline, null);
}
}
Cắm HttpClient:
Scheme http = new Scheme("http", PlainSocketFactory.getSocketFactory(), 80);
Scheme ftp = new Scheme("ftp", PlainSocketFactory.getSocketFactory(), 21);
SchemeRegistry sr = new SchemeRegistry();
sr.register(http);
sr.register(ftp);
HttpClient httpClient = new DefaultHttpClient(new IcyClientConnManager(params, sr), params);
này vẫn đang được thử nghiệm nhưng kết quả bước đầu rất hứa hẹn.
Related: http://stackoverflow.com/questions/1963105/listen-to-a-shoutcast-with-android – blahdiblah
Tôi không nghĩ rằng câu hỏi này liên quan đến bài đăng đó. Tôi không có vấn đề với việc biết làm thế nào để dòng nội dung SHOUTcast và phân tích siêu dữ liệu vv ... Tôi có tất cả điều này được thực hiện và làm việc tuyệt vời. Vấn đề là với Android 4.4 mới nhất HttpURLConnection là nghiêm ngặt hơn nhiều gây ra các vấn đề ở cấp độ thấp hơn. – Jona
Sai ngôn ngữ, nhưng hãy xem một số giải pháp được đề xuất ở đây: http://stackoverflow.com/q/9881305/362536 Về cơ bản, tôi đã kết thúc viết mã có mặt trước máy khách HTTP để viết lại 'ICY 'như' HTTP/1.0', và sau đó để nó một mình. Có lẽ bạn có thể làm điều gì đó tương tự cho Android? – Brad