【问题标题】:How to update a custom image Live Tile every minute in Windows Phone 8.1?如何在 Windows Phone 8.1 中每分钟更新自定义图像动态磁贴?
【发布时间】:2015-01-19 00:09:09
【问题描述】:

有很多 Windows Phone 8.1 应用程序(例如时钟集线器、模拟时钟磁贴等)允许您在主屏幕上固定模拟时钟。

我正在尝试按照sample 做同样的事情,它向我展示了如何每分钟更新一个 XML 文档。

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

我尝试使用XamlRenderingBackgroundTaskRenderTargetBitmap 来生成图像,这个位有效。我不确定如何每分钟更新此图像。

任何帮助将不胜感激!

【问题讨论】:

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


    【解决方案1】:

    我提取了您提供的示例并对其进行了修改,以每分钟生成一个自定义图像动态磁贴。

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

    UserControl 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;
    }
    

    【讨论】:

    • 嗨,你有你创建的项目供下载吗?
    • 你有这个项目可以用来修改应用吗?
    • 那是不久前的事了,我现在没有了。但是上面的代码还不够吗?
    【解决方案2】:

    我不会完全回答这个问题,因为我自己目前正在努力让它发挥作用。但是,我会为您指明正确的方向。我过去在 Windows 8 上做过这个。

    您需要做的是创建磁贴更新器并每隔一段时间安排一次磁贴更新。在这种情况下,每分钟更新一次。选择的图块架构可以是图像或文本或两者的组合。

    您可以在此处找到 TileSchema 目录 http://msdn.microsoft.com/en-us/library/windows/apps/hh761491.aspx

    这里有 Tile Schema 的详细信息 http://msdn.microsoft.com/en-us/library/windows/apps/br212859.aspx

    这是一个 Windows 8 示例 http://code.msdn.microsoft.com/windowsapps/scheduled-notifications-da477093

    这是我的代码中的一个 sn-p,到目前为止它不能正常工作.. tile 是空白的

    TileUpdater updater = TileUpdateManager.CreateTileUpdaterForApplication();
    XmlDocument document = new XmlDocument();
    document.LoadXml(str2);
    ScheduledTileNotification notification2 = new ScheduledTileNotification(document, new DateTimeOffset(time4));
    notification2.ExpirationTime = (new DateTimeOffset?((DateTimeOffset)time4.AddMinutes(1.0)));
    ScheduledTileNotification notification = notification2;
    updater.AddToSchedule(notification);
    

    完成后,我会写一篇博文并在此处添加链接

    我创建了一个尝试从示例应用程序(不是后台任务)中执行此操作的重现项目。 http://1drv.ms/1nai8nn

    【讨论】:

    • 我打算使用内容图像而不是 iso 商店中的图像.. 让我们看看它现在是否有效.. 图像太多了
    • 祝你好运!我其实也想过同样的事情。但是在我的情况下,我还需要以数字格式显示时间,那将是太多图像无法存储...
    • 我在做完全相同的事情 24 x 60 图像
    • 哦,别忘了方形和宽瓷砖
    • @Jessica 和 Hermit - 所以你们都在制作时钟应用程序? :P 这基本上是杰西卡问题的答案。这就是每分钟更新磁贴的方式。隐士,我猜xml不正确?您是否尝试过使用NotificationsExtensions 库?如果您分享更多代码,我可能会告诉您问题所在。
    【解决方案3】:

    我将示例工作添加到 Windows Phone Silverlight 8.1。您必须在 WMAppManifest.xml 中将 Notification Services 从 MPN 更改为 WNS,并在 Package.appxmanifest(声明选项卡)中添加后台任务、勾选系统事件、计时器。

    @Justin XL:你的代码对我不起作用,出现错误

    Border tileUIElement = XamlReader.Load(xml) as Border;

    错误:应用程序调用了一个为不同线程编组的接口。

    【讨论】:

    • 这并不是这个特定问题的真正答案。我想我的答案对你不起作用的原因是因为你没有使用 XamlRenderingBackgroundTask。尝试用它替换您的 IBackgroundTask。
    • 是的,它成功了。但建议在后台任务中使用 C++ 而不是 C# 来渲染 Xaml。
    • 没错,将C#代码转换成C++应该不难。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-19
    • 1970-01-01
    相关资源
    最近更新 更多