Using Tile Toolkit with Background Agents

Dec 23, 2011 at 6:12 AM

Hi There,

Great job with the tookit - I think it can go a long way to improving the ease of making beautify, consistent Live Tile apps for Windows Phone.

I am currently trying to use this with a scheduled background agent and am running into mixed results. It seems to work great in the emulator while debugging, however when I try to run it on a device the task dies when it gets to GetShellTileData()

System.NullReferenceException: NullReferenceException
   at Ree7.TileToolkit.CustomTile.SavePNGToIsolatedStorage()
   at Ree7.TileToolkit.CustomTile.GetShellTileData()
   at MyApp.Core.Common.TileFunctions.GenerateLiveTile(String title, UInt32 count, String backTitle, String backContent)
   at MyApp.Core.Common.TileFunctions.GenerateAccountTile(Login login)
   at MyApp.Core.Common.TileFunctions.<>c__DisplayClassd.<UpdateAccountTile>b__9()
   at System.Reflection.RuntimeMethodInfo.InternalInvoke(RuntimeMethodInfo rtmi, Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
   at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at System.Delegate.DynamicInvokeOne(Object[] args)
   at System.MulticastDelegate.DynamicInvokeImpl(Object[] args)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.Dispatch(DispatcherPriority priority)
   at System.Windows.Threading.Dispatcher.OnInvoke(Object context)
   at System.Windows.Hosting.CallbackCookie.Invoke(Object[] args)
   at System.Windows.RuntimeHost.ManagedHost.InvokeDelegate(IntPtr pHandle, Int32 nParamCount, ScriptParam[] pParams, ScriptParam& pResult)

I am invoking the method in the following manner:

using (var autoResetEvent = new AutoResetEvent(false))
{
    Deployment.Current.Dispatcher.BeginInvoke(() =>
    {
        var bitmapImage = new BitmapImage()
        {
            CreateOptions = BitmapCreateOptions.None,
            UriSource = new Uri("/TileIcon.png", UriKind.RelativeOrAbsolute)
        };

        var tileTemplate = new NativeCountTileTemplate()
        {
            Background = null,
            Icon = bitmapImage,
            Count = count.ToString(),
            AppName = title
        };

        var customTile = CustomTileFactory.GetTemplatedTile("DepartmentTile", tileTemplate, TileSize.Standard);

        StandardTileData tileData = null;
        try
        {
            tileData = customTile.GetShellTileData();
            tileData.BackTitle = backTitle;
            tileData.BackContent = backContent;
            tileData.BackBackgroundImage = new Uri(string.Empty, UriKind.Relative);
        }
        catch (Exception ex)
        {
            ErrorLogger.ReportException(ex, null);
        }
            
        shellTile.Update(tileData);
        autoResetEvent.Set();
    });

    autoResetEvent.WaitOne();
}

Any insight would be appreciated.

Adam

Dec 23, 2011 at 12:24 PM

Hi,

Just a quick update. The issue seems to be related to the specific memory restrictions of the periodic agent. Periodic agents are restricted to use only 6MB of memory and I believe that the ControlToPng.RenderAsPNGStream() method is exceeding this:

 

System.OutOfMemoryException: OutOfMemoryException
   at System.IO.MemoryStream.set_Capacity(Int32 value)
   at System.IO.MemoryStream.EnsureCapacity(Int32 value)
   at System.IO.MemoryStream.Write(Byte[] buffer, Int32 offset, Int32 count)
   at Ree7.Utils.Imaging.PngEncoder.WriteChunk(Stream stream, Byte[] type, Byte[] data)
   at Ree7.Utils.Imaging.PngEncoder.Encode(Byte[] data, Int32 width, Int32 height)
   at Ree7.Utils.Imaging.EditableImage.GetStream()
   at Ree7.Utils.Imaging.ControlToPng.RenderAsPNGStream(UIElement e)
   at Ree7.TileToolkit.CustomTile.RenderAsPNG()
   at Ree7.TileToolkit.CustomTile.SavePNGToIsolatedStorage()
   at Ree7.TileToolkit.CustomTile.GetShellTileData()
   at MyApp.Core.Common.TileFunctions.GenerateLiveTile(String tileName, String title, UInt32 count, String backTitle, String backContent)

 

Cheers,
Adam

Feb 2, 2012 at 11:16 PM

Don't know what you did nanabite, but I just managed to get a live tile on my device with the Ree7 Tile Toolkit

Feb 5, 2012 at 9:54 PM

Ok did some testing and indeed sometimes the generation will fail ( but not always ), resulting in an empty live tile on the pinned tile on the homescreen

Apr 17, 2012 at 2:05 PM

I'm also seeing ControlToPng.RenderAsPNGStream go over the memory limitations when run from a PeriodicTask.

I've experimented with swapping out the PNG code and using WriteableBitmap SaveJpeg.  Seems to stay under the memory limits, but has the disadvantage of no transparency. :(

Russ