Download images and store them in isolated storage (Windows Phone 7 and 8)
For my windows phone app I need to retrieve some images from the internet. Windows Phone automatically caches them as long as the application is alive, but as soon as the application is stopped and restarted the cache is gone and images need to be retrieved again. I’ve found several proposals (e.g. One-time Cached Images in Windows Phone 7 or the extended version “Intelligent” Image Caching for WP 7) next to Image Tips for Windows Phone 7 and App performance considerations for Windows Phone but in the end I setup a solution based on Displaying an Image from Isolated Storage and Off-thread decoding of images on Mango The solution below is in vb.net for Windows Phone 7.1 (and Windows Phone 8 of course) and processes like this:
- Check whether the requested image is available in isolated storage. If so, display image from there.
- If not, download image in the background and display it to the user.
- After downloading save it to isolated storage.
The solution has the following advantages:
- Images are only load once.
- Images are loaded in the background.
- Easy to implement.
- Works fine also in a listbox with multiple images on the screen.
Implementation
New Class
First create a new class called ‘ImageCacheConverter.vb’ and add the following code:
Imports System.Windows.Data Imports System.Windows.Media.Imaging Imports System.IO Public Class imageCacheConverter Implements IValueConverter Private Shared ISF As IsolatedStorage.IsolatedStorageFile = IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication() ”’ <param name=”value”>Contains a path to the internet file, e.g. https://dotnetco.de/myimagefile.png</param> Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.Convert Dim path As String = TryCast(value, String) Dim filename As String If [String].IsNullOrEmpty(path) Then Return Nothing ElseIf path.Contains(“/”) Then filename = System.IO.Path.GetFileName(path) Else filename = path End If If ISF.FileExists(filename) Then Using sourceFile As IO.Stream = ISF.OpenFile(filename, FileMode.Open, FileAccess.Read) Dim bm As New BitmapImage() bm.SetSource(sourceFile) Return bm End Using Else Dim source As New BitmapImage(New Uri(path, UriKind.Absolute)) source.CreateOptions = BitmapCreateOptions.BackgroundCreation AddHandler source.ImageOpened, Sub(sender, e) SaveImageToISOAfterDownload(sender, e, filename) Return source End If End Function Private Sub SaveImageToISOAfterDownload(sender As Object, e As System.Windows.RoutedEventArgs, filename As String) If Not ISF.FileExists(filename) Then Dim bitmap As New WriteableBitmap(CType(sender, BitmapSource)) bitmap.SaveJpeg(ISF.CreateFile(filename), bitmap.PixelWidth, bitmap.PixelHeight, 0, 100) End If End Sub Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack Throw New NotImplementedException() End Function End Class
So in ‘Convert’ we first check whether the file exists in isolated storage. If so, the bitmap is returned. Otherwise the bitmap is retrieved from the given internet address. Additionally we set a handler to be executed as soon as the image is retrieved completely (AddHandler source.ImageOpened) and supply the filename so we could save the file later on. (As seen I save all images into the root directory of the isolated storage). That’s it for the programming part.
App.xaml
In App.xaml we first add the namespace (if not already done)
<Application (…) xmlns:local=”clr-namespace:MyNamespace”>
and add the converter to Application Resources
<Application.Resources> <local:imageCacheConverter x:Key=”imageCacheConverter”></local:imageCacheConverter> </Application.Resources>
Mainpage.xaml
So now in the MainPage.xaml we could use the image this way:
<Image Name="MyIcon" Source="{Binding ImageFilename, Converter={StaticResource imageCacheConverter}}" />
Done
So that’s it. Now you could retrieve your images only once and reuse them as long as your application is installed. No need again for an internet connection.