18

EDIT:Android MediaPlayer funziona bene in personalizzato applicazione streaming audio fino a Android 2.1, ma non nelle versioni superiori

Android 2.2 MediaPlayer is working fine with one SHOUTcast URL but not with the other one

ho bisogno di riprodurre i file audio da URL esterni (stream shoutcast). Attualmente i file audio vengono scaricati in modo incrementale & vengono riprodotti non appena riceviamo abbastanza audio nella memoria temporanea locale del telefono. sto usando il StreamingMediaPlayer class.

controllare questo pezzo di codice:

private MediaPlayer createMediaPlayer(File mediaFile) 
      throws IOException { 
     MediaPlayer mPlayer = new MediaPlayer(); 
     //example of mediaFile =/data/data/package/cache/playingMedia0.dat 
     FileInputStream fis = new FileInputStream(mediaFile); 
     mPlayer.setDataSource(fis.getFD()); 
     mPlayer.prepare(); 
     return mPlayer; 
    } 

Stato attuale:

1- Funziona bene da Android 1,6-2,1 ma non nelle versioni superiori come Android 2.2.

2- "mPlayer.setDataSource (fis.getFD())" è la riga che genera l'errore.

3- L'errore è "Impossibile per creare media player"

Altro Soluzione cercato:

ho cercato qui di seguito soluzione alternativa, ma niente ha funzionato finora.

Android 2.2 MediaPlayer is working fine with one SHOUTcast URL but not with the other one

Quello che sto cercando?

Il mio obiettivo è quello di avere una tranquillità di codice che può funzionare su Android 2.1 & superiore.

Questo problema è stato discusso anche qui:

1- Inconsistent 2.2 Media Player Behavior

2- android code for streaming shoutcast stream breaks in 2.2

3- Questo problema è stato discusso anche in un sacco di domande su questo sito, ma ho trovato la risposta no dove.

4- markmail.org

LogCat traccia:

Unable to to create media player 
Error copying buffered conent. 
java.lang.NullPointerException 
com.ms.iradio.StreamingMediaPlayer.startMediaPlayer(StreamingMediaPlayer.java:251) 
com.ms.iradio.StreamingMediaPlayer.access$2(StreamingMediaPlayer.java:221) 
com.ms.iradio.StreamingMediaPlayer$2.run(StreamingMediaPlayer.java:204) 
android.os.Handler.handleCallback(Handler.java:587) 
android.os.Handler.dispatchMessage(Handler.java:92) 
android.os.Looper.loop(Looper.java:123) 
android.app.ActivityThread.main(ActivityThread.java:3683) 
java.lang.reflect.Method.invokeNative(Native Method) 
java.lang.reflect.Method.invoke(Method.java:507) 
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 
dalvik.system.NativeStart.main(Native Method) 
+1

Forse questo link sarà rispondere alla tua domanda, e se no, si prega di inviare una traccia per l'errore che si ottiene: http://stackoverflow.com/questions/3834548/android-code-for-streaming-shoutcast- stream-breaks-in-2-2 – leanne

risposta

3

La classe StreamingMediaPlayer sta usando una tecnica di doppio buffering per aggirare le limitazioni in pre-release 1.2 di Android. Tutte le versioni di produzione del sistema operativo Android includono un MediaPlayer che supporta lo streaming multimediale (1). Consiglierei di farlo piuttosto che usare questa tecnica a doppio buffering per aggirare il problema.

Il sistema operativo Android 2.2 ha sostituito il vecchio codice del lettore multimediale con il lettore FrightCast, che probabilmente si comporta diversamente in questo caso.

I numeri di riga nella traccia dello stack non si associano al file a cui si collega, quindi presumo che ci sia una versione diversa che si sta effettivamente utilizzando.Devo indovinare che il numero NullPointerException è stato segnalato da MediaPlayer ma né lo FileInputStream né lo FileDescriptor restituito possono essere null.

(1) Prima della versione 2.2 il lettore multimediale non riconosceva i flussi ShoutCast con un'intestazione di versione "ICY/1.1" nella risposta. Con la creazione di un proxy che sostituisce questo con "HTTP/1.1" è possibile risolverlo. Vedere lo StreamProxy class here per un esempio.

+0

1- Sto utilizzando StreamingMediaPlayer solo alcune modifiche minori sono state apportate. 2- npr La classe StreamProxy richiede molte altre classi (ad esempio le news npr), l'ho già provata per usarla ma non riuscire a farlo correttamente. –

+0

Hmm ... la traccia dello stack mostra la riga 251 in #startMediaPlayer ma nella sorgente collegata tale riga si trova in #transferBufferToMediaPlayer. Inoltre, StreamProxy dalla sorgente NPR non richiede nulla dalla sorgente NPR, ma molte cose incluse nella fonte Android. [Vedi qui] (http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/PlaybackService.java#347) per un esempio di implementazione o [il test] (http://code.google.com/p/npr-android-app/source/browse/Npr_Test/src/org/npr/android/news/StreamProxyTest.java) caso. – jwadsack

+0

Grazie mille. lo proverò lunedì. Si prega di controllare anche questa domanda: http://stackoverflow.com/questions/8681550/android-2-2-mediaplayer-is-working-fine-with-one-shoutcast-url-but-not-with-the –

5

Il problema è che il tipo di contenuto "streaming audio/aacp" non è supportato direttamente. Alcune librerie di decodifica può essere utilizzato per giocare "AACP", si prega di vedere la soluzione qui di seguito:

Freeware Advanced Audio (AAC) Decoder for Android

How to use this library?

Consider legal issues while using it.

[L] a proiettare http://code.google.com/p/aacplayer-android/ è concesso in licenza sotto licenza GPL, in modo da poter creare applicazioni commerciali su di esso, ma si bisogno di fullfill GPL - soprattutto significa pubblicare il codice come bene. Se si utilizza il secondo progetto http://code.google.com/p/aacdecoder-android/, non è necessario pubblicare codice (la libreria è concessa in licenza sotto LGPL).

+0

aiutami a questo http://stackoverflow.com/questions/16264225/andriod-shoutcast-internet-radio -filenotfoundexception – String

1

sto usando questo codice ed eseguo 2.2 alla versione superiore per lo streaming scaricato.

import java.io.BufferedInputStream; 
import java.io.BufferedOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.net.URL; 
import java.net.URLConnection; 

import android.content.Context; 
import android.media.MediaPlayer; 
import android.os.Environment; 
import android.os.Handler; 
import android.util.Log; 
import android.view.View; 
import android.widget.Button; 
import android.widget.ImageButton; 
import android.widget.ProgressBar; 
import android.widget.TextView; 


public class StreamingMediaPlayer { 
private static final int INTIAL_KB_BUFFER = 96*10;//assume 96kbps*10secs/8bits per byte 

private TextView textStreamed; 

private ImageButton playButton; 

private ProgressBar progressBar; 
ProgressBar pb; 
int audiofiletime=0; 
private long mediaLengthInSeconds; 
private int totalKbRead = 0; 
int totalsize=0; 
int numread; 
int totalBytesRead = 0; 
private final Handler handler = new Handler(); 
private MediaPlayer mediaPlayer; 
private File downloadingMediaFile; 
private boolean isInterrupted; 
private Context context; 
private int counter = 0; 

public StreamingMediaPlayer(Context context,TextView textStreamed, ImageButton playButton, Button streamButton,ProgressBar progressBar,ProgressBar pb) 
{ 
    this.context = context; 
    this.textStreamed = textStreamed; 
    this.playButton = playButton; 
    this.progressBar = progressBar; 
    this.pb=pb; 
} 

/** 
* Progressivly download the media to a temporary location and update the MediaPlayer as new content becomes available. 
*/ 
public void startStreaming(final String mediaUrl) throws IOException { 


    //this.mediaLengthInSeconds = 100; 


    Runnable r = new Runnable() { 
     public void run() { 
      try { 
       downloadAudioIncrement(mediaUrl); 
      } catch (IOException e) { 
       Log.e(getClass().getName(), "Unable to initialize the MediaPlayer for fileUrl=" + mediaUrl, e); 
       return; 
      } 
     } 
    }; 
    new Thread(r).start(); 
} 

/** 
* Download the url stream to a temporary location and then call the setDataSource 
* for that local file 
*/ 
@SuppressWarnings({ "resource", "unused" }) 
public void downloadAudioIncrement(String mediaUrl) throws IOException { 

    URLConnection cn = new URL(mediaUrl).openConnection(); 
    cn.connect(); 
    InputStream stream = cn.getInputStream(); 
    if (stream == null) { 
     Log.e(getClass().getName(), "Unable to create InputStream for mediaUrl:" + mediaUrl); 
    } 

    ///////////////////save sdcard/////////////// 
    File direct = new File(Environment.getExternalStorageDirectory()+"/punya"); 

    if(!direct.exists()) { 
     if(direct.mkdir()); //directory is created; 
    } 

    String[] files=mediaUrl.split("/"); 

    String fileName=files[files.length-1]; 
    fileName = fileName.replace(".m4a", ".rdo"); 


    //create a new file, to save the downloaded file 

    File file = new File(direct,fileName); 

    @SuppressWarnings("resource") 
    FileOutputStream fileOutput = new FileOutputStream(file); 

    ///////////////////end///////////////// 

    totalsize=cn.getContentLength(); 

    //mediaLengthInKb = 10000; 

    downloadingMediaFile = new File(context.getCacheDir(),fileName); 

    if (downloadingMediaFile.exists()) { 
     downloadingMediaFile.delete(); 
    } 

    FileOutputStream out = new FileOutputStream(downloadingMediaFile); 
    byte buf[] = new byte[16384]; 
    int incrementalBytesRead = 0; 
    do { 
     numread = stream.read(buf); 
     if (numread <= 0) 
      break; 
     out.write(buf, 0, numread); 
     fileOutput.write(buf, 0, numread); 
     totalBytesRead += numread; 
     incrementalBytesRead += numread; 
     totalKbRead = totalBytesRead/1000; 
     // pb.setMax(100); 
     // pb.setProgress(totalKbRead); 

     testMediaBuffer(); 
     fireDataLoadUpdate(); 
    } while (validateNotInterrupted()); 
    stream.close(); 
    if (validateNotInterrupted()) { 
     fireDataFullyLoaded(); 
    } 
} 

private boolean validateNotInterrupted() { 
    if (isInterrupted) { 
     if (mediaPlayer != null) { 
      mediaPlayer.pause(); 
      //mediaPlayer.release(); 
     } 
     return false; 
    } else { 
     return true; 
    } 
} 


/** 
* Test whether we need to transfer buffered data to the MediaPlayer. 
* Interacting with MediaPlayer on non-main UI thread can causes crashes to so perform this using a Handler. 
*/ 
private void testMediaBuffer() { 
    Runnable updater = new Runnable() { 
     public void run() { 
      if (mediaPlayer == null) { 
       // Only create the MediaPlayer once we have the minimum buffered data 
       if (totalKbRead >= INTIAL_KB_BUFFER) { 
        try { 
         startMediaPlayer(); 
        } catch (Exception e) { 
         Log.e(getClass().getName(), "Error copying buffered conent.", e);    
        } 
       } 
      } else if (mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition() <= 1000){ 
       // NOTE: The media player has stopped at the end so transfer any existing buffered data 
       // We test for < 1second of data because the media player can stop when there is still 
       // a few milliseconds of data left to play 
       transferBufferToMediaPlayer(); 
      } 
     } 
    }; 
    handler.post(updater); 
} 

private void startMediaPlayer() { 
    try { 
     //File bufferedFile = new File(context.getCacheDir(),"playingMedia" + (counter++) + ".m4a"); 

     //moveFile(downloadingMediaFile,bufferedFile); 

     // Log.e(getClass().getName(),"Buffered File path: " + bufferedFile.getAbsolutePath()); 
     // Log.e(getClass().getName(),"Buffered File length: " + bufferedFile.length()+""); 

     mediaPlayer = createMediaPlayer(downloadingMediaFile); 

     //mediaPlayer.start(); 
     startPlayProgressUpdater();   
     //playButton.setEnabled(true); 
     playButton.setVisibility(View.VISIBLE); 
    } catch (IOException e) { 
     Log.e(getClass().getName(), "Error initializing the MediaPlayer.", e); 
     return; 
    } 
} 

private MediaPlayer createMediaPlayer(File mediaFile) 
     throws IOException { 
    MediaPlayer mPlayer = new MediaPlayer(); 
    mPlayer.setOnErrorListener(
      new MediaPlayer.OnErrorListener() { 
       public boolean onError(MediaPlayer mp, int what, int extra) { 
        Log.e(getClass().getName(), "Error in MediaPlayer: (" + what +") with extra (" +extra +")"); 
        return false; 
       } 
      }); 

    FileInputStream fis = new FileInputStream(mediaFile); 
    mPlayer.setDataSource(fis.getFD()); 
    mPlayer.prepare(); 
    return mPlayer; 
} 

/** 
* Transfer buffered data to the MediaPlayer. 
* NOTE: Interacting with a MediaPlayer on a non-main UI thread can cause thread-lock and crashes so 
* this method should always be called using a Handler. 
*/ 
private void transferBufferToMediaPlayer() { 
    try { 

     boolean wasPlaying = mediaPlayer.isPlaying(); 
     int curPosition = mediaPlayer.getCurrentPosition(); 

     File oldBufferedFile = new File(context.getCacheDir(),"playingMedia" + counter + ".m4a"); 
     File bufferedFile = new File(context.getCacheDir(),"playingMedia" + (counter++) + ".m4a"); 

     bufferedFile.deleteOnExit(); 
     moveFile(downloadingMediaFile,bufferedFile); 

     //mediaPlayer.pause(); 
     mediaPlayer.release(); 

     mediaPlayer = createMediaPlayer(bufferedFile); 
     mediaPlayer.seekTo(curPosition); 

     boolean atEndOfFile = mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition() <= 1000; 
     if (wasPlaying || atEndOfFile){ 
      mediaPlayer.start(); 
     } 

     oldBufferedFile.delete(); 

    }catch (Exception e) { 
     Log.e(getClass().getName(), "Error updating to newly loaded content.", e);     
    } 
} 

private void fireDataLoadUpdate() { 
    Runnable updater = new Runnable() { 
     public void run() { 

      //float loadProgress = ((float)totalBytesRead/(float)mediaLengthInKb); 
      //float per = ((float)numread/mediaLengthInKb) * 100; 
      float per = ((float)totalBytesRead/totalsize) * 100; 
      textStreamed.setText((totalKbRead + " Kb (" + (int)per + "%)")); 
      progressBar.setSecondaryProgress((int)(per)); 
      pb.setSecondaryProgress((int)(per)); 

     } 
    }; 
    handler.post(updater); 
} 

private void fireDataFullyLoaded() { 
    Runnable updater = new Runnable() { 
     public void run() { 
      transferBufferToMediaPlayer(); 

      downloadingMediaFile.delete(); 
      textStreamed.setText(("Download completed")); 

     } 
    }; 
    handler.post(updater); 
} 

public MediaPlayer getMediaPlayer() { 
    return mediaPlayer; 
} 

public void startPlayProgressUpdater() { 
    audiofiletime =mediaPlayer.getDuration(); 
    float progress = (((float)mediaPlayer.getCurrentPosition()/ audiofiletime) * 100); 
    progressBar.setProgress((int)(progress)); 
    //pb.setProgress((int)(progress*100)); 

    if (mediaPlayer.isPlaying()) { 
     Runnable notification = new Runnable() { 
      public void run() { 
       startPlayProgressUpdater(); 
      } 
     }; 
     handler.postDelayed(notification,1000); 
    } 
}  

public void interrupt() { 
    playButton.setEnabled(false); 
    isInterrupted = true; 
    validateNotInterrupted(); 
} 

/** 
* Move the file in oldLocation to newLocation. 
*/ 
public void moveFile(File oldLocation, File newLocation) 
     throws IOException { 

    if (oldLocation.exists()) { 
     BufferedInputStream reader = new BufferedInputStream(new FileInputStream(oldLocation)); 
     BufferedOutputStream writer = new BufferedOutputStream(new FileOutputStream(newLocation, false)); 
     try { 
      byte[] buff = new byte[5461]; 
      int numChars; 
      while ((numChars = reader.read( buff, 0, buff.length)) != -1) { 
       writer.write(buff, 0, numChars); 
      } 
     } catch(IOException ex) { 
      throw new IOException("IOException when transferring " + oldLocation.getPath() + " to " + newLocation.getPath()); 
     } finally { 
      try { 
       if (reader != null){      
        writer.close(); 
        reader.close(); 
       } 
      } catch(IOException ex){ 
       Log.e(getClass().getName(),"Error closing files when transferring " + oldLocation.getPath() + " to " + newLocation.getPath()); 
      } 
     } 
    } else { 
     throw new IOException("Old location does not exist when transferring " + oldLocation.getPath() + " to " + newLocation.getPath()); 
    } 
} 
} 
Problemi correlati