android 多媒体和相机详解二
2012-07-09 08:03
405 查看
释放MediaPlayer
MediaPlayer可能消耗大量的系统资源.因此你应该总是采取一些额外的措失来确保在一个MediaPlayer实例上不会挂起太长的时间.当你用完MediaPlayer时,你应该总是调用release()来保证任何分配给MediaPlayer的系统资源被正确地释放.例如,如果你正在使用MediaPlayer并且你的activity收到了一个对onStop()的调用,你必须释放MediaPlayer,因为当你的activtiy不再与用户交互时继续保持MediaPlayer会使用户有一点慢的感觉(除非你在后台播放媒体).当你的activityisresumed或restarted,你理所当然的需要创建一个新的MediaPlayer并且在恢复播放前重新准备它.
下面是如何释放MediaPlayer:
[java]
view plaincopyprint?
mediaPlayer.release();
mediaPlayer = null;
异步运行
首先,跟Activity一样,默认下所有的Service的工作都是在一个单独的线程中完成—实际上,如果你从同一个应用中运行一个activity和一个service,它们默认使用同一个线程("主线程").因此,service需要快速处理进入的intent并且永不对它们执行长时间的计算.如果要执行某些重型工作和阻塞调用,你必须异步地执行它们:可以在你自己实现的另外线程中,也可以使用框架的一些异步处理工具. 例如,当在主线程中使用一个MediaPlayer,你应该调用prepareAsync()而不是prepare(),并且实现一个MediaPlayer.OnPreparedListener来监听"准备"完成通知并开始播放.例如: [java] view plaincopyprint? 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]
view plaincopyprint?
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!
}
}
[java] view plaincopyprint? 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);
然而,此例中所请求的wakelock只能保证CPU保持清醒.如果你正通过Wi-Fi从网络串流媒体数据,你可能也想持有WifiLock.对它你必须手动请求和释放.所以,当你使用远程URL准备MediaPlayer,你应该创建并请求Wi-Filock.例如:
[java]
view plaincopyprint?
WifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE))
.createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");
wifiLock.acquire();
[java] view plaincopyprint? wifiLock.release(); wifiLock.release();
作为前台服务运行
Services一般用于执行后台任务,比如获取邮件,同步数据,下载内容以及其它工作.这些情况下,用户不会太注意service的执行,并且可能跟本注意不到它们的中断以及重新运行.但是现在考虑一下用service播放音乐.很明显,用户会非常注意这个service并且一些中断会严重影响用户体验.另外,这种service还是用户在其执行期间想与之交互的.此情况下,此服务应作为一个"foregroundservice"运行.一个前台具有高重要性—系统永不会杀死它,因为它跟用户直接相关.当运行于前台时,service还必须在状态通知栏上提供一个通知来保证用户能看到service正在运行并且允许他们打开一个activity与service交互.
为了把你的service搞到前台,你必须为状态栏创建一个Notification并且调用startForeground().例如:
[java]
view plaincopyprint?
String songName;
// assign the song name to songName
PendingIntent pi = PendingIntent.getActivity(getApplicationContext(),
0,
new Intent(getApplicationContext(), MainActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification();
notification.tickerText = text;
notification.icon = R.drawable.play0;
notification.flags |= Notification.FLAG_ONGOING_EVENT;
notification.setLatestEventInfo(getApplicationContext(),
"MusicPlayerSample",
"Playing: " + songName, pi);
startForeground(NOTIFICATION_ID, notification);
String songName;
// assign the song name to songName
PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0,
new Intent(getApplicationContext(), MainActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification();
notification.tickerText = text;
notification.icon = R.drawable.play0;
notification.flags |= Notification.FLAG_ONGOING_EVENT;
notification.setLatestEventInfo(getApplicationContext(), "MusicPlayerSample",
"Playing: " + songName, pi);
startForeground(NOTIFICATION_ID, notification);
当你的service在前台运行时,你所配置的通知就出现在设备的通知区域.如果用户选择了这个通知,系统就会调用你提供的PendingIntent.在上例中,它打开了一个activity(MainActivity).
图 1演示了你的通知如何显示给用户:
图 1.前台service的通知截图,左图显示了状态栏的通知,右图显示了通知打开的view.
你应该只在用户需要注意service的执行情况时才使它保持"前台service"的状态,一旦此情况改变,你就应该调用stopForeground()把前台状态释放掉:
[java]
view plaincopyprint?
stopForeground(true);
相关文章推荐
- android 多媒体和相机详解五
- android 多媒体和相机详解十一(大结局)
- android 多媒体和相机详解九 .
- android 多媒体和相机详解五
- android 多媒体和相机详解六
- android 多媒体和相机详解(1-5)
- android 多媒体和相机详解一 .
- android 多媒体和相机详解十 .
- android 多媒体和相机详解七
- android 多媒体和相机详解二
- android 多媒体和相机详解十一(大结局) .
- android 多媒体和相机详解八
- android 多媒体和相机详解三
- android 多媒体和相机详解二 .
- android 多媒体和相机详解七
- android 多媒体和相机详解三 .
- android 多媒体和相机详解十
- android 多媒体和相机详解八
- android 多媒体和相机详解四
- android 多媒体和相机详解(6-11)