简体   繁体   中英

Best way to render custom live tiles in the BackgroundTask (C#) with WP8.1 Universal app?

I'm in the process of re-writing my app to the Universal App model, optimized for Windows (Phone) 8.1.

I created my BackgroundTask (C#) that fetches some data from external sources, and the last step is to render a custom .PNG that can be used as a tile.

Previously, for Windows Phone 7.x and 8.0, I used a third party app called TCD.Controls.LiveTiles.Light that helps you converting XAML UserControls to .PNGs. This worked flawlessly, but it seems it have some compatibility issues with the Universal App model.

Now I was wondering - what is the best way to create .PNGs in the BackgroundTask?

I read about the C++ implementation of XamlRenderingBackgroundTask and RenderTargetBitmap but as I have not knowledge about C++, and my current task is already in C# I want to use C#.

Kind regards, Niels Laute

I was having the same problem but found this example of rendering a PNG in C#. I found this on https://social.msdn.microsoft.com/Forums/en-US/43295c90-43e8-4b08-8a25-958a1c3d0a0b/explanation-on-windowsuixamlmediaxamlrenderingbackgroundtask?forum=WindowsPhonePreviewSDK

using System;
using System.Threading.Tasks;
using Windows.ApplicationModel.Background;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Markup;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Windows.Graphics.Imaging;
using Windows.UI.Notifications;
using Windows.Data.Xml.Dom;

namespace BackgroundTask
{
    public sealed class AppTileUpdater : XamlRenderingBackgroundTask
    {
        protected override void OnRun(Windows.ApplicationModel.Background.IBackgroundTaskInstance taskInstance)
        {
            BackgroundTaskDeferral _deferral = taskInstance.GetDeferral();
            System.Diagnostics.Debug.WriteLine("OnRun called!");
            UpdateTileAsync(_deferral);
        }

        private async Task<string> ReadFile()
        {
            var folder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("Assets");
            var file = await folder.GetFileAsync("customTile.xml");
            string szCustomTileXML = await Windows.Storage.FileIO.ReadTextAsync(file);
            return szCustomTileXML;
        }
        private async void UpdateTileAsync(BackgroundTaskDeferral deferral)
        {

            var folder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("Assets");
            var file = await folder.GetFileAsync("customTile.xml");
            string szCustomTileXML = await Windows.Storage.FileIO.ReadTextAsync(file);

            Border tile = XamlReader.Load(szCustomTileXML) as Border;

            if (null != tile)
            {
                tile.Background = new SolidColorBrush(Windows.UI.Colors.Orange);
                Grid grid = tile.Child as Grid;
                TextBlock text = grid.FindName("Timestamp") as TextBlock;
                text.Text = DateTime.Now.ToString("hh:mm:ss");
                text = grid.FindName("TimeZone") as TextBlock;
                text.Text = TimeZoneInfo.Local.DisplayName;

                Image logo = grid.FindName("LogoImage") as Image;
                var img = new BitmapImage() { CreateOptions = BitmapCreateOptions.None };
                img.UriSource = new Uri("ms-appx:///Assets/acorn.png");

                RenderTargetBitmap rtb = new RenderTargetBitmap();
                await rtb.RenderAsync(tile, 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("UpdatedLiveTile.png", 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, (uint)rtb.PixelWidth, (uint)rtb.PixelHeight, 96,96, data);
                await enc.FlushAsync();                
            }
            var TileMgr = TileUpdateManager.CreateTileUpdaterForApplication();
            TileMgr.Clear();
            var tileTemplate = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150Image);
            var tileImageAttributes = tileTemplate.GetElementsByTagName("image");
            XmlElement tmp = tileImageAttributes[0] as XmlElement;
            tmp.SetAttribute("src", "UpdatedLiveTile.png");
            var notification = new TileNotification(tileTemplate);
            TileMgr.Update(notification);
            deferral.Complete();
        }

        public void Run(IBackgroundTaskInstance taskInstance)
        {
            System.Diagnostics.Debug.WriteLine("Run called!");
            OnRun(taskInstance);
        }
    }
}

Right now the most effective way is to use Win2D Framework and draw bitmap step by step. This approach will keep your resources free.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM