监听插拔SD卡

本文介绍了如何使用Intent.ACTION_MEDIA_EJECT和ACTION_MEDIA_MOUNTED来监听SD卡的拔出和装入操作,并强调了在监听过程中,如果SD卡被拔出而MediaPlayer正在使用其资源,会导致MEDIA_ERROR_SERVER_DIED错误。当发生该错误时,应用需要释放MediaPlayer对象并创建新的实例。同时提供了解决错误的监听器代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.

Constant Value: 100 (0x00000064)

此时必须要释放掉MediaPlayer,在重新获取


以下代码是处理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);








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值