windows-runtime - 如何在 Windows Phone 8.1 中每分钟更新一个自定义图像动态磁贴?

标签 windows-runtime windows-phone windows-phone-8.1 live-tile

有很多 Windows Phone 8.1 应用程序(例如 Clock hub、Analog Clock Tile 等)允许您在主屏幕上固定模拟时钟。

我正在尝试通过遵循此 sample 来做同样的事情它向我展示了如何每分钟更新一个 XML 文档。

但如果我要创建一个模拟时钟 block ,那么它需要是一个图像。

我已尝试将 XamlRenderingBackgroundTaskRenderTargetBitmap 一起使用来生成图像,这一点有效。我不确定如何每分钟更新此图像。

如有任何帮助,我们将不胜感激!

最佳答案

我对您提供的样本进行了修改,使其每分钟生成一个自定义图像动态磁贴。

我已经在我的手机上测试过了,它似乎工作正常。您可能需要进行更多测试,例如内存使用测试,以确保它不会超过上限(也许可以将 planTill 减少到 30 分钟以在循环中生成更少的图 block ?)。

用户控件 xml 文件 SquareFrontTile1.xml

<Border Height="360" Width="360" Background="#00b2f0" xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' xmlns:mc='http://schemas.openxmlformats.org/markup-compatibility/2006'>
  <TextBlock Text="{0}" HorizontalAlignment="Left" VerticalAlignment="Top" Foreground="White" FontSize="50.667" />
</Border>

代码

public static async void UpdateAsync(BackgroundTaskDeferral deferral)
{
    TileUpdater tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication();
    IReadOnlyList<ScheduledTileNotification> plannedUpdated = tileUpdater.GetScheduledTileNotifications();

    string language = GlobalizationPreferences.Languages.First();
    CultureInfo cultureInfo = new CultureInfo(language);

    DateTime now = DateTime.Now;
    DateTime planTill = now.AddHours(1);

    DateTime updateTime = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0).AddMinutes(1);
    if (plannedUpdated.Count > 0)
        updateTime = plannedUpdated.Select(x => x.DeliveryTime.DateTime).Union(new[] { updateTime }).Max();

    StorageFolder folder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("Assets");
    StorageFile file = await folder.GetFileAsync("SquareFrontTile1.xml");
    string xml = await Windows.Storage.FileIO.ReadTextAsync(file);
    string startXml = string.Format(xml, now.ToString(cultureInfo.DateTimeFormat.ShortTimePattern));

    XmlDocument tileDocumentNow = await GetTileXmlDocument(startXml);

    TileNotification notification = new TileNotification(tileDocumentNow) { ExpirationTime = now.AddMinutes(1) };
    tileUpdater.Update(notification);

    for (var startPlanning = updateTime; startPlanning < planTill; startPlanning = startPlanning.AddMinutes(1))
    {
        Debug.WriteLine(startPlanning);
        Debug.WriteLine(planTill);

        try
        {
            string updateXml = string.Format(xml, startPlanning.ToString(cultureInfo.DateTimeFormat.ShortTimePattern));
            XmlDocument updatedTileDocument = await GetTileXmlDocument(updateXml);

            ScheduledTileNotification scheduledNotification = new ScheduledTileNotification(updatedTileDocument, new DateTimeOffset(startPlanning)) { ExpirationTime = startPlanning.AddMinutes(1) };
            tileUpdater.AddToSchedule(scheduledNotification);

            Debug.WriteLine("schedule for: " + startPlanning);
        }
        catch (Exception e)
        {
            Debug.WriteLine("exception: " + e.Message);
        }
    }

    deferral.Complete();
}

private static async Task<XmlDocument> GetTileXmlDocument(string xml)
{
    Border tileUIElement = XamlReader.Load(xml) as Border;
    string liveTileImageName = string.Format("UpdatedLiveTile_{0}.png", DateTime.Now.Ticks.ToString());

    if (tileUIElement != null)
    {
        RenderTargetBitmap rtb = new RenderTargetBitmap();
        await rtb.RenderAsync(tileUIElement, 150, 150);
        IBuffer pixels = await rtb.GetPixelsAsync();
        DataReader dReader = Windows.Storage.Streams.DataReader.FromBuffer(pixels);
        byte[] data = new byte[pixels.Length];
        dReader.ReadBytes(data);

        var outputFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.CreateFileAsync(liveTileImageName, Windows.Storage.CreationCollisionOption.ReplaceExisting);
        var outputStream = await outputFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
        BitmapEncoder enc = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, outputStream);
        enc.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied, 150, 150, 96, 96, data);
        await enc.FlushAsync();
    }

    var tileDocument = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150Image);
    var tileImageAttributes = tileDocument.GetElementsByTagName("image");
    XmlElement tmp = tileImageAttributes[0] as XmlElement;
    tmp.SetAttribute("src", liveTileImageName);
    return tileDocument;
}

关于windows-runtime - 如何在 Windows Phone 8.1 中每分钟更新一个自定义图像动态磁贴?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24467269/

相关文章:

asp.net - 无法加载文件或程序集 'System.Net.Http, Version=4.0.0.0'

xaml - WinRT 中的数据触发器?

javascript - 带有 Javascript 的 Windows 8 应用程序中的 Twitter/Facebook 授权

c# - Windows Phone - 裁剪位图图像

windows - 通过 Azure 通知中心使用注册 ID 发送推送通知

c++ - 您可以使用 C++/CX 编写普通的 Windows 应用程序吗?

c# - 如何为amchart饼图的切片着色?

javascript - "Windows Phone HTML5 App"和 "Javascript Windows Store Project"之间的区别

c# - 在 WP8.1 应用程序中使用转换的问题

c# - 播放内存流,避免在WP8.1应用中它们之间出现间隙