问题
I've seen quite a few posts asking this question on SO but there doesn't seem to be a definitive answer (or at least an answer I like!)
I've got content protected behind basic auth (username/password) -- I can download it fine using the various HTTP download clases but for the life of me I can't sort out how to tell media player to stream it (and provide the authentication). I saw one post that suggested it wasn't possible since the MediaPlayer is all native code and doesn't things like the Authenticator.
There are plenty of examples of how to first download to a cached copy and then play that back but....That sort of sucks (and the files maybe 100's of MB's). I saw at least one proposal to download it in smalish chunks and then start & stop the playback (redirecting to the new file) but that sort of sucks also since there would (I presume) be a stutter (I haven't tried it though)
The best idea I have at this point is to start downloading to a cache file and then when it's 'full enough' start up playback while I continue to fill the file.... I hope that this works (but again, haven't tried it).
Am I missing something obvious? It's so painful to have all the various pieces almost working and I sort of convinced myself that there had to be a way to natively stream protected content (or have it take a already established & qualified InputStream) but it appears no joy.
BTW I'm a Mac/iPhone guy and a newb at Android so I'm still fighting a bit of Java learning.... Excuse me if I'm missing something obvious.
回答1:
If you control the server, one option might be to modify it so that there's an option to generate a temporary, random URL for the content upon authentication, and then stream that. Will the streaming functions accept a URL that includes script parameters?
To do things entirely on the phone, another option would be to write a trivial http proxy like server in either java or native code and run it in a background thread. Instead of pointing the media player at the server, you'd point it at your own on-device proxy. The proxy would pass requests through to the remote server, while handling authentication.
回答2:
One approach is to download the data yourself, decode it (from ??? to PCM) and use AudioTrack to play the PCM. The trick is in the decoding. What format is the stream encoded in?
The raw decoders for common protocols are available on the Android, but in C libraries. So you might have to add a JNI layer to do your decoding, again, depending on what encoding your stream is in.
回答3:
I had the same problem, and I solved it by putting the credentials in the URL. It's not officially supported for HTTP, but most of the web-clients support it.
The code following is based on this tutorial: http://www.coderzheaven.com/2012/08/14/stream-audio-android/
try {
// You can use HTTPS or HTTP as protocol.
String myURL = "https://example.com/song.mp3";
mp.reset();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.setOnPreparedListener(this);
mp.setOnErrorListener(this);
// These are the two lines, doing the magic ;) It transforms it to a url like this: https://user:password@example.com/song.mp3
UsernamePasswordCredentials credentials = connHelper.getCredetials();
myURL = myURL.replace("://", "://" + URLEncoder.encode(credentials.getUserName(), "UTF-8") + ":" + URLEncoder.encode(credentials.getPassword(), "UTF-8") + "@");
mp.setDataSource(myURL);
mp.prepareAsync();
mp.setOnCompletionListener(this);
} catch (Exception e) {
Log.e("StreamAudioDemo", e.getMessage());
}
NOTE: By using the URLEncoder here, we want to ungo problems like: If the username or password contains a colon or an @.
NOTE2: It may, or may not work for you, depending on your Server. If you run into that issue, I suggest you should take a look at that one: Why do browsers not send the Authentication header when the credentials are provided in the URL?
来源:https://stackoverflow.com/questions/2932362/how-to-stream-authenticated-content-with-mediaplayer-on-android