-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathpicture_in_picture.dart
149 lines (136 loc) · 4.35 KB
/
picture_in_picture.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import 'package:audio_session/audio_session.dart';
import 'package:bitmovin_player/bitmovin_player.dart';
import 'package:bitmovin_player_example/env/env.dart';
import 'package:bitmovin_player_example/events.dart';
import 'package:bitmovin_player_example/platform.dart';
import 'package:flutter/material.dart';
import 'package:logger/logger.dart';
class PictureInPicture extends StatefulWidget {
const PictureInPicture({super.key});
static String routeName = 'PictureInPicture';
@override
State<PictureInPicture> createState() => _PictureInPictureState();
}
class _PictureInPictureState extends State<PictureInPicture> {
final _playerViewKey = GlobalKey<PlayerViewState>();
final _sourceConfig = const SourceConfig(
url:
'https://cdn.bitmovin.com/content/assets/MI201109210084/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8',
type: SourceType.hls,
);
final _player = Player(
config: const PlayerConfig(
key: Env.bitmovinPlayerLicenseKey,
remoteControlConfig: RemoteControlConfig(isCastEnabled: false),
),
);
final _logger = Logger();
final _playerViewConfig = const PlayerViewConfig(
pictureInPictureConfig: PictureInPictureConfig(
isEnabled: true,
shouldEnterOnBackground: true,
),
);
final _eventsKey = GlobalKey<EventsState>();
bool _isInPictureInPicture = false;
void _onPictureInPictureEnterEvent(Event event) {
_onEvent(event);
setState(() {
_isInPictureInPicture = true;
});
}
void _onPictureInPictureExitEvent(Event event) {
_onEvent(event);
setState(() {
_isInPictureInPicture = false;
});
}
void _onEvent(Event event) {
final eventName = '${event.runtimeType}';
final eventData = '$eventName ${event.toJson()}';
_logger.d(eventData);
_eventsKey.currentState?.add(eventName);
}
@override
void initState() {
setupAudioSession();
_player.loadSourceConfig(_sourceConfig);
super.initState();
}
Future<void> setupAudioSession() async {
final session = await AudioSession.instance;
await session.configure(const AudioSessionConfiguration.music());
}
@override
void dispose() {
_player.dispose();
super.dispose();
}
// Since PiP on Android is basically just the whole activity fitted in a small
// floating window, we don't want to display the whole scaffold
bool get renderOnlyPlayerView => isAndroid && _isInPictureInPicture;
@override
Widget build(BuildContext context) {
final playerView = PlayerView(
player: _player,
key: _playerViewKey,
playerViewConfig: _playerViewConfig,
onPictureInPictureEnter: _onPictureInPictureEnterEvent,
onPictureInPictureEntered: _onEvent,
onPictureInPictureExit: _onPictureInPictureExitEvent,
onPictureInPictureExited: _onEvent,
);
if (renderOnlyPlayerView) {
return playerView;
}
return Scaffold(
appBar: AppBar(
title: const Text('Picture-in-Picture'),
),
body: Column(
children: [
AspectRatio(
aspectRatio: 16 / 9,
child: playerView,
),
Row(
children: [
Container(
margin: const EdgeInsets.only(left: 10, right: 5),
child: OutlinedButton(
style: OutlinedButton.styleFrom(
side: const BorderSide(color: Colors.blue),
),
onPressed: () {
_playerViewKey.currentState?.pictureInPicture
.enterPictureInPicture();
},
child: const Text('Enter PiP'),
),
),
Container(
margin: const EdgeInsets.all(5),
child: OutlinedButton(
style: OutlinedButton.styleFrom(
side: const BorderSide(color: Colors.blue),
),
onPressed: () {
_playerViewKey.currentState?.pictureInPicture
.exitPictureInPicture();
},
child: const Text('Exit PiP'),
),
),
],
),
Expanded(
child: Container(
margin: const EdgeInsets.fromLTRB(10, 10, 10, 40),
child: Events(key: _eventsKey),
),
),
],
),
);
}
}