public void registerExternalStorageListener() {
if (mUnmountReceiver == null) {
mUnmountReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (mReceiverUnregistered) {
return;
}
String action = intent.getAction();
if (action.equals(Intent.ACTION_MEDIA_EJECT)) {
LogUtil.d(TAG, "MEDIA_EJECT");
// For multi-SD card, we should decide whether the
// internal SD card is ejected
// String ejectCardPath = intent.getData().getPath();
mEjectingCardPath = intent.getData().getPath();
LogUtil.d(TAG, "ejected card path=" + mEjectingCardPath);
LogUtil.d(TAG, "main card path="
+ Environment.getExternalStorageDirectory().getPath());
boolean isPlayingSongInSdCard = false;
String songPath = mPlayQueue.getCurSongPath();
LogUtil.d(TAG, "ejected card songPath=" + songPath);
if(songPath != null && songPath.contains(mEjectingCardPath)) {
isPlayingSongInSdCard = true;
}
if (mEjectingCardPath.equals(Environment.getExternalStorageDirectory().getPath()) || isPlayingSongInSdCard) {
// internal card is being ejected
LogUtil.d(TAG, "MEDIA_EJECT: internal card unmounting...");
saveQueue(true);
mQueueIsSaveable = false;
mCardId = -1;
LogUtil.d(TAG, "card eject: cardid=" + mCardId);
}
mEjectingCardPath = null;
} else if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
LogUtil.d(TAG, "MEDIA_MOUNTED");
mCardId = MusicUtils.getSDCardId(mStorageManager);
if (mPlayer != null && mPlayer.isPlaying()) {
return;
}
String mountedCardPath = intent.getData().getPath();
LogUtil.d(TAG, "mounted card path=" + mountedCardPath);
LogUtil.d(TAG, "main card path="
+ Environment.getExternalStorageDirectory().getPath());
if (mountedCardPath.equals(Environment.getExternalStorageDirectory().getPath())) {
// internal card mounted
mReloadHandler.postDelayed(new Runnable() {
@Override
public void run() {
LogUtil.d(TAG, "MEDIA_MOUNTED: internal card mounted...");
reloadQueue();
if (!mOnlineMusic) {
notifyChange(QUEUE_CHANGED);
notifyChange(META_CHANGED);
}
mQueueIsSaveable = true;
}
}, 1000);
}
}
}
};
IntentFilter iFilter = new IntentFilter();
iFilter.addAction(Intent.ACTION_MEDIA_EJECT);
iFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
iFilter.addDataScheme("file");
registerReceiver(mUnmountReceiver, iFilter);
}
}
Intent.ACTION_MEDIA_EJECT:监听拔出sd卡
Intent.ACTION_MEDIA_MOUNTED:监听装入sd卡
还要必须加上filter.addDataScheme("file”);
如果在拔出SD卡时,MediaPlayer在使用SD卡上的资源,MediaPlayer就会触发
MEDIA_ERROR_SERVER_DIED
Added in
API level 1
int MEDIA_ERROR_SERVER_DIED
Media server died. In this case, the application must release the MediaPlayer object and instantiate a new one.
See also:
Constant Value: 100 (0x00000064)
以下代码是处理errorr的监听器:
MediaPlayer.OnErrorListener errorListener = new MediaPlayer.OnErrorListener() {
public boolean onError(MediaPlayer mp, int what, int extra) {
switch (what) {
case -38:// don't know this meaning, but we can get this
// code,try to play next song to avoid player's waiting
LogUtil.d(TAG, "MultiPlayer.onError -38 : " + what);
return true;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
case -19:
LogUtil.d(TAG, "onError: MEDIA_ERROR_SERVER_DIED");
mIsInitialized = false;
mCurrentMediaPlayer.release();
// Creating a new MediaPlayer and settings its wakemode does
// not
// require the media service, so it's OK to do this now,
// while the
// service is still being restarted
mCurrentMediaPlayer = new CompatMediaPlayer();
mCurrentMediaPlayer.setWakeMode(mService, PowerManager.PARTIAL_WAKE_LOCK);
mHandler.sendMessageDelayed(mHandler.obtainMessage(MediaPlaybackService.SERVER_DIED), 2000);
return true;
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
LogUtil.d(TAG, "onError: MEDIA_ERROR_UNKNOWN");
if(mService.isPlaying() == true){
mService.next(true);
}
return true;
default:
/*
* We should have used defined error codes as constants and
* handle them by 'case'. There are some constants in
* android.media.MediaPlayer but not enough. Because
* framework will return many error codes without
* pre-defined and there are also some operation status from
* JNI returned as error. As a result, we have to make a
* decision here: 1. For operation status INVALID_OPERATION
* whose code is -38, do nothing For every call to
* MediaPlayer, it will check its state, if the requesting
* operation is not allowed in the current state, it does
* nothing and return INVALID_OPERATION to JNI. JNI will
* notify operation status to upper layer as a error with
* MEDIA_ERROR, which, as a result, causes onError is
* called. Because MediaPlayer has protected itself from
* this operation, we have no reason to shutdown the player.
* 2. For other codes, notify user and shutdown player.
*/
LogUtil.d(TAG, "onError: what=" + what + ", extra=" + extra);
if (what != MediaPlaybackService.PVMF_DRM_CLOCK_ERROR) {
LogUtil.e("MultiPlayer", "isStreaming=" + mService.mOnlineMusic + " Unknown error ("
+ what + ", " + extra + ") returned from framework, stop player");
// Try to jump to next song in the playlist, if there
// are any
if (!mService.mOnlineMusic) {
if (mService.getOpenFailedCounter() < 10 && mService.mPlayQueue.getQueueSize() > 1
&& (mService.mPlayQueue.getCurPos() < mService.mPlayQueue.getQueueSize() - 1 || mService.getRepeatMode() == MediaPlaybackService.REPEAT_ALL)) {
mService.next(false);
mService.setOpenFailedCounter(mService.getOpenFailedCounter()+1);
} else if (mService.mPlayQueue.getCurPos() >= mService.mPlayQueue.getQueueSize() - 1) {
mService.stop(true);
mService.notifyChange(MediaPlaybackService.QUIT_PLAYBACK);
} else {
mService.stop(true);
}
if (mService.getOpenFailedCounter() != 0) {
// need to make sure we only shows this once
mService.setOpenFailedCounter(0);
if (!mService.isQuietMode()) {
mService.sendToastMessgeToMediaplayerHandler(R.string.fail_to_start_stream);
}
mService.setQuietMode(false);
}
} else {
if (what == MediaPlaybackService.MEDIA_ERROR_CANNOT_CONNECT_TO_SERVER) {
mService.stop(true);
mService. mPlayerState = MediaPlaybackService.PAUSED_CANNOT_CONNECT_TO_SERVER;
mService.notifyChange(MediaPlaybackService.PLAYSTATE_CHANGED);
mService.mPauseWhenNetDisConnect.set(true);
return true;
}
}
}
return true;
}
}
};
最后:player.setOnErrorListener(errorListener);