GeoFence and #WinRT API

For some reason I find myself doing some Windows Phone 8.1 development in Silverlight.. I know its a dead end and all the rest but I am working on a small app and Silverlight API was more mature at least for Windows Phone 8.1. One of the things I was adding was GeoFencing. GeoFencing was introduced to Windows Phone 8.1 WinRT API and some of it was exposed to Silverlight API (whoever made the decision on what APIs were available in WinRT and what in Silverlight needs to be shot.. at least made to feel real pain.

The way you set it up is you create GeoFence instances and add them.. System managed associated with your app. The app can access it from foreground or background.. nice right ? The constructor for GeoFence states that it requires IGeoshape along with an identifier at the very least.. IGeoshape is an enum which has possible values of Point, Circle, BoundingBox and Path. The constructor for GeoFence explicitly states now and again that the IGeoshape has to be a valid GeoCircle.. I know documentation can be wrong.. I mean why would you go through the hassle of create an Interface and passing it again if you enforce explicit type ?

I was wrong.. I tried it both the Silverlight and through WinRT API.. nope documentation is correct.. the API though designed well has shite implementation 😐 So what next ?

Well DIY. Here is my implementation.. Create a Rect instance with NorthWest X1, Y1 and SouthEast and X2 Y2 and monitor the change in geo position. Check if the new point is within Rect or not.. easy peasy.. well it works too.. Here is my implementation.

 

public class GeoMonitoringService
{
    Geolocator _locator = null;
    Dictionary<GeoSite, Rect> _locationRectangles = null;

    DataService _dataService = null;

    public event RoutedPropertyChangedEventHandler<GeomonitorStateChangedEventArgs> GeomonitorStateChanged;
    public bool lastState = false;

    public void Initialise(DataService dataService)
    {
        _locator = new Geolocator();
        _locator.DesiredAccuracy = PositionAccuracy.High;
        _locator.MovementThreshold = 1;
        _locator.ReportInterval = Convert.ToUInt32(TimeSpan.FromSeconds(5).TotalMilliseconds);

        this._locationRectangles = new Dictionary<GeoSite, Rect>();

        this._dataService = dataService;

        if (this._dataService?.SiteDictionary?.Count > 0)
        {
            foreach (var site in this._dataService.SiteDictionary.Values)
            {
                Rect r = new Rect(new Point(site.Latitude1, site.Longitude1), new Point(site.Latitude2, site.Longitude2));
                this._locationRectangles.Add(site, r);
            }
        }

        _locator.PositionChanged += GPSPositionChanged;
    }

    private void GPSPositionChanged(Geolocator sender, PositionChangedEventArgs args)
    {
        var geoPoint = args.Position.Coordinate.Point;
        Point p = new Point(geoPoint.Position.Latitude, geoPoint.Position.Longitude);

        KeyValuePair<GeoSite, Rect>? matchKVP = null;
        foreach (var entry in this._locationRectangles)
        {
            if (entry.Value.Contains(p))
            {
                matchKVP = entry;
                break;
            }
        }

        if (matchKVP.HasValue)
        {
            if (!lastState)
            {
                lastState = true;
                this.GeomonitorStateChanged?.Invoke(this, new RoutedPropertyChangedEventArgs<GeomonitorStateChangedEventArgs>(null, new GeomonitorStateChangedEventArgs(true, matchKVP.Value.Key)));
            }
        }
        else
        {
            if (lastState)
            {
                lastState = false;
                this.GeomonitorStateChanged?.Invoke(this, new RoutedPropertyChangedEventArgs<GeomonitorStateChangedEventArgs>(null, new GeomonitorStateChangedEventArgs(false, null)));
            }
        }
    }
}
Advertisement

WindowsPhone 8.1, NavigationBar and Silverlight apps #wpdev

With Windows Phone 8.1 Microsoft drastically changed on of the basic chassis requirements in Windows Phone since day 0. The hardware buttons at the bottom of the phone. There were many reasons and one of them was the ability to use same chassis for both Android and Windows Phone devices. This many cited was very important smaller OEMs that recently signed up to Windows Phone ecosystem.

WP7 resolutions:

  • 800 x 480

WP8 resolutions (and scaling factors as reported  by Silverlight apps):

  • 800 x 480     (1.0)
  • 1280 x 720   (1.5)
  • 1280 x 768   (1.6)
  • 1920 x 1080 (2.25)

For Silverlight Windows Phone app (most of the apps that is) the resolution defaults to 800 x 480. This fits nicely with Scaling factor 1.6 which was used by many early Nokia devices. The scaling factor 1.5 however gave 853 x 480. This primarily affected HTC 8 S/X devices and Samsung ATIV S devices only. Later when Lumia 1520 came out, it uses 1020 and that used 2.25 and that also had 853 x 480 res.

What this meant was that WP7 and any WP8 apps that fix their resolution would leave 53 px gap. With my 1Shot camera app, I have a complicated control structure and I ended up fixing many heights and widths.. Not only that I also move certain objects on OrientationChanged using specific values of TranslateX and TranslateY. Last week after a user complaint, I added code to detect 720p and 1080p resolutions and to stretch those by additional 53px. However I never tested this on newer 720p devices that no longer have hardware buttons.

What Windows Phone Dev team did was added another system control like ApplicationBar called NavigationBar. Unlike ApplicationBar, NavigationBar isn’t accessible from within application. Playing with emulator set to show NavigationBar did not show any change in size reported by

double width = Application.Current.Host.Content.ActualWidth;
double height = Application.Current.Host.Content.ActualHeight;

After much complaining around twitter I came across windows phone 8.1 hide NavigationBar post on MSDN Forums. One of the suggestions was using PhoneApplicationFrame.FullScreen. Setting it to true or false made no difference.. none at all. After another round of complains, I came across this post Layout and the Windows Phone navigation bar.. it suggest that SizeChanged event should take care of it and ActualWidth and ActualHeight properties will sort it out.

Being not particularly clever, I thought that Page’s SizeChanged would be fired.. sure it was firing but ActualWidth and ActualHeight were 0.0. Width and Height were NaN so that was useless. Thinking that I could do better than that, I tried using SizeChanged exposed by Application.Current.Host.Content.. nope no difference.. it wasn’t a particularly bright idea.. Yesterday I spent time deliberating whether I should use hardcoded lists to indicate NavigationBar availability or not.. I already do so for high resolution sensors.. nah too much hassle

So today I said.. surely there must be something… on SizeChanged event handler of page, I scanned App.RootFrame.. I found something.. a private field called _visibleRegion correctly showed that 53 px at the botton were not available on 720p emulator when NavigationBar was visible. I think I am clever than most…

private Thickness GetMargin()
{
    Thickness t = new Thickness();

    var field = App.RootFrame.GetType().GetField("_visibleRegion", BindingFlags.Instance | BindingFlags.NonPublic);

    if (field != null)
    {
        object visibleRegion = field.GetValue(App.RootFrame);

        if (visibleRegion != null && visibleRegion is Thickness)
        {
            t = (Thickness)visibleRegion;
        }
    }

    return t;
}

This would get me the right margin and I could just just correct a few bits and bingo.. hahah yah right.. FieldAccessExpcetion eat that you clever git.. Apps don’t run under full trust on phone and I couldn’t reflect to this level. Sigh.. This was hard.. why had Windows Phone team gone way out of their way to piss developers off ?? Having almost lost all hope, I thought, let me try subscribe to Page’s LayoutRoot grid’s SizeChanged event… had a look there.. event handler exposed NewValue and they showed the correct values!!! yay

double gridWidth = e.NewSize.Width > e.NewSize.Height ? e.NewSize.Width : e.NewSize.Height;
double gridHeight = e.NewSize.Width > e.NewSize.Height ? e.NewSize.Height : e.NewSize.Width;

double w = Application.Current.Host.Content.ActualWidth;
double h = Application.Current.Host.Content.ActualHeight;
double hostWidth = w > h ? w : h;
double hostHeight = w > h ? h : w;

bool hasSoftButtons = hostWidth > gridWidth;

Just for your sanity.. I always want Landscape mode so width is always greater than height based on supported resolutions.. so there you have it.. subscribe to LayoutRoot’s SizeChanged and get the right size.. OnResize, the dimensions reflect 800 x 480 resolution and not 853 x 480.

Finally!

WinRT License API, Silverlight 8.1 apps and sideload detection #wpdev

Since early 2011, I have been using the method described here.
Recently I have been upgrading all my apps to target Windows Phone 8.1 API. Most of previous API is still accessible in WP 8.1 SL8.1 apps. However a great deal more is available under WinRT API.

With my Alarm Clock app, I have started using WinRT API to pin and update Tiles. I have used WinRT API for background tasks as I can run them more frequently and I can detect Timezone change. I have added IAP to the app.
The app however is available in 2 flavours Free (with ads and restrictions) and Paid. So far I have only been updating the paid app. Of course I use sideload detection for Paid app however while considering update of Free version, I decided to use CurrenApp to execute License check and potentially offer to convert Free users in-place as opposed to getting them to buy another app!!

In good old SL API, I would have used

var license = new Microsoft.Phone.Marketplace.LicenseInformation();
IsTrial = license.IsTrial();

With WinRT that becomes

IsTrial = CurrentApp.LicenseInformation.IsTrial;

While developing and deploying if you observe the behaviour, the IsTrial never returns false. You cannot test Trial scenario without explicit pre-processor directives!
Of course CurrentAppSimulator is only available for WinRT app and not SL8.1 apps. The same behaviour would be exposed by the sideloaded apps. Not downloaded from store equates to full version. Like in good old days, WMAppPRHeader.xml is still attached after certification. So lets modify the code

try
{
   XDocument doc = XDocument.Load("WMAppPRHeader.xml");
 
   IsTrial = CurrentApp.LicenseInformation.IsTrial;
}
catch
{
   IsTrial = true;
}

You treat all apps without WMAppPRHeader.xml as trial. Job done!
Note that IAP are not affected. If you had TestIAP, it is not active by default.

CurrentApp.LicenseInformation.ProductLicenses[&amp;quot;TestIAP&amp;quot;].IsActive;

Happy coding!

DLL / Reference hell with #WP8 #SL81 and #WinRT component

Over the last month, I have gone back to “AlarmClock” app (my 3rd Windows Phone app from back in 2011). I have updated it to render time updates on live tile. In fact I am quite proud the mechanism I use. I additionally provided 50 downloadable font packs that users can choose from (purchasable in a set of 10).

Original solution
The update mechanism was initially based on Silverlight Background Task. The tile update mechanism of course updates tile based on local time. However a user reported that when travelling between timezones, the tiles kept showing previous timezone times until the next background task run started pushing new ones based on new local time.

I deliberated on this and came to the conclusion that somewhere something was fishy.. its possible that Tile updates are actually scheduled on UTC as opposed to local time or maybe I just don’t understand it. Either way, I had to fix this issue

Solution 2: Fix for Timezone change
The new windows phone 8.1 introduced a bunch of new WinRT API that included API for Background task including those that run on Timezone change. So I dumped SL based Background Task and went full stream with WinRT component. Added 2 WinRT classs on for Timer and another for Timezone and this worked great.

Another user wanted the clock and tile updates to support multiple Timezones – wanted to pin Hong Kong and Seattle. My app so far only supported local device timezone.

Soluion 3 – Multiple Timezone support

.NET 4.5 comes with TimeZoneInfo class.This provides a nice method GetSystemTimeZones which lists all timezones and make it possible to convert between those. However Windows Phone .NET Runtime does not come with this and there is not suitable WinRT API either. Yay!!
Oren Novotny created a good Win32 wrapper which works on both WP8, WP81, SL81 and WinRT
I fired up Nuget Package Manager and searched for timezone..found Timezone conversion between WinRT and PCL.. Added a reference to the App and reworked it to support user selectable timezone etc. This required me to select target between x86 and ARM – any CPU no longer an option.

Next step?? Add Timezone helper reference to WinRT component. Bang bang bang.. nugget sorted it all out.. that was easy.. modified the background processor to update all tiles with correct timezone times!! nice 🙂 What could possibly go wrong ?

Hit F6, (Old school.. modified VS 2013 to build o F6 like before).. all good. Hit F5… wait for it !!!!

Runtime exception – File not found System.Runtime.InteropService.. quick search showed reference conflict..

Step 1) Set WinRT component to x86 instead of Any CPU.. maybe that will do the trick!!!

Nope far from it… Result System.BadImageFormatException thown when trying to run the app.

Step 2) Download code and make a part of existing WinRT component..

Nope still the same error(s)

While deliberating, realised that I called code from Background Task directly from my app.. 3rd trial

Step 3)

Remove calls to code in Background Task from App
Nuget Reference to App
Code within WinRT component for internal use
App – x86 / ARM target
WinRT component – Any CPU tagt

Bingo.. It all work as advertised!!

Took me day to figure try out various options

WinRT and pointer manipulation #win8dev #winrtdev

We all know how Windows 8 introduced touch as a first class member in user input. If you have used Windows 8 it feels intuitive to touch.. hell I used to touch my non-touch laptop occasionally and not because I wanted to fondle it 🙂

Rewinding a bit.. in Silverlight and Windows Phone, we had a nice historic Touch.FrameReported event. This was the fastest way to detect pointer / touch interaction on the screen. It also supported multi-touch detection by means of exposing TouchFrameEventArges.GetTouchPoints.

We also know how famously .NET components were sliced and diced (lets leave it for some other time when I have had a drink or two). So its only natural that WinRT 1.0 native XAML didn’t have Touch.FrameReported.

The other high level mechanism for touch event detection was the set of manipulation events
* UIElement.ManipulationStarted
* UIElement.ManipulationDelta and
* UIElement.ManipulationCompleted

These made it to WinRT 1.0 XAML.. However there were changes. Now it comes armed with ManipulationMode.

The MEME RTFM definitely applies to me – I never read the manual… When we had proper MSDN lib for documentation it was all good.. now documentation is all over the place.. (Damn it… need to focus more… another thing to talk over a drink).

So what happened.. why trying to detect touch / pointer events, I started using Manipulation events but hell no.. the event’s just wouldn’t get called.. The mode has tons of options but to handle it yourself you need to set the ManipulationMode to All. Someone remind me something.. If I declare a bleeding event handler.. isn’t my intention already pretty clear ? (Something every logical from .NET lost in translation on its way to WinRT design).

So eventually I got that to work by setting ManipulationMode to All. Surprise surprise, the manipulation event args only expose a few things like Position and PointerType…So this definitely can’t do multi-touch.. sure it will detect all the touch inputs but it can’t tell the difference the two fingers!!

Time to give it the middle one and start looking at alternatives. Previously in WPF / Silverlight we had Mice events
* UIElement.MouseLeftButtonDown
* UIElement.MouseLeftButtonUp
* UIElement.MouseMove

Those didn’t directly made it. WinRT merged Mice and Touch events into Pointer events. So now we have
* UIElement.PointerPressed
* UIElement.PointerReleased
* UIElement.PointerMoved

The PointerRoutedEventArgs that are passed to the event handers not only give you current position and intermediate positions, they also give you access to Pointer associated with the event. Each touch point / mice button gets a unique id. This way you can detect activity of each touch points over the screen.

The post is very verbose and lot of gibberish.. let me throw some code snippet to lighten it up 🙂

private void LayoutRoot_PointerMoved(object sender, PointerRoutedEventArgs e)
{
    Point position2 = e.GetCurrentPoint(this.LayoutRoot).Position;
    Pointer pointer2 = e.Pointer;
    FreeSketch(position2, pointer2);
}

private void FreeSketch(Point position2, Pointer pointer2)
{
    if (bDraw && pointer1.PointerId == pointer2.PointerId)
    {
        Line l = new Line()
        {
            X1 = position1.X,
            Y1 = position1.Y,
            X2 = position2.X,
            Y2 = position2.Y,
            StrokeThickness = 5,
            Stroke = new SolidColorBrush(Colors.Blue),
            Fill = new SolidColorBrush(Colors.Blue)
        };
        this.LayoutRoot.Children.Add(l); // adding to canvas
        this.position1 = position2;
    }
}

Happy coding

Super Duper All in one VisibilityConverter for #wpdev

On the 4th of July I blogged about simple visibility converters to toggle visibility. Of course I used two converters then.. one Visibility and another inverse aka Invisibility.

I also said that some clever people might tell me that its possible to do both in a single converter. Whilst that is true, no one did so apparently no one really reads or cares 😐 Coding4Fun toolkit has a converter than exposes Inverted property but my idea was to be able to use the same converter by pass a parameter.

So here’s what I did

 

public class VisibilityConverter : IValueConverter
{
    public enum Mode
    {
        Default,
        Inverted,
    }

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Visibility returnVisibility = Visibility.Visible;
        Mode mode = Mode.Default;
        try
        {
            if(parameter != null)
                mode = (Mode)Enum.Parse(typeof(Mode), (string)parameter, true);
        }
        catch 
        {
            mode = Mode.Default;
        }

        if (value == null)
        {
            returnVisibility = Visibility.Collapsed;
        }
        else if(value is bool)
        {
            bool bVal = (bool)value;
            if (!bVal)
                returnVisibility = Visibility.Collapsed;
        }
        else if (value is string)
        {
            string itemVal = value as String;

            if (String.IsNullOrWhiteSpace(itemVal))
                returnVisibility = Visibility.Collapsed;
        }
        else if (value is IList)
        {
            IList objectList = value as IList;
            if (objectList == null || objectList.Count == 0)
                returnVisibility = Visibility.Collapsed;    
        }

        if (mode == Mode.Inverted)
            return returnVisibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
        else
            return returnVisibility;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

and how do I use it ? well this is how

<TextBlock Text="{Binding Review}" Visibility="{Binding Review, Converter={StaticResource VisibilityConverter}}" TextWrapping="Wrap" Style="{StaticResource PhoneTextNormalStyle}" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2"/>
<TextBlock Text="(rating only)" Visibility="{Binding Review, Converter={StaticResource VisibilityConverter}, ConverterParameter=Inverted}" Foreground="{StaticResource PhoneSubtleBrush}" TextWrapping="Wrap" Style="{StaticResource PhoneTextNormalStyle}" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2"/>

I could pass Default parameter or just leave it out and it defaults to normal behaviour. If I however pass Inverted parameter to the converter, it inverts the behaviour. Bingo.

Now waiting for the next clever people to tell me that I am using parameter designed for something else 🙂

LongListSelector and scroll to top #wpdev

I pulled out my Marauder’s Map, tapped my wand and said “I solemnly swear I’m up to no good”. Bang Visual Studio opens up and I am back to playing with Cineworld app. I know a few users hate my ever so frequent updates but I use the app and I need change 🙂

so I recently got to putting a DatePicker and LongListSelector for being able to “Show by date” film listings. It all worked – well mostly worked until I realised that LongListSelector was scrolled all the way to the bottom. I wonder why..

Of course there is no SelectedIndex I could magically set so did a quick search on the net.. StackOverflow usually has all the answers to “the life, the universe and everything else” but it didn’t really have one for this question.

There was a note saying use UpdateLayout and then ScrollTo and setting it to ItemSource’s first child did the trick for WP8 but not for WP7.

var dataLetter = cd.GetGroupForDate(userSelection); // get the grouped list of films

FilmsForSelectedDate.Clear(); // clear the bound observable collection

foreach (var entry in dataLetter)
    FilmsForSelectedDate.Add(entry);

lstShowByDate.UpdateLayout(); // call updatelayout

if (FilmsForSelectedDate.Count != 0)
    lstShowByDate.ScrollTo(FilmsForSelectedDate[0]); // set scroll to first group in the list

The problem I realised was that the first group in the LLS had zero items i.e. it was not being shown. This affected WP7 toolkit LongListSelector but not the native WP8 LongListSelector

var dataLetter = cd.GetGroupForDate(userSelection);

FilmsForSelectedDate.Clear();

foreach (var entry in dataLetter)
    FilmsForSelectedDate.Add(entry);

lstShowByDate.UpdateLayout();

if (FilmsForSelectedDate.Count != 0)
    lstShowByDate.ScrollTo(FilmsForSelectedDate.First(g => g.HasItems));

So the solution as shown above is, find the group that has items and set scroll to that element.

Mischief managed!

Converter to toggle visibility when content is empty #wpdev #wp8dev #wp7dev #win8dev

Recently Gustavo Guerra posted a question on StackOverflow.com stating that behaviour of TextBlock was different on Windows Phone 7 and Windows Phone 8. If the Text is empty, WP7 renders TextBlock with Height set to 0. On WP8, it occupies full height.

I replied back stating that he should consider using a Converter for the same. Of course I had a similar issue with Cineworld app. The screenshot shows ratings & review screen I implemented – its almost a copy of Windows Phone Store ratings & review.
wp_ss_20130704_0002[1]

what I noticed was that if user chose to not review it, the textbox would be fully render. So I did what I suggested Gustavo do. Created two converters – StringLengthInvisibilityConverter and StringLengthVisibilityConverter. Almost identical but doing the opposite thing.

 

public class StringLengthInvisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string itemVal = value as String;
        if (String.IsNullOrWhiteSpace(itemVal))
            return Visibility.Collapsed;
        else
            return Visibility.Visible;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

public class StringLengthVisibilityConverter : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string itemVal = value as String;
        if (String.IsNullOrWhiteSpace(itemVal))
            return Visibility.Visible;
        else
            return Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
<TextBlock Text="{Binding Review}" Visibility="{Binding Review, Converter={StaticResource InvisibilityConverter}}" TextWrapping="Wrap" Style="{StaticResource PhoneTextNormalStyle}" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2"/>
<TextBlock Text="(rating only)" Visibility="{Binding Review, Converter={StaticResource VisibilityConverter}}" Foreground="{StaticResource PhoneSubtleBrush}" TextWrapping="Wrap" Style="{StaticResource PhoneTextNormalStyle}" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2"/>

 

Now I know one of you clever person is going to tell me I could have just used one 😛 Let me tell you this:

  1. I thought of it
  2. I could have searched around
  3. Realised no one really cares
  4. Created two converters and got the job done 🙂
  5. Submitted update and nap time

.

FlipTile, CycleTile and various iterations of #wpdev sdks

As you might have realised, the last few weeks, cineworld app has been my obsession. I started work on WP8 port and then back-ported some changes to WP7 version of the app (its the only one that’s live at the moment so makes sense). So what did I do so far on it (WP7 version) ?

1) Moved to using 50% space when displaying film posters, moved film little on top of the posters, removed the button style that caused me many xaml exceptions on WP8
2) Moved to using good quality images only for ImageTile control.
3) Added background task to download data files and to set Tile images

This is live as we speak and a few people emailed me saying it looks great. Now I am not going to create yet another background task for WP8 version (since I wanted to use Cycle Tile Template for WP8 version of the app.
Microsoft’s own tile related pages show how to support newer tiles for WP7.8 and WP8 even though the app itself is built on WP 7.1 (Mango) sdk

So far I stayed away from temptation of managing image repository on the device. you can see that it gets messy eventually and you have to clean up and what not.. however after implementing basic solution, it started throwing exceptions.. files used for tiles cannot be remote. Bugger.. more work

Step 1): Download image files locally. I have been using AsyncWebClient (Custom wrapper with TaskCompletionSource) exposing awaitable DownloadFile method. Plug that in and download all the files. Its background tasks, I am not really fussed about parallel execution.. just manageable execution (read sync like)

Step 2): For Uri array using relative path and ??? still nothing. More work, a quick search about the net found me a couple of posts for “live tile isolated storage image WP7” File Path in Isolated File Storage is the one that I first opened and a quick scan reminded me of “isostore” based Uri

Step 3): Save all the images to Shell\SharedContent and switch all Uri to use isotore:/Shell/SharedContent/Filename.jpg

The code below will help you create live tiles with new tile templates from WP7.1 (Mango) sdk based project. I will be using the same code for WP8 in coming days since its the same background task

A word to the wise:
* You cannot determine if the template used by Tile is Standard or a new one.
* What I now do is Create a CycleTileData template when user wants to pin (if WP7.8 or WP8) else StandardTileData
* When iterating tiles, I try CycleTileData template and failing that try StandardTileData for update

Code snippets that might help:

Add AppExtra above App element in WMAppManifest.xml file (works for both WP7.8 and WP8)

<AppExtra xmlns="" AppPlatformVersion="8.0">
  <Extra Name="Tiles"/>
</AppExtra>
public async Task DownloadFileAsync(string url, string filename, string folder = null)
{
    // create a web client for downloading the string
    var wc = new WebClient();

    try
    {
        IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();

        string file = (folder == null ? filename : String.Format("{0}/{1}", folder, filename));
                
        using (Stream s = await wc.OpenReadTaskAsync(url))
        {
            using (Stream slocal = isf.OpenFile(file, FileMode.Create))
            {
                s.CopyTo(slocal);
            }
        }
    }
    catch (Exception ex)
    {
        if (1 == 1) // just to check exceptions during debugging. do whatever pleases you
        {
        }
    }
}

//works for both WP7.8 and WP8
private static Version TargetedVersion = new Version(7, 10, 8858);
public static bool IsTargetedVersion { get { return Environment.OSVersion.Version >= TargetedVersion; } }

private static void SetTileBackground(string[] filesToShow, string folder, Random random, ShellTile currentTile)
{
    bool tryFlip = false;

    if (Config.IsTargetedVersion)
    {
        try
        {
            Uri smallimage = new Uri("Images/CycleSmall.png", UriKind.Relative);
            Uri mediumimage = new Uri("Images/CycleMedium.png", UriKind.Relative);

            UpdateCycleTile(smallimage, mediumimage, folder, filesToShow, random, currentTile);
        }
        catch
        {
            tryFlip = true;
        }
    }
    else
        tryFlip = true;
            
    if(tryFlip)
    {
        int rand = random.Next(0, filesToShow.Length);

        StandardTileData NewTileData = new StandardTileData
        {
            BackBackgroundImage = new Uri(String.Format("isostore:{0}/{1}", folder, filesToShow[rand]), UriKind.Absolute)
        };

        currentTile.Update(NewTileData);
    }
}

public static void UpdateCycleTile(
    Uri smallBackgroundImage, Uri backgroundImage,
    string folder, string[] filesToShow, Random random, ShellTile currentTile)
{
    // Get the new cycleTileData type.
    Type cycleTileDataType = Type.GetType("Microsoft.Phone.Shell.CycleTileData, Microsoft.Phone");

    // Get the ShellTile type so we can call the new version of "Update" that takes the new Tile templates.
    Type shellTileType = Type.GetType("Microsoft.Phone.Shell.ShellTile, Microsoft.Phone");

    // Get the constructor for the new FlipTileData class and assign it to our variable to hold the Tile properties.
    var UpdateTileData = cycleTileDataType.GetConstructor(new Type[] { }).Invoke(null);

    // Set the properties. 
    SetProperty(UpdateTileData, "SmallBackgroundImage", smallBackgroundImage);

    Uri[] mediumImages = new Uri[9];

    mediumImages[0] = backgroundImage;
    for (int i = 1; i < 9; i++)
    {
        int rand = random.Next(filesToShow.Length);

        mediumImages[i] = new Uri(String.Format("isostore:{0}/{1}", folder, filesToShow[rand]), UriKind.Absolute);
    }

    SetProperty(UpdateTileData, "CycleImages", mediumImages);

    SetProperty(UpdateTileData, "Title", "my cineworld");
            
    // Invoke the new version of ShellTile.Update.
    shellTileType.GetMethod("Update").Invoke(currentTile, new Object[] { UpdateTileData });
}

private static void SetProperty(object instance, string name, object value)
{
    var setMethod = instance.GetType().GetProperty(name).GetSetMethod();
    setMethod.Invoke(instance, new object[] { value });
}

This by no means is fine / perfect code. Please treat it as a PoC and do whatever you do normally

Geolocator and MovementThreshold #wpdev #win8dev

Last few months, I have had too much on my plate. Been doing lot to Windows 8 and Phone development. Surprisingly Microsoft UK is keeping tabs on phone developers who aren’t adapting to #WP8 and seemingly, I was invited to a dev event targeting the likes of me 😛

Sure I am going and in anticipation of the event, I decided to port Cineworld app to WP8. Its been a challenging task. Reworking a few bits of LongListSelector, Visual Studio / Blend disliking all the xaml and of course a button style causing xaml exception. If that wasn’t enough:

Having used Geolocator in Windows 8 app, I decided to use the same for WP8 as its usually a lot faster than GeoCoordinateWatcher. I moved the code to be more like Win8 and noticed that the location detection was flaky at best. Now I did the stupid thing and like in WP7 version, I decided to set both DesiredAccuracy to High and MovementThreshold to 0 thinking absolutely nothing.

Of course that didn’t help it, it made matters worse, instead of flaky behaviour, it decided to call it quits.

var pos = await locator.GetGeopositionAsync(TimeSpan.FromMinutes(5), TimeSpan.FromSeconds(2));

instead of timing out, it started to hang. In desperation, I started looking at other events exposed by this class and tried hooking into StatusChanged event. Now things were bad, I noticed that it was getting operation aborted exception and decided that something was seriously wrong and that I should take a nap instead 🙂

Of course the problem was still there when I woke up the next day 😛 its only later that I decided to search on Geolocation and operation aborted and realised that I wasn’t the only one and it was all my fault – causality of me setting the MovementThreshold to 0. I set it to 10 instead and bingo.. it all works.

While I didn’t find it, I hope this post helps people like an earlier post helped me.