flutter开发实战-just_audio实现播放音频暂停音频设置音量等

flutter开发实战-just_audio实现播放音频暂停音频设置音量等

最近开发过程中遇到需要播放背景音等音频播放,这里使用just_audio来实现播放音频暂停音频设置音量等

在这里插入图片描述

一、引入just_audio

在pubspec.yaml引入just_audio

  just_audio: ^2.7.0

在iOS上,video_player使用的是AVPlayer进行播放。
在Android上,video_player使用的是ExoPlayer。

二、使用前设置

2.1 在iOS中的设置
在iOS工程中info.plist添加一下设置,以便支持Https,HTTP的视频地址

<key>NSAppTransportSecurity</key>
<dict>
	<key>NSAllowsArbitraryLoads</key>
	<true/>
</dict>

2.2 在Android中的设置
需要在/android/app/src/main/AndroidManifest.xml文件中添加网络权限

<uses-permission android:name="android.permission.INTERNET"/>

三、just_audio实现播放音频暂停音频设置音量等

引入just_audio后,可以使用AudioPlayer来播放音频

3.1 常用操作如下

  • 播放
await _audioPlayer.play();
  • 暂停
await _audioPlayer.pause();
  • seek
await _audioPlayer.seek(position);
  • 停止
await _audioPlayer.pause();
await _audioPlayer.seek(Duration.zero);
  • 设置音量
await _audioPlayer.setVolume(volume);

3.2 使用just_audio实现播放player

这里通过player来获取SDAudioPlayerState状态,控制音频的暂停音频设置音量等操作

import 'package:flutter_app/manager/logger_manager.dart';
import 'package:just_audio/just_audio.dart';

// 播放回调
typedef SDAudioPlayerCallBack = void Function(
    SDAudioPlayerState state, SDAudioPlayerError? error);

// 播放音频的状态
enum SDAudioPlayerState {
  idle, // 默认
  loading, // 加载中
  buffering, // 缓存中
  ready, // 可播放
  completed, // 播放完成
}

// 播放音频出现错误
class SDAudioPlayerError {
  String? message;
}

// 定义优先级的类
class SDMusicConfig {
  // 音频文件地址
  late String audioUrl = '';

  late bool runLoop = false; // 是否循环播放

  // 构造函数
  SDMusicConfig(this.audioUrl, this.audioPriority, this.runLoop);
}

// 播放音频文件
class SDMusicPlayer {
  // 音频播放
  late AudioPlayer _audioPlayer;

  // 优先级
  late SDMusicConfig _musicConfig;

  late bool _playing = false; // 是否正在播放

  late SDAudioPlayerState _playerState = SDAudioPlayerState.idle; // 状态

  late SDAudioPlayerCallBack? _playerCallBack;

  SDMusicPlayer(this._audioPlayer, this._musicConfig){
    setAudioUrl(this._musicConfig.audioUrl);
    openPlayCallBack((state, error) {

    });
  }

  SDMusicConfig getMusicConfig() {
    return _musicConfig;
  }

  void openPlayCallBack(SDAudioPlayerCallBack playerCallBack) {
    _playerCallBack = playerCallBack;
    _audioPlayer.playerStateStream.listen((state) {
      _playing = state.playing;

      switch(state.processingState) {
        case ProcessingState.idle: {
          _playerState = SDAudioPlayerState.idle;
          break;
        }
        case ProcessingState.loading: {
          _playerState = SDAudioPlayerState.loading;
          break;
        }
        case ProcessingState.buffering: {
          _playerState = SDAudioPlayerState.buffering;
          break;
        }
        case ProcessingState.ready: {
          _playerState = SDAudioPlayerState.ready;
          break;
        }
        case ProcessingState.completed: {
          _playerState = SDAudioPlayerState.completed;
          if (_musicConfig.runLoop == true) {
            // 循环播放的时候
            seek(Duration.zero);
            play();
          } else {
            stop();
          }
          break;
        }

        default:
      }

      if (_playerCallBack != null) {
        _playerCallBack!(_playerState, null);
      }
    });
  }

  // var duration = await player.setUrl('https://foo.com/bar.mp3');
  Future<void> setAudioUrl(String url) async {
    SDAudioPlayerError? error;
    if (url.isNotEmpty) {
      // Set the audio source but manually load audio at a later point.
      try {
        _audioPlayer.setUrl(url, preload: true);
        // Acquire platform decoders and start loading audio.
        var duration = await _audioPlayer.load();
        print("url:${url} duration:${duration}");
      } on PlayerException catch (e) {
        // iOS/macOS: maps to NSError.code
        // Android: maps to ExoPlayerException.type
        // Web: maps to MediaError.code
        // Linux/Windows: maps to PlayerErrorCode.index
        print("SDAudioPlayer Error code: ${e.code}");
        // iOS/macOS: maps to NSError.localizedDescription
        // Android: maps to ExoPlaybackException.getMessage()
        // Web/Linux: a generic message
        // Windows: MediaPlayerError.message
        print("SDAudioPlayer Error message: ${e.message}");
        error = SDAudioPlayerError();
        error.message = e.message;
      } on PlayerInterruptedException catch (e) {
        // This call was interrupted since another audio source was loaded or the
        // player was stopped or disposed before this audio source could complete
        // loading.
        LoggerManager()
            .debug("SDAudioPlayer Connection aborted: ${e.message}");
        error = SDAudioPlayerError();
        error.message = e.message;
      } catch (e) {
        // Fallback for all errors
        print("e: ${e}");
        error = SDAudioPlayerError();
        error.message = e.toString();
      }
    } else {
      error = SDAudioPlayerError();
      error.message = '播放地址不能为空';
    }

    if (_playerCallBack != null) {
      _playerCallBack!(_playerState, error);
    }
  }

  void play() async {
    // Usually you don't want to wait for playback to finish.
    if (_musicConfig.audioUrl != null && _musicConfig.audioUrl.isNotEmpty) {
      if (_playing == false) {
        // 正在播放
        await _audioPlayer.play();
      }
    }
  }

  void pause() async {
    if (_musicConfig.audioUrl != null && _musicConfig.audioUrl.isNotEmpty) {
      await _audioPlayer.pause();
    }
  }

  void stop() async {
    if (_musicConfig.audioUrl != null && _musicConfig.audioUrl.isNotEmpty) {
      await _audioPlayer.pause();
      await _audioPlayer.seek(Duration.zero);
    }
  }

  void seek(Duration position) async {
    if (_musicConfig.audioUrl != null && _musicConfig.audioUrl.isNotEmpty) {
      await _audioPlayer.seek(position);
    }
  }

  void setVolume(double volume) async {
    if (_musicConfig.audioUrl != null && _musicConfig.audioUrl.isNotEmpty) {
      await _audioPlayer.setVolume(volume);
    }
  }

  // 不需要该播放器,则需要调用该方法
  void dispose() async {
    await _audioPlayer.dispose();
  }
}

四、小结

flutter开发实战-just_audio实现播放音频暂停音频设置音量等。
学习记录,每天不停进步。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用vscode在vue项目中重命名文件选择了更新导入路径仍有部分导入路径没有更新

背景: 将一个js文件重命名&#xff0c;vscode弹出是否更新导入路径&#xff0c;选择更新导入后&#xff0c;发现js文件中导入路径都自动更新&#xff0c;vue文件中路径都没有更新。 解决方案&#xff1a; 在设置中搜索updateimport&#xff0c;将最下面的Vue>Update Imports…

步入React正殿 - 生命周期

目录 资料 三个阶段的生命周期函数 创建阶段 初始化阶段constructor 挂载阶段componentWillMount 挂载阶段render 挂载阶段componentDidMount 更新阶段【props或state改变】 更新阶段componentWillReceiveProps 更新阶段shouldComponentUpdate【可不使用&#xff0c;…

21款美规奔驰GLS450更换中规高配主机,汉化操作更简单

很多平行进口的奔驰GLS都有这么一个问题&#xff0c;原车的地图在国内定位不了&#xff0c;语音交互功能也识别不了中文&#xff0c;原厂记录仪也减少了&#xff0c;使用起来也是很不方便的。 可以实现以下功能&#xff1a; ①中国地图 ②语音小助手&#xff08;你好&#xf…

Handler机制(一)

Handler基础 Handler机制是什么&#xff1f; Handler是用来处理线程间通信的一套机制。 初级使用 第一步&#xff1a;在主线程中定义Handler private Handler mHandler new Handler(Looper.myLooper()){Overridepublic void handleMessage(NonNull Message msg) {super.ha…

C语言 字符指针

1、介绍 概念&#xff1a; 字符指针&#xff0c;就是字符类型的指针&#xff0c;同整型指针&#xff0c;指针指向的元素表示整型一样&#xff0c;字符指针指向的元素表示的是字符。 假设&#xff1a; char ch a;char * pc &ch; pc 就是字符指针变量&#xff0c;字符指…

Spring系列篇--关于IOC【控制反转】的详解

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Spring的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.什么是Spring 二.Spring的特点 三.什…

用node.js搭建一个视频推流服务

由于业务中有不少视频使用的场景&#xff0c;今天来说说如何使用node完成一个视频推流服务。 先看看效果&#xff1a; 这里的播放的视频是一个多个Partial Content组合起来的&#xff0c;每个Partial Content大小是1M。 一&#xff0c;项目搭建 &#xff08;1&#xff09;初…

Docker 安装和架构说明

Docker 并非是一个通用的容器工具&#xff0c;它依赖于已存在并运行的Linux内核环境。 Docker实质上是在已经运行的Liunx下制造了一个隔离的文件环境&#xff0c;因此他的执行效率几乎等同于所部署的linux主机。因此Docker必须部署在Linux内核系统上。如果其他系统想部署Docke…

使用maven打包时如何跳过test,有三种方式

方式一 针对spring项目&#xff1a; <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <skipTests>true</skipTests> </configuration> …

ios swift alert 自定义弹框 点击半透明部分弹框消失

文章目录 1.BaseAlertVC2.BindFrameNumAlertVC 1.BaseAlertVC import UIKitclass BaseAlertVC: GLBaseViewController {let centerView UIView()override func viewDidLoad() {super.viewDidLoad()view.backgroundColor UIColor(displayP3Red: 0, green: 0, blue: 0, alpha:…

【JVM】JVM垃圾收集器

文章目录 什么是JVM垃圾收集器四种垃圾收集器&#xff08;按类型分&#xff09;1.串行垃圾收集器(效率低&#xff09;2.并行垃圾收集器(JDK8默认使用此垃圾回收器&#xff09;3.CMS&#xff08;并发&#xff09;垃圾收集器(只针对老年代垃圾回收的&#xff09;4.G1垃圾回收器(在…

常见的路由协议之RIP协议与OSPF协议

目录 RIP OSPF 洪泛和广播的区别 路由协议是用于在网络中确定最佳路径的一组规则。它们主要用于在路由器之间交换路由信息&#xff0c;以便找到从源到目标的最佳路径。 常见的路由协议&#xff1a; RIP (Routing Information Protocol)&#xff1a;RIP 是一种基于距离向量算…

强训第33天

选择 C A ping是TCP/IP协议族的一部分&#xff0c;使用ICMP协议&#xff0c;ICMP底层使用IP协议。如果要ping其他网段&#xff0c;则需要设置网关。 如果是二层交换机故障&#xff0c;则ping同网段的也会不通。 C Dos攻击被称之为“拒绝服务攻击”&#xff0c;其目的是使计算机…

Windows 安装 pandoc 将 jupyter 导出 pdf 文件

Windows 安装 pandoc 将 jupyter 导出 pdf 文件 1. 下载 pandoc 安装文件2. 安装 pandoc3. 安装 nbconvert4. 使用 pandoc 1. 下载 pandoc 安装文件 访问 https://github.com/jgm/pandoc/releases&#xff0c;下载最新版安装文件&#xff0c;例如&#xff0c;3.1.6.1 版&#…

学习篇之React Fiber概念及原理

什么是React Fibber&#xff1f; React Fiber 是 React 框架的一种底层架构&#xff0c;为了改进 React 的渲染引擎&#xff0c;使其更加高效、灵活和可扩展。 传统上&#xff0c;React 使用一种称为堆栈调和递归算法来处理虚拟 DOM 的更新&#xff0c;这种方法在大型应用或者…

request发送http请求

今天正式开始为大家介绍接口自动化&#xff0c;相信很多做测试的朋友&#xff0c;都用过一些工具&#xff0c;比如jmeter&#xff0c;loadrunner&#xff0c;postman等等&#xff0c;所以今天先给那些基础不太好的同学&#xff0c;先讲讲postman如何来测接口以及如何用pthon代码…

div 中元素居中的N种常用方法

本文主要记录几种常用的div盒子水平垂直都居中的方法。本文主要参考了该篇博文并实践加以记录说明以加深理解记忆 css之div盒子居中常用方法大全 本文例子使用的 html body结构下的div 盒子模型如下&#xff1a; <body><div class"container"><div c…

前端跨域的原因以及解决方案(vue),一文让你真正理解跨域

跨域这个问题,可以说是前端的必需了解的,但是多少人是知其然不知所以然呢&#xff1f; 下面我们来梳理一下vue解决跨域的思路。 什么情况会跨域&#xff1f; ​ 跨域的本质就是浏览器基于同源策略的一种安全手段。所谓同源就是必须有以下三个相同点&#xff1a;协议相同、域名…

C语言 棱形图案

目录 一、问题分析 上部分&#xff1a; 下部分&#xff1a; 二、代码演示 一、问题分析 如上图所示&#xff0c;我们可以将棱形进行拆解&#xff0c;分为上下两个部分。 上部分&#xff1a; 通过观察&#xff0c;我们得到 单边空格数 上半部分总行数 - 行数 - 1 …

金蝶软件实现导入Excel数据分录行信息到单据体分录行中

>>>适合KIS云专业版V16.0|KIS云旗舰版V7.0|K/3 WISE 14.0等版本<<< 金蝶软件中实现[导入Excel数据业务分录行]信息到[金蝶单据体分录]中,在采购订单|采购入库单|销售订单|销售出库单等类型单据中,以少量的必要字段在excel表格中按模板填列好,很方便快捷地从…