I’ve seen a few posts on Twitter and this blog post by Jeff Wilcox about the issues with using a remote image on secondary live tiles, so I thought it might be useful to share the workaround I developed for a new WP7 application I have been working on that makes heavy use of secondary tiles.
In short, the issue with using remote URIs for the BackgroundImage
or BackBackgroundImage
properties of secondary live tiles is that the tiles will disappear after restarting the phone. Worse, the tile still appears in the ShellTile.ActiveTiles
list as though the tile is still pinned. This issue is mentioned in a few parts of the documentation, including here:
When creating a secondary Tile, the BackgroundImage and the BackBackgroundImage images must be created using a local resource.
I did some testing and determined that the issue is only caused by using a remote image URI during the initial tile creation — any tile updates that occur later on can use remote URIs without any trouble. In fact, you can update the tile with a remote URI immediately after creating it and the tile will still appear after the phone is restarted. (Note that the image displayed after a restart will be the static, local image and not the remote image. For my app, the tiles are regularly updated via push notifications but you could also update the tiles from within your app or background agent, etc.)
When a new tile is created, the user is brought to the home screen and your app will be terminated, but you still have about 10 seconds to execute code after pinning the new tile — more than enough time to update the background image URI.
Here’s one way of implementing this workaround in C#:
private static ShellTileData GenerateTileData(YourClass item, bool includeRemoteImage = false)
{
StandardTileData tileData = new StandardTileData();
tileData.Title = "Tile title";
if (includeRemoteImage)
tileData.BackgroundImage = new Uri(item.remoteImagePath);
else
tileData.BackgroundImage = new Uri("isostore:" + item.staticImagePath);
return tileData;
}
public static void PinItem(YourClass item)
{
Uri tileUri = new Uri(item.navURI, UriKind.Relative);
ShellTileData tileData = GenerateTileData(item);
ShellTile.Create(tileUri, tileData);
// Update the tile with a remote image
ShellTile tile = ShellTile.ActiveTiles.FirstOrDefault(t => t.NavigationUri.ToString() == item.navURI);
if (tile != null)
{
tileData = GenerateTileData(item, true);
tile.Update(tileData);
}
}
One other thing to note is that you can use images from Isolated Storage when creating a new live tile without any trouble. You could generate (or download) an image, save it to Isolated Storage, and set that as the initial background image, and then set a remote image URI for more up-to-date information.
Thanks, you’re a lifesaver! I have an app that needs to be able to pin tiles sourced from a large and oft-changing JSON feed. Pin access is available in various points in the app and it’s just not viable to download every possible tile in case the user decides to pin it.
Using your method I simply pin a tile with the name of the selected item item as the tile’s Title and “/Background.png” as the BackgroundImage. I then immediately update, stripping the Title and replacing BackgroundImage with a remote Uri.
Good old Windows Phone actually leaves the original Title and BackgroundImage alone until it has finished loading the remote BackgroundImage, and then replaces them both in one go — no blank tile!
I have noticed that contrary to what you state above, Windows Phone caches the new TileData (including remote image) and uses that when you restart instead of reverting to the original TileData.