dotnetco.de

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:

  1. Check whether the requested image is available in isolated storage. If so, display image from there.
  2. If not, download image in the background and display it to the user.
  3. After downloading save it to isolated storage.

The solution has the following advantages:

  1. Images are only load once.
  2. Images are loaded in the background.
  3. Easy to implement.
  4. 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.

Leave a Comment