diff --git a/packages/video_player/video_player/CHANGELOG.md b/packages/video_player/video_player/CHANGELOG.md index 013e20f93118..4122603d731a 100644 --- a/packages/video_player/video_player/CHANGELOG.md +++ b/packages/video_player/video_player/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.10.6 + +* Introduce VideoPlayerOptions to set the audio mix mode. + ## 0.10.5 * Support `web` by default. diff --git a/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java b/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java index 43123ef09238..f2844b10013e 100644 --- a/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java +++ b/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java @@ -57,15 +57,19 @@ final class VideoPlayer { private boolean isInitialized = false; + private final VideoPlayerOptions options; + VideoPlayer( Context context, EventChannel eventChannel, TextureRegistry.SurfaceTextureEntry textureEntry, String dataSource, Result result, - String formatHint) { + String formatHint, + VideoPlayerOptions options) { this.eventChannel = eventChannel; this.textureEntry = textureEntry; + this.options = options; TrackSelector trackSelector = new DefaultTrackSelector(); exoPlayer = ExoPlayerFactory.newSimpleInstance(context, trackSelector); @@ -165,7 +169,7 @@ public void onCancel(Object o) { surface = new Surface(textureEntry.surfaceTexture()); exoPlayer.setVideoSurface(surface); - setAudioAttributes(exoPlayer); + setAudioAttributes(exoPlayer, options.mixWithOthers); exoPlayer.addListener( new EventListener() { @@ -209,10 +213,10 @@ void sendBufferingUpdate() { } @SuppressWarnings("deprecation") - private static void setAudioAttributes(SimpleExoPlayer exoPlayer) { + private static void setAudioAttributes(SimpleExoPlayer exoPlayer, boolean isMixMode) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { exoPlayer.setAudioAttributes( - new AudioAttributes.Builder().setContentType(C.CONTENT_TYPE_MOVIE).build()); + new AudioAttributes.Builder().setContentType(C.CONTENT_TYPE_MOVIE).build(), !isMixMode); } else { exoPlayer.setAudioStreamType(C.STREAM_TYPE_MUSIC); } diff --git a/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerOptions.java b/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerOptions.java new file mode 100644 index 000000000000..5f57ace741d9 --- /dev/null +++ b/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerOptions.java @@ -0,0 +1,5 @@ +package io.flutter.plugins.videoplayer; + +public class VideoPlayerOptions { + public boolean mixWithOthers; +} diff --git a/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java b/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java index fdc0511e217b..02d35ae8337a 100644 --- a/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java +++ b/packages/video_player/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java @@ -23,6 +23,7 @@ public class VideoPlayerPlugin implements MethodCallHandler, FlutterPlugin { private static final String TAG = "VideoPlayerPlugin"; private final LongSparseArray videoPlayers = new LongSparseArray<>(); private FlutterState flutterState; + private VideoPlayerOptions options = new VideoPlayerOptions(); /** Register this with the v2 embedding for the plugin to respond to lifecycle callbacks. */ public VideoPlayerPlugin() {} @@ -95,6 +96,10 @@ public void onMethodCall(MethodCall call, Result result) { case "init": disposeAllPlayers(); break; + case "setMixWithOthers": + options.mixWithOthers = (boolean) call.arguments; + result.success(null); + break; case "create": { TextureRegistry.SurfaceTextureEntry handle = @@ -120,7 +125,8 @@ public void onMethodCall(MethodCall call, Result result) { handle, "asset:///" + assetLookupKey, result, - null); + null, + options); videoPlayers.put(handle.id(), player); } else { player = @@ -130,7 +136,8 @@ public void onMethodCall(MethodCall call, Result result) { handle, call.argument("uri"), result, - call.argument("formatHint")); + call.argument("formatHint"), + options); videoPlayers.put(handle.id(), player); } break; diff --git a/packages/video_player/video_player/example/lib/main.dart b/packages/video_player/video_player/example/lib/main.dart index f55d3f7dd593..ef13f541d607 100644 --- a/packages/video_player/video_player/example/lib/main.dart +++ b/packages/video_player/video_player/example/lib/main.dart @@ -231,7 +231,8 @@ abstract class _PlayerLifeCycleState extends State { class _NetworkPlayerLifeCycleState extends _PlayerLifeCycleState { @override VideoPlayerController createVideoPlayerController() { - return VideoPlayerController.network(widget.dataSource); + return VideoPlayerController.network(widget.dataSource, + videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true)); } } diff --git a/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m b/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m index 0d3a29ef14f5..6405b863c311 100644 --- a/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m +++ b/packages/video_player/video_player/ios/Classes/FLTVideoPlayerPlugin.m @@ -462,6 +462,16 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { } [_players removeAllObjects]; result(nil); + } else if ([@"setMixWithOthers" isEqualToString:call.method]) { + BOOL mixWithOthers = [call.arguments boolValue]; + if (mixWithOthers) { + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback + withOptions:AVAudioSessionCategoryOptionMixWithOthers + error:nil]; + } else { + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; + } + result(nil); } else if ([@"create" isEqualToString:call.method]) { NSDictionary* argsMap = call.arguments; FLTFrameUpdater* frameUpdater = [[FLTFrameUpdater alloc] initWithRegistry:_registry]; diff --git a/packages/video_player/video_player/lib/video_player.dart b/packages/video_player/video_player/lib/video_player.dart index cb24ac8cb100..e7c94fcf9e50 100644 --- a/packages/video_player/video_player/lib/video_player.dart +++ b/packages/video_player/video_player/lib/video_player.dart @@ -12,7 +12,7 @@ import 'package:meta/meta.dart'; import 'package:video_player_platform_interface/video_player_platform_interface.dart'; export 'package:video_player_platform_interface/video_player_platform_interface.dart' - show DurationRange, DataSourceType, VideoFormat; + show DurationRange, DataSourceType, VideoFormat, VideoPlayerOptions; // This will clear all open videos on the platform when a full restart is // performed. @@ -145,7 +145,8 @@ class VideoPlayerController extends ValueNotifier { /// The name of the asset is given by the [dataSource] argument and must not be /// null. The [package] argument must be non-null when the asset comes from a /// package and null otherwise. - VideoPlayerController.asset(this.dataSource, {this.package}) + VideoPlayerController.asset(this.dataSource, + {this.package, this.videoPlayerOptions}) : dataSourceType = DataSourceType.asset, formatHint = null, super(VideoPlayerValue(duration: null)); @@ -157,7 +158,8 @@ class VideoPlayerController extends ValueNotifier { /// null. /// **Android only**: The [formatHint] option allows the caller to override /// the video format detection code. - VideoPlayerController.network(this.dataSource, {this.formatHint}) + VideoPlayerController.network(this.dataSource, + {this.formatHint, this.videoPlayerOptions}) : dataSourceType = DataSourceType.network, package = null, super(VideoPlayerValue(duration: null)); @@ -166,7 +168,7 @@ class VideoPlayerController extends ValueNotifier { /// /// This will load the file from the file-URI given by: /// `'file://${file.path}'`. - VideoPlayerController.file(File file) + VideoPlayerController.file(File file, {this.videoPlayerOptions}) : dataSource = 'file://${file.path}', dataSourceType = DataSourceType.file, package = null, @@ -187,6 +189,9 @@ class VideoPlayerController extends ValueNotifier { /// is constructed with. final DataSourceType dataSourceType; + /// Provide additional configuration options (optional). Like setting the audio mode to mix + final VideoPlayerOptions videoPlayerOptions; + /// Only set for [asset] videos. The package that the asset was loaded from. final String package; Timer _timer; @@ -229,6 +234,11 @@ class VideoPlayerController extends ValueNotifier { ); break; } + if (videoPlayerOptions?.mixWithOthers != null) { + await VideoPlayerPlatform.instance + .setMixWithOthers(videoPlayerOptions.mixWithOthers); + } + _textureId = await VideoPlayerPlatform.instance.create(dataSourceDescription); _creatingCompleter.complete(null); diff --git a/packages/video_player/video_player/pubspec.yaml b/packages/video_player/video_player/pubspec.yaml index 43c9ead07d25..ef1d84f6e104 100644 --- a/packages/video_player/video_player/pubspec.yaml +++ b/packages/video_player/video_player/pubspec.yaml @@ -1,7 +1,7 @@ name: video_player description: Flutter plugin for displaying inline video with other Flutter widgets on Android and iOS. -version: 0.10.5 +version: 0.10.6 homepage: https://github.com/flutter/plugins/tree/master/packages/video_player/video_player flutter: @@ -17,7 +17,7 @@ flutter: dependencies: meta: "^1.0.5" - video_player_platform_interface: ^1.0.1 + video_player_platform_interface: ^1.0.5 # The design on https://flutter.dev/go/federated-plugins was to leave # this constraint as "any". We cannot do it right now as it fails pub publish # validation, so we set a ^ constraint. diff --git a/packages/video_player/video_player/test/video_player_test.dart b/packages/video_player/video_player/test/video_player_test.dart index d2a90b7182c9..c099fd6aeb4f 100644 --- a/packages/video_player/video_player/test/video_player_test.dart +++ b/packages/video_player/video_player/test/video_player_test.dart @@ -47,6 +47,9 @@ class FakeController extends ValueNotifier @override VideoFormat get formatHint => null; + + @override + VideoPlayerOptions get videoPlayerOptions => null; } void main() { @@ -424,6 +427,27 @@ void main() { expect(colors.bufferedColor, bufferedColor); expect(colors.backgroundColor, backgroundColor); }); + + test('setMixWithOthers', () { + bool mixWithOthers = false; + const MethodChannel('flutter.io/videoPlayer') + .setMockMethodCallHandler((MethodCall methodCall) async { + switch (methodCall.method) { + case 'setMixWithOthers': + return mixWithOthers = methodCall.arguments; + case 'create': + return {'textureId': 100}; + default: + return null; + } + }); + + final VideoPlayerController controller = VideoPlayerController.file( + File(''), + videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true)); + controller.initialize(); + expect(mixWithOthers, true); + }); } class FakeVideoPlayerPlatform { diff --git a/packages/video_player/video_player_platform_interface/CHANGELOG.md b/packages/video_player/video_player_platform_interface/CHANGELOG.md index 79be27a9b3b1..8469c13413db 100644 --- a/packages/video_player/video_player_platform_interface/CHANGELOG.md +++ b/packages/video_player/video_player_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.5 + +* Add VideoPlayerOptions with audo mix mode + ## 1.0.4 * Remove the deprecated `author:` field from pubspec.yaml diff --git a/packages/video_player/video_player_platform_interface/lib/method_channel_video_player.dart b/packages/video_player/video_player_platform_interface/lib/method_channel_video_player.dart index eb227ce18ec5..57f7b0523f80 100644 --- a/packages/video_player/video_player_platform_interface/lib/method_channel_video_player.dart +++ b/packages/video_player/video_player_platform_interface/lib/method_channel_video_player.dart @@ -156,6 +156,11 @@ class MethodChannelVideoPlayer extends VideoPlayerPlatform { return Texture(textureId: textureId); } + @override + Future setMixWithOthers(bool mixWithOthers) { + return _channel.invokeMethod('setMixWithOthers', mixWithOthers); + } + EventChannel _eventChannelFor(int textureId) { return EventChannel('flutter.io/videoPlayer/videoEvents$textureId'); } diff --git a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart index 4c1f2b67c4fc..279810aaaf63 100644 --- a/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart +++ b/packages/video_player/video_player_platform_interface/lib/video_player_platform_interface.dart @@ -110,6 +110,11 @@ abstract class VideoPlayerPlatform { throw UnimplementedError('buildView() has not been implemented.'); } + /// Sets the audio mode to mix with other sources + Future setMixWithOthers(bool mixWithOthers) { + throw UnimplementedError('setMixWithOthers() has not been implemented.'); + } + // This method makes sure that VideoPlayer isn't implemented with `implements`. // // See class doc for more details on why implementing this class is forbidden. @@ -331,3 +336,13 @@ class DurationRange { @override int get hashCode => start.hashCode ^ end.hashCode; } + +/// [VideoPlayerOptions] can be optionally used to set additional player settings +class VideoPlayerOptions { + /// Set this to true to mix the video players audio with other audio sources. + /// The default value is false + final bool mixWithOthers; + + /// set additional optional player settings + VideoPlayerOptions({this.mixWithOthers = false}); +} diff --git a/packages/video_player/video_player_platform_interface/pubspec.yaml b/packages/video_player/video_player_platform_interface/pubspec.yaml index 8bae5563b0a9..077b59afb663 100644 --- a/packages/video_player/video_player_platform_interface/pubspec.yaml +++ b/packages/video_player/video_player_platform_interface/pubspec.yaml @@ -3,7 +3,7 @@ description: A common platform interface for the video_player plugin. homepage: https://github.com/flutter/plugins/tree/master/packages/video_player/video_player_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 1.0.4 +version: 1.0.5 dependencies: flutter: