April 2012

Volume 27 Number 04

Windows Phone - Transforming an Android App into a Windows Phone App

By Stan Chatman | April 2012

One of my major pet peeves is when a client has an existing iPhone or Android app and requests that it be ported to the Windows Phone platform but states that it must look and feel the same as it does in the iPhone or Android app. Insisting that the UI remains the same means that users will miss out on many of the native features unique to the Windows Phone platform that can enhance user experience. Once the OS update to Windows Phone, code-named “Mango,” was released, one of my major goals was to transform several of the apps I created for Android into Windows Phone apps. I deliberately use the word transform rather than port because it better indicates the process of moving an existing phone app to the Windows Phone platform. In this article I discuss the transformation of the Hollywood Empire app for Android into a Windows Phone app.

Before getting into the details of the Android to Windows Phone transformation, I’ll provide some background on building the original application so that you can better understand all the steps involved in the transformation.    

Overview of Hollywood Empire

Hollywood Empire is a drag-and-drop discovery casual game that has a similar game mechanic to the popular game Alchemy. The player starts with four actors, and the object is to drag an actor on top of another one. If the actors have appeared in a movie together, the player will earn the box office earnings from that movie and unlock another actor. Players can post their scores to a global high-score table and also share their successes with other users via Facebook or Twitter. They can also suggest their own movie combinations to be considered for the game. If a player gets stuck, the game offers hints. Although the game play is simple, the game becomes more challenging as the number of actors on the game board increases. Figure 1 shows two screenshots from the Windows Phone version of Hollywood Empire.

Sample screenshots from Windows Phone version of Hollywood Empire
Figure 1 Sample screenshots from Windows Phone version of Hollywood Empire

Movie Data Source

In the original design for Hollywood Empire, one of our major concerns was where the data that would drive the game would come from. At first we thought we could gather data from IMDb (Internet Movie Database, https://www.imdb.com/). We soon realized, however, that IMDb didn’t have an API that would allow us to get the data we needed for our engine. Despite the many home-grown IMDb screen-scraper SDKs available, none was reliable enough for our needs. We then found a similar movie database called TMDb (The Movie Database, https://www.themoviedb.org/). TMDb is open source and provides much of the same information as IMDb. It also links to IMDb so that the user can get information from there using actor and movie keys. TMDb also had a very good API (https://api.themoviedb.org/) that could retrieve the actor and movie information we needed. We also found a really good open source .NET wrapper API for TMDb (https://themoviedbapi.codeplex.com/), which saved us a lot of time given that we didn’t have to write our own help/wrapper classes.

Once we determined the source for our data, we had to decide whether the data would be provided in real-time or from a local data store. After some preliminary testing on extracting the data in real-time, we determined that it wouldn’t provide an optimal user experience because of potential throttling scenarios. In addition, the API didn’t provide the type of data we needed, which meant that we would have to write additional Web services, thus adding additional complexities. In the end, we decided to store our data locally on the device.

The table design for Hollywood Empire consists of the three tables shown in Table 1.

Table 1 Hollywood Empire tables

Table Name Description
hollywoodempire_actor Contains all relevant information for each actor
hollywoodempire_moviecombos Contains all possible combinations between two actors and the movies they appear in together
hollywoodempire_movie Contains all relevant information for every movie

Constructing these tables was a three-step process.

Step 1: Manually Create the Actor Table

The hollywoodempire_actor table contains information for approximately 150 actors who were selected based on their name recognition, popularity and relevance in the movie industry. We fed their names into themoviedb API to gather the information we needed and derived the actor table from there. Figure 2 shows what this file looks like in Microsoft Excel 2010. The id is just a sequential-based key uniquely identifying the actor. The name is the name of the actor as it appears in the TMDb database. The image is the name of the jpg thumbnail for the actor. The URL is the link to the IMDb system in case additional information is needed. The type describes whether the person is an actor or a director.

Actor table in Excel
Figure 2 Actor table in Excel

Step 2:  Create the Movie Combos Table

As the code in Figure 3 demonstrates, creating the movie combos is a straightforward process. The method GetActorsFromCSV shown in Figure 4 is a helper method that reads the file created in Step 1 and builds a dictionary of TmdbPerson (defined in the .NET wrapper API for TMDb mentioned earlier). In Figure 5 the layout for the TmdbPerson class is defined. This class defines the object returned by making a Person.getInfo call in the themoviedbapi API (https://api.themoviedb.org/3/person). The key data returned from this service is defined in the filmography field. It lists all the movies that an actor has appeared in. This information is used to determine any movies two actors have appeared in together.

The MoviesAppearedTogether helper method, shown in Figure 6, takes two TmdbPerson objects and returns a list of all movies the two actors have appeared in together. This helper application can run and build the hollywoodempire_moviecombos CSV file on demand in under a minute. Currently the hollywoodempire_moviecombos CSV file is comprised of about 6000 records.

Figure 3 Method to build movie combos table

private void Create_MovieCombo_Table(object sender, RoutedEventArgs e)
{
    List<string> movieListAll = new List<string>();
    StringBuilder sb = new StringBuilder();
    string mydocpath =  
      Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
    actList = api.GetActorsFromCSV();
    foreach (String act1 in actList.Keys)
    {
        foreach (String act2 in actList.Keys)
        {
            if (act1 != act2)
            {
                TmdbPerson p1 = actList[act1];
                TmdbPerson p2 = actList[act2];
                List<string> movieList = 
                  api.MoviesAppearedTogether(p1, p2);
                foreach (string mvt in movieList)
                {
                    sb.Append('"' + mvt + '"' + "," + 
                      '"' + act1 + '"' + "," + '"' + act2 + '"');
                    sb.AppendLine();
                }
            }
        }
    }
    using (StreamWriter outfile =
    new StreamWriter(mydocpath + @"\movieListAll_vs2008_export.csv"))
    {
        outfile.Write(sb.ToString());
    }
}

Figure 4 Method to build TmdbPerson dictionary from actor csv file

public Dictionary<String, TmdbPerson> GetActorsFromCSV()
{
    Dictionary<String, TmdbPerson> actHash = 
      new Dictionary<String, TmdbPerson>();
    using (CsvReader csv =
           new CsvReader(new 
             StreamReader("hollywoodempire_actor.csv"), true))
    {
        List<string> actList = new List<string>();
        int fieldCount = csv.FieldCount;
        string[] headers = csv.GetFieldHeaders();
        while (csv.ReadNextRecord())
        {
            for (int i = 0; i < fieldCount; i++)
                Console.Write(string.Format("{0}",
                               csv[i]));
            TmdbPerson[] actor = PersonSearch(csv[1]).ToArray();
            TmdbPerson actorCorrect = new TmdbPerson();
            foreach (TmdbPerson tp in actor)
            {
                TmdbPerson temp = GetPersonInfo(tp.Id);
                if (temp.KnownMovies > actorCorrect.KnownMovies)
                {
                    actorCorrect = temp;
                }
            }
            actHash.Add(csv[1], actorCorrect);
            Console.WriteLine();
        }
        return actHash;
    }
}

Figure 5 TmdbPerson class definition

[DataContract]
public class TmdbPerson
{
    [DataMember(Name="score")]
    public string Score { get; set; }
    [DataMember(Name="popularity")]
    public string Popularity { get; set; }
    [DataMember(Name="name")]
    public string Name { get; set; }
    [DataMember(Name="url")]
    public string Url { get; set; }
    [DataMember(Name="id")]
    public int Id { get; set; }
    [DataMember(Name="biography")]
    public string Biography { get; set; }
    [DataMember(Name="known_movies")]
    public int KnownMovies { get; set; }
    [DataMember(Name="birthday")]
    public string BirthdayString { get; set; }
    public DateTime? Birthday
    {
        get
        {
            DateTime d;
            if (string.IsNullOrEmpty(BirthdayString) || 
              !DateTime.TryParse(BirthdayString, out d))
                return null;
            else
                return d;
        }
    }
    [DataMember(Name="birthplace")]
    public string Birthplace { get; set; }
    [DataMember(Name = "profile")]
    public List<TmdbImage> Images { get; set; }
    [DataMember(Name = "filmography")]
    public List<TmdbPersonFilm> Filmography { get; set; }
}

Figure 6 Method that returns movies two actors have appeared in together

public List<string> MoviesAppearedTogether(TmdbPerson act1, TmdbPerson act2)
{
    List<string> moviesTogetherList = new List<string>();
    foreach (TmdbPersonFilm film1 in act1.Filmography)
    {
        foreach (TmdbPersonFilm film2 in act2.Filmography)
        {
            if (film1.Name.Trim() == film2.Name.Trim())
            {
                moviesTogetherList.Add(film1.Name);
            }
        }
    }
    return moviesTogetherList;
}

Step 3: Derive the Movie Table

After the hollywoodempire_moviecombos CSV file is created, it’s used to determine all unique movies that are needed for the movie table. Table 2 describes the information needed for the hollywoodempire_movie CSV file.

Table 2 Description of movie file

Field Name Description
MovieName Name of movie
Image URL of movie thumbnail poster
Revenue Box office revenue amount
Trailer YouTube movie trailer URL
ReleaseDate Release date of movie

The easiest way to produce the unique movie text file is to do a unique filter in Excel on the movie name field and hide all the other fields. The unique movie file currently produces roughly 950 movie names. After the unique movie file has been created, each movie name can be searched for in the themoviedb database and stored in the movie CSV file. In addition to the relevant movie information, the appropriate movie poster thumbnail is downloaded. Figure 7 shows the code that retrieves the movie information and downloads the image poster. The latest version of the code has checks to see whether the movie images have already been downloaded. If so, it skips downloading the media, to speed up processing time. Movies that have already been processed are stored in a local file so that only new movies are processed. The GetMoviesFromCSV method creates a list in memory that contains the unique movie names. We then iterate through this list and retrieve the necessary movie information.

Figure 7 Method that retrieves movie information and image thumbnail

private void Create_Movie_File(object sender, RoutedEventArgs e)
{
    movList = api.GetMoviesFromCSV();
    …
    foreach (string mov in movList)
    {
        bool proc = false;
        foreach (string movproc in movProcessed)
        {
            if (movproc.Trim() == mov.Trim())
            {
                proc = true;
                break;
            }
        }
        if (!proc)
        {
            TmdbMovie[] movie = api.MovieSearch(mov).ToArray();
            TmdbMovie movie2;
            imagename = "notfound.jpg";
            revenue = "20000000";
            string picURL = null;
            trailer = "https://www.themoviedb.org/movie";
            if (movie.Length > 0)
            {
                if (movie[0].Posters.Count > 0)
                {
                    if (movie[0].Posters.Count > 0)
                    {
                        picURL = movie[0].Posters.FirstOrDefault().ImageInfo.Url;
                    }
                    else
                    {
                        picURL = null;
                    }                          
                    if (picURL != null && picURL.Trim() != "")
                    {
                        string[] picFileName = picURL.Split('/');
                        imagename = picFileName[picFileName.Length - 1].ToLower().Replace('-', '_');
                        movie2 = api.GetMovieInfo(movie[0].Id);
                        revenue = movie2.Revenue;
                        if (revenue == "0" || revenue == "") revenue = "20000000";
                        trailer = movie2.Trailer;
                        year = String.Format("{0:MM/dd/yyyy}", movie2.Released);
                        String checkFile = mypicpath + "\\Hollywood Empire\\tmdb_images" + 
                          @"\" + picFileName[picFileName.Length - 1].ToLower().Replace('-', '_');
                        if (!File.Exists(checkFile))
                        {
                            byte[] picdata = api.GetImageData(picURL);
                            writeByteArrayToFile(picdata, imagename);
                        }
                    }
                }
            }
          …
        }
    }
    using (StreamWriter outfile =
     new StreamWriter(mydocpath + @"\hollywoodempire_movie_tmdb_vs2008.csv"))
    {
        outfile.Write(sb.ToString());
    }
}

Utilizing SQL Server Compact Local Database

Now that all the relevant CSV files have been created, the next step is determining how to store and consume this information on the mobile device. In the original Android version, we initially thought we could use SQLite to store and consume the data. Using this approach caused performance issues, however, so we decided to go with in-memory Java hash tables that would be read from the CSV files. This approach worked fairly well in the Java version except when we needed to search the hash tables to find the next available movie combo for the user. The performance was slowed because a manual sequential search had to be done every time.

Many of the issues we faced in the Android version were resolved when we transformed the game to Windows Phone. LINQ resolved many of the search issues for tables/collection search and filters. SQL Server Compact also provided us with a more robust and mature database framework compared to SQLite. To utilize SQL Server Compact databases in our Windows Phone version of Hollywood Empire, we needed to create a SQL Server Compact database, import our CSV files into the newly created database and create entity object classes to use the database in Windows Phone.

Step 1: Create SQL Compact Database

We used SQL Server 2008 R2 to create the SQL Server Compact database. In the management screen, under Server type, we selected SQL Server Compact, and for Database file, selected . Then in the create prompt, we chose the location of the new database file, as shown in Figure 8.

NOTE One of the handy features of SQL Server Compact is that if you choose to password-protect your database, you get a fully RSA encrypted database for free. This is an added benefit of a SQL Server Compact database if security is a priority for your application.

Management screen prompts for creating new SQL Server Compact database
Figure 8 Management screen prompts for creating new SQL Server Compact database

Step 2: Import CSV Files

Once we created the actual SQL Server Compact database, we needed to create the tables and import the appropriate CSV files. Although SQL Server Management Studio doesn’t have a feature that allows CSV files to be imported into SQL Server Compact tables, the ExportSqlCE add-in, which can be downloaded at exportsqlce.codeplex.com,let us import from either SQL Server Management Studio or Visual Studio. This tool reads a CSV file and compares it to the table schema; if no issues are found, it creates an INSERT script that can be run to insert the values into the appropriate tables. Figure 9 shows the INSERT script generated when importing from the actor CSV file, and Figure 10shows the populated actor table after the INSERT script has been run.

Figure 9 Sample INSERT created from ExportSqlCE ImportFromCSV function

INSERT INTO [hollywoodempire_actor] ([id],[name],[image],[url],[type]) VALUES ('1',N'Leonardo DiCaprio',N'leonardodicaprio.jpg',N'https://www.imdb.com/name/nm0000138/',N'Actor');
GO
INSERT INTO [hollywoodempire_actor] ([id],[name],[image],[url],[type]) VALUES ('2',N'Jennifer Connelly',N'jenniferconnelly.jpg',N'https://www.imdb.com/name/nm0000124/',N'Actor');
GO
INSERT INTO [hollywoodempire_actor] ([id],[name],[image],[url],[type]) VALUES ('3',N'Johnny Depp',N'johnnydepp.jpg',N'https://www.imdb.com/name/nm0000136/',N'Actor');
GO
INSERT INTO [hollywoodempire_actor] ([id],[name],[image],[url],[type]) VALUES ('4',N'Marion Cotillard',N'marioncotillard.jpg',N'https://www.imdb.com/name/nm0182839/',N'Actor');
GO
INSERT INTO [hollywoodempire_actor] ([id],[name],[image],[url],[type]) VALUES ('5',N'Djimon Hounsou',N'djimonhounsou.jpg',N'https://www.imdb.com/name/nm0005023/',N'Actor');
GO
…

SQL Server Management screen after INSERT script has run and actor table populated
Figure 10 SQL Server Management screen after INSERT script has run and actor table populated

Step 3: Create Entity Object Classes to Use the Database in Windows Phone

The official Microsoft approach to using a SQL Server Compact database in a Windows Phone application is “code first.” The basic premise of this approach is that the developer creates database contexts and relationships in code and the database is then generated based on these code definitions. In our Windows Phone application, we used a different, unofficial approach that included the following steps:

  1. Use Visual Studio or SQL Server Management Studio visual designers to create a SQL Server Compact Edition 3.5 database on the development PC.
  2. Start a Visual Studio command prompt.
  3. Run the SQLMetal tool to generate a LINQ to SQL code file.
    1. cd C:\TheMovieDB_New\SQLCE
    2. Sqlmetal /code:HollyWoodEmpireEntities.cs /context:HollyWoodEmpireDataContext  /pluralize HollyWoodEmpire.sdf
  4. Include generated code in the Windows Phone project. (See Figure 11.)
  5. Change the outputted entity file to get it to compile:
    1. Add a reference to "System.Data.Linq":
    2. Remove two constructors that refer to System.Data.IDbConnection.

This process is described in detail at windowsphonegeek.com/articles/Using-SqlMetal-to-generate-Windows-Phone-Mango-Local-Database-classes.

After SQLMetal is run, the outputted file that contains the database entities is stored in the Models directory, as shown in Figure 11. (Note that our SQL Server Compact database is stored in the AppData folder.) As you can see in Figure 12, there are two locations within the Windows Phone app container where data can be stored. Most developers are familiar with Isolated Storage, the sandboxed part of the Windows Phone in which file system APIs can be used to store files and folders. The other location is AppData, or the Install folder. Everything in AppData is read-only, and when an app update is installed, all the current files are deleted and replaced with the new contents of the Silverlight XAP files. This differs from the Isolated Storage area, which is maintained when an app is updated—that is, no existing data is destroyed.

Hollywood Empire project layout
Figure 11 Hollywood Empire project layout

Overview of local data storage
Figure 12 Overview of local data storage

Once the SQL Server Compact database and the database entity classes were created, the final step was to allow these artifacts to be consumed in our Windows Phone project. Figure 13 illustrates the creation of an instance of the database context that takes a connection string as a parameter. This connection string points to the location of the database in AppData and also specifies that the database is read-only. In the constructor of the MainViewModel, a check is made to see whether the database already exists; if not (false), the database is created. After the database has been created, it can be used like any other DataContext and LINQ queries can be run against it.

Figure 13 Code to create a database context for a SQL Server Compact database

public class MainViewModel : BaseViewModel
    {
        #region Fields
        public static ObservableCollection<Hollywoodempire_actor> 
          Hollywoodempire_actors_cache;
        public static ObservableCollection<Hollywoodempire_moviecombo> 
          Hollywoodempire_moviecombos_cache;
        public static ObservableCollection<Hollywoodempire_movie> 
          Hollywoodempire_movies_cache;
        public HollyWoodEmpireDataContext db = 
          new HollyWoodEmpireDataContext(@"Data Source = 
          'appdata:/AppData/HollyWoodEmpire.sdf'; 
                                  File Mode = read only;");
        private PlayerViewModel _currentPlayer;
        private HighScoreViewModel _highScore;
        private bool _isProgressBarVisible;
        private Visibility _progressBarVisibility;
        #endregion Fields
        #region Constructors
        public MainViewModel()
        {
            if (!db.DatabaseExists())
                db.CreateDatabase();
        }
…

LINQ, Where Art Thou?

When programming on the Android platform in Java, one of the .NET components I missed the most was LINQ. Java doesn’t have anything comparable to LINQ that allows you to do queries on a collection set. One of the key features of Hollywood Empire is the capability to give players a hint when they are stuck. In the Android version of the game, the method that would perform this function suffered some performance issues simply because it used a brute-force manual sequential scan of all the Java hash tables to return the correct result. In the Windows Phone version, we were able to design a much more elegant solution utilizing LINQ queries that produced less code and also ran in sub-millisecond time.

Drag and Drop

One of the key features of Hollywood Empire is its drag-and-drop capability. In the Android version, drag-and-drop functionality proved to be somewhat challenging because the layout that allows for freestyle drag-and-drop (AbsoluteLayout) has been deprecated and is unsupported. Incorporating drag-and-drop capability into our Windows Phone version of Hollywood Empire was relatively simple. We just added the MouseDragElementBehavior to the actor XAML control, as shown in Figure 14. Using this behavior allows the developer to freely drag the actor object inside the main canvas layout. As shown in Figure 15, two events are used for the drag control: Manipulation_Started and Manipulation_Completed. In the Manipulation_Started event, the z-index of the drag object is set to the current time in seconds, allowing the object being dragged always to appear on top of the other objects. The Manipulation_Completed event has checks to see whether the dropped object is in the bounding rectangle of another actor and whether a valid movie match is found.

Figure 14 Drag and drop XAML

<Border x:Name="ActorCanvas" HorizontalAlignment="Center" 
    Background="{StaticResource PhoneAccentBrush}" BorderThickness="2" 
    BorderBrush="{StaticResource PhoneContrastBackgroundBrush}">
       <i:Interaction.Behaviors>
              <el:MouseDragElementBehavior x:Name="mousedrag"/>
       </i:Interaction.Behaviors>
       <StackPanel x:Name="ActorPanel" HorizontalAlignment="Center" 
         Width="90" Canvas.ZIndex="{Binding zIndex}" VerticalAlignment="Top">
              <Image x:Name="ActImg" 
                Source="{Binding Actor.Image, StringFormat=../../Images/Actors/\{0\}}" 
                Width="70" Height="100" VerticalAlignment="Top" 
                Stretch="UniformToFill" Margin="3"/>
              <TextBlock Text="{Binding Actor.Name, Mode=TwoWay}" 
                HorizontalAlignment="Center" FontSize="14.667" TextWrapping="Wrap" 
                Style="{StaticResource PhoneTextTitle2Style}" FontWeight="Bold"/>
       </StackPanel>
</Border>
…

Figure 15 Manipulation_Started and Manipulation_Completed events

private void ActorControl2_ManipulationCompleted(object sender, 
  System.Windows.Input.ManipulationCompletedEventArgs e)
{       
    var ctrl = sender as ActorControl2;
    var act = ctrl.DataContext as ActorViewModel;
    var z = DateTime.Now.TimeOfDay.TotalSeconds;
    act.zIndex = z;
    act.PosLeft_Current = ctrl.mousedrag.X;
    act.PosTop_Current = act.PosTop_Current + 
       e.TotalManipulation.Translation.Y;
    ContentPresenter cp = 
     (ContentPresenter)itemsControl.ItemContainerGenerator.ContainerFromItem(act);
    cp.SetValue(Canvas.ZIndexProperty, Convert.ToInt32(z));
    App.ViewModel.CheckForMatch(act, App.ViewModel.CurrentPlayer.ActorInventory);
}
private void ActorControl2_ManipulationStarted(object sender, 
  System.Windows.Input.ManipulationStartedEventArgs e)
{
    var act = (sender as FrameworkElement).DataContext as ActorViewModel;
    var z = DateTime.Now.TimeOfDay.TotalSeconds;
    ContentPresenter cp = 
     (ContentPresenter)itemsControl.ItemContainerGenerator.ContainerFromItem(act);
    cp.SetValue(Canvas.ZIndexProperty, Convert.ToInt32(z));
}

Utilizing the LongListSelector Control

One of the more elegant features of Windows Phone is the LongListSelector control. LongListSelector is an advanced ListBox that supports full data and UI virtualization, flat lists and grouped lists. It helps users scroll through long lists of data. Basically, a quick-jump grid overlays the list when the user selects one of the group headers; after that, when an item is selected from the grid, the user is automatically redirected to the long list at the selected point. In Hollywood Empire the LongListSelector is used to allow the player to manage actors. In our Windows Phone design, shown in Figure 16, the LongListSelector screen resembles what users would see on their People list, thus adding to a consistent user experience. In the Android version, we used a ListBox to display the data and a TextBox that filtered on the actor’s first name. Users who have played both the Windows Phone and Android versions have commented that the LongListSelector (or Jumplist, as it’s sometimes called) is a more elegant approach.

LongListSelector of actors
Figure 16 LongListSelector of actors

Pivot Control in Place of Tab Control

One of the comments we received from users who tested both the Android and the Windows Phone versions of Hollywood Empire was how much more they liked the Windows Phone pivot control compared to the tab control used in the Android version. What they liked most about the pivot control was the transition animation when swiping to another page/screen. In the Windows Phone version, we replaced the tab with the pivot control as much as possible and in some cases used the application bar to remove functions that were in tabs.

Facebook Integration

In October 2011, I attended a Windows Phone Boot Camp hosted by Microsoft in Chicago. This class was taught by Jeff Blankenburg (https://jeffblankenburg.com/31daysofmango/) of 31 Days of Mango fame. When asked what I most wanted to get out of the class, my answer was to find out how to integrate Facebook with my game. Jeff said that with Windows Phone I could get full Facebook integration with fewer than 10 lines of code. His response was not what I was expecting since the Android version of Hollywood Empire has close to 800 lines of code including the Android Facebook SDK source. But he was right. I was able to integrate my game with both Facebook and Twitter using fewer than 10 lines of code, as shown in Figure 17. This streamlining is accomplished by using the ShareLinkTask that is part of the Microsoft.Phone.Tasks assembly.

Figure 17 Facebook integration sharing code

private void share_Click(object sender, System.EventArgs e)
{
    string message = " just unlocked "
      + App.ViewModel.CurrentPlayer.MovieMatch.MovieName
      + " and received "
      + App.ViewModel.CurrentPlayer.MovieMatch.MovieBoxOffice.Value.ToString("c")
      + " in Box Office dollars by playing HollyWood Empire.";
    ShareLinkTask share = new ShareLinkTask();
    share.LinkUri = new Uri("https://www.facebook.com/album.php?aid=44178&id=184237228261252&saved#!/pages/HollyWood-Empire-for-Android/184237228261252?v=wall");
    share.Message = message;
    share.Title = " They want to celebrate the occasion by sharing the link to HollyWood Empire so you too can earn Box Office dollars by unlocking movies.";
    share.Show();
}

YouTube Integration

In the Android version of Hollywood Empire, adding the functionality for a user to click a movie title and then launch the YouTube movie trailer automatically, without clicking the play button, was easy. Android has a YouTube launcher that allows the user to select the native YouTube app or the browser version. Windows Phone currently lacks this capability. A user who has installed the YouTube app from the Windows Phone marketplace can play YouTube videos; if the YouTube app isn’t installed, the user is redirected to the install screen for the YouTube app. We didn’t want to go this route, so after days of searching we finally ran across a third-party add-in, YouTube.Play (mytoolkit.codeplex.com/wikipage?title=YouTube) that allows YouTube videos to launch on a Windows Phone. YouTube.Play downloads the YouTube page of the desired YouTube-ID, searches for the appropriate MP4-link and then plays the video with MediaPlayerLauncher. This workaround is acceptable for now, but we hope that future versions of Windows Phone better accommodate YouTube videos.

Future Direction of Hollywood Empire

Now you know how we transformed Hollywood Empire from Android to Windows Phone. Having the experience of developing on both the Android and Windows Phone platforms, I have formed opinions about both platforms. Table 3 lists the pros and cons of working on the Android platform.

Table 3 Pros and cons of Android platform

Pros Cons

Interesting core framework design: API sharing between apps (Activities/Provider)

Simple way to manage different resolutions (low, med and high)

Fast certification process

Eclipse is a great tool for coding (e.g., refactoring, unit testing, views)

Device fragmentation (hard to test)

Simulator is low and not user friendly

UI template and code association are not well integrated

Java with closures are too verbose compared to C# lambda

My experience with Windows Phone development has been positive. Going forward, the Windows Phone development platform will be my first choice because it has a mature set of development tools (Visual Studio and Expression Blend), a better certification process (it screens out apps that don’t adhere to basic quality controls) and is completely transparent.

In the future, I hope to enhance Hollywood Empire by making the creation of the movie database an automated process that run in Azure as a worker role every Wednesday and Friday night to coincide with most major movie release dates. This capability would allow for more frequent updates and remove the need to update the movie database manually.

The final version of the Hollywood Empire application for Windows Phone is available on the Windows Phone Marketplace at windowsphone.com/en-US/apps/f8ad91e5-29a2-45b6-a8a9-e3e96373bfe8.


Stanley D. Chatman has been a developer for more than 20 years and currently works as a group manager at Avanade Inc. He specializes in client UI development for Windows Phone, Silverlight, Windows Presentation Foundation and more recently, Windows 8 Metro styled applications.

Thanks to the following technical experts for reviewing this article: Moe, Larry and Curly.