Windows Phone 8: MediaElement fails to play under Lock Screen – Workaround

Disclaimer!:  I am not a Window Phone Expert though dabble occasionally…

Summary

The Media Element on Windows Phone 8 sometimes/often fails to play media under the lock screen.  Forcing a layout update works around the problem.

Scenario

My app features several pages that load automatically in a sequence to play various pieces of audio.  (These same pages do other things too when the phone is unlocked, but when locked everything else is disabled except the playing of the audio).

Each page plays a piece of audio using the Media Player.  On some pages the audio was playing happily under the lock screen.  On other pages the audio refused to play (no error, the call to the media player was seemingly ignored).

Investigation

After several hours of comparing the pages I tracked down the single line of code that was making the difference.  On pages where the audio was playing, the following line was present and this single line made the all important difference:

myPivotControl.Items.Remove(myPivotItemTobeRemoved);

Guessing that this might be triggering a layout update, I swapped this line for the following:

ContentPanel.UpdateLayout();

Same effect.  When this line was executed before the call to the MediaPlayer element, the audio played.  If I skipped calling this line, the audio didn’t play.

Download

The simple project I used to explore this issue can be downloaded here.  Leaving the “Force Layout Updates” box unticked demonstrates the problem.  Ticking the box runs the extra line of code and the audio plays fine.

Note

I haven’t tested this on the latest version of the WP8 Emulators.  I have however tested it on my Lumia 920 which is running the latest updates and the behaviour is the same.

Windows Phone 8: LongListSelector Memory Leak

Disclaimer!:  I am not a Window Phone Expert though dabble occasionally… 

Summary

The clean-up for the Windows Phone LongListSelector control on Windows Phone 8 often does not recover a relatively large amount of memory that the control has been using.  Some/much of the lost memory can be recovered as shown below.

Scenario

I was writing a language learning app and had a page that contained a Pivot control with half a dozen PivotItems.  Most of these PivotItems contained a LongListSelector.  This page was typically loaded many times during typical use of the app.  Memory use was observed to rapidly grow to 150MB and more, despite only text – no images or other media – being used.

Investigation

I extracted a small but representative sample of the offending code into a separate app to investigate.  This can be downloaded here.

The start screen is below.  The check box allows my fix/workaround to be switched on/off.

20140124-05

To demonstrate the issue, don’t tick the checkbox.  Click start.

The next screen is a sample screen from my language app, filled with random dummy data.  In my app, this screen is used often in between various other screens.  To simulate this, I clicked the “Next” button 30 times (the page URL contains a dummy random parameter to ensure it reloads each time).  At the end of this, the phone shows memory use has increased rapidly:

20140124-01

For good measure, I added a button to force a full, blocking garbage collection.  This recovered a small amount of memory:

20140124-02

Clearly, nearly 100MB with only small amounts of text and no use of images/sound/video is quite excessive.

The memory use over the lifetime of the text was captured in the Memory Profiler:

20140124-06

It is worth noting that the total memory captured in the Memory Profiler was only 13MB.  This can be downloaded here.

Clearly there is a large discrepancy between the 13MB total being reported in the profiler and the nearly 100MB use observed.  The profiler doesn’t cover system memory, which got me thinking that something within one of the native controls could be the cause.

It is worth noting that I was already removing the page from the Back Stack and I had verified that the page was being cleaned up by putting a debug statement in the page destructor.  So, although the clean-up was happening in theory, it certainly wasn’t cleaning up everything.

Workaround / Fix

After some trial and error improvement, I found an approach that was able to recover most/all of the memory that was being lost.  This involved clearing all of the values of the dependency properties on the LongListSelector controls (and the Pivot control too).  A snippet of the code is given at the bottom of this post.

I am not sure if this is widely regarded as normal practice.  It did not seem obvious to me.

Running the test app again, this time with the Cleanup checkbox ticked:

After the 30 pages:

20140124-03

After forcing a garbage collection:

20140124-04

Clearly, significantly better.  Also reflected in the Memory Profile:

20140124-07

Code Sample

The workaround/fix makes use of the DependencyObject.ClearValue method:

20140124-08

20140124-09

The full source code can be found in the sample project.  The workaround/fix is located around line 105 in PivotPage.xaml.cs

This does seem rather an ugly brute force fix and perhaps others are possible.  But sometimes you just have to go with what works…