Je pense avoir trouvé une solution. J'apprécierais que d'autres personnes intéressées l'essaient d'elles-mêmes et rapportent les résultats avec leurs modèles d'appareils et leur version SDK.
J'ai vu des messages similaires qui directement à cela, mais je pensais que je le publierais car il est plus récent et semble fonctionner sur les nouvelles versions du SDK - jusqu'à présent, il fonctionne sur mon Nexus One fonctionnant sous Android 2.3.6. La solution repose sur la mise en mémoire tampon du flux d'entrée dans un fichier local (j'ai ce fichier sur le stockage externe mais il sera probablement possible de le placer sur le stockage interne) et de fournir le descripteur de ce fichier à l'instance MediaPlayer .
Les essais suivants dans un procédé doInBackground de certains AsyncTask qui fait AudioPlayback:
@Override
protected
Void doInBackground(LibraryItem... params)
{
...
MediaPlayer player = new MediaPlayer();
setListeners(player);
try {
_remoteStream = getMyInputStreamSomehow();
File tempFile = File.createTempFile(...);
tempFile.deleteOnExit();
_localInStream = new FileInputStream(tempFile);
_localOutStream = new FileOutputStream(tempFile);
int buffered = bufferMedia(
_remoteStream, _localOutStream, BUFFER_TARGET_SIZE // = 128KB for instance
);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource(_localInStream.getFD());
player.prepareAsync();
int streamed = 0;
while (buffered >= 0) {
buffered = bufferMedia(
_remoteStream, _localOutStream, BUFFER_TARGET_SIZE
);
}
}
catch (Exception exception) {
// Handle errors as you see fit
}
return null;
}
les tampons de méthode bufferMedia nbytes octets ou jusqu'à la fin de l'entrée est atteinte:
private
int bufferMedia(InputStream inStream, OutputStream outStream, int nBytes)
throws IOException
{
final int BUFFER_SIZE = 8 * (1 << 10);
byte[] buffer = new byte[BUFFER_SIZE]; // TODO: Do static allocation instead
int buffered = 0, read = -1;
while (buffered < nBytes) {
read = inStream.read(buffer);
if (read == -1) {
break;
}
outStream.write(buffer, 0, read);
outStream.flush();
buffered += read;
}
if (read == -1 && buffered == 0) {
return -1;
}
return buffered;
}
La méthode setListeners Définit des gestionnaires pour divers événements MediaPlayer. Le plus important est le OnCompletionListener qui est appelé lorsque la lecture est terminée. En cas de sous-utilisation du tampon (en raison, disons, d'une connexion réseau lente temporaire), le lecteur atteindra la fin du fichier local et passera à l'état PlaybackCompleted. J'identifie ces situations en comparant la position de _localInStream par rapport à la taille du flux d'entrée. Si la position est plus petite, puis la lecture est vraiment terminée et je réinitialiser le MediaPlayer:
private
void setListeners(MediaPlayer player)
{
// Set some other listeners as well
player.setOnSeekCompleteListener(
new MediaPlayer.OnSeekCompleteListener()
{
@Override
public
void onSeekComplete(MediaPlayer mp)
{
mp.start();
}
}
);
player.setOnCompletionListener(
new MediaPlayer.OnCompletionListener()
{
@Override
public
void onCompletion(MediaPlayer mp)
{
try {
long bytePosition = _localInStream.getChannel().position();
int timePosition = mp.getCurrentPosition();
int duration = mp.getDuration();
if (bytePosition < _track.size) {
mp.reset();
mp.setDataSource(_localInStream.getFD());
mp.prepare();
mp.seekTo(timePosition);
} else {
mp.release();
}
} catch (IOException exception) {
// Handle errors as you see fit
}
}
}
);
}
Je ne peux pas vérifier si cela a fait une différence, mais si vous êtes chanceux, MediaPlayer Uri pourrait supporter l'authentification '' https: // nom d'utilisateur: mot de passe @ server.com/stream.data''. Si votre authentification est quelque chose de différent de celui par défaut, il s'agit d'un refus. – harism
Non, l'authentification n'est pas basée sur un mot de passe. – smichak