android 多媒体和相机详解二
释放MediaPlayer
MediaPlayer可能消耗大量的系统资源.因此你应该总是采取一些额外的措失来确保在一个MediaPlayer实例上不会挂起太长的时间.当你用完MediaPlayer时,你应该总是调用release()来保证任何分配给MediaPlayer的系统资源被正确地释放.例如,如果你正在使用MediaPlayer并且你的activity收到了一个对onStop()的调用,你必须释放MediaPlayer,因为当你的activtiy不再与用户交互时继续保持MediaPlayer会使用户有一点慢的感觉(除非你在后台播放媒体).当你的activityis resumed或restarted,你理所当然的需要创建一个新的MediaPlayer并且在恢复播放前重新准备它.
下面是如何释放MediaPlayer:
[java]
mediaPlayer.release();
mediaPlayer = null;
mediaPlayer.release();
mediaPlayer = null;
作为一个例子,想像一下如果当你的activitystopped时你忘记了释放MediaPlayer,而activity重新start时又创建了一个新的MediaPlayer这样的问题.就像你知道的,当用户改变屏幕的方向(或用另外的方法改变了设备的配置),系统处理的方式是重启activity(默认情况),于是当用户来回旋转设备时你可能消耗掉了所有的系统资源,因为在每次方向改变时,你都创建了一个新的MediaPlayer但是从不釋放它.
你现在可能对如何在没有activity时仍然在后台播放媒体感兴趣了,请看下一章.
使用带有MediaPlayer的service
如果你希望你的媒体在你的应用不出现在屏幕上时仍能在后台播放—也就是,你希望当用户与其它应用交互时仍能继续播放—那么你必须启动一个Service并且通过它控制MediaPlayer实例.但此方式下你应该小心慬慎,因为用户和系统都对一个应用运行一个后台service时应该如何与剩余的系统交互抱有期望值.如果你的应用不能满足这些期望,用户体验可能很坏.本节描述你应该注意的主要问题并且给出如何达到要求的建议.
异步运行
首先,跟Activity一样,默认下所有的Service的工作都是在一个单独的线程中完成—实际上,如果你从同一个应用中运行一个activity和一个service,它们默认使用同一个线程("主线程").因此,service需要快速处理进入的intent并且永不对它们执行长时间的计算.如果要执行某些重型工作和阻塞调用,你必须异步地执行它们:可以在你自己实现的另外线程中,也可以使用框架的一些异步处理工具.
例如,当在主线程中使用一个MediaPlayer,你应该调用prepareAsync()而不是prepare(),并且实现一个MediaPlayer.OnPreparedListener来监听"准备"完成通知并开始播放.例如:
[java]
public class MyService extends Service implements MediaPlayer.OnPreparedListener {
private static final 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();
}
}
public class MyService extends Service implements MediaPlayer.OnPreparedListener {
private static final 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();
}
}
处理异步错误
在异步操作时,错误通常是用异常或错误码通知的,但是无论何时你使用异步资源,你都应确保你的应用能被正确的通知错误.在使用MediaPlayer时,你可以通过实现一个MediaPlayer.OnErrorListener并把它设置给你的MediaPlayer实例来达到此目的.
[java]
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!
}
}
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!
}
}
有一点很重要:当错误发生时,MediaPlayer变为错误状态,你必须在重新使用它之前重置它才行.
使用唤醒锁
当设计在后台播放媒体的应用时,当你的service正在运行时,设备可能进入休眠.因为Android系统在休眠时会试着节省电能,那么系统会试着关闭电话的任何不必要的特性,包括CPU和WiFi.然而,如果你的service正在播放或接收音乐,你就想阻止系统干涉你的播放工作.
为了在上述情况下保证你的service继续运行,你必须使用"wakelocks".一个wakelock是一种通知系统在手机空闲时也应为你的应用保留所用特性的途径.
注意:你总是应该保守的使用wakelocks并且仅在真证需要时才持有它.因为它们会显著的减少设备电池的寿命.
当你的MediaPlayer播放时,要保持CPU持续运行,在初始化MediaPlayer时需调用setWakeMode().一旦你这样做了,MediaPlayer就会在播放时持有一个特定的锁,并在暂停或停止时释放它:
[java]
mMediaPlayer = new MediaPlayer();
// ... other initialization here ...
mMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mMediaPlayer = new MediaPlayer();
// ... other initialization here ...
mMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
然而,此例中所请求的wakeloc
补充:移动开发 , Android ,