首页 > 其他分享 >mediaplayer 正确使用

mediaplayer 正确使用

时间:2024-09-10 09:13:43浏览次数:1  
标签:Log mediaplayer private final mediaPlayer TAG 使用 IjkRelease 正确

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(() -> one rrorCallback(i, "error code:" + code));
                return true;
            });

            mediaPlayer.prepareAsync();
        } catch (Exception e) {
            final String errorMsg = e.getMessage();
            handler.post(() -> one rrorCallback(-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 one rrorCallback(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());
        }
    }

}

标签:Log,mediaplayer,private,final,mediaPlayer,TAG,使用,IjkRelease,正确
From: https://www.cnblogs.com/futureli/p/18405778

相关文章

  • 前端怎么在页面中使用颜色选择器
    这里借助Vue.js提供的颜色选择器组件库vue-color首先安装这个库npminstallvue-color具体使用方法如下<template><divclass="color"><div>1.material<material-pickerv-model="colors"/></div><div>......
  • 【vue+el-table】表格操作列宽度跟随按钮个数自适应, 方法封装全局使用
    效果图以上图片分别代表不同用户权限下所能看到的按钮个数,操作列宽度也会自适应宽度,就不会一直处于最大宽度,导致其他权限用户看到的页面出现大量留白问题.目录解决方法解决过程中可能出现的问题width赋值时为什么不放update()中btnDom为什么不能直接调用for......
  • 使用MindFormers本地部署大模型
    MindSporeTransformers即时MindFormers套件的目标是构建一个大模型训练、微调、评估、推理、部署的全流程开发套件,提供业内主流的Transformer类预训练模型和SOTA下游任务应用,涵盖丰富的并行特性。期望帮助用户轻松的实现大模型训练和创新研发。安装MindFormers直接使用pip安......
  • 从自研到使用开源再到自研,我的工作流开发心路历程
    项目简介......
  • C#笔记7 网络通信抽象,Socket类的介绍和简单使用
    一、背景介绍在前面不算详细的基础知识和基本编程背景下,我们开始了今天重头菜,也就是开始与远方的计算机建立起一个连接,正式打通计算机与计算机之间的桥梁。C#笔记6网络编程基础,解释端口套接字,代码实例分析DNS,IPAddress等类-CSDN博客前文我们讲了计算机中间运行着怎么样的连......
  • 中文关键字检索分析-导出到csv或者excel-多文件或文件夹-使用python和asyncio和pandas
    1.02版本把原来的tab一个个拼接成文件输出,改成pandas的dataframe使用asyncio库来使用协程,但是测试下来速度好像是差不多的。可能速度太快了,没能很好的测出来差异。原来的最初的代码是java版本的,现在用python重写一遍java版本使用completableFuture来异步IO,主要是文件输......
  • 使用 Parallel 类进行多线程编码(下)
    2.Parallel.ForEach()的使用 从ForEach()这个名字可以看出该方法是用来遍历泛型集合的,新建一个ASP.NETCore Web应用的项目,如下:         在Index.cshtml.cs文件中增加一个UserInfo.cs的类,代码如下:publicclassUserInfo{publicint......
  • 如何使用Filter(过滤器二)
    目录一、过滤器链二、执行顺序三、示例说明一、过滤器链本片文章接如何使用Filter(过滤器一)-CSDN博客https://blog.csdn.net/u011529483/article/details/142059978?spm=1001.2014.3001.5502继续说说过滤器的执行顺序。过滤器和拦截器一样都是可以配置多个的,以链式的形......
  • 使用js闭包实现可取消的axios请求
    在平常开发中,经常会遇到重复请求的情况,也许是因为网络问题,也许是因为接口问题等等,传统做法是客户端采用防抖来限制用户发送接口的频率,一般出个loading转圈圈的形式,但是很少使用取消请求的做法,现在我来记录一下,如何采用闭包来封装一个可取消请求的函数,首先需要了解的是1.闭包2.......
  • 【图像去噪】实用小技巧 | 使用matlab将.mat格式的图像转成.png格式的图像,适用于DnD数
    请先看【专栏介绍文章】:【图像去噪(ImageDenoising)】关于【图像去噪】专栏的相关说明,包含适配人群、专栏简介、专栏亮点、阅读方法、定价理由、品质承诺、关于更新、去噪概述、文章目录、资料汇总、问题汇总(更新中)图像形式的DND数据集(.png格式)下载链接见本文底部,订阅专栏免......