2012-01-23 46 views
3

我正在开发Android 2.2中的应用程序。我需要获取流在线广播的元数据,例如shoutcast。如何获取流在线收音机的元数据

我使用类IcyStreamMeta:

public class IcyStreamMeta<Message> { 

protected URL streamUrl; 
private Map<String, String> metadata; 
private boolean isError; 

public IcyStreamMeta(URL streamUrl) { 
    setStreamUrl(streamUrl); 

    isError = false; 
} 

/** 
* Get artist using stream's title 
* 
* @return String 
* @throws IOException 
*/ 
public String getArtist() throws IOException { 
    Map<String, String> data = getMetadata(); 

    if (!data.containsKey("StreamTitle")) 
     return ""; 

    String streamTitle = data.get("StreamTitle"); 
    String title = streamTitle.substring(0, streamTitle.indexOf("-")); 
    return title.trim(); 
} 

/** 
* Get title using stream's title 
* 
* @return String 
* @throws IOException 
*/ 
public String getTitle() throws IOException { 
    Map<String, String> 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; 
} 

public void refreshMeta() throws IOException { 
    retreiveMetadata(); 
} 

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; 
} 
} 

而我的主要活动我使用的功能:

public void getMeta(){ 

    timer = new Timer(); 
    timer.schedule(new TimerTask() { 
     public void run() { 

      URL url; 
      //Message msg = handler.obtainMessage(); 
      try { 
       Log.d("Metadatos","Dentro del try para obtener los metadatos"); 
       url = new URL("http://relay5.slayradio.org:8000"); 
        IcyStreamMeta icy = new IcyStreamMeta(url); 
        //Log.d("Metadatos","El metadata de la url es "+icy.getMetadata().toString()); 

        Log.d("Metadatos","El titulo de la cancion es "+icy.getTitle()); 
        //msg.obj = icy.getTitle(); 

       Log.d("Metadatos","El nombre del artista es "+icy.getArtist()); 
       //handler.sendMessage(msg); 
      } catch (MalformedURLException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      }catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

     } 
    }, 0, 10000); 

} 

当我运行应用程序时,没有得到的元数据。我已经看过所有的帖子,但我找不到解决方案,我需要你的帮助。

Regards, Juan。

+1

我已经解决了它。问候 – Juanfren

+6

你能分享代码吗? – info

回答

16
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; 
    }} 

在第二类中创建的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()); 
      } 
     } 
    } 

和呼叫的AsyncTask如下

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

在定时器的运行方法写代码

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

上面的代码工作对我很好。 让我知道如果有任何怀疑和抱歉的格式。

+1

感谢分享代码....对我真的很有帮助。 –

+1

@ hims_3009此代码完美无缺!感谢您节省了我几个小时:) –

+3

我做了一个小样本Android项目,使用代码片段。 https://github.com/dazza5000/IcyStreamMetaDataExample – dazza5000