无法从Android中的文件中的Shoutcast服务器下载HTTP音频流

时间:2011-11-16 13:03:10

标签: android download audio-streaming android-service shoutcast

我正在尝试使用服务从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块中执行代码。什么可能导致这种行为?

0 个答案:

没有答案