Skip to content

Commit

Permalink
Feature/january changes 2 (#205)
Browse files Browse the repository at this point in the history
* Added placeholder until play example

* Added playback stalled feature in iOS

* Added playback stalled feature in iOS

* BetterPlayerTheme addition, custom controls rework

* Exposed BetterPlayerPlaylistState and betterPlayerController getter within.

* Overridden duration implementation

* Overridden duration implementation

* Overridden duration implementation

* Overridden duration implementation

* Updated readme, general refactor

* PR refactor
  • Loading branch information
jhomlala authored Jan 9, 2021
1 parent b3e9cbe commit 87255d4
Show file tree
Hide file tree
Showing 27 changed files with 394 additions and 108 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 0.0.44
* Added placeholder until play example
* Added playback stalled feature in iOS. iOS version should behave same as Android once video failed to load.
* Added BetterPlayerTheme to controls configuration (added by https://github.com/maine98).
* [BREAKING_CHANGE] Changed custom controls builder in BetterPlayerControlsConfiguration. Now it accepts BetterPlayerController.
* Exposed BetterPlayerPlaylistState and betterPlayerController getter within.
* Added overriddenDuration to BetterPlayerDataSource.

## 0.0.43
* Added autoDispose flag in BetterPlayerConfiguration
* Added removeEventsListener in BetterPlayerController
Expand Down
31 changes: 28 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ This plugin is based on [Chewie](https://github.com/brianegan/chewie). Chewie is

```yaml
dependencies:
better_player: ^0.0.43
better_player: ^0.0.44
```
2. Install it
Expand Down Expand Up @@ -467,8 +467,12 @@ var betterPlayerConfiguration = BetterPlayerConfiguration(
///Time to hide controls
final Duration controlsHideTime;
///Custom controls, it will override Material/Cupertino controls
final Widget customControls;
///Parameter used to build custom controls
final Widget Function(BetterPlayerController controller)
customControlsBuilder;
///Parameter used to change theme of the player
final BetterPlayerTheme playerTheme;
///Flag used to show/hide controls
final bool showControls;
Expand Down Expand Up @@ -817,6 +821,27 @@ If null then aspectRatio from BetterPlayerConfiguration will be used.
betterPlayerController.setOverriddenAspectRatio(1.0);
```

### Overridden duration
If overridden duration is set then video player will play video until this duration.
```dart
BetterPlayerDataSource dataSource = BetterPlayerDataSource(
BetterPlayerDataSourceType.network,
Constants.elephantDreamVideoUrl,
///Play only 10 seconds of this video.
overriddenDuration: Duration(seconds: 10),
);
```

### (iOS only) Add into info.plist (to support fullscreen rotation):
```xml
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
```

### More documentation
https://pub.dev/documentation/better_player/latest/better_player/better_player-library.html

Expand Down
26 changes: 20 additions & 6 deletions android/src/main/java/com/jhomlala/better_player/BetterPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.util.Log;
import android.view.Surface;

import com.google.android.exoplayer2.C;
Expand All @@ -30,6 +31,7 @@
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.source.ClippingMediaSource;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.dash.DashMediaSource;
Expand Down Expand Up @@ -85,6 +87,7 @@ final class BetterPlayer {
private Runnable refreshRunnable;
private EventListener exoPlayerEventListener;
private Bitmap bitmap;
private long overriddenDuration;

BetterPlayer(
Context context,
Expand All @@ -102,15 +105,15 @@ final class BetterPlayer {

void setDataSource(
Context context, String key, String dataSource, String formatHint, Result result,
Map<String, String> headers, boolean useCache, long maxCacheSize, long maxCacheFileSize) {
Map<String, String> headers, boolean useCache, long maxCacheSize, long maxCacheFileSize,
long overriddenDuration) {
this.key = key;

this.overriddenDuration = overriddenDuration;
isInitialized = false;

Uri uri = Uri.parse(dataSource);
DataSource.Factory dataSourceFactory;


if (isHTTP(uri)) {
DefaultHttpDataSourceFactory defaultHttpDataSourceFactory =
new DefaultHttpDataSourceFactory(
Expand All @@ -130,11 +133,17 @@ void setDataSource(
dataSourceFactory = defaultHttpDataSourceFactory;
}
} else {

dataSourceFactory = new DefaultDataSourceFactory(context, "ExoPlayer");
}

MediaSource mediaSource = buildMediaSource(uri, dataSourceFactory, formatHint, context);
exoPlayer.prepare(mediaSource);
if (overriddenDuration != 0) {
ClippingMediaSource clippingMediaSource = new ClippingMediaSource(mediaSource, 0, overriddenDuration * 1000);
exoPlayer.prepare(clippingMediaSource);
} else {
exoPlayer.prepare(mediaSource);
}

result.success(null);
}
Expand Down Expand Up @@ -297,7 +306,7 @@ public boolean dispatchStop(Player player, boolean reset) {
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
mediaSession.setMetadata(new MediaMetadataCompat.Builder()
.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, exoPlayer.getDuration())
.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, getDuration())
.build());
}
};
Expand All @@ -306,6 +315,7 @@ public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
exoPlayer.seekTo(0);
}


public void removeNotificationData() {
exoPlayer.removeListener(exoPlayerEventListener);
if (refreshHandler != null) {
Expand Down Expand Up @@ -523,7 +533,7 @@ private void sendInitialized() {
Map<String, Object> event = new HashMap<>();
event.put("event", "initialized");
event.put("key", key);
event.put("duration", exoPlayer.getDuration());
event.put("duration", getDuration());

if (exoPlayer.getVideoFormat() != null) {
Format videoFormat = exoPlayer.getVideoFormat();
Expand All @@ -542,6 +552,10 @@ private void sendInitialized() {
}
}

private long getDuration() {
return exoPlayer.getDuration();
}

void dispose() {
removeNotificationData();
if (isInitialized) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public class BetterPlayerPlugin implements MethodCallHandler, FlutterPlugin {
private static final String AUTHOR_PARAMETER = "author";
private static final String IMAGE_URL_PARAMETER = "imageUrl";
private static final String NOTIFICATION_CHANNEL_NAME_PARAMETER = "notificationChannelName";
private static final String OVERRIDDEN_DURATION_PARAMETER = "overriddenDuration";

private static final String INIT_METHOD = "init";
private static final String CREATE_METHOD = "create";
Expand Down Expand Up @@ -128,7 +129,6 @@ private void disposeAllPlayers() {
}
videoPlayers.clear();
dataSources.clear();
;
}

private void onDestroy() {
Expand Down Expand Up @@ -240,6 +240,7 @@ private void setDataSource(MethodCall call, Result result, BetterPlayer player)
dataSources.put(getTextureId(player), dataSource);
String key = getParameter(dataSource, KEY_PARAMETER, "");
Map<String, String> headers = getParameter(dataSource, HEADERS_PARAMETER, new HashMap<>());
Number overriddenDuration = getParameter(dataSource, OVERRIDDEN_DURATION_PARAMETER, 0);

if (dataSource.get(ASSET_PARAMETER) != null) {
String asset = getParameter(dataSource, ASSET_PARAMETER, "");
Expand All @@ -261,7 +262,9 @@ private void setDataSource(MethodCall call, Result result, BetterPlayer player)
headers,
false,
0L,
0L);
0L,
overriddenDuration.longValue()
);
} else {
boolean useCache = getParameter(dataSource, USE_CACHE_PARAMETER, false);
Number maxCacheSizeNumber = getParameter(dataSource, MAX_CACHE_SIZE_PARAMETER, 0);
Expand All @@ -279,7 +282,9 @@ private void setDataSource(MethodCall call, Result result, BetterPlayer player)
headers,
useCache,
maxCacheSize,
maxCacheFileSize);
maxCacheFileSize,
overriddenDuration.longValue()
);
}
}

Expand Down
3 changes: 2 additions & 1 deletion example/lib/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class Constants {
"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4";
static const String verticalVideoUrl =
"http://www.exit109.com/~dnn/clips/RW20seconds_1.mp4";

static String logo = "logo.png";
static String placeholderUrl =
"https://imgix.bustle.com/uploads/image/2020/8/5/23905b9c-6b8c-47fa-bc0f-434de1d7e9bf-avengers-5.jpg";
}
8 changes: 4 additions & 4 deletions example/lib/pages/change_player_theme_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class ChangePlayerThemePage extends StatefulWidget {
class _ChangePlayerThemePageState extends State<ChangePlayerThemePage> {
BetterPlayerController _betterPlayerController;
BetterPlayerDataSource _dataSource;
PlayerTheme _playerTheme = PlayerTheme.material;
BetterPlayerTheme _playerTheme = BetterPlayerTheme.material;

@override
void initState() {
Expand Down Expand Up @@ -57,7 +57,7 @@ class _ChangePlayerThemePageState extends State<ChangePlayerThemePage> {
child: Text("MATERIAL"),
onPressed: () {
setState(() {
_playerTheme = PlayerTheme.material;
_playerTheme = BetterPlayerTheme.material;
_betterPlayerController.pause();
_betterPlayerController = new BetterPlayerController(
BetterPlayerConfiguration(
Expand All @@ -76,7 +76,7 @@ class _ChangePlayerThemePageState extends State<ChangePlayerThemePage> {
child: Text("CUPERTINO"),
onPressed: () {
setState(() {
_playerTheme = PlayerTheme.cupertino;
_playerTheme = BetterPlayerTheme.cupertino;
_betterPlayerController.pause();
_betterPlayerController = new BetterPlayerController(
BetterPlayerConfiguration(
Expand All @@ -95,7 +95,7 @@ class _ChangePlayerThemePageState extends State<ChangePlayerThemePage> {
child: Text("CUSTOM"),
onPressed: () {
setState(() {
_playerTheme = PlayerTheme.custom;
_playerTheme = BetterPlayerTheme.custom;
_betterPlayerController.pause();
_betterPlayerController = new BetterPlayerController(
BetterPlayerConfiguration(
Expand Down
1 change: 1 addition & 0 deletions example/lib/pages/normal_player_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class _NormalPlayerPageState extends State<NormalPlayerPage> {
BetterPlayerDataSource dataSource = BetterPlayerDataSource(
BetterPlayerDataSourceType.network,
Constants.forBiggerBlazesUrl,
overriddenDuration: Duration(seconds: 5),
);
_betterPlayerController = BetterPlayerController(betterPlayerConfiguration);
_betterPlayerController.setupDataSource(dataSource);
Expand Down
61 changes: 61 additions & 0 deletions example/lib/pages/overriden_duration_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import 'package:better_player/better_player.dart';
import 'package:better_player_example/constants.dart';
import 'package:flutter/material.dart';

class OverriddenDurationPage extends StatefulWidget {
@override
_OverriddenDurationPageState createState() => _OverriddenDurationPageState();
}

class _OverriddenDurationPageState extends State<OverriddenDurationPage> {
BetterPlayerController _betterPlayerController;

@override
void initState() {
BetterPlayerConfiguration betterPlayerConfiguration =
BetterPlayerConfiguration(
aspectRatio: 16 / 9,
fit: BoxFit.contain,
handleLifecycle: true,
);
_betterPlayerController = BetterPlayerController(betterPlayerConfiguration);
_setupDataSource();
super.initState();
}

void _setupDataSource() async {
BetterPlayerDataSource dataSource = BetterPlayerDataSource(
BetterPlayerDataSourceType.network,
Constants.elephantDreamVideoUrl,

///Play only 10 seconds of this video.
overriddenDuration: Duration(seconds: 10),
);
_betterPlayerController.setupDataSource(dataSource);
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Notification player"),
),
body: Column(
children: [
const SizedBox(height: 8),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Text(
"Click play on player to show notification in status bar.",
style: TextStyle(fontSize: 16),
),
),
AspectRatio(
aspectRatio: 16 / 9,
child: BetterPlayer(controller: _betterPlayerController),
),
],
),
);
}
}
Loading

0 comments on commit 87255d4

Please sign in to comment.