Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
14eab7b
Add support to make AndroidForegroundService optional to MediaElement
ne0rrmatrix May 7, 2025
44a9928
Rename foreground service property for clarity
ne0rrmatrix May 7, 2025
c683d61
Update media playback service and permissions
ne0rrmatrix May 7, 2025
0feee28
Add tests for AndroidForegroundService default behavior
ne0rrmatrix May 7, 2025
f6407f6
Set service on by default
ne0rrmatrix May 8, 2025
63ad21b
Remove old intent filter that was added by accident
ne0rrmatrix May 8, 2025
1e60956
Rename AndroidForegroundServiceEnabled property
ne0rrmatrix May 8, 2025
5a3c0fe
Merge branch 'main' into MediaElementOptionService
ne0rrmatrix Jun 3, 2025
904ae95
Merge branch 'main' into MediaElementOptionService
ne0rrmatrix Jun 8, 2025
ea35514
Merge branch 'main' into MediaElementOptionService
ne0rrmatrix Jun 25, 2025
cecaf32
Merge branch 'main' into MediaElementOptionService
ne0rrmatrix Jul 3, 2025
178e8ae
Enable Android Foreground Service for MediaElement
ne0rrmatrix Jul 3, 2025
25b22c6
Merge branch 'MediaElementOptionService' of https://github.com/ne0rrm…
ne0rrmatrix Jul 3, 2025
1168302
Merge branch 'main' into MediaElementOptionService
ne0rrmatrix Jul 3, 2025
838d9a5
Merge branch 'main' into MediaElementOptionService
ne0rrmatrix Jul 3, 2025
7aba464
Merge branch 'main' into MediaElementOptionService
ne0rrmatrix Jul 8, 2025
a83de86
Merge branch 'main' into MediaElementOptionService
ne0rrmatrix Jul 30, 2025
ed62a22
Update src/CommunityToolkit.Maui.MediaElement/MediaElementOptions.sha…
ne0rrmatrix Aug 3, 2025
84b337c
Merge branch 'main' into MediaElementOptionService
ne0rrmatrix Aug 3, 2025
58e07a8
Merge branch 'main' into MediaElementOptionService
ne0rrmatrix Oct 10, 2025
cb63525
Merge branch 'main' into MediaElementOptionService
ne0rrmatrix Oct 16, 2025
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
1 change: 1 addition & 0 deletions samples/CommunityToolkit.Maui.Sample/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public static MauiApp CreateMauiApp()
.UseMauiCommunityToolkitMediaElement(static options =>
{
options.SetDefaultAndroidViewType(AndroidViewType.TextureView);
options.SetDefaultAndroidForegroundService(true);
})
.ConfigureMauiHandlers(static handlers =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,23 @@
android:supportsRtl="true">

<meta-data android:name="com.google.android.geo.API_KEY" android:value="PASTE-YOUR-API-KEY-HERE" />

<service android:name="communityToolkit.maui.media.services" android:stopWithTask="true" android:exported="false" android:enabled="true"
android:foregroundServiceType="mediaPlayback">
<intent-filter>
<action android:name="androidx.media3.session.MediaSessionService"/>
</intent-filter>
</service>
</application>

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"/>
<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/>
<!-- Samsung -->
<uses-permission android:name="com.sec.android.provider.badge.permission.READ"/>
<uses-permission android:name="com.sec.android.provider.badge.permission.WRITE"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
{
// Update the default MediaElementOptions for MediaElement if Action is not null
options?.Invoke(new MediaElementOptions(builder));

// Perform Handler configuration
builder.ConfigureMauiHandlers(h =>
{
Expand All @@ -33,7 +33,7 @@
});

#if ANDROID
builder.Services.AddSingleton<Media.Services.MediaControlsService>();

Check warning on line 36 in src/CommunityToolkit.Maui.MediaElement/AppBuilderExtensions.shared.cs

View workflow job for this annotation

GitHub Actions / Build Library (windows-latest)

This call site is reachable on: 'Android' 26.0 and later, 'iOS' 15.0 and later, 'maccatalyst' 15.0 and later, 'Tizen' 6.5 and later, 'Windows' 10.0.17763 and later. 'MediaControlsService' is only supported on: 'Android' 26.0 and later. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)

Check warning on line 36 in src/CommunityToolkit.Maui.MediaElement/AppBuilderExtensions.shared.cs

View workflow job for this annotation

GitHub Actions / Build Library (macos-15)

This call site is reachable on: 'Android' 26.0 and later, 'iOS' 15.0 and later, 'maccatalyst' 15.0 and later, 'Tizen' 6.5 and later, 'Windows' 10.0.17763 and later. 'MediaControlsService' is only supported on: 'Android' 26.0 and later. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)
#endif

return builder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
2 changes: 2 additions & 0 deletions src/CommunityToolkit.Maui.MediaElement/MediaElement.shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ internal event EventHandler StopRequested
/// </summary>
public AndroidViewType AndroidViewType { get; init; } = MediaElementOptions.DefaultAndroidViewType;

internal bool IsAndroidForegroundServiceEnabled { get; init; } = MediaElementOptions.IsAndroidForegroundServiceEnabled;

/// <summary>
/// Gets or sets whether the media should start playing as soon as it's loaded.
/// Default is <see langword="false"/>. This is a bindable property.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,19 @@ internal MediaElementOptions(in MauiAppBuilder builder) : this()
/// </summary>
internal static AndroidViewType DefaultAndroidViewType { get; private set; } = AndroidViewType.SurfaceView;

/// <summary>
/// Set Android Foreground Service for MediaElement on construction
/// </summary>
internal static bool IsAndroidForegroundServiceEnabled { get; private set; } = true;

/// <summary>
/// Set Android View type for MediaElement as SurfaceView or TextureView on construction
/// </summary>
public void SetDefaultAndroidViewType(AndroidViewType androidViewType) => DefaultAndroidViewType = androidViewType;

/// <summary>
/// Set Android Foreground Service for MediaElement on construction
/// </summary>
/// <param name="androidForegroundServiceEnabled">Specifies whether the Android Foreground Service should be enabled for the MediaElement. Set to <c>true</c> to enable, or <c>false</c> to disable.</param>
public void SetDefaultAndroidForegroundService(bool androidForegroundServiceEnabled) => IsAndroidForegroundServiceEnabled = androidForegroundServiceEnabled;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -130,11 +131,11 @@ or PlaybackState.StateSkippingToQueueItem
/// <returns>The platform native counterpart of <see cref="MediaElement"/>.</returns>
/// <exception cref="NullReferenceException">Thrown when <see cref="Context"/> is <see langword="null"/> or when the platform view could not be created.</exception>
[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)
Expand Down Expand Up @@ -353,7 +354,7 @@ protected virtual async partial ValueTask PlatformUpdateSource()
return;
}

if (connection is null)
if (connection is null && androidForegroundServiceEnabled)
{
StartService();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading