In a previous article I showed how to use the audio background task agent to run the audio even when your application is no longer in the foreground. In that article we used audio that was downloaded from the Internet. If you wish to use local audio you must copy it to isolated storage.
While this may seem intimidating at first, the actual steps are straightforward and the process is relatively simple.
For example, assuming that you want to copy the three Sample audio files that come with Windows 7, you would create a method, CopyToIsolatedStorage, in your app.xaml.CS file. The method GetUserStoreForApplication will return an IsolatedStorageFile which you will place in a using statement to ensure that it is closed as soon as you are finished with it, thus avoiding a resource leak
private void CopyToIsolatedStorage() { using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication()) { } }
Create an array of your file names, and then iterate through that array to add each to isolated storage.
private void CopyToIsolatedStorage() { using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication()) { string[ ] files = new string[ ] { "Kalimba.mp3", "Maid with the Flaxen Hair.mp3", "Sleep Away.mp3" }; foreach (var _fileName in files) { } } }
Examine each filename to see if it is already in isolated storage. If not, create the path and a StreamResourceInfo object based on the full file name and path.
if (!storage.FileExists( _fileName )) { string _filePath = "Audio/" + _fileName; StreamResourceInfo resource = Application.GetResourceStream( new Uri( _filePath, UriKind.Relative ) );
Next, create an IsolatedStorageFileStream (which again you’ll put into a using statement to prevent a resource leak) and read from the original file to the file in isolated storage, as bytes.
using (IsolatedStorageFileStream file = storage.CreateFile( _fileName )) { int chunkSize = 4096; byte[ ] bytes = new byte[chunkSize]; int byteCount; while ((byteCount = resource.Stream.Read( bytes, 0, chunkSize )) > 0) { file.Write( bytes, 0, byteCount ); } }
Here’s the complete method for context:
private void CopyToIsolatedStorage() { using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication()) { string[ ] files = new string[ ] { "Kalimba.mp3", "Maid with the Flaxen Hair.mp3", "Sleep Away.mp3" }; foreach (var _fileName in files) { if (!storage.FileExists( _fileName )) { string _filePath = "Audio/" + _fileName; StreamResourceInfo resource = Application.GetResourceStream( new Uri( _filePath, UriKind.Relative ) ); using (IsolatedStorageFileStream file = storage.CreateFile( _fileName )) { int chunkSize = 4096; byte[ ] bytes = new byte[chunkSize]; int byteCount; while ((byteCount = resource.Stream.Read( bytes, 0, chunkSize )) > 0) { file.Write( bytes, 0, byteCount ); } } } } } }
Don’t forget to put a call to this method in the constructor:
public App() { UnhandledException += Application_UnhandledException; CopyToIsolatedStorage();
Hey Jesse, this looks good for files on the local filesystem. I am wondering how would you approach saving audio from a remote server that would stream on the phone ?
Async and Errors?
Suggestion:
Use the the new Await and Async capabilities (provided for Silverlight 4 & 5 RC in the Async CTP ver3) to download the chunks asynchronously and to respond to errors and timeouts.
I really like this piece of code .I believe it will become
more wonderful if we spend more time searching it..thanks!
Hi Jesse, thank you for this really useful piece of code. Easy, and quite powerful!