How to stream video and audio from SkyDrive on Windows Phone
In this post I will explain how to stream video and audio files from SkyDrive in MediaElement control or MediaPlayerLauncher. If you ever tried to play your media files from SkyDrive in your WP7 application using Live Connect API, you will probably get error message like “3002 AG_E_NOT_FOUND” or “Sorry, we can’t open this file on your phone“:
What is happening?
If you try to open your media file by pasting url in your desktop browser, you will notice that file url has format like:
http://storage.live.com/<folder_id>/MyVideo.wmv
But, when your default player starts streaming (e.g. Windows Media Player), you can see in playing file properties that it’s location is different; url is redirected to other location like:
http://frbedg.sn2.livefilestore.com/<folder_id>/MyVideo.wmv
On Windows Phone, for security reasons, the Silverlight runtime restricts access to certain classes of URLs classes in the System.Net and System.Windows.Controls namespace. These restrictions are designed to prevent networking threats (for example, threats based on a Silverlight application run from an internet server getting access to resources on a local intranet server). This means that MediaElement won’t redirect passed Source Uri value to other url address, and you will get error mentioned above. And this is not problem only with SkyDrive. You can experience this problem on other web-based hosting services.
The trick is to get second url by component that is not affected by this restriction, which is in our case WebBrowser control. All you have to do is to put WebBrowser control to your XAML page, set Visibility to Collapsed, and add handler to Navigated event:
<Grid x:Name="LayoutRoot" Background="Transparent" Margin="12,0,12,0"> <MediaElement Name="movie" AutoPlay="True" Stretch="Uniform" /> <phone:WebBrowser Name="webBrowser" Navigating="webBrowser_Navigating" Visibility="Collapsed" /> </Grid>
Navigating event occurs every time before the WebBrowser control navigates to a new document. So, we only have to get uri when event triggers second time, and then set MediaElement Source property to that value, or launch MediaPlayerLauncher:
private void webBrowser_Navigating(object sender, NavigatingEventArgs e) { if (e.Uri.ToString() != file.Source) { e.Cancel = true; if (launchInControl) movie.Source = e.Uri; else { MediaPlayerLauncher mediaPlayerLauncher = new MediaPlayerLauncher(); mediaPlayerLauncher.Media = e.Uri; mediaPlayerLauncher.Controls = MediaPlaybackControls.All; mediaPlayerLauncher.Show(); } } }
And that’s it. Streaming will start. Happy coding.
Complete working zip solution can be downloaded from here (don’t forget to put your app client ID in MainPage.xaml).