您的位置:首页 > 移动开发 > Android开发

Android开发指南之MediaPlayer

2017-05-11 15:58 169 查看

MediaPlayer

本文翻译至Android API开发指南之MediaPlayer。帮助我们了解什么是MediaPlayer及其基本用法与注意事项。

Android的多媒体框架支持各种常见的媒体类型,因此将各种音视频和图片资源融入你的app中将轻而易举。

播放的音视频来源主要有以下3大类:

1.app的资源文件(raw resources)

2.文件系统中的音视频文件

3.获取网络音视频资源

注意:播放音频数据仅仅支持标准输出设备。当前主要包括移动设备的扬声器和头戴式蓝牙耳机。并且不能在拨打电话的同时播放音频文件。

一、基础类

我们通常用到下面两个类来播放音频和视频

1.MediaPlayer

MediaPlayer提供API播放音频和视频。

2.AudioManager

AudioManager类用来管理音频资源和音频输出。

二、Manifest文件声明

使用MediaPlayer之前我们必须确保根据自己的需求声明了相应的权限。

1.Internet Permission 如果通过网络获取媒体资源,必须在Manifest文件中声明:

<uses-permission android:name="android.permission.INTERNET" />


2.Wake Lock Permission 如果你的app需要保持常亮而不进入睡眠状态,或者你使用了MediaPlayer.setScreenOnWhilePlaying() 或MediaPlayer.setWakeMode()方法,则必须在Manifest文件中声明:

<uses-permission android:name="android.permission.WAKE_LOCK" />


三、使用MediaPlayer

使用MediaPlayer最重要的类是MediaPlayer,通过该类能够以最少的设置来获取、解析和播放音视频。它支持3种类型的资源途径:

1.本地资源(Local resources)

2.内部URLs(例如ContentResolver

3.外部URLs(网络资源)

关于Android支持的所有媒体格式,请查看Supported Media Formats

使用示例:

1.获取App内部res/raw/directory中的资源

MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
mediaPlayer.start(); //不需要调用prepare(),因为create()方法已经帮你实现了。


值得注意的是,上例中的raw资源系统不会以特定方式进行解析。因此,该raw资源不能是原始音频,必须为已经被正确解析过后的Android所支持的媒体格式。

2.通过内部URL(例如ContentResolver)获取资源

Uri myUri = ....; // 初始化Uri
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(getApplicationContext(), myUri);
mediaPlayer.prepare();
mediaPlayer.start();


3.通过HTTP获取资源

String url = "http://........"; // url地址
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // 可能会很耗时! (例如buffering, etc)
mediaPlayer.start();


注意:如果你传入的url是一个网络媒体文件,那么该文件必能进行渐进式下载

当你调用setDataSource()方法时,因为你引用的文件可能不存在,必须处理IllegalArgumentException 和IOException异常。

四、Asynchronous preparation(异步preparation)

在使用MediaPlayer时有几件事必须注意。例如在prepare()方法中进行media数据的获取和解析可能会很耗时,只要是耗时的方法,都不要在UI线程中执行,因为这很可能会导致ANR。

为了避免在UI线程中执行耗时任务,MediaPlayer提供了prepareAsync()方法。该方法在后台准备media数据并且立即返回。当media数据准备完毕后,回调MediaPlayer.OnPreparedListener的onPrepared()方法,通过 setOnPreparedListener()方法进行事件注册。

五、状态管理(Managing state)

另外一件需要注意的事情就是MediaPlayer是基于状态的。意思是当你编写代码的时候必须随时意识到MediaPlayer存在一种内部状态(internal state),因为只有当播放器在某些特定状态时一些操作才是合法的。在错误的状态执行了错误的操作,后果自负(:P)。

MediaPlayer类中的状态图说明了哪些方法将MediaPlayer从一个状态转为另一个状态。



例如,当create一个新的MediaPlayer时,进入Idle状态。在这个状态你应该调用setDataSource()方法进行初始化,将它转变为Initialized状态。具体方法和状态转换如上图所示。所以我们在调用MediaPlayer相关的方法时,一定要在正确的状态中调用,否则就可能出错。

六、释放MediaPlayer资源

mediaPlayer.release();
mediaPlayer = null;


将MediaPlayer与所在Activity或Service的生命周期进行绑定,当Activity或Service销毁时一定要在onDestroy()方法中释放MediaPlayer资源。

七、在Service中使用MediaPlayer实例

如果你想在后台播放媒体,即使你的应用程序已经不可见了,那么我们就该启动一个Service来控制MediaPlayer。可以了解下 MediaBrowserServiceCompat和 MediaBrowserCompat(Building an Audio App)。

1.异步运行(Running asynchronously)

public class MyService extends Service implements MediaPlayer.OnPreparedListener {
private static final String ACTION_PLAY = "com.example.action.PLAY";
MediaPlayer mMediaPlayer = null;

public int onStartCommand(Intent intent, int flags, int startId) {
...
if (intent.getAction().equals(ACTION_PLAY)) {
mMediaPlayer = ... // initialize it here
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.prepareAsync(); // prepare async to not block main thread
}
}

/** Called when MediaPlayer is ready */
public void onPrepared(MediaPlayer player) {
player.start();
}
}


2.处理异步错误

public class MyService extends Service implements MediaPlayer.OnErrorListener {
MediaPlayer mMediaPlayer;

public void initMediaPlayer() {
// ...initialize the MediaPlayer here...

mMediaPlayer.setOnErrorListener(this);
}

@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// ... react appropriately ...
// The MediaPlayer has moved to the Error state, must be reset!
}
}


3.使用wake locks(唤醒锁)

当手机进入睡眠状态的时候,如果想让你的应用保持运行,就得用到wake locks。

注意:该用的时候用,不该用的时候别用,因为损耗电池。

初始化的时候调用setWakeMode()方法。 MediaPlayer会在媒体播放时保持这个锁,在pause或stop的时候release。

mMediaPlayer = new MediaPlayer();
// ... other initialization here ...
mMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);


当你使用wifi访问网络资源的时候,你还需要create和acquire一个wi-fi lock:

WifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE))
.createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");

wifiLock.acquire();


当pause或stop你的MediaPlayer,或者断网了,需要释放wi-fi lock:

wifiLock.release();


4.回收资源

public class MyService extends Service {
MediaPlayer mMediaPlayer;
// ...

@Override
public void onDestroy() {
if (mMediaPlayer != null) mMediaPlayer.release();
}
}


当然你也可以自己控制在什么地方释放资源,但是切记一定要在不需要的时候释放。

5.通过ContentResolver获取media资源

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());
}


得到了id后就可以播放啦:

long id = /* retrieve it from somewhere */;
Uri contentUri = ContentUris.withAppendedId(
android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);

mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setDataSource(getApplicationContext(), contentUri);

// ...prepare and start...


本文简要的介绍了MediaPlayer的使用方法与注意事项,具体在项目中的应用将在后续进行说明。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息