Flutter保存并恢复AudioPlayer位置



我在flutter中使用audioplayers库,我试图将玩家位置保存并恢复到第一个位置以外的位置,就像缓存玩家搜索栏位置一样,在这段代码中,我试图用SharedPreference保存并恢复,但我的实现不成功

class ApplicationSettings {
ApplicationSettings(StreamingSharedPreferences preferences)
: showIntro = preferences.getBool('showIntro', defaultValue: false),
pageViewIndex = preferences.getInt('pageViewIndex', defaultValue: 0),
audioPosition = preferences.getString('audioPosition', defaultValue: "{}")
;
final Preference<bool> showIntro;
final Preference<int> pageViewIndex;
final Preference<String> audioPosition;
}

AudioInformation类:

part'audio_information.g.dart';
@JsonSerializable(nullable: true)
class AudioInformation {
final String productName;
final int audioPosition;
AudioInformation(this.productName, this.audioPosition);
factory AudioInformation.fromJson(Map<String, dynamic> json) => _$AudioInformationFromJson(json);
Map<String, dynamic> toJson() => _$AudioInformationToJson(this);
}

PlayerWidget类:

enum PlayerState { stopped, playing, paused }
enum PlayingRouteState { speakers, earpiece }
class PlayerWidget extends StatefulWidget {
final String url;
final PlayerMode mode;
final String productName;
final String imageUrl;
PlayerWidget({Key key, @required this.url, this.mode = PlayerMode.MEDIA_PLAYER, @required this.productName, @required this.imageUrl}) : super(key: key);
@override
State<StatefulWidget> createState() {
return _PlayerWidgetState(url, mode);
}
}
class _PlayerWidgetState extends State<PlayerWidget> {
_PlayerWidgetState(this.url, this.mode);
String url;
PlayerMode mode;
AudioPlayer _audioPlayer;
Duration _duration;
Duration _position;
PlayerState _playerState = PlayerState.stopped;
PlayingRouteState _playingRouteState = PlayingRouteState.speakers;
StreamSubscription _durationSubscription;
StreamSubscription _positionSubscription;
StreamSubscription _playerCompleteSubscription;
StreamSubscription _playerErrorSubscription;
StreamSubscription _playerStateSubscription;
StreamSubscription<PlayerControlCommand> _playerControlCommandSubscription;
get _isPlaying => _playerState == PlayerState.playing;
get _isPaused => _playerState == PlayerState.paused;
get _durationText => _duration?.toString()?.split('.')?.first ?? '';
get _positionText => _position?.toString()?.split('.')?.first ?? '';
Preference<String> _audioPosition;
@override
void didChangeDependencies() {
super.didChangeDependencies();
_audioPosition = Provider.of<ApplicationSettings>(context).audioPosition;
}
@override
void initState() {
super.initState();
_initAudioPlayer();
_play();
}
@override
void dispose() {
_audioPlayer.dispose();
_durationSubscription?.cancel();
_positionSubscription?.cancel();
_playerCompleteSubscription?.cancel();
_playerErrorSubscription?.cancel();
_playerStateSubscription?.cancel();
_playerControlCommandSubscription?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return PreferenceBuilder(
preference: _audioPosition,
builder: (context, String audioDetail) {
/* SAVE position*/
AudioInformation _audio = AudioInformation('${widget.productName}',  _duration?.inMilliseconds?.round()??0);
_audioPosition.setValue(_audio.toJson().toString());
return Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(Icons.audiotrack_outlined),
Expanded(
child: Text(
' - ${widget.productName}',
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
],
),
),
body: Stack(
children: [
Positioned.fill(
child: CachedNetworkImage(
imageUrl: widget.imageUrl,
fit: BoxFit.cover,
)),
Container(
width: double.infinity,
height: double.infinity,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 2.0, sigmaY: 2.0),
child: Container(
color: Colors.white.withOpacity(0.7),
),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.all(16.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(11.0),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.2), offset: Offset(0.0, 0.0), spreadRadius: 1.0)],
border: Border.all(color: Colors.black)),
child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: CachedNetworkImage(
imageUrl: '${widget.imageUrl}',
fit: BoxFit.cover,
width: 150.0,
),
),
),
Container(
margin: EdgeInsets.all(8.0),
padding: EdgeInsets.all(5.0),
decoration: BoxDecoration(color: Colors.white.withOpacity(0.5), border: Border.all(color: Colors.black), borderRadius: BorderRadius.circular(5.0)),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconButton(
key: Key('play_button'),
onPressed: _isPlaying ? null : () => _play(),
iconSize: 64.0,
icon: Icon(MdiIcons.playCircle),
color: Colors.black,
),
IconButton(
key: Key('pause_button'),
onPressed: _isPlaying ? () => _pause() : null,
iconSize: 64.0,
icon: Icon(MdiIcons.pauseCircle),
color: Colors.green[900],
),
IconButton(
key: Key('stop_button'),
onPressed: _isPlaying || _isPaused ? () => _stop() : null,
iconSize: 64.0,
icon: Icon(MdiIcons.stopCircle),
color: Colors.indigo[700],
),
],
),
Slider(
onChanged: (v) {
final position = v * _duration.inMilliseconds;
_audioPlayer.seek(Duration(milliseconds: position.round()));
/* SAVE position*/
AudioInformation _audio = AudioInformation('${widget.productName}', position.round());
_audioPosition.setValue(_audio.toJson().toString());
},
value: (_position != null && _duration != null && _position.inMilliseconds > 0 && _position.inMilliseconds < _duration.inMilliseconds)
? _position.inMilliseconds / _duration.inMilliseconds
: 0.0,
),
],
),
),
_durationText != null && _durationText.toString().isNotEmpty
? Container(
height: 43.0,
padding: EdgeInsets.all(8.0),
decoration: BoxDecoration(color: Colors.white.withOpacity(0.5), border: Border.all(color: Colors.black), borderRadius: BorderRadius.circular(5.0)),
child: Text(
_position != null
? '${_positionText ?? ''} / ${_durationText ?? ''}'
: _duration != null
? _durationText
: ' --- ',
style: TextStyle(fontSize: 24.0),
),
)
: Container(
height: 43.0,
),
],
),
],
),
);
});
}
void _initAudioPlayer() {
_audioPlayer = AudioPlayer(mode: mode);
_durationSubscription = _audioPlayer.onDurationChanged.listen((duration) {
setState(() => _duration = duration);
});
_positionSubscription = _audioPlayer.onAudioPositionChanged.listen((p) => setState(() {
_position = p;
}));
_playerCompleteSubscription = _audioPlayer.onPlayerCompletion.listen((event) {
_onComplete();
setState(() {
_position = _duration;
});
});
_playerErrorSubscription = _audioPlayer.onPlayerError.listen((msg) {
print('audioPlayer error : $msg');
setState(() {
_playerState = PlayerState.stopped;
_duration = Duration(seconds: 0);
_position = Duration(seconds: 0);
});
});
_playerControlCommandSubscription = _audioPlayer.onPlayerCommand.listen((command) {
print('command');
});
_audioPlayer.onPlayerStateChanged.listen((state) {
if (!mounted) return;
});
_audioPlayer.onNotificationPlayerStateChanged.listen((state) {
if (!mounted) return;
//setState(() => _audioPlayerState = state);
});
_playingRouteState = PlayingRouteState.speakers;
}
Future<int> _play() async {
final playPosition = (_position != null && _duration != null && _position.inMilliseconds > 0 && _position.inMilliseconds < _duration.inMilliseconds) ? _position : null;
final result = await _audioPlayer.play(url, position: playPosition);
if (result == 1) setState(() => _playerState = PlayerState.playing);
_audioPlayer.setPlaybackRate(playbackRate: 1.0);

/* RESTORE position*/
if (_audioPosition?.getValue() != null) {
final _res = jsonDecode(_audioPosition.getValue());
int pos = _audioPosition.getValue() == '{}' ? 0 : _res['audioPosition'];
_audioPlayer.seek(Duration(milliseconds: pos));
}
return result;
}
Future<int> _pause() async {
final result = await _audioPlayer.pause();
if (result == 1) setState(() => _playerState = PlayerState.paused);
return result;
}
Future<int> _stop() async {
final result = await _audioPlayer.stop();
if (result == 1) {
setState(() {
_playerState = PlayerState.stopped;
_position = Duration();
});
}
return result;
}
void _onComplete() {
setState(() => _playerState = PlayerState.stopped);
}
}

在PreferenceBuilder小部件中,您应该删除第一个"保存位置";代码,当小部件第一次构建时,scaffold返回之前的那2行代码用零值覆盖保存的音频位置的值,这是因为当小部件首次构建时,持续时间为null。保存共享参考中音频位置的更好位置是在中

_audioplayer.onAudioPositionChanged()中的功能

_initAudioPlayer()

功能。你可以查看下面的片段来了解我所说的

AudioInformation _audio = AudioInformation('${widget.productName}', p?.inMilliseconds?.round() ?? 0);
_audioPosition.setValue(_audio.toJson().toString());
setState(() {
_position = p;
});
});

这应该可以解决面临的问题

相关内容

  • 没有找到相关文章

最新更新