1

我正在尝试使用 Android 的 MediaPlayer 库流式传输音频。

在某些情况下,流 URL 是一个不寻常的端口。例如,http://203.150.225.77:8400。如果我尝试从浏览器的防火墙后面访问此流,它会给我一个“糟糕!Google Chrome 无法连接到203.150.225.77:8400”错误。

从我的 android 设备中的媒体播放器,我得到:MusicStream(1806): Media Player Error: Stream URL Invalid (1) -1004

目前,我只是在处理这个异常。但是,我希望能够在启动 MediaPlayer 之前预先测试 URL 以确定流是否可用。

因此,我创建了一个函数来使用 HttpURLConnection 测试 url,如下所示:

protected int isURLValid(MusicStream streamInstance, String urlString)
{
    streamInstance.timeout = 0;
    int success = 0;
    try
    {

        URL url;
        url = new URL(urlString);
        HttpURLConnection urlConnection;
        urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setConnectTimeout(1000);
        urlConnection.setReadTimeout(1000);
        urlConnection.getHeaderFields();
        new Thread(new InterruptThread(Thread.currentThread(), urlConnection,streamInstance)).start();

        if (streamInstance.timeout == 0)
        {
            success = 1;
        }

    }
    catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        Log.w("MusicStream", "MalformedURLException");
        Log.w("MusicStream", e);

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        Log.w("MusicStream", "IOException");
        Log.w("MusicStream", e);
    } catch (Exception e) {
        this.exception = e;
        Log.w("MusicStream", "Exception");
        Log.w("MusicStream", e);

    }


    return success;

}

正如您在上面的代码中看到的,我在 5000 毫秒后启动了一个新线程以超时。这是我的线程:

public class InterruptThread implements Runnable {
    Thread parent;
    URLConnection con;
    MusicStream streamInstance;

    public InterruptThread(Thread parent, URLConnection con, MusicStream streamInstance) {
        this.parent = parent;
        this.con = con;
        this.streamInstance = streamInstance;
    }

    public void run() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {

        }
        Log.d("MusicStream", "Timer thread forcing parent to quit connection");
        ((HttpURLConnection)con).disconnect();
        Log.d("MusicStream","Timer thread closed connection held by parent, exiting");
        streamInstance.timeout = 1;
    }
}

尽管如此,当我引用我的函数时:

if (isURLValid(streamInstance[0],streamURL) == 1){
    // Valid URL!
    Log.d("MusicStream", "The stream is valid!");
    this.ResultString = streamURL;
    streamInstance[0].setFirewallError(MusicStream.GONE,streamURL);
}
else{
    // Streaming URL invalid. 
    // Firewall Error
    errorCode = MusicStream.FIREWALL_ERROR;
    Log.d("MusicStream", "The stream is not valid!");
    streamInstance[0].setFirewallError(MusicStream.VISIBLE,streamURL);
}

日志输出如下

A stream has been supplied: http://203.150.225.77:8400
The stream is valid!
MusicStream(1806): Media Player Error: Stream URL Invalid (1) -1004

一旦我将设备从无线切换到 3G,流媒体就可以工作了,所以我有点不知所措,为什么我的 url 检查机制在防火墙后面返回有效。任何人都可以看到为什么我的支票返回有效的任何原因,并可能就我如何以更简单的方式检查状态提出建议?

额外的想法:我在想也许某些防火墙会以“阻止”页面响应,在这种情况下获取标题将不起作用。但是,这里不是这种情况。

4

1 回答 1

0

这并不处理所有内容,但我发现防火墙后面流返回有效的 html 标头。看到的标题如下:

防火墙后面:

Content Length:     3469
Content Encoding:   null
Content Type:       text/html
Content Expiration: 0
Content Date:       1381912000000

在另一台设备上,我收到了一个空响应:

Content Length:     -1
Content Encoding:   null
Content Type:       null
Content Expiration: 0
Content Date:       0

不在防火墙后面的有效流返回 mpeg 标头。注意内容类型和长度:

Content Length:     -1
Content Encoding:   null
Content Type:       audio/mpeg
Content Expiration: 0
Content Date:       0

要检查我的 url,我只需要检查内容类型和长度是否符合音频流的预期。

于 2013-10-16T08:35:59.903 回答