locked
SecondaryTile isn't updated correctly when notification queue is enabled

    Question

  • Hello,

    When a SecondaryTile receives notifications having the notification queue enabled it becomes a static tile that displays the first notification, instead of a live tile that switches between all the notifications in the queue. You can see what I mean with the following code:

    <Page
        x:Class="TileUpdaterQueue.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:TileUpdaterQueue"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                <Button Content="Pin first tile with notifications" Click="PinFirstTileWithNotifications" />
                <Button Content="Pin first tile" Click="PinFirstTile" />
                <Button Content="Send notifications to first tile" Click="ResendNotifications" />
                <Button Content="Pin second tile" Click="PinSecondTile" />
            </StackPanel>
        </Grid>
    </Page>
    using System;
    using System.Threading.Tasks;
    using Windows.Foundation;
    using Windows.UI.Notifications;
    using Windows.UI.StartScreen;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Media;
    
    namespace TileUpdaterQueue
    {
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
            }
    
            private async void PinFirstTile(object sender, Windows.UI.Xaml.RoutedEventArgs e)
            {
                await PinTile(sender, false);
            }
    
            private async void PinFirstTileWithNotifications(object sender, Windows.UI.Xaml.RoutedEventArgs e)
            {
                await PinTile(sender, true);
            }
    
            private static async Task PinTile(object sender, bool sendNotifications)
            {
                SecondaryTile secondaryTile = new SecondaryTile("livetiletest1", "Live tile", "1",
                    new Uri("ms-appx:///Assets/Logo.png"), TileSize.Default);
                secondaryTile.VisualElements.ShowNameOnSquare150x150Logo = true;
    
                bool isPinned = await secondaryTile.RequestCreateForSelectionAsync(GetElementRect((FrameworkElement)sender), Windows.UI.Popups.Placement.Above);
                if (isPinned && sendNotifications)
                {
                    SendNotifications();
                }
            }
    
            private void ResendNotifications(object sender, RoutedEventArgs e)
            {
                SendNotifications();
            }
    
            private static void SendNotifications()
            {
                string notification1XmlString = "<tile>"
                    + "<visual version='2'>"
                    + "<binding template='TileSquare150x150Text04' fallback='TileSquareText04'>"
                    + "<text id='1'>First notification</text>"
                    + "</binding>"
                    + "</visual>"
                    + "</tile>";
    
                Windows.Data.Xml.Dom.XmlDocument notification1DOM = new Windows.Data.Xml.Dom.XmlDocument();
                notification1DOM.LoadXml(notification1XmlString);
                TileNotification notification1 = new TileNotification(notification1DOM);
    
                string notification2XmlString = "<tile>"
                    + "<visual version='2'>"
                    + "<binding template='TileSquare150x150Text04' fallback='TileSquareText04'>"
                    + "<text id='1'>Second notification</text>"
                    + "</binding>"
                    + "</visual>"
                    + "</tile>";
    
                Windows.Data.Xml.Dom.XmlDocument notification2DOM = new Windows.Data.Xml.Dom.XmlDocument();
                notification2DOM.LoadXml(notification2XmlString);
                TileNotification notification2 = new TileNotification(notification2DOM);
    
                // Send the notification to the secondary tile by creating a secondary tile updater
                var updater = TileUpdateManager.CreateTileUpdaterForApplication("livetiletest1");
                updater.Clear();
                updater.EnableNotificationQueue(true);
                updater.Update(notification1);
                updater.Update(notification2);
            }
    
            private async void PinSecondTile(object sender, Windows.UI.Xaml.RoutedEventArgs e)
            {
                SecondaryTile secondaryTile = new SecondaryTile("livetiletest2", "Second tile", "2",
                    new Uri("ms-appx:///Assets/Logo.png"), TileSize.Default);
                secondaryTile.VisualElements.ShowNameOnSquare150x150Logo = true;
    
                bool isPinned = await secondaryTile.RequestCreateForSelectionAsync(GetElementRect((FrameworkElement)sender), Windows.UI.Popups.Placement.Above);
            }
    
            public static Rect GetElementRect(FrameworkElement element)
            {
                GeneralTransform buttonTransform = element.TransformToVisual(null);
                Point point = buttonTransform.TransformPoint(new Point());
                return new Rect(point, new Size(element.ActualWidth, element.ActualHeight));
            }
        }
    }

    If you pin the first tile with notifications, or pin it without notifications and then send the notifications, you get a static tile, if you then send the notifications again or pin the second tile the first tile becomes a live tile. It also turns into a live tile if instead of pinning the second tile from the sample app you pin anything else to the Start screen (doesn't matter if it's another SecondaryTile or one of the installed applications) or if the device is restarted or the user signs out and signs back in.

    In Windows 8 the SecondaryTile becomes a live tile right away when you do this. I've seen this behavior in both Windows 8.1 Preview and RTM, is this a bug or is it just the way notification queues work in Windows 8.1?


    Monday, September 23, 2013 2:46 PM

Answers

  • Hi Gabriel,

    I have opened a bug for tracking this issue with the appropriate team, and right now I cannot provide an ETA for the fix. In the meantime, you can continue to use a 'delayed' notification to avoid this race condition.

    Thanks,

    Prashant.


    Windows Store Developer Solutions #WSDevSol || Want more solutions? See our blog, http://aka.ms/t4vuvz

    Monday, September 30, 2013 10:32 PM
    Moderator

All replies

  • Unfortunately, I cannot reproduce the issue. I also tried modifying the sample mentioned here: http://code.msdn.microsoft.com/windowsapps/Secondary-Tiles-Sample-edf2a178 and changed SecondaryTileNotification.xaml.cs (Scenario 6) with the below code, but I can see the two notifications scroll between themselves.  Your code is very much similar to the SDK code, so the only possible reason I think you are seeing this is because of the following note here: http://msdn.microsoft.com/en-us/library/windows/apps/hh781199.aspx

    "Note  The amount of time each notification in the queue is displayed and the order in which they appear on the tile is based on several internal factors and cannot be controlled by applications."

    Can you reproduce this problem on multiple machines or just a single one?

            private void SendTileNotificationWithStringManipulation_Click(object sender, RoutedEventArgs e)
            {
                Button button = sender as Button;
                if (button != null)
                {
                    string tileXmlString = "<tile>"
                                         + "<visual version='2'>"
                                         + "<binding template='TileWide310x150Text04' fallback='TileWideText04'>"
                                         + "<text id='1'>Primary text 310*150</text>"
                                         + "</binding>"
                                         + "<binding template='TileSquare150x150Text04' fallback='TileSquareText04'>"
                                         + "<text id='1'>Primary text 150*150</text>"
                                         + "</binding>"
                                         + "</visual>"
                                         + "</tile>";
    
                    Windows.Data.Xml.Dom.XmlDocument tileDOM = new Windows.Data.Xml.Dom.XmlDocument();
                    tileDOM.LoadXml(tileXmlString);
                    TileNotification tile = new TileNotification(tileDOM);
    
    
                    string tileXmlString2 = "<tile>"
                                         + "<visual version='2'>"
                                         + "<binding template='TileWide310x150Text04' fallback='TileWideText04'>"
                                         + "<text id='1'>Secondary text 310*150</text>"
                                         + "</binding>"
                                         + "<binding template='TileSquare150x150Text04' fallback='TileSquareText04'>"
                                         + "<text id='1'>Secondary text 150*150</text>"
                                         + "</binding>"
                                         + "</visual>"
                                         + "</tile>";
    
                    Windows.Data.Xml.Dom.XmlDocument tileDOM2 = new Windows.Data.Xml.Dom.XmlDocument();
                    tileDOM2.LoadXml(tileXmlString2);
                    TileNotification tile2 = new TileNotification(tileDOM2);
    
                    // Send the notification to the secondary tile by creating a secondary tile updater
                    var updater = TileUpdateManager.CreateTileUpdaterForSecondaryTile(MainPage.dynamicTileId);
                    updater.Clear();
                    updater.EnableNotificationQueue(true);
                    
                    updater.Update(tile);
                    updater.Update(tile2);
    
                    rootPage.NotifyUser("Tile notification sent to " + MainPage.dynamicTileId, NotifyType.StatusMessage);
                }



    Windows Store Developer Solutions #WSDevSol || Want more solutions? See our blog, http://aka.ms/t4vuvz


    Tuesday, September 24, 2013 12:05 AM
    Moderator
  • Thanks for your help Prashant.

    For the sample I posted I took the code from that SecondaryTile sample, simplified it as much as possible and narrowed the issue down to the EnableNotificationQueue(true) call, if I comment that line the tile becomes a live tile as soon as it receives the notifications but it only displays one since the queue is disabled.

    I've tested it in Windows 8.1 Preview and RTM, both running on Hyper-V, I know this has happened on, at least, another machine because I found this issue after an user of my Windows 8 app contacted me asking if I knew why this was happening using the app in Windows 8.1 Preview. I'll install RTM in another machine I have to see if it happens there too.

    Unfortunately that note doesn't apply, I know it's a static tile not only because I don't see it switch between the different notifications but also because Windows tells me it's a static tile, when I pin the first tile and send the notifications to it this is what I have:

    As you can see the app bar isn't showing the option to turn off the live tile and the tile has the badge. But as soon as I pin the second tile, or do any of the other things I mentioned, I get this:

    The badge is gone, it switches between the notifications and the option to turn off the live tile is there.

    In case it helps in any way the machine where I'm using Hyper-V is running Windows 8 Pro x64 on an i5-3570 3.4Ghz with the MSI Z77A-G45 motherboard, Asus GTX 660Ti DirectCU II OC 3GB, G.Skill Ares DDR3 1600 PC3-12800 8GB 2x4GB CL9, 2 Seagate Barracuda 7200.14 1TB in Raid 0 and a WD Caviar Green 640GB SATA2. Also I have the virtual machines set up so they have 4GB of ram.


    Tuesday, September 24, 2013 8:54 AM
  • I just finished installing Windows 8.1 Pro x64 RTM on a laptop, I ran the sample I posted on it and saw the same behavior, the first tile is a static tile that displays one of the notifications and turns into a live tile as soon as you pin something else. It's a Compaq Presario C720ES with 2GB of RAM instead of the 1GB it came with.
    Tuesday, September 24, 2013 1:40 PM
  • Hi Gabriel,

    I understand your problem. Just to check if this is some sort of a race condition, can you check if adding a delay like the below helps? For example, you can delay the first update by 1 second and the second one by 2 seconds and check if it solves your problem. Can you test it and let me know? Based on your test we can move forward.

     

                // Send the notification to the secondary tile by creating a secondary tile updater
                var updater = TileUpdateManager.CreateTileUpdaterForApplication("livetiletest1");
                updater.Clear();
                updater.EnableNotificationQueue(true);
                ThreadPoolTimer.CreateTimer((source) =>
                {
                    updater.Update(notification1);
                }, TimeSpan.FromSeconds(1)); 
                ThreadPoolTimer.CreateTimer((source) => 
                {
                    updater.Update(notification2);
                }, TimeSpan.FromSeconds(2));

    Thanks,

    Prashant


    Windows Store Developer Solutions #WSDevSol || Want more solutions? See our blog, http://aka.ms/t4vuvz

    Wednesday, September 25, 2013 1:02 AM
    Moderator
  • Hello Prashant,

    The SecondaryTile is updated correctly when the notifications are delayed like that.

    Wednesday, September 25, 2013 9:02 AM
  • Hi Gabriel,

    I have opened a bug for tracking this issue with the appropriate team, and right now I cannot provide an ETA for the fix. In the meantime, you can continue to use a 'delayed' notification to avoid this race condition.

    Thanks,

    Prashant.


    Windows Store Developer Solutions #WSDevSol || Want more solutions? See our blog, http://aka.ms/t4vuvz

    Monday, September 30, 2013 10:32 PM
    Moderator