Question

According to changes for kitakt 4.4 there were some problems with playing shoutcast streams (those returning "ICY" instead of "HTTP/1.x" response).

So solution for kitkat was to reregister "icy" protocol prefix in JVM once before we opened a stream by this:

try {
        java.net.URL.setURLStreamHandlerFactory( new java.net.URLStreamHandlerFactory(){
            public java.net.URLStreamHandler createURLStreamHandler( String protocol ) {
                Log.d( LOG, "Asking for stream handler for protocol: '" + protocol + "'" );
                if ("icy".equals( protocol )) return new com.spoledge.aacdecoder.IcyURLStreamHandler();
                return null;
            }
        });
}
catch (Throwable t) {
        Log.w( LOG, "Cannot set the ICY URLStreamHandler - maybe already set ? - " + t );
}

I have problem with open audio stream to make it register. After I call url.opnestream(stream) I got exception:

java.net.ProtocolException: Unexpected status line: ICY 200 OK

How could I fix it?


Here is sample of registering audio, so far what I did..

try {
    URL url = null;
    url = new URL(u);
    inputStream = url.openStream();

    startTime = System.currentTimeMillis();

    Boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);

    String fileName = File.separator + "radio_" + "recording_" + channelMetadata.replaceAll("\\W", "") + System.currentTimeMillis();

    if(isSDPresent)
    {
        outputSource = Environment.getExternalStorageDirectory() + fileName;
    }
    else
    {
        outputSource = Environment.getDataDirectory() + fileName;
    }

    if(contentType.equals("audio/aacp"))
        fileOutputStream = new FileOutputStream(outputSource  + ".acc");
    else if(contentType.equals("audio/mpeg"))
        fileOutputStream = new FileOutputStream(outputSource + ".mp3");
    else
        fileOutputStream = new FileOutputStream(outputSource + ".nieznany_format");

    int bytesRead = 0;
    int bytes;
    while (((bytes = inputStream.read()) != -1) && isRecording) {

        fileOutputStream.write(bytes);
        bytesRead++;

        stopTime = System.currentTimeMillis();

        long seconds = (Math.abs(startTime-stopTime));
        int minutes = 1000 * 60 * 60;

        if(minutes<=seconds)
        {
            Log.d("xxx", "recording task exceed stopped");
            break;
        }
    }

    inputStream.close();
    fileOutputStream.close();

} catch (IOException e) {
    e.printStackTrace();
    isRecording = false;
}

isRecording = false;
return null;
Was it helpful?

Solution

Various changes were made for Android 4.4, and it seems that the non-standard ShoutCast ICY header is not supported by Android.

It seems though that the good people of OkHttp fixed the issue (issue 1 and issue 2) already a few days ago.
What you can do, is simply use OkHttp lib directly in your application and by that you'll use the newer OkHttp version (the one with the fix) and not the one shipped with Android (where you'll have to wait for an OS update).
This will also fix it for your application running on other devices that might suffer from that issue.

OTHER TIPS

The answer of Assaf Gamliel worked for me. For those not familiar with this, you have to download the last .jar from okHttp and the .jar from the dependency okio . Add them to your libs directory and connect like this :

OkHttpClient client = new OkHttpClient();
 Request request = new Request.Builder()
 .url(mediaUrl)
 .build();

 Response response = client.newCall(request).execute();
 InputStream stream = response.body().byteStream();

The easiest fix ever. which is 100% working for me, for shoutcast , change your URL ex. "http://192.168.1.1:9292" to "icy://192.168.1.1:9292" and you'll be fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top