Flutter for OpenHarmony 音频播放萌系小指南:给 App 加上软乎乎的 “小音箱”✨
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
一、开篇:给鸿蒙 App 加上会唱歌的小音箱🎵
哈喽~这次我给 Flutter 鸿蒙 App 装上了一个软乎乎的小音箱!就像给 App 配了个会唱歌的小伙伴,点击按钮就能播放音乐,拖动进度条还能快进后退,用起来超治愈~
这次的小项目里,我搞定了这几件大事:
给鸿蒙 App 集成了just_audio音频库,适配了鸿蒙的多媒体框架
做了个粉粉的播放器 UI,有播放 / 暂停按钮和圆乎乎的进度条
处理了播放状态,加载、播放、暂停都有可爱的小提示
接下来就和我一起看看,怎么给鸿蒙 App 加上这个会唱歌的小音箱吧~
二、第一步:集成音频库,给 App 装个 “唱歌小引擎”🎶
要让 App 唱歌,首先得给它装个 “唱歌小引擎”~我选了和开源鸿蒙兼容性超棒的just_audio,它对鸿蒙的多媒体框架适配得很好,不用折腾原生代码,集成起来超省心!
一开始集成的时候,我踩了个小坑:网络音频加载不出来,像被按了静音键一样~后来才发现,是网络权限没开!给 App 加上ohos.permission.INTERNET权限后,音乐一下子就跑出来了,超惊喜~

pubspec.yaml 依赖配置
yaml
dependencies:
  flutter:
    sdk: flutter
  just_audio: ^0.9.36
鸿蒙权限配置(module.json5)
json
{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET",
        "reason": "加载网络音频需要联网权限哦~",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "inuse"
        }
      }
    ]
  }
}

三、第二步:粉粉的播放器 UI,软乎乎的交互🎀
光会唱歌还不够,我给播放器做了个粉粉的 UI,软乎乎的进度条和圆乎乎的按钮,用起来心情都变好了~
进度条我用了Slider组件,拖动的时候会跟着手指滑来滑去,像个软软的糖果条;播放按钮也加了状态变化,播放时会变成暂停图标,暂停时又变回播放图标,超可爱~
萌系播放器 UI 完整代码

dart
import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart';

class CuteAudioPlayer extends StatefulWidget {
  const CuteAudioPlayer({super.key});

  
  State<CuteAudioPlayer> createState() => _CuteAudioPlayerState();
}

class _CuteAudioPlayerState extends State<CuteAudioPlayer> {
  final AudioPlayer _player = AudioPlayer();
  bool _isLoading = true;

  
  void initState() {
    super.initState();
    _initAudio();
  }

  Future<void> _initAudio() async {
    try {
      // 加载示例音频
      await _player.setUrl('https://example.com/cute_song.mp3');
      setState(() => _isLoading = false);
    } catch (e) {
      setState(() => _isLoading = false);
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('音乐加载失败啦,再试试吧~')),
        );
      }
    }
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('软乎乎的小音箱🎵')),
      body: Padding(
        padding: const EdgeInsets.all(24.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            if (_isLoading)
              const CircularProgressIndicator(color: Colors.pink)
            else ...[
              // 进度条
              StreamBuilder<Duration>(
                stream: _player.positionStream,
                builder: (context, snapshot) {
                  final position = snapshot.data ?? Duration.zero;
                  final duration = _player.duration ?? Duration.zero;
                  return Column(
                    children: [
                      Slider(
                        value: position.inSeconds.toDouble(),
                        max: duration.inSeconds.toDouble(),
                        activeColor: Colors.pink,
                        onChanged: (value) {
                          _player.seek(Duration(seconds: value.toInt()));
                        },
                      ),
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          Text(_formatTime(position)),
                          Text(_formatTime(duration)),
                        ],
                      ),
                    ],
                  );
                },
              ),
              const SizedBox(height: 30),
              // 播放按钮
              StreamBuilder<PlayerState>(
                stream: _player.playerStateStream,
                builder: (context, snapshot) {
                  final isPlaying = snapshot.data?.playing ?? false;
                  return IconButton(
                    iconSize: 64,
                    color: Colors.pink,
                    icon: Icon(
                      isPlaying ? Icons.pause_circle : Icons.play_circle,
                    ),
                    onPressed: () {
                      if (isPlaying) {
                        _player.pause();
                      } else {
                        _player.play();
                      }
                    },
                  );
                },
              ),
            ],
          ],
        ),
      ),
    );
  }

  // 时间格式化
  String _formatTime(Duration d) {
    final m = d.inMinutes.remainder(60).toString().padLeft(2, '0');
    final s = d.inSeconds.remainder(60).toString().padLeft(2, '0');
    return '$m:$s';
  }

  
  void dispose() {
    _player.dispose();
    super.dispose();
  }
}

四、第三步:处理播放状态,让小音箱乖乖听话💡
为了让小音箱更贴心,我还处理了播放状态~加载音乐时会显示粉粉的加载圈,网络不好时会弹出温柔的提示,播放完成后会自动回到暂停状态,像个会照顾人的小管家~
在鸿蒙真机上跑的时候,状态切换超丝滑,播放、暂停、拖动进度条都没有卡顿,粉粉的进度条跟着音乐节奏滑来滑去,看着超治愈~
五、真机体验:小音箱在鸿蒙设备上唱歌啦🎉
我把这个软乎乎的小音箱装到鸿蒙真机上试了试,效果超棒:
网络音乐加载很快,进度条会跟着音乐慢慢滑
点击播放按钮,音乐就会温柔地响起来,暂停按钮会乖乖切换
拖动进度条,音乐就会跳到对应的位置,超听话
就算把 App 退到后台,音乐也会继续播放,像个随身小音箱~
这是我的运行截图:在这里插入图片描述

六、复盘小技巧:让小音箱在鸿蒙上更乖💡
折腾下来,我也总结了几个让音频播放变乖的小技巧:
记得开网络权限,不然网络音乐加载不出来哦
进度条用Slider就很适配,粉粉的颜色超可爱
网络不好的时候加个温柔的提示,用户体验会更好
真机测试比模拟器靠谱,后台播放效果只有真机才看得出来~
七、结尾:会唱歌的小音箱谁不爱呀~
这次给鸿蒙 App 装上的软乎乎小音箱,不仅实用还超可爱!看着粉粉的进度条和会切换的按钮,听着温柔的音乐,用起来心情都变好了~

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐