8

我已经看到了许多显示 CycleTile 的示例,但这些都使用了本地图像。一旦应用程序首次运行并将 CycleTile 指向远程图像,是否可以设置这些图像?或者如果我确实需要先将这些保存到手机中,我怎样才能让 CycleTile 引用它们?

4

2 回答 2

21

CycleTileTemplate & CycleTileData 仅支持本地 URI,不支持远程 Web URI。这意味着您只能从从 XAP 安装的文件或从 IsoStore 中的文件设置循环图像的来源。

为了支持 CycleTileData 中的远程图像,您需要在周期性后台代理中下载图像,将它们保存到 IsoStore,然后使用这些图像更新 CycleTileData。推送通知在这里不起作用,因为图像需要是本地的,ShellTileSchedule 也不需要。

确保将图像保存到“/Shared/ShellContent”下的 IsoStore,并将其 URI 设置为“isostore:/Shared/Shellcontent/myImage.png”,否则开始屏幕磁贴将无法访问它们。

让我们看一个例子。首先,我们首先编写一个并行线程算法,该算法启动 9 个下载线程,等待结果,然后更新切片:

private IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();

private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
        var threadFinishEvents = new List<WaitHandle>();

        DownloadImages(threadFinishEvents);

        new Thread(()=>
        {
            Mutex.WaitAll(threadFinishEvents.ToArray());

            UpdateTiles();

            isoStore.Dispose();
        }).Start();
}

接下来,我们将 9 个图像下载到 IsoStore“/Shared/ShellContent”。我们将特别注意为每个 Web 下载添加新的线程标志,并在文件位于 IsoStore 后将标志设置为完成。

private void DownloadImages(List<WaitHandle> threadFinishEvents)
{
    for (int i = 0; i < 9; i++)
    {
        var localI = i;

        var threadFinish = new EventWaitHandle(false, EventResetMode.ManualReset);
        threadFinishEvents.Add(threadFinish);

        var request = WebRequest.CreateHttp("http://www.justinangel.net/storage/691x336.png");
        request.BeginGetResponse(ir =>
        {
            var result = request.EndGetResponse(ir);
            using (var isoStoreFile = isoStore.OpenFile("shared/shellcontent/myImage" + localI + ".png",
                                                        FileMode.Create,
                                                        FileAccess.ReadWrite))
            using (var response = result.GetResponseStream())
            {
                var dataBuffer = new byte[1024];
                while (response.Read(dataBuffer, 0, dataBuffer.Length) > 0)
                {
                    isoStoreFile.Write(dataBuffer, 0, dataBuffer.Length);
                }
            }

            threadFinish.Set();
        }, null);
    }
}

最后,我们将更新动态磁贴以使用 IsoStore 中的新图像。

private void UpdateTiles()
{
    ShellTile.ActiveTiles
        .First()
        .Update(new CycleTileData()
        {
            Title = "Cyclical",
            CycleImages = new Uri[]
            {
                new Uri("isostore:/Shared/ShellContent/myImage0.png", UriKind.Absolute), 
                new Uri("isostore:/Shared/ShellContent/myImage1.png", UriKind.Absolute), 
                new Uri("isostore:/Shared/ShellContent/myImage2.png", UriKind.Absolute), 
                new Uri("isostore:/Shared/ShellContent/myImage3.png", UriKind.Absolute), 
                new Uri("isostore:/Shared/ShellContent/myImage4.png", UriKind.Absolute), 
                new Uri("isostore:/Shared/ShellContent/myImage5.png", UriKind.Absolute), 
                new Uri("isostore:/Shared/ShellContent/myImage6.png", UriKind.Absolute), 
                new Uri("isostore:/Shared/ShellContent/myImage7.png", UriKind.Absolute), 
                new Uri("isostore:/Shared/ShellContent/myImage8.png", UriKind.Absolute), 
            }
        });
}

有几件有趣的事情需要考虑:

  1. 周期性后台代理只有 25 秒的时间来完成它们的操作,因此在激活 Mutex.WaitAll 时添加计时器阈值并让它优雅地失败可能是有意义的。
  2. 在某些网络条件下,在 25 秒内下载 9 张图像可能根本无法工作,因此最好对此进行优化。您可以使用更少的图像,也可以每 30 分钟只更新几张图像。
  3. 将 CycleTileData 更新到相同的文件 URI 不会触发磁贴的更新 (AFAIK)。因此,您将需要比 myImage0 更好的文件名,而是为图像提供唯一的文件名。
于 2013-01-04T02:15:33.983 回答
2

对于 CycleTile,图像必须是本地的。您可以设置一个定期任务来刷新图像,然后将这些图像存储在本地/隔离存储中的 shared/shellcontent 特殊文件夹中(例如,ms-appdata:///local/shared/shellcontent/image01.png)

Windows Phone 8 Jumpstart 的第 7 节是一个很好的参考 - 特别是大约 25:30。

于 2013-01-04T00:49:55.060 回答