mediaplayer 正确使用

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 player
            if (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());
        }
    }

}
posted @ 2024-09-10 09:17  future_li  阅读(51)  评论(0)    收藏  举报