private MediaPlayer create(final PlayConfig config) throws IOException { stopPlay(); MediaPlayer player; switch (config.mType) { case PlayConfig.TYPE_URI: Log.d(TAG, "MediaPlayer to start play uri: " + config.mUri); player = new MediaPlayer(); player.setDataSource(config.mContext, config.mUri); return player; case PlayConfig.TYPE_FILE: Log.d(TAG, "MediaPlayer to start play file: " + config.mAudioFile.getName()); player = new MediaPlayer(); player.setDataSource(config.mAudioFile.getAbsolutePath()); return player; case PlayConfig.TYPE_RES: Log.d(TAG, "MediaPlayer to start play: " + config.mAudioResource); player = MediaPlayer.create(config.mContext, config.mAudioResource); return player; case PlayConfig.TYPE_URL: Log.d(TAG, "MediaPlayer to start play: " + config.mUrl); player = new MediaPlayer(); player.setDataSource(config.mUrl); return player; default: // can't happen, just fix checkstyle throw new IllegalArgumentException("Unknown type: " + config.mType); } }
private void setMediaPlayerListener(final MediaPlayer player, final ObservableEmitter<Boolean> emitter) { player.setOnCompletionListener(mp -> { Log.d(TAG, "OnCompletionListener::onCompletion"); // could not call stopPlay immediately, otherwise the second sound // could not play, thus no complete notification // TODO discover why? Observable.timer(50, TimeUnit.MILLISECONDS).subscribe(aLong -> { stopPlay(); emitter.onComplete(); }, emitter::onError); }); player.setOnErrorListener((mp, what, extra) -> { Log.d(TAG, "OnErrorListener::onError" + what + ", " + extra); emitter.onError(new Throwable("Player error: " + what + ", " + extra)); stopPlay(); return true; }); }
@Override protected void onDestroy() { super.onDestroy(); if (mRxAudioPlayer != null) { mRxAudioPlayer.stopPlay(); } compositeDisposable.dispose(); }
private void setMediaPlayerListener(final MediaPlayer player, final MediaPlayer.OnCompletionListener onCompletionListener, final MediaPlayer.OnErrorListener onErrorListener) { player.setOnCompletionListener(mp -> { Log.d(TAG, "OnCompletionListener::onCompletion"); // could not call stopPlay immediately, otherwise the second sound // could not play, thus no complete notification // TODO discover why? Observable.timer(50, TimeUnit.MILLISECONDS).subscribe(aLong -> { stopPlay(); onCompletionListener.onCompletion(mp); }, throwable -> Log.d(TAG, "OnCompletionListener::onError, " + throwable.getMessage())); }); player.setOnErrorListener((mp, what, extra) -> { Log.d(TAG, "OnErrorListener::onError" + what + ", " + extra); onErrorListener.onError(mp, what, extra); stopPlay(); return true; }); }
/** * Non reactive API. */ @WorkerThread public boolean playNonRxy(@NonNull final PlayConfig config, final MediaPlayer.OnCompletionListener onCompletionListener, final MediaPlayer.OnErrorListener onErrorListener) { if (!config.isArgumentValid()) { return false; } try { MediaPlayer player = create(config); setMediaPlayerListener(player, onCompletionListener, onErrorListener); player.setVolume(config.mLeftVolume, config.mRightVolume); player.setAudioStreamType(config.mStreamType); player.setLooping(config.mLooping); if (config.needPrepare()) { player.prepare(); } player.start(); mPlayer = player; return true; } catch (RuntimeException | IOException e) { Log.w(TAG, "startPlay fail, IllegalArgumentException: " + e.getMessage()); stopPlay(); return false; } }
/** * play audio from local file. should be scheduled in IO thread. */ public Observable<Boolean> play(@NonNull final PlayConfig config) { if (!config.isArgumentValid()) { return Observable.error(new IllegalArgumentException("")); } return Observable.<Boolean>create(emitter -> { MediaPlayer player = create(config); setMediaPlayerListener(player, emitter); player.setVolume(config.mLeftVolume, config.mRightVolume); player.setAudioStreamType(config.mStreamType); player.setLooping(config.mLooping); if (config.needPrepare()) { player.prepare(); } player.start(); mPlayer = player; emitter.onNext(true); }).doOnError(e -> stopPlay()); }
/** * prepare audio from local file. should be scheduled in IO thread. */ public Observable<Boolean> prepare(@NonNull final PlayConfig config) { if (!config.isArgumentValid() || !config.isLocalSource()) { return Observable.error(new IllegalArgumentException("")); } return Observable.<Boolean>create(emitter -> { MediaPlayer player = create(config); setMediaPlayerListener(player, emitter); player.setVolume(config.mLeftVolume, config.mRightVolume); player.setAudioStreamType(config.mStreamType); player.setLooping(config.mLooping); if (config.needPrepare()) { player.prepare(); } mPlayer = player; emitter.onNext(true); }).doOnError(e -> stopPlay()); }