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

news2024/12/24 2:31:40

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实现播放音频暂停音频设置音量等。
学习记录,每天不停进步。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为OD机试真题 Java 实现【欢快的周末】【2023 B卷 100分】,深度优先搜索dfs算法

目录 专栏导读一、题目描述二、输入描述三、输出描述四、深度优先搜索dfs五、解题思路六、Java算法源码七、效果展示1、输入2、输出3、说明4、如果修改一下呢&#xff1f;5、来&#xff0c;TFBOYS&#xff0c;试一下&#xff1f; 华为OD机试 2023B卷题库疯狂收录中&#xff0c;…

Ubuntu类IOS主题设置

1.依次执行下面三条命令&#xff1a; sudo apt install gnome-shell-extensions sudo apt install gnome-tweak-tool sudo apt install chrome-gnome-shell2.下载主题&#xff0c;也是命令&#xff1a; git clone <https://github.com/qingchendelaike/GNOME-OSX-II-Theme…

VGGNet剪枝实战:使用VGGNet训练、稀疏训练、剪枝、微调等,剪枝出只有3M的模型(二)

文章目录 稀疏训练VGGNet剪枝导入库文件测试函数定义全局参数BN通道排序制作Mask剪枝操作 微调微调方法微调结果 稀疏训练VGGNet 新建train_sp.py脚本。稀疏化训练的过程和正常训练类似&#xff0c;不同的是在BN层中各权重加入稀疏因子&#xff0c;代码如下&#xff1a; def …

通达OA前台getshell

你永远要记住&#xff0c;你跟别人不一样&#xff0c;你是一个有另外世界的人 漏洞复现 访问网站url&#xff1a; 将exp中的target替换为目标url Payload替换为自己的木马即可 ​关键exp如下&#xff1a; 执行exp漏洞利用&#xff0c;中间过程会询问是否删除文件&#x…

Mysql load data隐藏字符特殊字符ESC的方法

mysqlimport --userroot --passwordroot1234 --default-character-setutf8 --fields-terminated-by"$(echo -ne \033)" --lines-terminated-by\n --local shenl /root/xab.dat https://jisuan5.com/ascii/ ascii码值 SHOW GLOBAL VARIABLES LIKE local_infile; LO…

微服务Ribbon-负载均衡原理

目录 一、LoadBalancerIntercepor 二、LoadBalancerClient 三、负载均衡策略IRule 四、总结 上一篇中&#xff0c;我们添加了LoadBalanced注解&#xff0c;即可实现负载均衡功能&#xff0c;这是什么原理呢&#xff1f; SpringCloud底层其实是利用了一个名为Ribbon的组件&…

SpringBoot学习——springboot整合email springboot整合阿里云短信服务

目录 引出springboot整合email配置邮箱导入依赖application.yml配置email业务类测试类 springboot整合阿里云短信服务申请阿里云短信服务测试短信服务获取阿里云的accessKeyspringboot整合阿里云短信导包工具类 总结 引出 1.springboot整合email&#xff0c;qq邮箱&#xff0c;…

计算机网络实验3:双绞线跳线的制作和测试

文章目录 1. 主要教学内容2. 双绞线跳线的制作和测试 1. 主要教学内容 实验内容&#xff1a;掌握双绞线制作过程中的剥线、理线、插线、压线以及测线。所需学时&#xff1a;2。重难点&#xff1a;双绞线的类别及其用途周次&#xff1a;第2周。教材相关章节&#xff1a;第5章&a…

Android Studio实现Spinner下拉列表

效果图 点击下拉列表 点击某一个下拉列表 MainActivity package com.example.spinneradapterpro;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.Spinn…

怎样的公司称为集团?

集团是什么&#xff1f; 集团的意思是有目的组织起来共同行动的团体。企业集团不具有独立的法人资格。《公司法》中并没有“集团”一说。只有有限责任公司和股份有限公司的提法。有的公司进行多元化经营战略&#xff0c;在多个领域均成立了相应的子公司&#xff0c;这样&#…

【递归算法实践】验证二叉搜索树

目录 1. 递归算法 2. 递归实现验证二叉搜索树 3. 递归解法的实现逻辑 4. 递归实现的实例分析 1. 递归算法 递归是一种通过函数自身调用来解决问题的算法&#xff0c;它可以使代码更加简洁和优雅&#xff0c;同时也能够解决许多复杂的问题。在递归中&#xff0c;函数会不断…

【Windows10下启动RocketMQ报错:找不到或无法加载主类 Files\Java\jdk1.8.0_301\lib\dt.jar】解决方法

Windows10下启动RocketMQ报错&#xff1a;找不到或无法加载主类 一、问题产生二、产生原因三、解决办法 一、问题产生 参考RocketMQ Github官网上的说明&#xff0c;下载rocketmq-all-5.1.3-bin-release.zip&#xff0c;解压配置环境变量后&#xff0c;执行如下命令&#xff1a…

基于2.4G RF开发的无线游戏手柄解决方案

平时喜欢玩游戏的朋友&#xff0c;肯定知道键鼠在某些类型的游戏适配和操作方面&#xff0c;不如手柄。作为一个游戏爱好者&#xff0c;还得配上一个游戏手柄才行。比如动作和格斗、体育游戏&#xff0c;由于手柄更合理的摇杆位置和按键布局&#xff0c;操作起来也是得心应手。…

6.pip简介,第三方库的安装

引言 使用过Visual Studio的小伙伴可能对npm不陌生&#xff0c;没错&#xff0c;pip与npm的功能是一样的。 首先要知道&#xff0c;Python这门语言拥有着丰富的标准库以及先辈们开发的各种功能强大的第三方库。而今天我们主要学习的呢就是关于Python中的包管理工具。它是Pytho…

图像的镜像变换之c++实现(qt + 不调包)

1.基本原理 1.水平镜像变化 设图像的宽度为width&#xff0c;则水平镜像变化的映射关系如下&#xff1a; 2.垂直镜像变化 设图像的宽度为height&#xff0c;则垂直镜像变化的映射关系如下&#xff1a; 2.代码实现&#xff08;代码是我以前自学图像处理时写的&#xff0c;代码很…

VS Code安装使用教程

目录 1. VS Code是什么&#xff1f; 2. VS Code的下载和安装 下载&#xff1a; 安装&#xff1a; 2.2 环境的介绍 3. VS Code配置C/C开发环境 3.1 下载和配置MinGW-w64编译器套件 下载&#xff1a; 配置&#xff1a; 3.2 安装C/C插件 3.3 重启VSCode 4. 在VSCode上编…

如何快速创建学校录取查询系统?

作为一名老师&#xff0c;我深知学生及家长们对于录取情况的关注和期待。因此&#xff0c;学校公布录取情况表是非常重要的一项工作。在这篇文章中&#xff0c;我将分享学校公布录取情况表的步骤和流程&#xff0c;帮助大家更好地了解录取情况。 老教师一般是使用易查分来让家…

坤简炫酷的JQuery轮播图插件

介绍&#xff1a; 找到了一个炫酷的JQuery轮播图插件&#xff0c;只需要配置三四行代码就可以实现很多二维三维炫酷的切换效果。 视频效果及教程&#xff1a; https://www.bilibili.com/video/BV1Fu4y1d776/ 代码&#xff1a; https://github.com/w-x-x-w/AwesomeWeb 使用…

[软件工具][原创]OCR识字找图关键词找图以文搜图工具使用教程

OCR识字找图工具功能简介&#xff1a; 当你有一批图片但是想提取图片里面包含关键词的的图片&#xff0c;以前都是手工肉眼打开去找&#xff0c;其实这个大可不必&#xff0c;现在只需输入关键词&#xff0c;软件会自动搜索所有图片&#xff0c;只要包含指定关键词就会复制或者…