我们可以使用MediaPlayer播放多种媒体文件。我们可以播放应用内部的音视频文件,文件系统的音视频文件,或者来自网络的流媒体文件。
如果要加载流媒体内容,需求申请网络权限
<uses-permission android:name="android.permission.INTERNET" />
如果我们要使用MediaPlayer.setScreenOnWhilePlaying() or MediaPlayer.setWakeMode() 方法,需要申请Wake Lock权限
<uses-permission android:name="android.permission.WAKE_LOCK" />
使用MediaPlayer播放本地raw文件
MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
mediaPlayer.start(); // no need to call prepare(); create() does that for you
使用create方法创建MediaPlayer之后,不需要调用prepare,create方法会为我们调用此方法。
加载文件系统中的uri文件,请使用以下方法:
Uri myUri = ....; // initialize Uri here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioAttributes(
new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_MEDIA)
.build()
);
mediaPlayer.setDataSource(getApplicationContext(), myUri);
mediaPlayer.prepare();
mediaPlayer.start();
播放流媒体文件方法如下:
String url = "http://........"; // your URL here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioAttributes(
new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_MEDIA)
.build()
);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.start();
prepare方法会拉取,解析媒体文件,因此它属于耗时操作,我们可以使用prepareAsync方法,它会在子线程执行操作,当prepare结束时会回调我们通过setOnPreparedListener设置的MediaPlayer.OnPreparedListener中的onPrepared()方法。
当我们不需要MediaPlayer时记得释放它
mediaPlayer.release();
mediaPlayer = null;
如果我们要开发音频类的应用,一般需要把MediaPlayer放在Service中,这样就可以在后台播放音频。
为避免设备休眠,我们需要在MediaPlayer初始化时设置setWakeMode,使设备保持指定的锁定状态,并在暂停或停止时释放锁定。
mediaPlayer = new MediaPlayer();
// ... other initialization here ...
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
除了在必要的实际释放MediaPlayer之外,我们还应该重写Service的onDestroy方法释放它
public class MyService extends Service {
MediaPlayer mediaPlayer;
// ...
@Override
public void onDestroy() {
super.onDestroy();
if (mediaPlayer != null) mediaPlayer.release();
}
}
数字版权管理 (DRM)
如果要播放受DRM保护的资源,同步的方法如下:
setDataSource();
setOnDrmConfigHelper(); // optional, for custom configuration
prepare();
if (getDrmInfo() != null) {
prepareDrm();
getKeyRequest();
provideKeyResponse();
}
// MediaPlayer is now ready to use
start();
// ...play/pause/resume...
stop();
releaseDrm();
具体步骤如下:
- 如果您希望应用执行自定义配置,请定义 OnDrmConfigHelper 接口,并使用 setOnDrmConfigHelper()将其附加到播放器。
- 调用 prepare()。
- 调用 getDrmInfo()。如果来源具有 DRM 内容,则该方法会返回一个非 null MediaPlayer.DrmInfo 值。
如果存在 MediaPlayer.DrmInfo:
- 检查可用 UUID 的映射,然后选择一个。
- 通过调用 prepareDrm() 为当前来源准备 DRM 配置。
- 如果您创建并注册了 OnDrmConfigHelper 回调,则系统会在执行 prepareDrm() 时调用该回调。这样一来,您就能够在打开 DRM 会话之前执行 DRM 属性的自定义配置。该回调会在名为 prepareDrm() 的线程中同步调用。要访问 DRM 属性,请调用 getDrmPropertyString() 和 setDrmPropertyString()。避免执行冗长的操作。
- 如果尚未配置设备,prepareDrm() 还会访问配置服务器来配置该设备。所需的时间因网络连接而有所不同。
- 要获取不透明的密钥请求字节数组以发送到许可服务器,请调用 getKeyRequest()。
- 要向 DRM 引擎告知从许可服务器接收到的密钥响应,请调用 provideKeyResponse()。结果取决于密钥请求的类型:
- 如果响应针对的是离线密钥请求,则结果为密钥组标识符。您可以将此密钥组标识符与 restoreKeys() 结合使用,以将这些密钥恢复到新的会话中。
- 如果响应针对的是流式传输或释放请求,则结果为 null。
我们可以从ContentResolver中检索媒体资源
ContentResolver contentResolver = getContentResolver();
Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor cursor = contentResolver.query(uri, null, null, null, null);
if (cursor == null) {
// query failed, handle error.
} else if (!cursor.moveToFirst()) {
// no media on the device
} else {
int titleColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE);
int idColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID);
do {
long thisId = cursor.getLong(idColumn);
String thisTitle = cursor.getString(titleColumn);
// ...process entry...
} while (cursor.moveToNext());
}
我们可以结合MediaPlayer和ContentResolver使用
long id = /* retrieve it from somewhere */;
Uri contentUri = ContentUris.withAppendedId(
android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(getApplicationContext(), contentUri);
// ...prepare and start...
参考:
网友评论