我正在尝试使用服务从Shoutcast服务器下载HTTP音频流,但我无法找到我做错的地方。我尝试使用简单的输入/输出文件操作,它实际上对我有用。但我面临的问题是,它正在为文件添加更多音频,即使我停止了我下载Stream的Thread。我正在使用此代码进行下载。
public class DownloadService extends Service{
private static final String LOG_TAG = DownloadService.class.getName();
private int port = 0;
public int getPort()
{
return port;
}
private boolean isRunning = true;
private ServerSocket socket;
private Thread thread;
private static final String FOLDER_NAME = "Songs";
private static final String FILE_FORMAT = ".mp3";
private long tempFileName = 0;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
}
@Override
public void onCreate() {
init();
Log.d(LOG_TAG, "running");
thread = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while(isRunning)
{
try
{
Socket client = socket.accept();
if(client == null)
{
continue;
}
Log.d(LOG_TAG, "client connected");
HttpRequest request = readRequest(client);
processRequest(request);
}
catch(SocketTimeoutException e)
{
// Do nothing
}
catch(IOException e)
{
Log.e(LOG_TAG, "Error connecting to client", e);
}
}
Log.d(LOG_TAG, "Proxy interrupted. Shutting down.");
}
});
thread.start();
}
public void init()
{
try
{
socket = new ServerSocket(port, 0, InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 }));
socket.setSoTimeout(5000);
port = socket.getLocalPort();
Log.d(LOG_TAG, "port " + port + " obtained");
}
catch(UnknownHostException e)
{
Log.e(LOG_TAG, "Error initializing server", e);
}
catch(IOException e)
{
Log.e(LOG_TAG, "Error initializing server", e);
}
}
public void stop()
{
isRunning = false;
if(thread == null)
{
throw new IllegalStateException("Cannot stop proxy; it has not been started.");
}
thread.interrupt();
try
{
thread.join(5000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
private HttpRequest readRequest(Socket client)
{
HttpRequest request = null;
InputStream is;
String firstLine;
try
{
is = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
firstLine = reader.readLine();
}
catch(IOException e)
{
Log.e(LOG_TAG, "Error parsing request", e);
return request;
}
if(firstLine == null)
{
Log.i(LOG_TAG, "Proxy client closed connection without a request.");
return request;
}
StringTokenizer st = new StringTokenizer(firstLine);
String method = st.nextToken();
String uri = st.nextToken();
Log.d(LOG_TAG, uri);
String realUri = uri.substring(1);
Log.d(LOG_TAG, realUri);
request = new BasicHttpRequest(method, realUri);
return request;
}
private HttpResponse download(String url)
{
DefaultHttpClient seed = new DefaultHttpClient();
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
SingleClientConnManager mgr = new MyClientConnManager(seed.getParams(), registry);
DefaultHttpClient http = new DefaultHttpClient(mgr, seed.getParams());
HttpGet method = new HttpGet(url);
HttpResponse response = null;
try
{
Log.d(LOG_TAG, "starting download");
response = http.execute(method);
Log.d(LOG_TAG, "downloaded");
}
catch(ClientProtocolException e)
{
Log.e(LOG_TAG, "Error downloading", e);
}
catch(IOException e)
{
Log.e(LOG_TAG, "Error downloading", e);
}
return response;
}
private void processRequest(HttpRequest request) throws IllegalStateException, IOException
{
OutputStream writer = null;
if(request == null)
{
return;
}
Log.d(LOG_TAG, "processing");
String url = request.getRequestLine().getUri();
HttpResponse realResponse = download("http://shoutcast2.omroep.nl:8104/";);
if(realResponse == null)
{
return;
}
Log.d(LOG_TAG, "downloading...");
InputStream data = realResponse.getEntity().getContent();
StatusLine line = realResponse.getStatusLine();
HttpResponse response = new BasicHttpResponse(line);
response.setHeaders(realResponse.getAllHeaders());
Log.d(LOG_TAG, "reading headers");
StringBuilder httpString = new StringBuilder();
httpString.append(response.getStatusLine().toString());
httpString.append("\n");
for(Header h : response.getAllHeaders())
{
httpString.append(h.getName()).append(": ").append(h.getValue()).append("\n");
}
httpString.append("\n");
Log.d(LOG_TAG, "headers done");
tempFileName = System.currentTimeMillis();
writer = new BufferedOutputStream(new FileOutputStream(
new File(getFolderName() + tempFileName + FILE_FORMAT)));
try
{
byte[] buffer = httpString.toString().getBytes();
int readBytes = -1;
Log.d(LOG_TAG, "writing to client");
writer.write(buffer, 0, buffer.length);
// Start streaming content.
byte[] buff = new byte[1024 * 50];
while(isRunning && (readBytes = data.read(buff, 0, buff.length)) != -1)
{
writer.write(buff, 0, readBytes);
}
}
catch(Exception e)
{
Log.e("", e.getMessage(), e);
}
finally
{
if(data != null)
{
data.close();
}
writer.close();
}
}
private String getFolderName()
{
final String FOLDER_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()
+ File.separator + FOLDER_NAME;
File folder = new File(FOLDER_PATH);
if (!folder.exists()) {
folder.mkdir();
}
return (folder.getAbsolutePath() + File.separator);
}
private class IcyLineParser extends BasicLineParser
{
private static final String ICY_PROTOCOL_NAME = "ICY";
private IcyLineParser()
{
super();
}
@Override
public boolean hasProtocolVersion(CharArrayBuffer buffer, ParserCursor cursor)
{
boolean superFound = super.hasProtocolVersion(buffer, cursor);
if(superFound)
{
return true;
}
int index = cursor.getPos();
final int protolength = ICY_PROTOCOL_NAME.length();
if(buffer.length() < protolength)
return false; // not long enough for "HTTP/1.1"
if(index < 0)
{
// end of line, no tolerance for trailing whitespace
// this works only for single-digit major and minor version
index = buffer.length() - protolength;
}
else if(index == 0)
{
// beginning of line, tolerate leading whitespace
while((index < buffer.length()) && HTTP.isWhitespace(buffer.charAt(index)))
{
index++;
}
} // else within line, don't tolerate whitespace
if(index + protolength > buffer.length())
return false;
return buffer.substring(index, index + protolength).equals(ICY_PROTOCOL_NAME);
}
@Override
public Header parseHeader(CharArrayBuffer buffer) throws ParseException
{
return super.parseHeader(buffer);
}
@Override
public ProtocolVersion parseProtocolVersion(CharArrayBuffer buffer, ParserCursor cursor) throws ParseException
{
if(buffer == null)
{
throw new IllegalArgumentException("Char array buffer may not be null");
}
if(cursor == null)
{
throw new IllegalArgumentException("Parser cursor may not be null");
}
final int protolength = ICY_PROTOCOL_NAME.length();
int indexFrom = cursor.getPos();
int indexTo = cursor.getUpperBound();
skipWhitespace(buffer, cursor);
int i = cursor.getPos();
// long enough for "HTTP/1.1"?
if(i + protolength + 4 > indexTo)
{
throw new ParseException("Not a valid protocol version: " + buffer.substring(indexFrom, indexTo));
}
// check the protocol name and slash
if(!buffer.substring(i, i + protolength).equals(ICY_PROTOCOL_NAME))
{
return super.parseProtocolVersion(buffer, cursor);
}
cursor.updatePos(i + protolength);
return createProtocolVersion(1, 0);
}
@Override
public RequestLine parseRequestLine(CharArrayBuffer buffer, ParserCursor cursor) throws ParseException
{
return super.parseRequestLine(buffer, cursor);
}
@Override
public StatusLine parseStatusLine(CharArrayBuffer buffer, ParserCursor cursor) throws ParseException
{
StatusLine superLine = super.parseStatusLine(buffer, cursor);
return superLine;
}
}
class MyClientConnection extends DefaultClientConnection
{
@Override
protected HttpMessageParser createResponseParser(final SessionInputBuffer buffer, final HttpResponseFactory responseFactory, final HttpParams params)
{
return new DefaultResponseParser(buffer, new IcyLineParser(), responseFactory, params);
}
}
class MyClientConnectionOperator extends DefaultClientConnectionOperator
{
public MyClientConnectionOperator(final SchemeRegistry sr)
{
super(sr);
}
@Override
public OperatedClientConnection createConnection()
{
return new MyClientConnection();
}
}
class MyClientConnManager extends SingleClientConnManager
{
private MyClientConnManager(HttpParams params, SchemeRegistry schreg)
{
super(params, schreg);
}
@Override
protected ClientConnectionOperator createConnectionOperator(final SchemeRegistry sr)
{
return new MyClientConnectionOperator(sr);
}
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
stop();
}
}
代码的执行从onCreate()开始,但之后它没有在Thread中的try-catch块中执行代码。什么可能导致这种行为?