ex

Fork of mbed-os-example-mbed5-blinky by mbed-os-examples

dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/player/MediaPlayerImpl.java

Committer:
TMBOY
Date:
2017-07-18
Revision:
45:2aa9f933c8d2

File content as of revision 45:2aa9f933c8d2:

/*
 * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.baidu.duer.dcs.androidsystemimpl.player;

import android.app.Service;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import com.baidu.duer.dcs.androidapp.DcsSampleApplication;
import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
import com.baidu.duer.dcs.util.LogUtil;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * android MediaPlayer -android平台中实现音频的播放逻辑
 * <p>
 * Created by guxiuzhong@baidu.com on 2017/5/31.
 */
public class MediaPlayerImpl implements IMediaPlayer {
    private static final String TAG = MediaPlayerImpl.class.getSimpleName();
    public static final String ASSERT_PREFIX = "assets://";
    private static final String KEY_SP_VOLUME = "currentVolume";
    private static final String KEY_SP_MUTE = "isMute";
    private IMediaPlayer.PlayState mCurrentState = IMediaPlayer.PlayState.IDLE;
    private MediaPlayer mMediaPlayer;
    private float currentVolume = 0.8f;                 // 默认音量80%
    private boolean isMute;
    private boolean isError38;
    private float currentPercent;
    private int currentSeekMilliseconds;
    private IAudioStreamStore audioStreamStore;         // stream流数据保存
    private List<IMediaPlayer.IMediaPlayerListener> mediaPlayerListeners;
    private boolean isActive;
    private TelephonyManager telephonyManager;

    public MediaPlayerImpl() {
        mMediaPlayer = new MediaPlayer();
        // set audio stream type
        mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        mMediaPlayer.setOnBufferingUpdateListener(bufferingUpdateListener);
        mMediaPlayer.setOnErrorListener(errorListener);
        mMediaPlayer.setOnPreparedListener(preparedListener);
        mMediaPlayer.setOnCompletionListener(completionListener);
        mMediaPlayer.setOnSeekCompleteListener(seekCompleteListener);
        // 不同的音频源,此回调有的不回调!!!
        // mMediaPlayer.setOnInfoListener(infoListener);

        // 读取音量和静音的数据
        currentVolume = (float) MediaPlayerPreferenceUtil.get(DcsSampleApplication.getInstance(),
                KEY_SP_VOLUME, 0.8f);
        isMute = (boolean) MediaPlayerPreferenceUtil.get(DcsSampleApplication.getInstance(),
                KEY_SP_MUTE, false);
        // LinkedList
        mediaPlayerListeners = Collections.synchronizedList(new LinkedList<IMediaPlayer.IMediaPlayerListener>());

        // 来电监听
        telephonyManager = (TelephonyManager)
                DcsSampleApplication.getInstance().getSystemService(Service.TELEPHONY_SERVICE);
        telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
    }

    private PhoneStateListener phoneStateListener = new PhoneStateListener() {
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            super.onCallStateChanged(state, incomingNumber);
            switch (state) {
                // 电话挂断
                case TelephonyManager.CALL_STATE_IDLE:
                    resume();
                    break;
                // 等待接电话
                case TelephonyManager.CALL_STATE_RINGING:
                    pause();
                    break;
                // 通话中
                case TelephonyManager.CALL_STATE_OFFHOOK:
                    break;
                default:
                    break;
            }
        }
    };

    private IAudioStreamStore.OnStoreListener onStoreListener = new IAudioStreamStore.SimpleOnStoreListener() {
        @Override
        public void onComplete(String path) {
            LogUtil.e(TAG, "onStoreListener,path:" + path);
            // after down star play
            File file = new File(path);
            if (file.exists() && file.length() > 0) {
                play(path);
            } else {
                mCurrentState = IMediaPlayer.PlayState.ERROR;
                fireOnError("play path not exists or length<0 ",
                        IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_DEVICE_ERROR);
            }
        }
    };

    @Override
    public void play(MediaResource mediaResource) {
        if (mediaResource.isStream) {
            play(mediaResource.stream);
        } else {
            play(mediaResource.url);
        }
    }

    private void play(InputStream stream) {
        LogUtil.e(TAG, "play stream");
        if (audioStreamStore == null) {
            audioStreamStore = new AudioStreamStoreImpl();
        }
        audioStreamStore.setOnStoreListener(onStoreListener);
        audioStreamStore.save(stream);
    }

    private void play(String url) {
        if (TextUtils.isEmpty(url)) {
            LogUtil.d(TAG, "play-url is empty");
            fireOnError("play-url is empty.",
                    IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_DEVICE_ERROR);
            mCurrentState = IMediaPlayer.PlayState.ERROR;
            return;
        }
        fireOnInit();
        LogUtil.d(TAG, "play-url:" + url);
        if (url.startsWith(ASSERT_PREFIX) && url.length() > ASSERT_PREFIX.length()) {
            playAsset(url.substring(ASSERT_PREFIX.length()));
        } else {
            try {
                mMediaPlayer.reset();
                mMediaPlayer.setDataSource(url);
                // Async
                mMediaPlayer.prepareAsync();
                mCurrentState = IMediaPlayer.PlayState.PREPARING;
            } catch (IOException e) {
                e.printStackTrace();
                LogUtil.d(TAG, "playPath", e);
                mCurrentState = IMediaPlayer.PlayState.ERROR;
                fireOnError("IOException play url :"
                        + url, IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_DEVICE_ERROR);
            }
        }
    }

    private void playAsset(String resName) {
        LogUtil.d(TAG, "playAsset:" + resName);
        try {
            AssetManager am = DcsSampleApplication.getInstance().getAssets();
            AssetFileDescriptor afd = am.openFd(resName);
            mMediaPlayer.reset();
            mMediaPlayer.setDataSource(afd.getFileDescriptor(),
                    afd.getStartOffset(), afd.getLength());
            mMediaPlayer.prepareAsync();
            mCurrentState = IMediaPlayer.PlayState.PREPARING;
        } catch (IOException e) {
            e.printStackTrace();
            LogUtil.d(TAG, "playAsset", e);
            mCurrentState = IMediaPlayer.PlayState.ERROR;
            fireOnError("IOException play playAsset",
                    IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_DEVICE_ERROR);
        }
    }

    @Override
    public void pause() {
        if (mCurrentState == IMediaPlayer.PlayState.PLAYING
                || mCurrentState == IMediaPlayer.PlayState.PREPARED
                || mCurrentState == IMediaPlayer.PlayState.PREPARING) {
            mMediaPlayer.pause();
            mCurrentState = IMediaPlayer.PlayState.PAUSED;
            fireOnPaused();
        }
    }

    @Override
    public void stop() {
        if (mMediaPlayer != null) {
            mMediaPlayer.stop();
            mCurrentState = IMediaPlayer.PlayState.STOPPED;
            // delete audio file
            if (audioStreamStore != null) {
                audioStreamStore.cancel();
                audioStreamStore.speakAfter();
            }
            fireStopped();
        }
    }


    @Override
    public void resume() {
        if (mCurrentState == IMediaPlayer.PlayState.PAUSED) {
            mMediaPlayer.start();
            mCurrentState = IMediaPlayer.PlayState.PLAYING;
            firePlaying();
        }
    }

    @Override
    public void release() {
        if (mMediaPlayer != null) {
            mMediaPlayer.stop();
            mMediaPlayer.release();
            mMediaPlayer = null;
            mCurrentState = IMediaPlayer.PlayState.IDLE;
            fireOnRelease();
        }
        if (audioStreamStore != null) {
            audioStreamStore.cancel();
            audioStreamStore.speakAfter();
        }
        mediaPlayerListeners.clear();
    }

    @Override
    public PlayState getPlayState() {
        return mCurrentState;
    }

    @Override
    public void seekTo(int pos) {
        currentSeekMilliseconds = pos;
        LogUtil.d(TAG, "seekTo,currentSeekMilliseconds:" + currentSeekMilliseconds);
        if (mMediaPlayer != null && mCurrentState == IMediaPlayer.PlayState.PREPARED) {
            mMediaPlayer.seekTo(pos);
        }
    }

    /**
     * 设置音量
     *
     * @param volume 0.0 -1.0
     */
    @Override
    public void setVolume(float volume) {
        // 设置音量就不再静音了,比如:说了调衡音量等操作
        isMute = false;
        currentVolume = volume;
        if (mMediaPlayer != null) {
            mMediaPlayer.setVolume(volume, volume);
        }
        //  保存数据
        MediaPlayerPreferenceUtil.put(DcsSampleApplication.getInstance(),
                KEY_SP_VOLUME, currentVolume);
        MediaPlayerPreferenceUtil.put(DcsSampleApplication.getInstance(),
                KEY_SP_MUTE, isMute);
    }

    @Override
    public float getVolume() {
        return currentVolume;
    }

    @Override
    public void setMute(boolean mute) {
        isMute = mute;
        if (mMediaPlayer != null) {
            if (mute) {
                mMediaPlayer.setVolume(0, 0);
            } else {
                mMediaPlayer.setVolume(currentVolume, currentVolume);
            }
        }
        //  保存数据
        MediaPlayerPreferenceUtil.put(DcsSampleApplication.getInstance(),
                KEY_SP_MUTE, isMute);
    }

    @Override
    public boolean getMute() {
        return isMute;
    }

    @Override
    public long getCurrentPosition() {
        if (mMediaPlayer == null) {
            return 0;
        }
        if (mCurrentState == IMediaPlayer.PlayState.IDLE || mCurrentState == IMediaPlayer.PlayState.ERROR) {
            return 0;
        }
        return mMediaPlayer.getCurrentPosition();
    }

    @Override
    public long getDuration() {
        if (mMediaPlayer == null) {
            return 0;
        }
        if (mCurrentState == IMediaPlayer.PlayState.IDLE || mCurrentState == IMediaPlayer.PlayState.ERROR) {
            return 0;
        }
        return mMediaPlayer.getDuration();
    }

    @Override
    public float getBufferPercentage() {
        return currentPercent;
    }


    @Override
    public void addMediaPlayerListener(IMediaPlayerListener listener) {
        if (!mediaPlayerListeners.contains(listener)) {
            mediaPlayerListeners.add(listener);
        }
    }

    @Override
    public void removeMediaPlayerListener(IMediaPlayerListener listener) {
        if (mediaPlayerListeners.contains(listener)) {
            mediaPlayerListeners.remove(listener);
        }
    }

    @Override
    public void setActive(boolean isActive) {
        this.isActive = isActive;
    }

    @Override
    public boolean isActive() {
        return isActive;
    }

    private void fireOnError(String error, ErrorType errorType) {
        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
            if (listener != null) {
                listener.onError(error, errorType);
            }
        }
    }

    private void fireOnInit() {
        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
            if (listener != null) {
                listener.onInit();
            }
        }
    }

    private void fireOnPaused() {
        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
            if (listener != null) {
                listener.onPaused();
            }
        }
    }

    private void fireStopped() {
        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
            if (listener != null) {
                listener.onStopped();
            }
        }
    }

    private void firePlaying() {
        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
            if (listener != null) {
                listener.onPlaying();
            }
        }
    }

    private void fireOnRelease() {
        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
            if (listener != null) {
                listener.onRelease();
            }
        }
    }

    private void fireOnPrepared() {
        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
            if (listener != null) {
                listener.onPrepared();
            }
        }
    }

    private void fireOonBufferingUpdate(int percent) {
        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
            if (listener != null) {
                listener.onBufferingUpdate(percent);
            }
        }
    }

    private void fireOnCompletion() {
        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
            if (listener != null) {
                listener.onCompletion();
            }
        }
    }

    private MediaPlayer.OnPreparedListener preparedListener = new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mp) {
            LogUtil.d(TAG, "onPrepared");
            mCurrentState = IMediaPlayer.PlayState.PREPARED;
            isError38 = false;
            fireOnPrepared();
            // must be called  after  prepareAsync or prepare
            LogUtil.d(TAG, "currentVolume:" + currentVolume);
            LogUtil.d(TAG, "currentSeekMilliseconds:" + currentSeekMilliseconds);
            //  一开始就说话让它静音了
            if (isMute) {
                mMediaPlayer.setVolume(0, 0);
            } else {
                setVolume(currentVolume);
            }
            seekTo(currentSeekMilliseconds);
        }
    };

    private MediaPlayer.OnBufferingUpdateListener bufferingUpdateListener =
            new MediaPlayer.OnBufferingUpdateListener() {
                @Override
                public void onBufferingUpdate(MediaPlayer mp, int percent) {
                    currentPercent = percent * 1.0f;
                    fireOonBufferingUpdate(percent);
                }
            };
    private MediaPlayer.OnErrorListener errorListener = new MediaPlayer.OnErrorListener() {
        @Override
        public boolean onError(MediaPlayer mp, int what, int extra) {
            LogUtil.d(TAG, "onError:" + what + ", extra:" + extra);
            if (what == -38) {
                isError38 = true;
                return false;
            }
            isError38 = false;
            mCurrentState = IMediaPlayer.PlayState.ERROR;
            JSONObject jsonObject = new JSONObject();
            try {
                jsonObject.put("msg", "what: " + what + "; extra:" + extra);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            IMediaPlayer.ErrorType errorType;
            switch (what) {
                case MediaPlayer.MEDIA_ERROR_IO:
                    // Stream服务端返回错误 (bad request, unauthorized, forbidden, not found etc)
                    errorType = IMediaPlayer.ErrorType.MEDIA_ERROR_INVALID_REQUEST;
                    break;
                case MediaPlayer.MEDIA_ERROR_TIMED_OUT:
                    // 端无法连接stream服务端
                    errorType = IMediaPlayer.ErrorType.MEDIA_ERROR_SERVICE_UNAVAILABLE;
                    break;
                case MediaPlayer.MEDIA_ERROR_UNSUPPORTED:
                    // 端内部错误
                    errorType = IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_DEVICE_ERROR;
                    break;
                case MediaPlayer.MEDIA_ERROR_MALFORMED:
                    // stream服务端接受请求,但未能正确处理 ?????
                    errorType = IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_SERVER_ERROR;
                    break;
                default:
                    // 未知错误
                    errorType = IMediaPlayer.ErrorType.MEDIA_ERROR_UNKNOWN;
                    break;
            }
            fireOnError(jsonObject.toString(), errorType);
            return false;
        }
    };

    private MediaPlayer.OnSeekCompleteListener seekCompleteListener = new MediaPlayer.OnSeekCompleteListener() {
        @Override
        public void onSeekComplete(MediaPlayer mp) {
            LogUtil.d(TAG, "onSeekComplete");
            if (mCurrentState == IMediaPlayer.PlayState.PREPARED) {
                mp.start();
                mCurrentState = IMediaPlayer.PlayState.PLAYING;
                firePlaying();
            }
        }
    };

    private MediaPlayer.OnCompletionListener completionListener = new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mp) {
            if (isError38) {
                return;
            }
            LogUtil.d(TAG, "onCompletion");
            // delete audio file
            if (audioStreamStore != null) {
                audioStreamStore.cancel();
                audioStreamStore.speakAfter();
            }
            mCurrentState = IMediaPlayer.PlayState.COMPLETED;
            fireOnCompletion();
        }
    };
}