Two Google Maps Tips

Google Map

Centre a map on a collection of pins

The basic way to centre a Google Map is to give it co-ordinates of where you want the map to centre. But what if you have a collection of pin/markers and you want to show all of them but don’t know beforehand where they will be.

The solution is to create a LatLngBounds object and for each of your pins call the extend method of your bounds object. Once this is done call fitBounds on your map.

var bounds = new google.maps.LatLngBounds();

$.each(mapMarkers(), function(index, value) {
    bounds.extend(value.marker.position);
});

map.fitBounds(bounds);

 

Loading a map in a hidden div

The reason for doing this could be that you have a set of tabs and a non-visible one contains the Google Map. If you instantiate a Google Map when it isn’t visible you end up with the smallest map size possible.

One popular solution for this is to only create the map when the tab is being displayed, which is a good option as it means the map is only loaded when it’s viewed. However if your using something like Knockout to bind you’ve views to a model it may not be possible to attach an event to the tab change.

Google Maps actually have an event handler for just this scenario called resize. You simply need to trigger it at the point in which you can size the map.

google.maps.event.trigger(map, 'resize')
Advertisements

Integrating with the Windows Phone 8 Media Hub

Windows Phone Music and Video Hub

One of my favourite features of Windows Phone is the ability for apps to integrate with the different hubs on the phone. The Music and Video hub lets developers do this not only by having their app listed in the apps section, but also by feeding data to the new and history lists plus the currently playing tile.

To add a track to the history list have a look at the following code:

MediaHistoryItem mediaHistoryItem = new MediaHistoryItem();
mediaHistoryItem.ImageStream = image;
mediaHistoryItem.Source = "";
mediaHistoryItem.Title = "Track Title";
mediaHistoryItem.PlayerContext["playSong"] = "Track Identifier";
MediaHistory mediaHistory = MediaHistory.Instance;

mediaHistory.WriteRecentPlay(mediaHistoryItem);

To add a track to the new list is relatively similar:

MediaHistoryItem mediaHistoryItem = new MediaHistoryItem();
mediaHistoryItem.ImageStream = image;
mediaHistoryItem.Source = "";
mediaHistoryItem.Title = "Track Title";
mediaHistoryItem.PlayerContext["playSong"] = "Track Identifier";
MediaHistory mediaHistory = MediaHistory.Instance;

mediaHistory.WriteAcquiredItem(mediaHistoryItem);

Some things to note though; Your image must be 173 x 173px, a title must be given that describes what is playing (not just the name of your app) and the keyString property should be populated with an identifier that you can use to identify the track.
When a user presses the tile in either of the new or history lists it will trigger your app to be opened. In the OnNavigatedTo even you can query the QueryString from the NavigationContext to find the identifier for the song selected by the user.

bool _historyItemLaunch = false;            // Indicates whether the app was launched from a MediaHistoryItem.
const String _playSongKey = "playSong";    // Key for MediaHistoryItem key-value pair.
Song _playingSong = null;                   // The song to play.

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    MediaLibrary library = new MediaLibrary();

    if (NavigationContext.QueryString.ContainsKey(_playSongKey))
    {
        // We were launched from a history item.
        // Change _playingSong even if something was already playing 
        // because the user directly chose a song history item.

        // Use the navigation context to find the song by name.
        String songToPlay = NavigationContext.QueryString[_playSongKey];

        foreach (Song song in library.Songs)
        {
            if (0 == String.Compare(songToPlay, song.Name))
            {
                _playingSong = song;
                break;
            }
        }

        // Set a flag to indicate that we were started from a 
        // history item and that we should immediately start 
        // playing the song after the UI has finished loading.
        _historyItemLaunch = true;
    }
}

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
    if (_historyItemLaunch)
    {
        // We were launched from a history item, start playing the song.
        if (_playingSong != null)
        {
            MediaPlayer.Play(_playingSong);
        }
    }
}

There is also an option to write to the now playing section of the hub, however if you are playing your track using BackgroundAudioPlaer this is not needed as it is automatically handled for you from the track information.

Creating Training Buddy’s Live Tile

IC600903

Live tiles are probably the best known feature about Windows Phone. Unlike iOS’s plain grid of app icons Microsoft designed their phones home screen to provide users with data without having to open the app. With Windows Phone 8 the feature was updated so that 3rd party apps like Training Buddy could offer full width tiles along with new layout templates.

Adding a live tile to your app is a great idea as it is one of the features users often look for when their choosing an app. The app store also handily points out if an app uses a live tile or not.

The Design

There are 3 tile templates to choose from when you add a live tile to your app. These are Flip, Iconic and Cycle.

Flip gives the illusion that the tile has a front and a back and will flip over after a few seconds.

IC600901

Iconic has space for an image and a large number, a bit like the icon for messages and emails. When in its largest size there is also wide content zones that can contain text.

IC625724

Cycle lets you choose 9 images that the app will Cycle through.

IC601177

For Training Buddy I have used the Iconic template. You will probably find like myself that the type of app you are creating will more than likely determine what template you are going to use. As Training Buddy’s live tile was ultimately going to show details of the users last activity, Iconic was the obvious choice. The smaller sizes don’t really have enough space to give any activity stats and the large version gives you an additional space for a smaller image that was perfect for the activity type image (running, cycling, walking).

Another alternative is to make a completely custom design and write something in your app to render it as an image. You can then display the image using either the flip or cycle template.

The Code

The second reason you everyone should add live tiles to their app is because the code is so simple (this is the actual code from Training Buddy).

// Application Tile is always the first Tile, even if it is not pinned to Start.
            ShellTile TileToFind = ShellTile.ActiveTiles.First();

            // Application should always be found
            if (TileToFind != null)
            {
                string WideContent1 = "";
                string WideContent2 = "";
                string WideContent3 = "";
                string activityLogo = "";
                if (App.settings.LiveTile)
                {
                    var lastActivity = (from a in AllActivities
                                        orderby a.StartDateTime descending
                                        select a).Take(1);

                    if (lastActivity.Count() > 0)
                    {
                        if (App.settings.DistanceMeasurement == "Miles")
                        {
                            WideContent3 = "Distance: " + lastActivity.First().Distance.ToString("0.##") + " miles";
                        }
                        else
                        {
                            WideContent3 = "Distance: " + (lastActivity.First().Distance * 1.609344).ToString("0.##") + " km";
                        }
                        WideContent2 = "Date: " + lastActivity.First().StartDateTime.ToShortDateString();
                        switch (lastActivity.First().ActivityType.ToLower())
                        {
                            case "running":
                                WideContent1 = "Last Run";
                                break;
                            case "walking":
                                WideContent1 = "Last Walk";
                                break;
                            case "cycling":
                                WideContent1 = "Last Cycle";
                                break;
                            case "swimming":
                                WideContent1 = "Last Swim";
                                break;
                        }

                        activityLogo = "/Assets/" + lastActivity.First().ActivityType + "Black-70.png";

                        if (lastActivity.First().CaloriesBurned > 0)
                        {
                            WideContent3 += " Calories: " + lastActivity.First().CaloriesBurned.ToString("0.#");
                        }

                    }

                }

                IconicTileData tileDate = new IconicTileData
                {
                    Title = "Training Buddy",
                    WideContent1 = WideContent1,
                    WideContent2 = WideContent2,
                    WideContent3 = WideContent3,
                    IconImage = new Uri("/Assets/RunningBlack-150.png", UriKind.Relative),
                    SmallIconImage = new Uri(activityLogo, UriKind.Relative)
                };

                // Update the Application Tile
                TileToFind.Update(tileDate);
            }

First I’m finding the application tile. It is possible to create additional tiles for your app which is another great feature, but if you want to just update the main tile it will be the first one returned.

Next I’m checking to see if the user has turned on the live tile or not. If they haven’t then I’m just setting the tile back to its default state.

The following lines are then getting the content to display on the tile and building up the strings on local variables.

Lastly and most importantly I’m creating a new instance of IconicTileData and setting each of its properties with the data to show. Then it’s just a case of calling Update on the tile instance and providing it with the new IconicTileData object.

The Tile

And here’s the result

Training Buddy Live Tile

Live tiles are really easy to create so if your developing an app you should definitely take the time to add one.

Screenshots in Windows Phone 8

As a person who’s used Windows Phone since the very first version I know that one of the missing features was the ability to take screen shots! This was infuriating for developers who wanted a screen shot of their app working to place in the app store (then called marketplace). What made it even worse though was the simulator also lacked the button! Thankfully an update to the simulator fixed this, but the phone was still lacking.

Until….. I don’t know when, but the other day I accidentally did it and now know that screenshots are taken by holding power and pressing the windows key before the slide to power off box appears.

I’ve also hear in WP8.1 this will be replaced with power button and volume down as the requirement for physical back, windows and search buttons is to be removed.