diff --git a/samples/CommunityToolkit.Maui.Sample/MauiProgram.cs b/samples/CommunityToolkit.Maui.Sample/MauiProgram.cs
index 1dd763355a..d5f9e188f5 100644
--- a/samples/CommunityToolkit.Maui.Sample/MauiProgram.cs
+++ b/samples/CommunityToolkit.Maui.Sample/MauiProgram.cs
@@ -72,6 +72,7 @@ public static MauiApp CreateMauiApp()
.UseMauiCommunityToolkitMediaElement(static options =>
{
options.SetDefaultAndroidViewType(AndroidViewType.TextureView);
+ options.SetDefaultAndroidForegroundService(true);
})
.ConfigureMauiHandlers(static handlers =>
{
diff --git a/samples/CommunityToolkit.Maui.Sample/Platforms/Android/AndroidManifest.xml b/samples/CommunityToolkit.Maui.Sample/Platforms/Android/AndroidManifest.xml
index 8f95e12183..48265afc3f 100644
--- a/samples/CommunityToolkit.Maui.Sample/Platforms/Android/AndroidManifest.xml
+++ b/samples/CommunityToolkit.Maui.Sample/Platforms/Android/AndroidManifest.xml
@@ -4,12 +4,23 @@
android:supportsRtl="true">
+
+
+
+
+
+
+
+
+
+
diff --git a/src/CommunityToolkit.Maui.MediaElement/AppBuilderExtensions.shared.cs b/src/CommunityToolkit.Maui.MediaElement/AppBuilderExtensions.shared.cs
index 3f7eb88638..e3d70f8d39 100644
--- a/src/CommunityToolkit.Maui.MediaElement/AppBuilderExtensions.shared.cs
+++ b/src/CommunityToolkit.Maui.MediaElement/AppBuilderExtensions.shared.cs
@@ -25,7 +25,7 @@ public static MauiAppBuilder UseMauiCommunityToolkitMediaElement(this MauiAppBui
{
// Update the default MediaElementOptions for MediaElement if Action is not null
options?.Invoke(new MediaElementOptions(builder));
-
+
// Perform Handler configuration
builder.ConfigureMauiHandlers(h =>
{
diff --git a/src/CommunityToolkit.Maui.MediaElement/Handlers/MediaElementHandler.android.cs b/src/CommunityToolkit.Maui.MediaElement/Handlers/MediaElementHandler.android.cs
index bd1e00e6e7..9a1ed2e361 100644
--- a/src/CommunityToolkit.Maui.MediaElement/Handlers/MediaElementHandler.android.cs
+++ b/src/CommunityToolkit.Maui.MediaElement/Handlers/MediaElementHandler.android.cs
@@ -24,7 +24,7 @@ protected override MauiMediaElement CreatePlatformView()
VirtualView,
Dispatcher.GetForCurrentThread() ?? throw new InvalidOperationException($"{nameof(IDispatcher)} cannot be null"));
- var (_, playerView) = MediaManager.CreatePlatformView(VirtualView.AndroidViewType);
+ var (_, playerView) = MediaManager.CreatePlatformView(VirtualView.AndroidViewType, VirtualView.IsAndroidForegroundServiceEnabled);
return new(Context, playerView);
}
diff --git a/src/CommunityToolkit.Maui.MediaElement/MediaElement.shared.cs b/src/CommunityToolkit.Maui.MediaElement/MediaElement.shared.cs
index 6d663135f2..d6fceec637 100644
--- a/src/CommunityToolkit.Maui.MediaElement/MediaElement.shared.cs
+++ b/src/CommunityToolkit.Maui.MediaElement/MediaElement.shared.cs
@@ -225,6 +225,8 @@ internal event EventHandler StopRequested
///
public AndroidViewType AndroidViewType { get; init; } = MediaElementOptions.DefaultAndroidViewType;
+ internal bool IsAndroidForegroundServiceEnabled { get; init; } = MediaElementOptions.IsAndroidForegroundServiceEnabled;
+
///
/// Gets or sets whether the media should start playing as soon as it's loaded.
/// Default is . This is a bindable property.
diff --git a/src/CommunityToolkit.Maui.MediaElement/MediaElementOptions.shared.cs b/src/CommunityToolkit.Maui.MediaElement/MediaElementOptions.shared.cs
index 48ae9649c7..0acb383fab 100644
--- a/src/CommunityToolkit.Maui.MediaElement/MediaElementOptions.shared.cs
+++ b/src/CommunityToolkit.Maui.MediaElement/MediaElementOptions.shared.cs
@@ -22,8 +22,19 @@ internal MediaElementOptions(in MauiAppBuilder builder) : this()
///
internal static AndroidViewType DefaultAndroidViewType { get; private set; } = AndroidViewType.SurfaceView;
+ ///
+ /// Set Android Foreground Service for MediaElement on construction
+ ///
+ internal static bool IsAndroidForegroundServiceEnabled { get; private set; } = true;
+
///
/// Set Android View type for MediaElement as SurfaceView or TextureView on construction
///
public void SetDefaultAndroidViewType(AndroidViewType androidViewType) => DefaultAndroidViewType = androidViewType;
+
+ ///
+ /// Set Android Foreground Service for MediaElement on construction
+ ///
+ /// Specifies whether the Android Foreground Service should be enabled for the MediaElement. Set to true to enable, or false to disable.
+ public void SetDefaultAndroidForegroundService(bool androidForegroundServiceEnabled) => IsAndroidForegroundServiceEnabled = androidForegroundServiceEnabled;
}
\ No newline at end of file
diff --git a/src/CommunityToolkit.Maui.MediaElement/Views/MauiMediaElement.android.cs b/src/CommunityToolkit.Maui.MediaElement/Views/MauiMediaElement.android.cs
index b9799a3874..381346ff17 100644
--- a/src/CommunityToolkit.Maui.MediaElement/Views/MauiMediaElement.android.cs
+++ b/src/CommunityToolkit.Maui.MediaElement/Views/MauiMediaElement.android.cs
@@ -8,11 +8,6 @@
using AndroidX.Media3.UI;
using CommunityToolkit.Maui.Views;
-[assembly: UsesPermission(Android.Manifest.Permission.ForegroundServiceMediaPlayback)]
-[assembly: UsesPermission(Android.Manifest.Permission.ForegroundService)]
-[assembly: UsesPermission(Android.Manifest.Permission.MediaContentControl)]
-[assembly: UsesPermission(Android.Manifest.Permission.PostNotifications)]
-
namespace CommunityToolkit.Maui.Core.Views;
///
diff --git a/src/CommunityToolkit.Maui.MediaElement/Views/MediaManager.android.cs b/src/CommunityToolkit.Maui.MediaElement/Views/MediaManager.android.cs
index 7da0a27ea8..24ef7be27a 100644
--- a/src/CommunityToolkit.Maui.MediaElement/Views/MediaManager.android.cs
+++ b/src/CommunityToolkit.Maui.MediaElement/Views/MediaManager.android.cs
@@ -21,6 +21,7 @@ namespace CommunityToolkit.Maui.Core.Views;
public partial class MediaManager : Java.Lang.Object, IPlayerListener
{
+ bool androidForegroundServiceEnabled;
const int bufferState = 2;
const int readyState = 3;
const int endedState = 4;
@@ -130,11 +131,11 @@ or PlaybackState.StateSkippingToQueueItem
/// The platform native counterpart of .
/// Thrown when is or when the platform view could not be created.
[MemberNotNull(nameof(Player), nameof(PlayerView), nameof(session))]
- public (PlatformMediaElement platformView, PlayerView PlayerView) CreatePlatformView(AndroidViewType androidViewType)
+ public (PlatformMediaElement platformView, PlayerView PlayerView) CreatePlatformView(AndroidViewType androidViewType, bool androidForegroundServiceEnabled)
{
Player = new ExoPlayerBuilder(MauiContext.Context).Build() ?? throw new InvalidOperationException("Player cannot be null");
Player.AddListener(this);
-
+ this.androidForegroundServiceEnabled = androidForegroundServiceEnabled;
if (androidViewType is AndroidViewType.SurfaceView)
{
PlayerView = new PlayerView(MauiContext.Context)
@@ -353,7 +354,7 @@ protected virtual async partial ValueTask PlatformUpdateSource()
return;
}
- if (connection is null)
+ if (connection is null && androidForegroundServiceEnabled)
{
StartService();
}
diff --git a/src/CommunityToolkit.Maui.UnitTests/Extensions/AppBuilderExtensionsTests.cs b/src/CommunityToolkit.Maui.UnitTests/Extensions/AppBuilderExtensionsTests.cs
index 27ef4de017..42bdd5cd30 100644
--- a/src/CommunityToolkit.Maui.UnitTests/Extensions/AppBuilderExtensionsTests.cs
+++ b/src/CommunityToolkit.Maui.UnitTests/Extensions/AppBuilderExtensionsTests.cs
@@ -166,5 +166,24 @@ public void UseMauiCommunityToolkitMediaElement_ShouldSetDefaultAndroidViewType(
MediaElementOptions.DefaultAndroidViewType.Should().Be(AndroidViewType.TextureView);
}
+
+ [Fact]
+ public void UseMauiCommunityToolkitMediaElement_ShouldSetAndroidServiceByDefault()
+ {
+ var builder = MauiApp.CreateBuilder();
+ builder.UseMauiCommunityToolkitMediaElement();
+ MediaElementOptions.IsAndroidForegroundServiceEnabled.Should().Be(true);
+ }
+
+ [Fact]
+ public void UseMauiCommunityToolkitMediaElement_ServiceCanBeDisabled()
+ {
+ var builder = MauiApp.CreateBuilder();
+ builder.UseMauiCommunityToolkitMediaElement(static options =>
+ {
+ options.SetDefaultAndroidForegroundService(false);
+ });
+ MediaElementOptions.IsAndroidForegroundServiceEnabled.Should().Be(false);
+ }
}
#pragma warning restore CA1416
\ No newline at end of file