Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Platform support for web #193

Merged
merged 31 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
dfd401b
Update dependency
hawk23 Nov 20, 2024
37c69d9
Add boilerplate for web
hawk23 Nov 20, 2024
3b0ee68
Support running demo app on web
hawk23 Nov 20, 2024
bf1b245
Add TODO
hawk23 Nov 20, 2024
3ecb841
Remove unused code
hawk23 Nov 21, 2024
b77517a
Introduce abstraction to communicate with platform
hawk23 Nov 21, 2024
18d41bf
Register view factory for web
hawk23 Nov 21, 2024
6515d7b
Abstract away method channel handling as it is only needed on certain…
hawk23 Nov 21, 2024
3026f21
Align folder structure and naming
hawk23 Nov 21, 2024
9dd99bb
Align naming and add web platform player
hawk23 Nov 21, 2024
c81ac71
Integrate bitmovinplayer.js
hawk23 Nov 21, 2024
cbd9eb7
Implement conversion separately
hawk23 Nov 21, 2024
10704b1
Merge remote-tracking branch 'origin/main' into feature/support-web
hawk23 Nov 21, 2024
83e495d
Fill API gaps
hawk23 Nov 21, 2024
e134bbb
PoC for web event handling
hawk23 Nov 21, 2024
e93ff40
Refactor event handling to be platform agnostic
hawk23 Nov 22, 2024
77521be
Add comment
hawk23 Nov 22, 2024
c87c727
Make private
hawk23 Nov 22, 2024
de8358d
Remove auto-generated comment
hawk23 Nov 22, 2024
1c9854b
Support incorrect iOS event naming
hawk23 Nov 22, 2024
2ae0734
Remove unneeded name annotation
hawk23 Nov 22, 2024
477eb8a
platform abstraction of method and event channel for player view
hawk23 Nov 22, 2024
c2a4b7d
Restructure code and cleanup
hawk23 Nov 22, 2024
cc330fb
Extract web player event handling into own component
hawk23 Nov 25, 2024
45db8e8
Support more events
hawk23 Nov 25, 2024
9b9add7
forward API call
hawk23 Nov 26, 2024
3d06f1c
Support basic events
hawk23 Nov 26, 2024
e2b7e92
Add CHANGELOG entry
hawk23 Nov 26, 2024
49f1d04
Support basic configs
hawk23 Nov 26, 2024
37ac2ef
More detailed Changelog entry
hawk23 Nov 26, 2024
c6c68b4
Add more doc and minor refactoring
hawk23 Nov 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions .metadata
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled.
# This file should be version controlled and should not be manually edited.

version:
revision: 7048ed95a5ad3e43d697e0c397464193991fc230
channel: stable
revision: "dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668"
channel: "stable"

project_type: plugin

# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 7048ed95a5ad3e43d697e0c397464193991fc230
base_revision: 7048ed95a5ad3e43d697e0c397464193991fc230
create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
- platform: android
create_revision: 7048ed95a5ad3e43d697e0c397464193991fc230
base_revision: 7048ed95a5ad3e43d697e0c397464193991fc230
create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
- platform: ios
create_revision: 7048ed95a5ad3e43d697e0c397464193991fc230
base_revision: 7048ed95a5ad3e43d697e0c397464193991fc230
create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
- platform: web
create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668

# User provided section

Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/),
and this project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]
- Introduce platform support for web.
- Supported API calls: `loadSource(source)`, `play`, `pause`, `mute`, `unmute`, `seek(time)`, `timeShift(timeShift)`, `getCurrentTime`, `getTimeShift`, `getDuration`, `getMaxTimeShift`, `isLive`, `isPlaying`, `isAirplayActive`, `isAirplayAvailable`, `castVideo`, `castStop`, `isCastAvailable`, `isCasting`, `showAirPlayTargetPicker`, `destroy`
- Supported events: `play`,`playing`,`paused`,`timeChanged`,`seek`,`seeked`,`timeShift`,`timeShifted`,`playbackFinished`,`error`,`muted`,`unmuted`,`warning`,`ready`,`sourceLoaded`,`sourceUnloaded`

## [0.12.0] - 2024-11-06
### Changed
- Update Bitmovin's native Android Player SDK version to `3.91.0`
Expand Down
3 changes: 3 additions & 0 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Bitmovin Player example

Demonstrates how to use the `bitmovin_player` plugin.
3 changes: 2 additions & 1 deletion example/integration_test/subtitle_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:player_testing/player_testing.dart';

Expand All @@ -8,7 +9,7 @@ void main() {
group('when loading a source with subtitles in the manifest', () {
testWidgets('emits subtitle added events for each subtitle', (_) async {
// No subtitle added event for the off-item on iOS
final expectedCount = Platform.isAndroid ? 5 : 4;
final expectedCount = !kIsWeb && Platform.isAndroid ? 5 : 4;
await startPlayerTest(() async {
await callPlayerAndExpectEvents(
(player) => player.loadSourceConfig(Sources.sintel),
Expand Down
11 changes: 5 additions & 6 deletions example/lib/pages/analytics.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import 'dart:io';

import 'package:bitmovin_player/bitmovin_player.dart';
import 'package:bitmovin_player_example/controls.dart';
import 'package:bitmovin_player_example/env/env.dart';
import 'package:bitmovin_player_example/platform.dart';
import 'package:bitmovin_player_example/player_view_container.dart';
import 'package:flutter/material.dart';

Expand All @@ -16,10 +15,10 @@ class PlayerAnalytics extends StatefulWidget {

class _PlayerAnalyticsState extends State<PlayerAnalytics> {
final _sourceConfig = SourceConfig(
url: Platform.isAndroid
? 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/mpds/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.mpd'
: 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8',
type: Platform.isAndroid ? SourceType.dash : SourceType.hls,
url: isIOS
? 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8'
: 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/mpds/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.mpd',
type: isIOS ? SourceType.hls : SourceType.dash,
analyticsSourceMetadata: const SourceMetadata(
title: 'Collecting SourceMetadata Title',
customData:
Expand Down
11 changes: 5 additions & 6 deletions example/lib/pages/audio_only.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import 'dart:io';

import 'package:bitmovin_player/bitmovin_player.dart';
import 'package:bitmovin_player_example/controls.dart';
import 'package:bitmovin_player_example/env/env.dart';
import 'package:bitmovin_player_example/platform.dart';
import 'package:flutter/material.dart';

class AudioOnly extends StatefulWidget {
Expand All @@ -15,10 +14,10 @@ class AudioOnly extends StatefulWidget {

class _AudioOnlyState extends State<AudioOnly> {
final _sourceConfig = SourceConfig(
url: Platform.isAndroid
? 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/mpds/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.mpd'
: 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8',
type: Platform.isAndroid ? SourceType.dash : SourceType.hls,
url: isIOS
? 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8'
: 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/mpds/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.mpd',
type: isIOS ? SourceType.hls : SourceType.dash,
);
final _player = Player(
config: const PlayerConfig(
Expand Down
11 changes: 5 additions & 6 deletions example/lib/pages/background_playback.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import 'dart:io';

import 'package:audio_session/audio_session.dart';
import 'package:bitmovin_player/bitmovin_player.dart';
import 'package:bitmovin_player_example/controls.dart';
import 'package:bitmovin_player_example/env/env.dart';
import 'package:bitmovin_player_example/platform.dart';
import 'package:bitmovin_player_example/player_view_container.dart';
import 'package:flutter/material.dart';

Expand All @@ -21,10 +20,10 @@ class BackgroundPlayback extends StatefulWidget {

class _BackgroundPlaybackState extends State<BackgroundPlayback> {
final _sourceConfig = SourceConfig(
url: Platform.isAndroid
? 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/mpds/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.mpd'
: 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8',
type: Platform.isAndroid ? SourceType.dash : SourceType.hls,
url: isIOS
? 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8'
: 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/mpds/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.mpd',
type: isIOS ? SourceType.hls : SourceType.dash,
);
final _player = Player(
config: const PlayerConfig(
Expand Down
11 changes: 5 additions & 6 deletions example/lib/pages/basic_playback.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import 'dart:io';

import 'package:bitmovin_player/bitmovin_player.dart';
import 'package:bitmovin_player_example/controls.dart';
import 'package:bitmovin_player_example/env/env.dart';
import 'package:bitmovin_player_example/platform.dart';
import 'package:bitmovin_player_example/player_view_container.dart';
import 'package:flutter/material.dart';

Expand All @@ -16,10 +15,10 @@ class BasicPlayback extends StatefulWidget {

class _BasicPlaybackState extends State<BasicPlayback> {
final _sourceConfig = SourceConfig(
url: Platform.isAndroid
? 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/mpds/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.mpd'
: 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8',
type: Platform.isAndroid ? SourceType.dash : SourceType.hls,
url: isIOS
? 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8'
: 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/mpds/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.mpd',
type: isIOS ? SourceType.hls : SourceType.dash,
);
final _player = Player(
config: const PlayerConfig(
Expand Down
8 changes: 4 additions & 4 deletions example/lib/pages/casting.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'dart:async';
import 'dart:io';

import 'package:bitmovin_player/bitmovin_player.dart';
import 'package:bitmovin_player_example/controls.dart';
import 'package:bitmovin_player_example/env/env.dart';
import 'package:bitmovin_player_example/platform.dart';
import 'package:bitmovin_player_example/player_view_container.dart';
import 'package:flutter/material.dart';
import 'package:logger/logger.dart';
Expand All @@ -29,9 +29,9 @@ const artOfMotionDash =
const artOfMotionHls =
'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8';

final SourceConfig _sourceConfig = Platform.isAndroid
? const SourceConfig(url: artOfMotionDash, type: SourceType.dash)
: const SourceConfig(url: artOfMotionHls, type: SourceType.hls);
final SourceConfig _sourceConfig = isIOS
? const SourceConfig(url: artOfMotionHls, type: SourceType.hls)
: const SourceConfig(url: artOfMotionDash, type: SourceType.dash);

class _CastingState extends State<Casting> {
factory _CastingState() {
Expand Down
11 changes: 5 additions & 6 deletions example/lib/pages/custom_html_ui.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import 'dart:io';

import 'package:bitmovin_player/bitmovin_player.dart';
import 'package:bitmovin_player_example/controls.dart';
import 'package:bitmovin_player_example/env/env.dart';
import 'package:bitmovin_player_example/platform.dart';
import 'package:bitmovin_player_example/player_view_container.dart';
import 'package:flutter/material.dart';

Expand All @@ -16,10 +15,10 @@ class CustomHtmlUi extends StatefulWidget {

class _CustomHtmlUiState extends State<CustomHtmlUi> {
final _sourceConfig = SourceConfig(
url: Platform.isAndroid
? 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/mpds/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.mpd'
: 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8',
type: Platform.isAndroid ? SourceType.dash : SourceType.hls,
url: isIOS
? 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8'
: 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/mpds/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.mpd',
type: isIOS ? SourceType.hls : SourceType.dash,
);
final _player = Player(
config: const PlayerConfig(
Expand Down
11 changes: 5 additions & 6 deletions example/lib/pages/drm_playback.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import 'dart:io';

import 'package:bitmovin_player/bitmovin_player.dart';
import 'package:bitmovin_player_example/controls.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:bitmovin_player_example/player_view_container.dart';
import 'package:flutter/material.dart';
import 'package:logger/logger.dart';
Expand All @@ -19,10 +18,10 @@ class DrmPlayback extends StatefulWidget {
class _DrmPlaybackState extends State<DrmPlayback> {
final GlobalKey<EventsState> _eventsKey = GlobalKey<EventsState>();
final _sourceConfig = SourceConfig(
url: Platform.isAndroid
? 'https://bitmovin-a.akamaihd.net/content/art-of-motion_drm/mpds/11331.mpd'
: 'https://fps.ezdrm.com/demo/video/ezdrm.m3u8',
type: Platform.isAndroid ? SourceType.dash : SourceType.hls,
url: isIOS
? 'https://fps.ezdrm.com/demo/video/ezdrm.m3u8'
: 'https://bitmovin-a.akamaihd.net/content/art-of-motion_drm/mpds/11331.mpd',
type: isIOS ? SourceType.hls : SourceType.dash,
drmConfig: DrmConfig(
fairplay: FairplayConfig(
licenseUrl:
Expand Down
11 changes: 5 additions & 6 deletions example/lib/pages/event_subscription.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import 'dart:io';

import 'package:bitmovin_player/bitmovin_player.dart';
import 'package:bitmovin_player_example/controls.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:bitmovin_player_example/player_view_container.dart';
import 'package:flutter/material.dart';
import 'package:logger/logger.dart';
Expand All @@ -19,10 +18,10 @@ class EventSubscription extends StatefulWidget {
class _EventSubscriptionState extends State<EventSubscription> {
final _eventsKey = GlobalKey<EventsState>();
final _sourceConfig = SourceConfig(
url: Platform.isAndroid
? 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/mpds/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.mpd'
: 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8',
type: Platform.isAndroid ? SourceType.dash : SourceType.hls,
url: isIOS
? 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8'
: 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/mpds/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.mpd',
type: isIOS ? SourceType.hls : SourceType.dash,
);
final _player = Player(
config: const PlayerConfig(
Expand Down
5 changes: 2 additions & 3 deletions example/lib/pages/home.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import 'dart:io';

import 'package:bitmovin_player_example/pages/analytics.dart';
import 'package:bitmovin_player_example/pages/audio_only.dart';
import 'package:bitmovin_player_example/pages/background_playback.dart';
Expand All @@ -10,6 +8,7 @@ import 'package:bitmovin_player_example/pages/drm_playback.dart';
import 'package:bitmovin_player_example/pages/event_subscription.dart';
import 'package:bitmovin_player_example/pages/fullscreen_handling.dart';
import 'package:bitmovin_player_example/pages/picture_in_picture.dart';
import 'package:bitmovin_player_example/platform.dart';
import 'package:flutter/material.dart';

List<_Sample> _samples = [];
Expand All @@ -27,7 +26,7 @@ void buildSamples() {
_Sample('Picture-in-Picture', PictureInPicture.routeName),
];

if (Platform.isIOS) {
if (isIOS) {
_samples.add(_Sample('Background Playback', BackgroundPlayback.routeName));
}
}
Expand Down
5 changes: 2 additions & 3 deletions example/lib/pages/picture_in_picture.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import 'dart:io' show Platform;

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';

Expand Down Expand Up @@ -80,7 +79,7 @@ class _PictureInPictureState extends State<PictureInPicture> {

// 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 => Platform.isAndroid && _isInPictureInPicture;
bool get renderOnlyPlayerView => isAndroid && _isInPictureInPicture;

@override
Widget build(BuildContext context) {
Expand Down
7 changes: 7 additions & 0 deletions example/lib/platform.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import 'dart:io';

import 'package:flutter/foundation.dart';

const bool isWeb = kIsWeb;
final bool isIOS = !isWeb && Platform.isIOS;
final bool isAndroid = !isWeb && Platform.isAndroid;
20 changes: 18 additions & 2 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
js:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.7"
json_annotation:
dependency: transitive
description:
Expand Down Expand Up @@ -374,10 +382,18 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev"
source: hosted
version: "14.2.5"
web:
dependency: transitive
description:
name: web
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
url: "https://pub.dev"
source: hosted
version: "14.2.4"
version: "1.1.0"
webdriver:
dependency: transitive
description:
Expand Down
Binary file added example/web/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/web/icons/Icon-192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/web/icons/Icon-512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/web/icons/Icon-maskable-192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/web/icons/Icon-maskable-512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading