ex

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

Revision:
45:2aa9f933c8d2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/player/MediaPlayerImpl.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,527 @@
+/*
+ * 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();
+        }
+    };
+}
\ No newline at end of file