Giter Site home page Giter Site logo

baseflow / xamarinmediamanager Goto Github PK

View Code? Open in Web Editor NEW
763.0 52.0 304.0 20.17 MB

Cross platform Xamarin plugin to play and control Audio and Video

Home Page: https://baseflow.com

License: MIT License

C# 100.00%
mediamanager nuget xamarin audio video media netstandard exoplayer mediaplayer player

xamarinmediamanager's Introduction

MediaManager - Cross platform media plugin for Xamarin and Windows

  • Designed to be simple and easy to use
  • Native playback of media files from remote http(s), embedded and local sources
  • Native media notifications and remote controls
  • Queue and playback management by default
  • Playback status (Playing, Buffering, Loading, Paused, Progress)
  • Events for media handling to hook into

Status:

Build status GitHub tag NuGet MyGet

Support

  • Feel free to open an issue. Make sure to use one of the templates!
  • Commercial support is available. Integration with your app or services, samples, feature request, etc. Email: [email protected]
  • Powered by: baseflow.com

Wiki

More documenatation and information is available on the Wiki

Blogs

Installation

Add the NuGet package to all the projects you want to use it in.

  • In Visual Studio - Tools > NuGet Package Manager > Manage Packages for Solution
  • Select the Browse tab, search for MediaManager
  • Select Plugin.MediaManager
  • Install into each project within your solution

Platform Support

Platform Supported Version Player
.Net Standard Yes 2.0+ MediaManager
Xamarin.Forms Yes 3.2+ MediaManager
Xamarin.Android Yes API 16+ ExoPlayer
Xamarin.iOS Yes iOS 10+ AVPlayer
Xamarin.Mac Yes 3.0+ AVPlayer
Xamarin.tvOS Yes 10.0+ AVPlayer
Tizen Yes 4.0+ MediaPlayer
Windows 10 UWP Yes 10+ MediaPlayer
Windows WPF (.NET Framework) Yes 4.7.2+ MediaPlayer
Windows WPF (.NET Core) Yes 3.1+ MediaPlayer

Usage

Call MediaManager.Current from any .Net library or Xamarin project to gain access to APIs.

IMPORTANT: Initialize plugin

Make sure to call Init() in all the native platforms on startup of your app.

CrossMediaManager.Current.Init();

Optionally provide the Activity on Android. This will also be used to bind the Android Service and will be used as Intent to launch from a notification.

public class MainActivity : AppCompatActivity
{
	protected override void OnCreate(Bundle savedInstanceState)
	{
		base.OnCreate(savedInstanceState);
		SetContentView(Resource.Layout.main_activity);

		CrossMediaManager.Current.Init(this);
	}
}

When tapping the notification, it will launch your activity with an intent. In most cases, you probably want to set LaunchMode on your Activity to SingleTop. That should bring your app back into focus when tapped. You can read more about it here

[Activity(LaunchMode = LaunchMode.SingleTop)]
public class MainActivity : AppCompatActivity

If you want to handle when the app is opened via a notification tap, you can override OnNewIntent on your activity:

protected override void OnNewIntent(Intent intent)
{
    base.OnNewIntent(intent);
    // TODO: Handle app opened from notification tap.
}

Disposing

The player can be disposed via CrossMediaManager.Current.Dispose(). Make sure to call CrossMediaManager.Current.Init() if you used dispose before playing another media file.

Play a single media item

//Audio
await CrossMediaManager.Current.Play("https://ia800806.us.archive.org/15/items/Mp3Playlist_555/AaronNeville-CrazyLove.mp3");
//Video
await CrossMediaManager.Current.Play("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");

Play multiple media items

public IList<string> Mp3UrlList => new[]{
	"https://ia800806.us.archive.org/15/items/Mp3Playlist_555/AaronNeville-CrazyLove.mp3",
	"https://ia800605.us.archive.org/32/items/Mp3Playlist_555/CelineDion-IfICould.mp3",
	"https://ia800605.us.archive.org/32/items/Mp3Playlist_555/Daughtry-Homeacoustic.mp3",
	"https://storage.googleapis.com/uamp/The_Kyoto_Connection_-_Wake_Up/01_-_Intro_-_The_Way_Of_Waking_Up_feat_Alan_Watts.mp3",
	"https://aphid.fireside.fm/d/1437767933/02d84890-e58d-43eb-ab4c-26bcc8524289/d9b38b7f-5ede-4ca7-a5d6-a18d5605aba1.mp3"
	};

await CrossMediaManager.Current.Play(Mp3UrlList);

Other play possibilities

Task<IMediaItem> Play(IMediaItem mediaItem);
Task<IMediaItem> Play(string uri);
Task<IMediaItem> Play(IEnumerable<IMediaItem> items);
Task<IMediaItem> Play(IEnumerable<string> items);
Task<IMediaItem> Play(FileInfo file);
Task<IMediaItem> Play(DirectoryInfo directoryInfo);
Task<IMediaItem> PlayFromAssembly(string resourceName, Assembly assembly = null);
Task<IMediaItem> PlayFromResource(string resourceName);
  • Playing from a File can be done for example by using the File and Directory api's. You download a file from the internet and save it somewhere using these .NET api's.
  • When playing from Assembly you need to add a media file to a assembly and set the build action to Embedded resource.
  • When playing from a Resource you should add your media file for example to the Assets or raw folder on Android, and the Resources folder on iOS.

For example:

await CrossMediaManager.Current.PlayFromAssembly("somefile.mp3", typeof(BaseViewModel).Assembly);
await CrossMediaManager.Current.PlayFromResource("assets:///somefile.mp3");
await CrossMediaManager.Android.PlayFromResource(Resource.Raw.somefile.ToString());

Control the player

await CrossMediaManager.Current.Play();
await CrossMediaManager.Current.Pause();
await CrossMediaManager.Current.PlayPause();
await CrossMediaManager.Current.Stop();

await CrossMediaManager.Current.StepForward();
await CrossMediaManager.Current.StepBackward();

await CrossMediaManager.Current.SeekToStart();
await CrossMediaManager.Current.SeekTo(TimeSpan position);

Control the Queue

await CrossMediaManager.Current.PlayPrevious();
await CrossMediaManager.Current.PlayNext();
await CrossMediaManager.Current.PlayPreviousOrSeekToStart();
await CrossMediaManager.Current.PlayQueueItem(IMediaItem mediaItem);
await CrossMediaManager.Current.PlayQueueItem(int index);

Extensions:

void ToggleRepeat();
void ToggleShuffle();

Retrieve and set information

IDictionary<string, string> RequestHeaders { get; set; }
TimeSpan StepSizeForward { get; set; }
TimeSpan StepSizeBackward { get; set; }
MediaPlayerState State { get; }
TimeSpan Position { get; }
TimeSpan Duration { get; }
TimeSpan Buffered { get; }
float Speed { get; set; }
RepeatMode RepeatMode { get; set; }
ShuffleMode ShuffleMode { get; set; }
bool ClearQueueOnPlay { get; set; }
bool AutoPlay { get; set; }
bool KeepScreenOn { get; set; }

Extensions:

bool IsPlaying();
bool IsBuffering();
bool IsPrepared();
bool IsStopped();

Properties available on CrossMediaManager.Current.MediaPlayer.*

IVideoView VideoView { get; set; }
bool AutoAttachVideoView { get; set; }
VideoAspectMode VideoAspect { get; set; }
bool ShowPlaybackControls { get; set; }
int VideoHeight { get; }
int VideoWidth { get; }

Hook into events

event StateChangedEventHandler StateChanged;
event BufferedChangedEventHandler BufferedChanged;
event PositionChangedEventHandler PositionChanged;
event MediaItemFinishedEventHandler MediaItemFinished;
event MediaItemChangedEventHandler MediaItemChanged;
event MediaItemFailedEventHandler MediaItemFailed;

Retrieve metadata for media

Depending on the platform and the media item metadata will be extracted from ID3 data in the file.

CrossMediaManager.Current.Queue.Current.Title;
CrossMediaManager.Current.Queue.Current.AlbumArt;
CrossMediaManager.Current.Queue.Current.*

Since the metadata might not be available immediately you can subscribe for updates like this:

var mediaItem = await CrossMediaManager.Current.Play("https://ia800806.us.archive.org/15/items/Mp3Playlist_555/AaronNeville-CrazyLove.mp3");
mediaItem.MetadataUpdated += (sender, args) => {
	var title = args.MediaItem.Title;
};

Alternatively you could also use the PropertyChanged event to see updates to the metadata.

You can also get a single frame from a video:

string url = "https://something.com/something.mov";
var mediaItem = await CrossMediaManager.Current.Extractor.CreateMediaItem(url);
var image = await CrossMediaManager.Current.Extractor.GetVideoFrame(mediaItem, TimeSpan.FromSeconds(1));
ImageSource imageSource = image.ToImageSource();
FormsImage.Source = imageSource;

Add Video Player to the UI

The video view will automatically be attached to the player. If you have multiple video views and you want to hook it up yourself do:

CrossMediaManager.Current.MediaPlayer.AutoAttachVideoView = false;

After that you can manually add the video view like this:

For android we need a VideoView in the axml layout.

<mediamanager.platforms.android.video.VideoView
	android:id="@+id/your_videoview"
	android:layout_width="match_parent"
	android:layout_height="300dp" />

Then find the view in code:

playerView = view.FindViewById<VideoView>(Resource.Id.your_videoview);

For iOS, MacOS or tvOS we need to add a VideoView either in code, or in a Xib or Storyboard.

var playerView = new VideoView();
View.AddSubview(playerView);

Then for all platforms we have to add the player view to the MediaPlayer

CrossMediaManager.Current.MediaPlayer.VideoView = playerView;

Play a non standard format like HLS, Dash or SS

MediaManager will try to make a guess which media type or format is used. Sometimes this will not be picked up or be wrong, but you can enforce it by setting it yourself like this:

var item = await CrossMediaManager.Current.Extractor.CreateMediaItem("https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_16x9/bipbop_16x9_variant.m3u8");
item.MediaType = MediaType.Hls;

await CrossMediaManager.Current.Play(item);

By enforcing it there is still no guarantee that the native system actually is able to play the item.

Platform specific features

Feature Android iOS, Mac, tvOS UWP Tizen WPF
Audio โœ“ โœ“ โœ“ โœ“ โœ“
Video โœ“ โœ“ โœ“ โœ“ โœ“
Queue โœ“ โœ“ โœ“ โœ“ โœ“
Notifications โœ“ โœ“ โœ“ โœ“ โœ“
Volume โœ“ โœ“ โœ“ โœ“ โœ“
Media Extraction โœ“ โœ“ โœ“ โœ“ โœ“
HLS โœ“ โœ“
DASH โœ“
SmoothStreaming โœ“
ChromeCast โœ“
Airplay โœ“
Xamarin.Forms โœ“ โœ“ โœ“ โœ“

You can also directly access the native platform implementation if you need it!

//Android
CrossMediaManager.Android.*
//iOS, MacOS or tvOS
CrossMediaManager.Apple.*
//UWP
CrossMediaManager.Windows.*
//Tizen
CrossMediaManager.Tizen.*
//WPF
CrossMediaManager.Wpf.*

Xamarin.Forms

Adding a VideoView to a Page in Forms is easy as this:

<mm:VideoView VerticalOptions="FillAndExpand" Source="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" />

Your Xamarin.Forms page could look like this:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:mm="clr-namespace:MediaManager.Forms;assembly=MediaManager.Forms"
    x:Class="YourClassName" >
    <ContentPage.Content>
        <StackLayout>
            <mm:VideoView VerticalOptions="FillAndExpand" Source="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" ShowControls="False" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

You can even use the normal Play(object) method and not set source. When you navigate to the view that contains the VideoView, the player will automatically attach to the view.

If you want a Page that contains a player you can open the VideoPage.

Navigation.PushAsync(new MediaManager.Forms.VideoPage());

Reactive extensions

Add the Reactive NuGet package to all the projects you want to use it in.

Usage:

CrossMediaManager.Current.Reactive().*

FFmpegMediaMetadataRetriever on Android

If you want to use FFmpegMediaMetadataRetriever on Android to extract the metadata you can set to use this extension like this:

CrossMediaManager.Android.Extractor = new FFmpegMediaExtractor();

Intercept share requests from the native platform or other apps

Android:

//Add code to the OnCreate(Bundle savedInstanceState) of your MainActivity
if(await CrossMediaManager.Android.PlayFromIntent(Intent))
{
    //If true maybe do an action like opening a Player Page.
}

IMPORTANT

Android:

  • This library will automatically request the following permissions: AccessWifiState, AccessNetworkState, Internet, ForegroundService and WakeLock. You do not need to add them to your AndroidManifest.
  • Your app must target Android SDK v28 or higher
  • This library uses ExoPlayer for video playback. This requires that you enable the following
  • Dex tool to D8: <AndroidDexTool>d8</AndroidDexTool>
  • Optional enable R8 Linker to make code smaller: <AndroidLinkTool>r8</AndroidLinkTool>
  • Aapt2 build tools: <AndroidUseAapt2>true</AndroidUseAapt2>
  • Disable multi-dex when using D8 and R8 with AAPT2. Your code should be small enough with those.

iOS:

  • In order for the audio to contiunue to play in the background you have to add the 'Audio, Airplay and Picture in Picture Background mode' and 'Background fetch' to your Info.plist
<key>UIBackgroundModes</key>
<array>
	<string>audio</string>
	<string>fetch</string>
</array>
  • If you are playing audio from a http resource you have to take care of ATS. Optionally you can disable this for playing media. Add the following to your info.plist:
<key>NSAppTransportSecurity</key>
<dict>
	<key>NSAllowsArbitraryLoadsInMedia</key>
	<true/>
</dict>

If you want to disable more you could add: NSAllowsLocalNetworking or even NSAllowsArbitraryLoads to disable all checks.

  • If you want to display a artwork/cover that is embedded into an MP3 file, make sure that you use ID3 v2.3 (not v2.4).

UWP:

  • In the Package.appxmanifest under capabilities you need to select: "Background Media Playback", "Internet"
  • Optionally add "Music Library" and "Videos Library" as well if you use that

Tizen:

  • You must request http://tizen.org/privilege/internet, http://tizen.org/privilege/mediastorage, and http://tizen.org/privilege/externalstorage privileges

Building the source code

  • On Windows you need Visual Studio 2019 with the latest Xamarin, .NET Core, UWP and Windows 10 SDK installed.
  • On Visual Studio for Mac 2019 multi-target is not supported. Therefor you need to compile from command line on a Mac. Simple go to the folder where the source code is and run: msbuild MediaManager.sln /t:rebuild to make a release build run: msbuild MediaManager.sln /t:rebuild /p:Configuration=Release. To restore your nuget packages run: msbuild MediaManager.sln /t:restore.

xamarinmediamanager's People

Contributors

archangelwtf avatar brim-borium avatar brminnick avatar bubavanhalen avatar cheesebaron avatar cskoubo avatar dansiegel avatar escamoteur avatar fela98 avatar haarmees avatar inrego avatar jamsoft avatar janwiebe-jump avatar jmartine2 avatar juanumusic avatar martijn00 avatar mike-rowley avatar modplug avatar myrobotzone avatar nacompllo avatar nickrandolph avatar orzech85 avatar paulppn avatar simonsimcity avatar sjoerd0301 avatar suplanus avatar tekkies avatar tiwahu avatar tuke307 avatar zeprogfactory avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xamarinmediamanager's Issues

Xamarin.Forms 2.3.2.127 compatibility

This NuGet won't install in .Droid project because of wanting Xamaring.Android.Support.v4 23.4.0.1 - but that version is not compatable with current Xamarin.Forms 2.3.2.127 constraint of 23.3.0

IMediaManager.Cover no longer exists

I was attempting to use the lastest MediaManager with my project, and it appears that IMediaManager.Cover no longer exists (as of PR# 44 I believe).

If this was intentional, what is the new way of accessing the current cover?

Xamarin Forms - How get raw/example.mp3

I use xamarin forms pcl, i can not fetch the file is in the raw folder. How do I do?

screenshot_1

var siren = CrossMediaManager.Current;

if (!resultA)
{
   SirenSource.Source = "noaudio.png";
   await siren.Play("siren.mp3", MediaFileType.AudioUrl);
   resultA = true;
}
else
{
   SirenSource.Source = "audio.png";
   await siren.Stop();
   resultA = false;
}

Specific Eventargs for the Eventhandler

We have a lot of great events in the interface, but unfortunately they only provide the information that something has happend, but no data with it. So that you always have to access properties to get the actual interesting data. So it could be better like this:

public delegate void StatusChangedEventHandler(object sender, EventArgs e);

-> public delegate void StatusChangedEventHandler(object sender, PlayerStatus status);

public delegate void CoverReloadedEventHandler(object sender, EventArgs e)

--> not sure if it makes sense here to pass the new image;

public delegate void PlayingEventHandler(object sender, EventArgs e);

--> Would make sense to have a PlayinState class which contains: Position, Duration and Buffer

public delegate void BufferingEventHandler(object sender, EventArgs e);

--> public delegate void BufferingEventHandler(object sender, int);

public delegate void TrackFinishedEventHandler(object sender, EventArgs e);

--> Possibly passing the Track in the Queue

What's the aim of this package? Minimal corss-platform playing or full-fledged media player?

Since I've now adjusted much on the MediaQueue and am also planing on integrating some stuff like soft-fadeout and jumping to start if the user presses "previous" after he played more than 4sec, I am asking myself: What is the primary goal of this library?

Is it to have a minimal playing instance, or is it to provide a package, that contains all needed to implement a full-fledged feature-loaded media player?

Is f.e. #8 still within the range of this package, or is it more just simply playing items - without any additional work for features a user would expect from a media player?

Should this may be divided into two packages, where one of them just cares about playing cross-platform and the other one focuses on the media player like features?

We could also say, that we aim for the full-fledged implementation and users, who like tiny app-sizes can rely on the linker (https://developer.xamarin.com/guides/ios/advanced_topics/linker/) to shrink the size of the app again. But - in another way - code isn't that large in size, isn't it? It's most likely to be resources that blow up the app-size ...

Android - Java.Lang.RuntimeException: Invalid notification (no valid small icon)

I am getting this exception randomly on certain devices. Looking at the stack trace on the crash, it appears to be coming from MediaNotificationManagerImplementation.StartNotification().

According to this StackOverflow question:
http://stackoverflow.com/questions/33642484/android-notificationmanager-giving-me-no-valid-small-icon-error

It appears that it is caused by not setting the small icon in the notification builder. Here's the code in XMM that should be doing this:

var icon = (_appliactionContext.Resources?.GetIdentifier("xam_mediamanager_notify_ic", "drawable", _appliactionContext?.PackageName)).GetValueOrDefault(0);
           
...

_builder.SetSmallIcon(icon != 0 ? icon : _appliactionContext.ApplicationInfo.Icon);

So, it would seem that it can find neither the xam_mediamanager_notify_ic resource, or _appliactionContext.ApplicationInfo.Icon. To fix this, do I need to provide the xam_mediamanager_notify_ic resource in my own application package?

Android: Long pause before Playback from URI

I don't know why, but but when running the Android Sample App it takes about 30s before I hear the song playing. Can it be that the whole track is first downloaded before it starts playing?

Audio and video capture

It would be nice to be able to capture audio / video or both from the device.
Could be configurable via a ICaptureSettings interface.

CrossMedia.CaptureAudio(audioCaptureSettings)
CrossMedia.CaptureVideo(videoCaptureSettings)

UWP sample app crashes

I tried the UWP sample app, but can't get it to work. I'm running on a Windows 10 laptop. When I start the app, it immediately crashes with the following exception:

An exception of type 'System.Runtime.InteropServices.COMException' occurred in Plugin.MediaManager.dll but was not handled in user code

Additional information: ClassFactory cannot supply requested class (Exception from HRESULT: 0x80040111 (CLASS_E_CLASSNOTAVAILABLE))

It is happening in the following line of code in MediaManagerImplementation.cs:

_player = new MediaPlayer();

Here is the call stack:

Plugin.MediaManager.dll!Plugin.MediaManager.MediaManagerImplementation.MediaManagerImplementation() Line 25 C#
Plugin.MediaManager.dll!Plugin.MediaManager.CrossMediaManager.CreateMediaManager() Line 34 C#
[External Code]
Plugin.MediaManager.dll!Plugin.MediaManager.CrossMediaManager.Current.get() Line 20 C#
MediaSample.UWP.exe!MediaSample.UWP.MainPage.MainPage() Line 21 C#
[External Code]
MediaSample.UWP.exe!MediaSample.UWP.App.OnLaunched(Windows.ApplicationModel.Activation.LaunchActivatedEventArgs e) Line 78 C#

Remote control event not working in the sample app.

In the MediaSample android app the remote control events for controlling the playback state are not working. Clicking the play/pause button on the lock screen and in the notification area are not working. I am testing on Galaxy s6 (api 23)

Can't read Status before playing

If you try to read the Status field of the MediaManager and you haven't called Play() yet, then you get a Null Reference Exception in line 47 of MediaPlayerService.cs (Android).

    public int MediaPlayerState
    {
        get{
            return mediaControllerCompat.PlaybackState.State;
        }
    }

This appears to be because mediaControllerCompat is only initialized in the Play() method.

My application has logic so that if I try to press the Play button, the click handler will return if the Status is not PlayerStatus.STOPPED. So, the first time I try to play a song, I get the exception.

This is happening in the Android implementation. Not sure about other implementations.

Sample app code gone

It looks like as of the August 10 update, all of the sample app code is gone. Could it be restored? The app is there, but it is a default app that doesn't play music.

Android AlternateRemoteCallback missing

A while back, I added the MediaManagerImplementation.AlternateRemoteCallback property in order to handle remote media commands (play, pause, skip, etc.). This property seems to have been removed when the interface was changed recently. Was this intentional? If so, what is the new way to handle these events?

Counter-intuitive ToggleRepeat method in the IMeidaQueue interface

IMO the ToggleRepeat() in the IMediaQueue is a very counter-intuitive interface design. There are 3 different RepeatTypes, however there is just a toggle method to switch it. That means that the user of the player is forced to have a None, RepeatOne and a RepeatAll function.

This leaves us with a really confusing code, and also behavior, like we can see MediaQueue implementation of ToggleRepeat .

Otherwise he is forced to use dirty methods like Toggling twice after RepeatOne to get to None and so on. Why can't we simply have setter for the RepeatMode and remove the ToggleRepeat method?

If someone really wants the ToggleRepeat behavior, and also maybe other things that are tightly coupled to the UI, they could create a MediaQueueController that wraps a MediaQueue instead so it wouldn't bloat the business logic interface.

What do you think? Can I just go ahead and remove the method or do you have another opinion?

Android: Un-pausing media makes it start from the beginning

If a song is paused, and you un-pause it by calling MediaManager.PlayPause(), the song starts over from the beginning instead of continuing where it left off.

I have fixed this by modifying AudioPlayerBase.Play(), so that if the media is paused, it now calls MediaPlayerService.TogglePlayPause(true) instead of MediaPlayserService.Play(). Pull request to come soon.

Xamarin Forms?

Does XamarinMediaManager work with Xamarin Forms apps?

Your sample app works, and I was also able to get my own minimal simple test app to play a song from a straight Xamarin Android app. However, when I try to do the equivalent thing using a Xamarin Forms PCL project, nothing plays. Here's my code:

using MediaManager.Plugin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Xamarin.Forms;

namespace XMMTestXamarinForms
{
    public class App : Application
    {
        public App()
        {
            Button myButton = new Button { Text = "Click Me To Play Music" };
            myButton.Clicked += MyButton_Clicked;

            // The root page of your application
            MainPage = new ContentPage
            {
                Content = new StackLayout
                {
                    VerticalOptions = LayoutOptions.Center,
                    Children = {
                        myButton
                    }
                }
            };

        }

        private async void MyButton_Clicked(object sender, EventArgs e)
        {
           CrossMediaManager.Current.Play("http://www.montemagno.com/sample.mp3");
        }

        protected override void OnStart()
        {
            // Handle when your app starts
        }

        protected override void OnSleep()
        {
            // Handle when your app sleeps
        }

        protected override void OnResume()
        {
            // Handle when your app resumes
        }
    }
}

This is all in the App.cs file in the PCL project. I have not put any code in the .Droid project.

I added references to MediaManager.Plugin and MediaManager.Plugin.Abstractions to both the PCL project and the .Droid project. I also did add the required permissions in the Android application manifest.

What am I missing?

MediaForms.UWP sample does not build

The UWP Forms sample does not build.
Here is the build output:

1>------ Build started: Project: Plugin.MediaManager.Forms.UWP, Configuration: Debug x86 ------
1>  Plugin.MediaManager.Forms.UWP -> C:\Users\ndc\Source\Repos\XamarinMediaManager\MediaManager\Plugin.MediaManager.Forms\Plugin.MediaManager.Forms.UWP\bin\x86\Debug\Plugin.MediaManager.Forms.UWP.dll
2>------ Build started: Project: MediaForms.UWP, Configuration: Debug x86 ------
2>  MediaForms.UWP -> C:\Users\ndc\Source\Repos\XamarinMediaManager\Samples\Forms\MediaForms.UWP\bin\x86\Debug\MediaForms.UWP.exe
2>C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\AppxPackage\Microsoft.AppXPackage.Targets(1692,5): error APPX1101: Payload contains two or more files with the same destination path 'Plugin.MediaManager.pdb'. Source files: 
2>C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\AppxPackage\Microsoft.AppXPackage.Targets(1692,5): error APPX1101: C:\Users\ndc\Source\Repos\XamarinMediaManager\MediaManager\Plugin.MediaManager\bin\Debug\Plugin.MediaManager.pdb
2>C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\AppxPackage\Microsoft.AppXPackage.Targets(1692,5): error APPX1101: C:\Users\ndc\Source\Repos\XamarinMediaManager\MediaManager\Plugin.MediaManager.UWP\bin\x86\Debug\Plugin.MediaManager.pdb
3>------ Skipped Deploy: Project: MediaForms.UWP, Configuration: Debug x86 ------
3>Project not selected to build for this solution configuration 
========== Build: 1 succeeded, 1 failed, 5 up-to-date, 0 skipped ==========

Crossfade songs

I want to have an option to cross-fade between songs. The current implementation pauses the current playing track and starts the new song. The new implementation should wait until the next song has enough data to start playing (check the buffer of the player) and slightly taking down the volume of the currently playing song while start playing the new song by slightly increasing the volume.

It should be possible to:

  • Start buffering the song way before the cross-fading starts of (because it may needs some time to load)
  • Set the seconds for when the cross-fading should start

Please include this in a test and decide what to do:

  • What to do if a track is shorter than 2x the time of cross-fading (fading in and fading out)

Maybe it's worth thinking of opening up for a queue, that should just be an instance implementing IEnumerable. The programmer can decide if he wants to have a simple list like new List<Track>() or a more advanced implementation, including shuffling, repeating, etc - but that's up to the integration then.

Calling MediaQueue.Clear() does not clear current

After stopping playback, I am attempting to discard all items in the MediaQueue. However, calling MediaQueue.Clear() keeps the current item cached. Setting CrossMediaManager.Current.MediaQueue = null; causes the manager to crash when attempting to start a new item later.

Android - Exception "No player is set"

I am randomly encountering this error. It is coming from MediaManagerBase.CurrentPlaybackManager' getter:

            get
            {
                if (_currentPlaybackManager == null && _currentMediaFile != null) SetCurrentPlayer(_currentMediaFile.Type);

                if (_currentPlaybackManager == null) throw new Exception("No player is set");
                _currentPlaybackManager.RequestHeaders = RequestHeaders;
                return _currentPlaybackManager;
            }

The first line is calling SetCurrentPlayer(), which is as follows:

        private void SetCurrentPlayer(MediaFileType fileType)
        {
            if (_currentPlaybackManager != null)
            {
                RemoveEventHandlers();
            }
            switch (fileType)
            {
                case MediaFileType.AudioUrl:
                case MediaFileType.AudioFile:
                    _currentPlaybackManager = AudioPlayer;
                    break;
                case MediaFileType.VideoUrl:
                case MediaFileType.VideoFile:
                    _currentPlaybackManager = VideoPlayer;
                    break;
                case MediaFileType.Other:
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
            AddEventHandlers();
        }

The only code path that I can see that would permit _currentPlaybackManager to remain null (and thus cause the exception) is if the fileType passed in is MediaFileType.Other.

Any thoughts on how to fix this?

Error executing sample

I just followed all steps from the main README, installed Plugin.MediaManager in all projects and put this code on a button:
await CrossMediaManager.Current.Play("https://archive.org/download/testmp3testfile/mpthreetest.mp3" , MediaFileType.AudioUrl);

When i click the button, the audio plays, but a exception is showed

System.ArgumentException: TimeSpan does not accept floating point Not-a-Number values.
  at at (wrapper managed-to-native) UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
  at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Users/builder/data/lanes/3969/7beaef43/source/xamarin-macios/src/UIKit/UIApplication.cs:79
  at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00038] in /Users/builder/data/lanes/3969/7beaef43/source/xamarin-macios/src/UIKit/UIApplication.cs:63
  at TestApp.iOS.Application.Main (System.String[] args) [0x00008] in /Users/disiqueira/Playground/TestApp/iOS/Main.cs:17

Edit: I am doing a Xamarin Forms project, but debugging on an Iphone 7 iOS 10.2

Local files not working on some Android devices

I can not get Xamarin Media Manager to work on some devices with local files. On two of my devices (Samsung Galaxy S4 and Samsung Galaxy Tab 2), everything works fine for both HTTP sources and local files. However, on two other devices (Kindle Fire and HTC One M8), HTTP sources work fine, but local files refuse to play.

I hooked the Kindle Fire up to my development machine so that I could debug it. In the sample app, I changed the url from:
"http://www.montemagno.com/sample.mp3"
to
"/storage/sdcard1/Music/Fresh Prince of Bel Air Theme Song.mp3"
(which is an existing file on the tablet)

I found that the failure is occurring in the following line in MediaPlayerService.cs:

await mediaPlayer.SetDataSourceAsync(ApplicationContext, Android.Net.Uri.Parse(audioUrl));
That line is throwing the following exception:

Java.Lang.RuntimeException: setDataSource failed: status = 0x80000000
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw

Again, the exact same code works fine on all local files on my two Samsung devices, but on the other two devices, I can't get it to work with ANY local MP3 files (including files that work fine on my phone). The same MP3 files also play fine on the Kindle Fire with the stock Amazon Music app.

Has anyone else run into this issue?

Event when a new media file starts playing?

I used to subscribe to the CoverReloaded event so that I would know when new album art was available, so that I could update my UI. However, with the new interface change, that event no longer exists. So, I decided that I should subscribe to an event that tells me when a new song starts playing instead. However, I can't find one that works.

I first tried using MediaQueue.QueueMediaChanged. However, if I subscribe to this event, my handler never gets called. Due to the way that my app works, I only play one song at a time, using the Play() function, so there is never more than one song in the queue. I am assuming that this is the reason.

I then though of using the IMediaManager.MediaFileChanged event, but it appears (from the comments in the Interface) and looking at the code, that this event is only raised when a song FINISHES playing, not when it starts, which is what I need.

I was thinking of adding a call to OnMediaFileChanged in the Play() method so that I could get a notification when a new song starts, but I'm not sure if this is the best solution. Is this a good solution, or is there a better way to achieve this?

Android: If audio is paused by user, other device sounds cause it to unpause.

If the user pauses playback, and then the media focus experiences a transinent loss (i.e. a notification sound or an incoming phone call), when the sound ends, the music then starts playing again. This is not desirable, because if the user manually paused the music beforehand, they would not want it to start playing again unless they manually started it again.

Android - MediaPlayerService.Play(IMediaFile) Exception

I am occasionally getting an Unhandled Exception in this method. The call to _mediaPlayer.PrepareAsync() raises a Java.Lang.IllegalStateException every so often.

In researching this issue on StackOverflow, I found that this occurs if you try to Prepare the media player if it is already prepared. I made a fix to this by putting a try/catch around the call. Pull request to come soon.

Never finishes stopping or pausing playback

I'm writing an Android and iOS application with Xamarin.Forms in a PCL.

While testing on iOS (Have not yet tested on Android) The audio stream starts correctly with CrossMediaManager.Current.Play(). Stopping playback either via CrossMediaManager.Current.PlayPause() or CrossMediaManager.Current.Stop() does stop the audio coming from the speaker, but does not exit the awaited method nor does it trigger a StatusChanged event.

Android exception in MusicBroadcastReceiver - Service Intent must be explicit

I am recently experiencing a crash due to an exception in MusicBroadcastReceiver, in the second line below:

var stopIntent = new Intent(MediaPlayerService.ActionStop);
context.StartService(stopIntent);

The exception is:

Java.Lang.RuntimeException: Service Intent must be explicit: Intent { act=com.xamarin.action.STOP }

I googled this exception and found the this StackOverflow question about it. I think I get the gist of it's saying, but I'm not sure what exactly to change it to in this instance. Can anyone help?

Background audio

Hi,

nice piece of code. Does it also support background audio for iOS/android?

Regards,

Per

Andorid - Can't play same song twice in a row

I'm unable to play the same song twice in a row. I traced the code and here's what's happening:

The first time the song is played, it plays fine.
The second time, MediaServiceBase.Play() calls CheckIfFileAlreadyIsPlaying(), which in this situation sets the song position to zero and returns True, which causes the Play() function to return without doing anything.

CheckIfFileIsAlreadyPlaying() is returning True because of the following check: (mediaFile?.Url == CurrentFile?.Url) which I guess will be True in this case because CurrentFile still contains the same Url as the last time it was played.

Any thoughts on the best way to fix this?

Nuget

I can't find this on nuget.com?

Can you provide a link?

Android - Queue keeps building up, tracks repeating

My app does not use queues. I receive the MediaFinished event when a song ends, and in the handler, my app chooses the next song to play, and calls Play(IMediaFile mediaFile).

Since the interface change, I am having the following problem:

My app plays Song1.
When Song1 ends, it plays Song2.
When Song2 ends, my app requests to play Song3, but instead Song1 plays again.
Song1 keeps playing each time my app tries to play a new song.

I debugged this, and I found that for some reason, PlayNext() is being called. I have included the call stack at the end of this email.

I put a breakpoint in PlayNext(), and in this part of the code:

        public async Task PlayNext()
        {
            if (MediaQueue.HasNext())
            {
                await CurrentPlaybackManager.Stop();
                MediaQueue.SetNextAsCurrent();
                await Task.WhenAll(
                    CurrentPlaybackManager.Play(_currentMediaFile),
                    GetMediaInformation(new[] {_currentMediaFile}));
            }

I found that MediaQueue has multiple songs in it (Song1, Song2, Song3, etc.), and the logic is making Song1 keep playing because it never leaves the queue. Even though the songs end, they don't get removed from the queue, so they keep building up.

When a song ends shouldn't it be automatically removed from the queue?

Am I doing something wrong, or is this a bug?

I'm wondering if perhaps my call to Play() is somehow interrupting the removal of the previous song from the queue?

Call stack:

0x40 in Plugin.MediaManager.Abstractions.Implementations.MediaManagerBase.PlayNext at C:\Users\joemj\Source\Repos\XamarinMediaManager\MediaManager\Plugin.MediaManager.Abstractions\Implementations\MediaManagerBase.cs:58,17 C#
[External Code]
0x5A in Plugin.MediaManager.Abstractions.Implementations.MediaManagerBase.OnMediaFinished at C:\Users\joemj\Source\Repos\XamarinMediaManager\MediaManager\Plugin.MediaManager.Abstractions\Implementations\MediaManagerBase.cs:249,13 C#
0xF in Plugin.MediaManager.AudioPlayerBase<Plugin.MediaManager.MediaPlayerService>.b__57_3 at C:\Users\joemj\Source\Repos\XamarinMediaManager\MediaManager\Plugin.MediaManager.Android\Audio\AudioPlayerBase.cs:143,73 C#
0xF in Plugin.MediaManager.MediaServiceBase.OnMediaFinished at C:\Users\joemj\Source\Repos\XamarinMediaManager\MediaManager\Plugin.MediaManager.Android\MediaPlayerService\MediaServiceBase.cs:303,13 C#
0xD in Plugin.MediaManager.MediaPlayerService.OnCompletion at C:\Users\joemj\Source\Repos\XamarinMediaManager\MediaManager\Plugin.MediaManager.Android\MediaPlayerService\MediaPlayerService.cs:232,13 C#
0x13 in Android.Media.MediaPlayer.IOnCompletionListenerInvoker.n_OnCompletion_Landroid_media_MediaPlayer_ at /Users/builder/data/lanes/3511/ce955cc0/source/monodroid/src/Mono.Android/platforms/android-24/src/generated/Android.Media.MediaPlayer.cs:233,5 C#

Unable to provide custom IMediaNotificationManager implementation (Android)

I'm seeking for a way to implement a custom notification. Specificly I want to be able to change some of the style elements like the background color and buttons.

The MediaManagerImplementation provides a setter for the MediaNotificationManager but I'm unable to get the MediaSession Token. So the notification won't show. The default MediaNotificationManager will also be regenerated after adding a new item to the Queue.

Is there a way to get the MediaSession token? Or am I looking at the wrong approach here?

Android WifiLock under-locked exception

In MediaPlayerService.ReleaseWifiLock(), the call to WifiManager.WifiLock.Release() is intermittently throwing java.lang.RuntimeException: WifiLock under-locked xamarin_wifi_lock.

(working on fixing this)

Video playback

Would be nice to be able to play back video from file or url.
Clients would need to send in a view / surface to render the video on.

What about ExoMediaPlayer for Android?

I just saw, that you're also managing a port of the ExoMediaPlayer for Xamarin ... Was there a reason not to use it in this project, or just the lack of time? ๐Ÿ˜‰

MediaForms.UWP sample does not play video (only audio)

Sample Forms don't display Video, as seen on image below. Audio and controls are OK.
Had to change MediaFormsPage Constructor to:

private SynchronizationContext _uiCtx;
        public MediaFormsPage()
        {
            InitializeComponent();
            _uiCtx = SynchronizationContext.Current;
            CrossMediaManager.Current.PlayingChanged += (sender, e) =>
            {
                _uiCtx.Post((o) =>
                {
                    //UI Stuff goes here
                    ProgressBar.Progress = e.Progress;
                    Duration.Text = "" + e.Duration.TotalSeconds.ToString() + " seconds";
                }, null);
            };
        }

mediamanager uwp_novideo

Android - Unpausing paused media causes application to freeze

I have been having a problem where pausing playback, then un-pausing it would cause my application to freeze. I traced the issue and found that the first line of code in MediaServiceBase.Play() was blocking execution:

if(!ValidateMediaFile(mediaFile) || CheckIfFileAlreadyIsPlaying(mediaFile).Result)

On further investigation, I found that it was the ".Result" that was blocking. I changed the call to CheckIfFileAlreadyIsPlaying() to an "await" call instead of accessing .Result, and that fixed the issue.

Pull request coming soon.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.