mediaplayer 正确使用
package com.github.jasonhancn.tvcursor.util;import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.SurfaceHolder;import com.realtop.mqttutils.MUtils;public class NativePlayer {private static final String TAG = "NativePlayer";private final Handler handler;private final Runnable videoNextAction;private final String path;private final SurfaceHolder mSurfaceHolder;private final AudioManager audioManager;private final Context context;private final long fireTime;private final String ip;private MediaPlayer mediaPlayer;private boolean isPrepared;private boolean isCloseByUser;private long start;public static final int open_audio_delay = 288;public NativePlayer(Runnable videoNextAction, String path, SurfaceHolder mSurfaceHolder, AudioManager audioManager, Context context, long fireTime, String ip) {this.videoNextAction = videoNextAction;this.path = path;this.mSurfaceHolder = mSurfaceHolder;this.audioManager = audioManager;this.context = context;this.fireTime = fireTime;this.ip = ip;this.handler = new Handler(Looper.getMainLooper());IjkInit();}public void IjkInit() {if (mediaPlayer != null) return;start = System.currentTimeMillis();try {mediaPlayer = new MediaPlayer();mediaPlayer.setDataSource(path);Log.i(TAG, "IjkInit: player video path:" + path);if (mSurfaceHolder != null) mediaPlayer.setDisplay(mSurfaceHolder);mediaPlayer.setOnPreparedListener(iMediaPlayer -> handler.post(this::onPrepareCallback));mediaPlayer.setOnCompletionListener(iMediaPlayer -> handler.post(this::onCompleteCallback));mediaPlayer.setOnErrorListener((iMediaPlayer, i, code) -> {handler.post(() -> onErrorCallback(i, "error code:" + code));return true;});mediaPlayer.prepareAsync();} catch (Exception e) {final String errorMsg = e.getMessage();handler.post(() -> onErrorCallback(-118, errorMsg));}// 定时触发音量和同步timeTriggerVideoPlay(fireTime, ip);}private boolean isEnterPrepare = false;private void onPrepareCallback() {isPrepared = true;// 准备好前已经人工停止了if (isCloseByUser) {Log.i(TAG, "onPrepareCallback: user close media play:" + mediaPlayer);IjkRelease();return;}if (isEnterPrepare) {Log.i(TAG, "onPrepareCallback: again enter prepare");return;}isEnterPrepare = true;// 开始后面播放mediaPlayer.setVolume(0f, 0f);mediaPlayer.start();Log.i(TAG, "onPrepareCallback: prepare cost time:" + (System.currentTimeMillis() - start) + "; is playing:" + mediaPlayer.isPlaying());}private boolean isEnterComplete = false;private void onCompleteCallback() {isPrepared = true;if (isEnterComplete) {Log.i(TAG, "onCompleteCallback: again enter");return;}isEnterComplete = true;IjkRelease();handler.post(videoNextAction);Log.i(TAG, "completeCallback: video player end:" + (System.currentTimeMillis() - start) / 1000);}private boolean isEnterError = false;private void onErrorCallback(int i, String msg) {isPrepared = true;if (isEnterError) {Log.i(TAG, "onErrorCallback: again enter");return;}isEnterError = true;IjkRelease();handler.post(videoNextAction);Log.i(TAG, "errorCallback: play error code:" + i + "; use time:" + (System.currentTimeMillis() - start) / 1000);MUtils.showMsg(context, "Video play failure ! error code:" + i + "; msg:" + msg);}public void handleClose() {isCloseByUser = true;IjkRelease();}public void IjkRelease() {handler.removeCallbacksAndMessages(null);Log.i(TAG, "IjkRelease: enter: isPrepared:" + isPrepared+ "; isCloseByUser:" + isCloseByUser + "; media player:" + mediaPlayer);if (!isPrepared) {Log.i(TAG, "IjkRelease: player is not prepare");return;}if (mediaPlayer != null) {try {if (mediaPlayer.isPlaying()) {mediaPlayer.stop();Log.i(TAG, "IjkRelease: enter stop player");}} catch (Exception e) {Log.i(TAG, "IjkRelease: pause error:" + e.getMessage());}try {mediaPlayer.setOnCompletionListener(null);mediaPlayer.setOnPreparedListener(null);mediaPlayer.setOnErrorListener(null);} catch (Exception e) {Log.i(TAG, "IjkRelease: close listener error:" + e.getMessage());}try {mediaPlayer.release();} catch (Exception e) {Log.i(TAG, "IjkRelease: release error:" + e.getMessage());}mediaPlayer = null;Log.i(TAG, "IjkRelease: handle ok");}}private void timeTriggerVideoPlay(final long fireTime, String ip) {long delay = fireTime - System.currentTimeMillis();if (delay <= 0) {handler.postDelayed(NativePlayer.this::openMainDeviceAudio, open_audio_delay);Log.i(TAG, "timeTriggerVideoPlay: Time later: fire time:" + fireTime);return;}// 计算触发时间handler.postDelayed(() -> {long start = System.currentTimeMillis();if (isCloseByUser) return;try {if (mediaPlayer != null && mediaPlayer.isPlaying()) {mediaPlayer.seekTo(0);handler.postDelayed(NativePlayer.this::openMainDeviceAudio, open_audio_delay);Log.i(TAG, "timeTrigger: seek now: use time:" + (System.currentTimeMillis() - start));} else {Log.i(TAG, "timeTrigger: media condition no met");}} catch (Exception e) {Log.i(TAG, "run: error:" + e.getMessage());}}, delay);Log.i(TAG, "timeTriggerVideoPlay: fire time:" + fireTime + "; ip:" + ip + "; current time:"+ System.currentTimeMillis() + "; user close:" + isCloseByUser + "; delay:" + delay);}private void openMainDeviceAudio() {if (!MUtils.isMainDevice || audioManager == null || isCloseByUser) return;try {// ijk playerif (mediaPlayer != null && mediaPlayer.isPlaying()) {mediaPlayer.setVolume(1f, 1f);Log.i(TAG, "openMainDeviceAudio: set volume 1f");}} catch (Exception e) {Log.i(TAG, "openMainDeviceAudio: set volume error:" + e.getMessage());}}}