需求
在MediaPlayer进行播放时需要设置特定的User-Agent。
首先看StackvOerflow上的讨论,总共有2篇文章。
讨论1
http://stackoverflow.com/questions/8959300/how-do-i-include-http-headers-with-mediaplayer-setdatasource
The method setDataSource(Context context, Uri uri, Map<String, String> headers) has been included in the SDK (marked as @hide) for quite a long time (at least since Froyo 2.2.x, API Level 8), check out the change history:
And has been unhidden and open to public since Ice Cream Sandwich 4.0.x, API Level 14:
Workaround:
Prior to Ice Cream Sandwich 4.0.x, API Level 14, we can use reflection call this hide API:
Uri uri = Uri.parse(path);
Map<String, String> headers = new HashMap<String, String>();
headers.put("key1", "value1");
headers.put("key2", "value2");
mMediaPlayer = new MediaPlayer();
// Use java reflection call the hide API:
Method method = mMediaPlayer.getClass().getMethod("setDataSource", new Class[] { Context.class, Uri.class, Map.class });
method.invoke(mMediaPlayer, new Object[] {this, uri, headers});
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.prepareAsync();
... ...
讨论2
http://stackoverflow.com/questions/23858472/android-mediaplayer-set-http-agent
I am building an audio streaming android application using MediaPlayer.
I setup the stream to play using:
mMediaPlayer.setDataSource(finalUrl);
Using this syntax the user agent in HTTP header is Dalvik 1.6.0
I tried to update the http user-agent header using:
Map<String, String> headers = new HashMap<String, String>();
headers.put("User-Agent", "My custom User Agent name");
mMediaPlayer.setDataSource(getApplicationContext(), finalUri, headers);
查看MediaPlayer.java(android 4.2.2)
/**
* Sets the data source as a content Uri.
*
* @param context the Context to use when resolving the Uri
* @param uri the Content URI of the data you want to play
* @param headers the headers to be sent together with the request for the data
* @throws IllegalStateException if it is called in an invalid state
*/
public void setDataSource(Context context, Uri uri, Map<String, String> headers)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
if (headers != null && headers.size() > 0){
IWindowManager mWindowManager = IWindowManager.Stub.asInterface(
ServiceManager.getService(Context.WINDOW_SERVICE));
try{
Log.d("Hery", "setDataSource sys.html5.local true, run http");
mWindowManager.setSystemProp("sys.html5.local","true");
} catch (RemoteException ex) {
ex.printStackTrace();
}
}else{
IWindowManager mWindowManager = IWindowManager.Stub.asInterface(
ServiceManager.getService(Context.WINDOW_SERVICE));
try{
Log.d("Hery", "setDataSource sys.html5.local false, run local");
mWindowManager.setSystemProp("sys.html5.local","false");
} catch (RemoteException ex) {
ex.printStackTrace();
}
}
String scheme = uri.getScheme();
if(scheme == null || scheme.equals("file")) {
setDataSource(uri.getPath());
return;
}
AssetFileDescriptor fd = null;
try {
ContentResolver resolver = context.getContentResolver();
fd = resolver.openAssetFileDescriptor(uri, "r");
if (fd == null) {
return;
}
// Note: using getDeclaredLength so that our behavior is the same
// as previous versions when the content provider is returning
// a full file.
if (fd.getDeclaredLength() < 0) {
setDataSource(fd.getFileDescriptor());
} else {
setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getDeclaredLength());
}
return;
} catch (SecurityException ex) {
} catch (IOException ex) {
} finally {
if (fd != null) {
fd.close();
}
}
Log.d(TAG, "Couldn't open file on client side, trying server side");
setDataSource(uri.toString(), headers);
return;
}