how to get metadata of a streaming online radio

前端 未结 1 922
说谎
说谎 2020-12-29 00:20

I am developing an app in Android 2.2 . I need get metadata of a streaming online radio, for example shoutcast.

I use class IcyStreamMeta:

public cl         


        
相关标签:
1条回答
  • import java.io.IOException;
    import java.io.InputStream;
    import java.net.URL;
    import java.net.URLConnection;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class IcyStreamMeta 
    {
        protected URL streamUrl;
        private Map<String, String> metadata;
        private boolean isError;
        private Map<String, String> data;
    
        public IcyStreamMeta() 
        {
            isError = false;
        }
    
        /**
         * Get artist using stream's title
         *
         * @return String
         * @throws IOException
         */
        public String getArtist() throws IOException {
            data = getMetadata();
    
            if (!data.containsKey("StreamTitle"))
                return "";
    
            String streamTitle = data.get("StreamTitle");
            String title = streamTitle.substring(0, streamTitle.indexOf("-"));
            return title.trim();
        }
    
        /**
         * Get streamTitle
         *
         * @return String
         * @throws IOException
         */
        public String getStreamTitle() throws IOException 
        {
            data = getMetadata();
    
            if (!data.containsKey("StreamTitle"))
                return "";
    
            return data.get("StreamTitle");
        }
    
        /**
         * Get title using stream's title
         *
         * @return String
         * @throws IOException
         */
        public String getTitle() throws IOException {
            data = getMetadata();
    
            if (!data.containsKey("StreamTitle"))
                return "";
    
            String streamTitle = data.get("StreamTitle");
            String artist = streamTitle.substring(streamTitle.indexOf("-")+1);
            return artist.trim();
        }
    
        public Map<String, String> getMetadata() throws IOException {
            if (metadata == null) {
                refreshMeta();
            }
    
            return metadata;
        }
    
        synchronized public void refreshMeta() throws IOException 
        {
            retreiveMetadata();
        }
    
        synchronized private void retreiveMetadata() throws IOException 
        {
            URLConnection con = streamUrl.openConnection();
            con.setRequestProperty("Icy-MetaData", "1");
            con.setRequestProperty("Connection", "close");
            con.setRequestProperty("Accept", null);
            con.connect();
            int metaDataOffset = 0;
            Map<String, List<String>> headers = con.getHeaderFields();
            InputStream stream = con.getInputStream();
    
            if (headers.containsKey("icy-metaint")) {
                // Headers are sent via HTTP
                metaDataOffset = Integer.parseInt(headers.get("icy-metaint").get(0));
            } else {
                // Headers are sent within a stream
                StringBuilder strHeaders = new StringBuilder();
                char c;
                while ((c = (char)stream.read()) != -1) 
                {
                    strHeaders.append(c);
                    if (strHeaders.length() > 5 && (strHeaders.substring((strHeaders.length() - 4), strHeaders.length()).equals("\r\n\r\n"))) {
                        // end of headers
                        break;
                    }
                }
    
                // Match headers to get metadata offset within a stream
                Pattern p = Pattern.compile("\\r\\n(icy-metaint):\\s*(.*)\\r\\n");
                Matcher m = p.matcher(strHeaders.toString());
                if (m.find()) 
                {
                    metaDataOffset = Integer.parseInt(m.group(2));
                }
            }
    
            // In case no data was sent
            if (metaDataOffset == 0) 
            {
                isError = true;
                return;
            }
    
            // Read metadata
            int b;
            int count = 0;
            int metaDataLength = 4080; // 4080 is the max length
            boolean inData = false;
            StringBuilder metaData = new StringBuilder();
            // Stream position should be either at the beginning or right after headers
            while ((b = stream.read()) != -1) {
                count++;
    
                // Length of the metadata
                if (count == metaDataOffset + 1) {
                    metaDataLength = b * 16;
                }
    
                if (count > metaDataOffset + 1 && count < (metaDataOffset + metaDataLength)) {              
                    inData = true;
                } 
                else 
                {               
                    inData = false;             
                }               
                if (inData) 
                {       
                    if (b != 0) 
                    {           
                        metaData.append((char)b);               
                    }
                }
                if (count > (metaDataOffset + metaDataLength)) 
                {
                    break;
                }
            }
    
            // Set the data
            metadata = IcyStreamMeta.parseMetadata(metaData.toString());
    
            // Close
            stream.close();
    
        }
    
        public boolean isError() {
            return isError;
        }
    
        public URL getStreamUrl() {
            return streamUrl;
        }
    
        public void setStreamUrl(URL streamUrl) {
            this.metadata = null;
            this.streamUrl = streamUrl;
            this.isError = false;
        }
    
        public static Map<String, String> parseMetadata(String metaString) 
        {
            Map<String, String> metadata = new HashMap();
            String[] metaParts = metaString.split(";");
            Pattern p = Pattern.compile("^([a-zA-Z]+)=\\'([^\\']*)\\'$");
            Matcher m;
            for (int i = 0; i < metaParts.length; i++) {
                m = p.matcher(metaParts[i]);
                if (m.find()) {
                    metadata.put((String)m.group(1), (String)m.group(2));
                }
            }
    
            return metadata;
        }}
    

    In Second class create AsyncTask

    protected class MetadataTask2 extends AsyncTask<URL, Void, IcyStreamMeta> 
        {
            @Override
            protected IcyStreamMeta doInBackground(URL... urls) 
            {
                try 
                {
                    streamMeta.refreshMeta();
                    Log.e("Retrieving MetaData","Refreshed Metadata");
                } 
                catch (IOException e) 
                {
                    Log.e(MetadataTask2.class.toString(), e.getMessage());
                }
                return streamMeta;
            }
    
            @Override
            protected void onPostExecute(IcyStreamMeta result) 
            {
                try 
                {
                    title_artist=streamMeta.getStreamTitle();
                    Log.e("Retrieved title_artist", title_artist);
                    if(title_artist.length()>0)
                    {
                        updateMetadata();
                    }
                    metaFlag=true;
                }
                catch (IOException e) 
                {
                    Log.e(MetadataTask2.class.toString(), e.getMessage());
                }
            }
        }
    

    And Call AsyncTask as below

        streamMeta = new IcyStreamMeta();
        streamMeta.setStreamUrl(new URL(ConstantData.currentStationData.getUrl()));
        metadataTask2=new MetadataTask2();
        metadataTask2.execute(new URL(ConstantData.currentStationData.getUrl()));
    

    In Timer's Run method write code

        {
        streamMeta.refreshMeta();                               
        String title_artist=streamMeta.getStreamTitle();
        }
    

    Above code works fine for me. Let me know if Any Doubt and Sorry for Formatting.

    0 讨论(0)
提交回复
热议问题