mediaplayer 正确使用

news/2025/1/15 15:52:17/文章来源:https://www.cnblogs.com/futureli/p/18405778

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/794812.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何实现深拷贝?structuredClone

经典的面试题:如何实现深拷贝。 常规的回答主要是通过JSON或者遍历对象递归。主要是考核对对象操作方经典的面试题:如何实现深拷贝。 常规的回答主要是通过JSON或者遍历对象递归。主要是考核对对象操作方法的熟悉程度。今天来介绍另一个方案structuredClone()。什么是 struct…

信奥一本通题陈老师解题:1209:分数求和

​ 【题目描述】【输入】第一行是一个整数nn,表示分数个数,1≤n≤101≤n≤10; 接下来nn行,每行一个分数,用"p/qp/q"的形式表示,不含空格,p,qp,q均不超过1010。【输出】输出只有一行,即最终结果的最简形式。若为分数,用"p/qp/q"的形式表示。【输…

【OpenFeign 】OpenFeign 下的重试器的执行过程分析

1 前言 上节我们看了下 OpenFeign 里的重试,在从源码的角度看它的执行原理的时候,又意外的遇到了一个【OpenFeign 】OpenFeign 下未开启重试,服务却被调用了两次 的问题的分析,那本节我们就来看看重试器的一个入场以及执行的过程。 2 源码分析 首先我们要知道在默认的情况…

WiFi基础(三):802.11ac/ax/be 与 WiFi4、WiFi5、WiFi6、WiFi7

前面我们介绍了 802.11 b/g/n 的一些核心技术和基础概念,本章将介绍目前比较新的 WiFi5 和 WiFi6,以及在今年会发布的 WiFi7。liwen01 2024.09.08 前言 经过二十多年的发展,WiFi 在硬件能力、软件和算法、频谱资源、市场需求、电源与能效方面都有了很大的提升。所以我们能看…

一个类才几百行/搞定各种自定义委托/涵盖各种场景需求/所有委托一网打尽/用法极其简单

一、应用场景某个字段需要提供下拉框进行选择,下拉框可选是否允许编辑。 某个字段需要提供密码框进行输入,密文显示字段值。 某个字段需要提供日期框下拉选择日期时间。 某个字段需要提供微调框设定值。 某个字段需要提供进度条显示字段值。 某个字段列需要禁用。 各种委托控…

军工厂电气工程师到知名互联网公司程序员,我吃饭的家伙有哪些

大家好,我是欧阳。今年刚好是欧阳三十而立之年,虽然没有立起来。这篇文章来聊聊我从一名军工厂电气工程师到某知名互联网公司程序员,这期间我吃饭的家伙都有哪些。 军工厂期间 欧阳大学读的是“电气工程及其自动化专业”,毕业后进入了老家的一个军工厂,成为了一名电气工程…

用 SQL 写的俄罗斯方块游戏「GitHub 热点速览」

在开始介绍上周热门开源项目之前,要插播一条开源新闻:Nginx 已正式迁移至 GitHub。 近日,Nginx 官方宣布将 Nginx 开源项目,从 Mercurial 迁移至 GitHub 代码托管平台,并开始接受 PR 形式的贡献、Issues 问题反馈和功能请求等,GitHub 上的 Nginx 项目终于“活”了!GitHu…

喜欢干净简洁音乐播放器的朋友看过来

大家好,我是晓凡。 不少程序员小伙伴都喜欢边听音乐边敲代码,尤其在一个嘈杂的环境中,一个好的想法、好的思路可能就因为一瞬间的干扰就没了。 这时,如果耳机一戴上,听着音乐能更好的集中注意力;遇到bug也能临危不乱,想出更好的解决办法; 网易云音乐,算是一个相对简洁…

在vue3中手写按需加载图片

在我们的网页中.假如使用了大量的图片,每个图片都是需要去访问加载的 这就影响了我们的访问速度,手写一个按需加载组件,就可以解决这个问题 让图片处于页面视图的时候再加载,减轻网页访问负担利用vue3官网给出的钩子 我们常用的就是onMountent 如官网所示为了及时监测,这里使用…

单个48TB大小SQL Server数据库备份导致日志文件无法截断

单个48TB大小SQL Server数据库备份导致日志文件无法截断SQL Server 版本:SQL Server 2019背景在一个48T大小的单数据库环境中,采用简单恢复模式,日志文件大小限制为600G。执行一次完整备份时,耗时超过12小时,导致日志文件无法截断并达到上限,后续事务无法正常写入,导致整…

第一章 联言命题选言命题及其推理-德摩根定律及其练习题

听他讲一遍怎么做 自己怎么做 ==》对比 真值表做题!

第一章 联言命题选言命题及其推理-选言命题性质

可以同时发生的 相容选言命题 具备并存关系