android获取广播流数据

Posted

技术标签:

【中文标题】android获取广播流数据【英文标题】:android get radio stream data 【发布时间】:2014-03-27 15:49:34 【问题描述】:

我正在尝试使用此代码获取播放的歌曲:

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;

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("streamdata"))
        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("Current Song:")) 
        // Headers are sent via HTTP
        metaDataOffset = Integer.parseInt(headers.get("Current Song:").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;

我想使用的网址来自此页面:http://radio.m-1.fm/ 例如http://radio.m-1.fm/M-1PLIUS(即http://84.46.147.81/m1plius/mp3)但我收到错误java.net.SocketException: Permission denied 任何想法有什么问题?

【问题讨论】:

你在清单文件中添加&lt;uses-permission android:name="android.permission.INTERNET"/&gt;了吗?? 【参考方案1】:

Manifest.xml 中添加Internet 权限

<uses-permission android:name="android.permission.INTERNET"/>

参考这个Manifest.permissions

【讨论】:

以上是关于android获取广播流数据的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android 中创建广播流

android 广播分类

Android 高性能音频Oboe 音频流打开后 耳机 / 音箱 插拔事件处理 ( 动态注册广播接收者监听耳机插拔事件 | 重新打开 Oboe 音频流 )

如何从 android 上的调频广播源获取 pcm?

android:udp广播

BroadcastReceiver机制-Android12