<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Christian Jacob</title>
    <description>The latest articles on DEV Community by Christian Jacob (@mephisztoe).</description>
    <link>https://dev.to/mephisztoe</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F985242%2F8b108fb2-c11a-46d9-af03-10b31f53a0b8.jpeg</url>
      <title>DEV Community: Christian Jacob</title>
      <link>https://dev.to/mephisztoe</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mephisztoe"/>
    <language>en</language>
    <item>
      <title>New .NET MAUI Release</title>
      <dc:creator>Christian Jacob</dc:creator>
      <pubDate>Tue, 13 Dec 2022 22:11:03 +0000</pubDate>
      <link>https://dev.to/mephisztoe/new-net-maui-release-576k</link>
      <guid>https://dev.to/mephisztoe/new-net-maui-release-576k</guid>
      <description>&lt;p&gt;In my last post, I wrote about the .NET MAUI CommunityToolkit and more specifically, the MediaElement Library (which is currently a preview version).&lt;/p&gt;

&lt;p&gt;I also noted, that the Windows target depends on WindowsAppSDK version 1.2.x where as most Visual Studio SKUs still preinstall version 1.15.x. Since this results in a conflict, the only simple solution was to disable the Windows target if you wanted to try out CommunityToolkit.Maui.MediaElement.&lt;/p&gt;

&lt;p&gt;However, today, &lt;a href="https://github.com/dotnet/maui/releases/tag/7.0.52"&gt;Microsoft released an update on .NET MAUI&lt;/a&gt; for both .NET6 and .NET7 with the latter focussing on updates on all levels including the WindowsAppSDK to version 1.2.221109.1.&lt;/p&gt;

&lt;p&gt;So go ahead and update your Visual Studio to version 17.4.3 to get the latest bits!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>dotnetmaui</category>
      <category>microsoft</category>
    </item>
    <item>
      <title>Background audio streaming with CommunityToolkit.Maui.MediaElement (Preview) for Android and iOS</title>
      <dc:creator>Christian Jacob</dc:creator>
      <pubDate>Sun, 11 Dec 2022 23:02:25 +0000</pubDate>
      <link>https://dev.to/mephisztoe/background-audio-streaming-with-communitytoolkitmauimediaelement-preview-for-android-and-ios-340p</link>
      <guid>https://dev.to/mephisztoe/background-audio-streaming-with-communitytoolkitmauimediaelement-preview-for-android-and-ios-340p</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article is part of the .NET MAUI Advent Calender. Find all contributions &lt;a href="https://dev.to/icebeam7/net-maui-advent-calendar-48d0"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So people have been wondering since the very first previews of .NET MAUI how they will be supposed to play media files such as videos and mp3 files for instance. While they have always been able to utilize the Xamarin CommunityToolkit - which includes the well known MediaElement control - this only worked for iOS when trying to import it into a MAUI solution. So that you can play or stream media files on Android, you had to directly install ExoPlayer2. However, since MediaElement also has a reference to the ExoPlayer, things got really nasty. Either you found out how to implement platform dependent controls yourself to seperate these components from eachother, or you had to clutter your code with lots of precompiler directives to ensure that Android based code does not interfere with iOS based code and vice versa.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gerald Versluis to the rescue
&lt;/h2&gt;

&lt;p&gt;Not long ago, Gerald became active on this topic and started to implement Media Plugin .NET MAUI which is loosely based on the work of James Montemagno and his .NET Podcast App. The first iteration only showed how to play local mediafiles and was &lt;a href="https://github.com/jfversluis/Plugin.Maui.Audio"&gt;hosted in his private GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, things kinda went viral and so he decided to put a little more effort into this component. The result is an &lt;a href="https://github.com/CommunityToolkit/Maui/pull/667"&gt;active Pull Request&lt;/a&gt; on the official .NET MAUI CommunityToolkit!&lt;/p&gt;

&lt;h2&gt;
  
  
  First things first
&lt;/h2&gt;

&lt;p&gt;As of the time of writing, you may or may not run into some version conflicts when trying out preview libraries such as the CommunityToolkit.Maui.MediaElement. In &lt;em&gt;this&lt;/em&gt; case this could be due to the library referencing a newer version of the WindowsAppSDK compared to what your version of Visual Studio has installed. If this is the case, then you could skip targetting Windows for now and get back to this later when the library is finally released.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;UPDATE&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Microsoft released a new version of Visual Studio that also includes support for WindowsAppSDK 1.2.221109.1 which should render the last paragraph obsolete. More about it &lt;a href="https://dev.to/mephisztoe/new-net-maui-release-576k"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Play with it
&lt;/h2&gt;

&lt;p&gt;Before I show you how you can make the component stream audio content even when your app is not in the foreground ("Background Streaming"), let's dive into how to include the MediaElement in the first place, since it is still in preview (and actually still "only" a Pull Request - but don't let that frighten you).&lt;/p&gt;

&lt;p&gt;Detailed instructions on how to NuGet install MediaElement into your .NET MAUI project can be found on Geralds blog &lt;a href="https://blog.verslu.is/maui/mediaelement-for-net-maui-early-preview/"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The shortcut is this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to Tools &amp;gt; NuGet Package Manager &amp;gt; Package Manager Settings&lt;/li&gt;
&lt;li&gt;Go to Package Sources&lt;/li&gt;
&lt;li&gt;Hit the Plus Icon&lt;/li&gt;
&lt;li&gt;Create a new Package Source&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Name the new Package Source "Microsoft CommunityToolkit PR" and let it point to this URL: "&lt;a href="https://pkgs.dev.azure.com/dotnet/CommunityToolkit/_packaging/CommunityToolkit-PullRequests/nuget/v3/index.json"&gt;https://pkgs.dev.azure.com/dotnet/CommunityToolkit/_packaging/CommunityToolkit-PullRequests/nuget/v3/index.json&lt;/a&gt;"&lt;/p&gt;

&lt;p&gt;The magic is, that the CommunityToolkit GitHub repo automatically creates NuGet packages for Pull Request. Nice, eh?&lt;/p&gt;

&lt;h2&gt;
  
  
  Install the NuGet Package
&lt;/h2&gt;

&lt;p&gt;Next step is installing the NuGet Package into your project. I assume you already know how to install NuGet Packages, so I'll ommit detailed steps. However, this is the Package you want to install: CommunityToolkit.Maui.MediaElement. (Remember to tick the preview checkbox).&lt;/p&gt;

&lt;p&gt;As of the time of writing this, the Package is labeled as version 1.0.0-build-667.84118. &lt;em&gt;667&lt;/em&gt; refers to the Pull Request id.&lt;/p&gt;

&lt;p&gt;It also depends on the WindowsAppSDK Version 1.2.221116.1 which you might not have installed yet. As mentioned above this could result in errors and the easiest way to deal with this at the moment is removing the Windows target out of your .csproj file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initialize and configure the MediaElement
&lt;/h2&gt;

&lt;p&gt;Next thing you need to do is registering all necessary handlers. Luckily, there is an extension you can call from within your MauiProgram.cs:CreateMauiApp method (UseMauiCommunityToolkitMediaElement) like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;builder&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseMauiApp&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;**.&lt;/span&gt;&lt;span class="nf"&gt;UseMauiCommunityToolkitMediaElement&lt;/span&gt;&lt;span class="p"&gt;()**&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureFonts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fonts&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fonts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddFont&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"OpenSans-Regular.ttf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OpenSansRegular"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;fonts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddFont&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"OpenSans-Semibold.ttf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OpenSansSemibold"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this being more or less it, you could theoretically try to use the MediaElement right now.&lt;/p&gt;

&lt;p&gt;Open your MainPage.xaml and add the following namespace to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xmlns:media="clr-namespace:CommunityToolkit.Maui.MediaElement;assembly=CommunityToolkit.Maui.MediaElement"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can add the MediaElement itself to your page like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;media:MediaElement
    x:Name="mediaElement"    
    AutoPlay="True"  
    HeightRequest="100"
    Source="http://ais-sa5.cdnstream1.com/b55667_128mp3" /&amp;gt;        
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Android Settings to consider
&lt;/h2&gt;

&lt;p&gt;If you tried that right now, you may have run into an issue with ExoPlayer telling you that it cannot stream from an HTTP address. This is due to some security constraints. You can easily get around this problem by adding a network_security_config.xml file to your Platforms/Android/Resources/xml folder (create one if it does not exist yet) with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;network-security-config&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;domain-config&lt;/span&gt; &lt;span class="na"&gt;cleartextTrafficPermitted=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;domain&lt;/span&gt; &lt;span class="na"&gt;includeSubdomains=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;cdnstream1.com&lt;span class="nt"&gt;&amp;lt;/domain&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/domain-config&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/network-security-config&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More info on that can be found &lt;a href="https://learn.microsoft.com/en-us/dotnet/maui/data-cloud/local-web-services?view=net-maui-7.0"&gt;here&lt;/a&gt;. Finally you need to reference this configuration directly from within your AndroidManifest.xml file like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;application&lt;/span&gt; &lt;span class="err"&gt;**&lt;/span&gt;&lt;span class="na"&gt;android:networkSecurityConfig=&lt;/span&gt;&lt;span class="s"&gt;"@xml/network_security_config"&lt;/span&gt;&lt;span class="err"&gt;**&lt;/span&gt; &lt;span class="na"&gt;android:allowBackup=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;android:icon=&lt;/span&gt;&lt;span class="s"&gt;"@mipmap/appicon"&lt;/span&gt; &lt;span class="na"&gt;android:roundIcon=&lt;/span&gt;&lt;span class="s"&gt;"@mipmap/appicon_round"&lt;/span&gt; &lt;span class="na"&gt;android:supportsRtl=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/application&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  iOS Settings to consider
&lt;/h2&gt;

&lt;p&gt;You also might have noticed that on Android, the app is already capable of streaming in the background. On iOS this does not work, yet. Also, if your iPhone has the ability to enter a silent mode with a hardware button, you might have noticed, that the playback stops when the device is in silent mode.&lt;/p&gt;

&lt;p&gt;So that on iOS your app is able to stream even when being in background mode, you need to do two things.&lt;/p&gt;

&lt;p&gt;Step 1: Add the Background Audio Mode capability to your Info.plist file like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;UIBackgroundModes&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;audio&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: You need to register a lifecycle event so that the &lt;em&gt;AVAudioSession&lt;/em&gt; is set as a shared instance to the device. &lt;/p&gt;

&lt;p&gt;This is done in your CreateMauiApp method and needs to be restricted to the iOS target like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;builder&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseMauiApp&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseMauiCommunityToolkit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseMauiCommunityToolkitMediaElement&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;              
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureLifecycleEvents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="cp"&gt;#if IOS
&lt;/span&gt;        &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddiOS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ios&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ios&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FinishedLaunching&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;AVFoundation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AVAudioSession&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AVFoundation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AVAudioSession&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SharedInstance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCategory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AVFoundation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AVAudioSessionCategory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Playback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetActive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="cp"&gt;#endif
&lt;/span&gt;    &lt;span class="p"&gt;})&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything works as expected, you should now be able to background stream audio on iOS as well. Also, the stream does not stop when the device is set to silent mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interesting to know
&lt;/h2&gt;

&lt;p&gt;There is so much more to know. For instance you could make the MediaElement itself invisible and add an own ImageButton to control the state of the player. This could be something you might want to consider when building a streaming client for an online radio. Because in this case you won't need a visible MediaElement - in contrast to a case scenario in which you stream a video for example.&lt;/p&gt;

&lt;p&gt;I assume the most interesting parts in this article might be the hint about how to configure networking security for Android so that you can also stream from non encrypted HTTP addresses and of course the code snippet that allows you to register the MediaElements' iOS implementation as a shared instance so that you can stream in the background on your iPhone.&lt;/p&gt;

&lt;p&gt;Shoutout goes to Gerald for his awesome work and now have fun building awesome apps with it!&lt;/p&gt;

</description>
      <category>dotnetmaui</category>
      <category>csharp</category>
      <category>programming</category>
      <category>streaming</category>
    </item>
  </channel>
</rss>
