Domanda

Not very easy to explain:

I have this app for streaming online radio. The problem was first with m3u format (which android somehow cannot normally stream like pls), so I have to parse the url with this ParserM3UToURL (that I found somewhere)... like this:

Uri u = Uri.parse(ParserM3UToURL.parse(STREAM_URL, sdkVersion, c));
player = MediaPlayer.create(c, u);

Mostly it works ok but it has one bug...

I'm testing this on two devices one old 2.2.2. (api level 17), other 4.3 (api level 23). Older device works fine. It can stream radio over wifi or mobile data, but the newer device has some problem with streaming over mobile data (on wifi it works ok). The application crashes because the parse function returns null: http://pastebin.com/ghbAqGzM

And I assume there are many more phones with 4.x than 2.x android. Which of course is very painful for me. Somehow I have to fix this.. So I really hope somebody will have some clue about this. I hope my explanation was not to confusing...

This is the ParserM3UToURL.parse() function:

public static String parse(String paramString, int sdkVersion, Context c)
{
    try
    {
      StrictModeWrapper.init(c);
      HttpURLConnection localHttpURLConnection = (HttpURLConnection)new URL(paramString).openConnection();
      InputStream localInputStream = localHttpURLConnection.getInputStream();
      BufferedReader localBufferedReader = new BufferedReader(new InputStreamReader(localInputStream));
      StringBuffer localStringBuffer = new StringBuffer();
      while (true)
      {
        String str = localBufferedReader.readLine();
        if (str == null)
        {
          localHttpURLConnection.disconnect();
          localBufferedReader.close();
          localInputStream.close();
          break;
        }
        if (str.contains("http"))
        {
          localHttpURLConnection.disconnect();
          localBufferedReader.close();
          localInputStream.close();
          return str;
        }
        localStringBuffer.append(str);
      }
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
    return null;
}
È stato utile?

Soluzione 2

I solved it thanks to this question's comments: POST request failing when in 3G

The problem was actually with proxies on 3G. So if proxies are disabled, no weird http requests.

I modified my code a little. Thanks to Nana's answer I no longer need a m3u parser. I also no longer use HttpClient but HttpURLConnection instead. So when calling URL.openConnection() I add the Proxy.NO_PROXY parameter to that function and bam!

So the solution is "use HttpURLConnection not HttpClient and add NO_PROXY parameter":

conn = (HttpURLConnection) the_url.openConnection( Proxy.NO_PROXY );

Altri suggerimenti

Below is what i worked on to stream radio (m3Urls). The example below uses a service. When the service is started, the url is parsed. Note that in the onPostExecute, parsed file is prepared. Once the file is prepared(completed buffering), the file is played/started and stopped upon completion.

  public class BackgroundRadioService extends Service implements
        OnCompletionListener, OnPreparedListener{
     MediaPlayer mediaPlayer;


@Override
public void onCreate() {

    mediaPlayer = new MediaPlayer();
    mediaPlayer.setOnCompletionListener(this);
    mediaPlayer.setOnPreparedListener(this);

}

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
              parseM3uUrlAndPrepare("http://listen.radionomy.com/andalousse.m3u");
    return START_STICKY;
    }



  private void parseM3uUrlAndPrepare(final String url){

AsyncTask<String, Integer, String> asyn = new  AsyncTask<String, Integer, String>(){

        HttpClient httpClient;
        HttpGet getRequest;
        HttpResponse httpResponse = null;
        String filePath = "";

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                 httpClient = new DefaultHttpClient();


                    getRequest = new HttpGet(url);

            }

        @Override
        protected String doInBackground(String... params) {

                try {
                    httpResponse = httpClient.execute(getRequest);
                } catch (ClientProtocolException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                if(httpResponse != null)
                if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                    // ERROR MESSAGE


                } else {
                    InputStream inputStream = null;
                    try {
                        inputStream = httpResponse.getEntity().getContent();
                    } catch (IllegalStateException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    } catch (IOException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    } 
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                    String line;
                    try {
                        while ((line = bufferedReader.readLine()) != null) {
                            //Log.v("PLAYLISTLINE", "ORIG: " + line);
                            if (line.startsWith("#")) { // Metadata

                            } else if (line.length() > 0) {
                                filePath = "";

                                if (line.startsWith("http://")) { // Assume it's a full URL
                                    filePath = line;
                                } else { // Assume it's relative
                                    try{
                                    filePath = getRequest.getURI().resolve(line).toString();
                                    }catch(IllegalArgumentException e){

                                    }catch(Exception e){

                                    }
                                }


                            }
                        }
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            return filePath;
        }

        @Override
        protected void onPostExecute(String filePath) {
            try {
            mediaPlayer.setDataSource(filePath);
            mediaPlayer.prepareAsync(); //this will prepare file a.k.a buffering

        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        }
    };          
        asyn.execute("");

}

@Override
        public void onPrepared(MediaPlayer mp) {
            // TODO Auto-generated method stub      
            mediaPlayer.start();    
}

@Override
    public void onCompletion(MediaPlayer mp) {  
        mediaPlayer.stop();
      }

}//end of Service class declaration

Note: This ignores playlists hence assumes the m3u parsed will return only one file. Let me know if you would like to handle playlists so I modify my answer :)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top