Thursday, October 7, 2010

Building a ‘real’ Windows Phone Twitter app Part 7 – Optimizing ProgressBar and First time app start up

 

ProgressBar

If you’ve been doing any Windows Phone development you may have run into Jeff Wilcox’s excellent blog: http://www.jeff.wilcox.name/blog/

He’s got on post in particular about the per issues with the built in ProgressBar: http://www.jeff.wilcox.name/2010/08/performanceprogressbar/

I’ll leave it as an exercise to follow this post as it’s quite simple. Roughly the steps are:

  1. Add a new file called “RelativeAnimatingContentControl.cs” and add the code provided in the blog.  I created this at the root of the project.
  2. Add a reference to the top of App.xaml.cs to reference the file and namespace from step 1.
  3. Add the style to the App.xaml.cs file as provided in Jeff’s blog post
  4. Add the style to all the “ProgressBar” elements whereever it’s used in the xaml files.  My code uses it in DetailPage.xsml, MainPage.xaml, TweetPage.xaml and TwitterAuthPage.xaml.  The progress bar code should look something like this:

<ProgressBar x:Name="ProgressBar" VerticalAlignment="Top" IsIndeterminate="False" Visibility="Collapsed" Style="{StaticResource PerformanceProgressBar}"/>

First Time App Start Up

Currently when our code launches MainPage.xaml is loaded the code behind will check if there is stored credentials.  If none are found it will load the TwitterAuthPage.xaml to show the user they need to authorize their Twitter account.  If you hit the back button you’ll be taken back to the MainPage.xaml file if you hit back button again the app will exit.

That seems ok right?  According to app submission policy, launching the app followed by the back key must exit the app and it will fail validation (I hit this one already).  There is a good solution however to this problem.

In App.xaml.cs add an event handler for navigating in the constructor (note I’ve taken the comments out of the code to make it easier to read.

public App()
{
    UnhandledException += Application_UnhandledException;

    if (System.Diagnostics.Debugger.IsAttached)
    {
        Application.Current.Host.Settings.EnableFrameRateCounter = true;
    }

    InitializeComponent();

    InitializePhoneApplication();

    RootFrame.Navigating += RootFrame_Navigating;
}

 

Under the “Properties” folder is the WMAppManifext.xml file we’re going to have it ask for a new xaml file when the app launches.  However we won’t be creating a file for this.  Change the “NavigationPage” attribute of the “DefaultTask node to:

<DefaultTask  Name ="_default" NavigationPage="Views/HomePage.xaml"/>

Now we need to add the event handler.  This handler will check to see if the “HomePage.xaml” file is ever called. If it’s called, we’ll then check if credentials have been stored, if they have load our MainPage.xaml otherwise load the TwitterAuthPage.xaml file:

private void RootFrame_Navigating(object sender, NavigatingCancelEventArgs e)
{
    // Only care about HomePage
    if (e.Uri.ToString().Contains("/HomePage.xaml") != true)
        return;

    e.Cancel = true;

    // check if credentials are stored
    var credentialsFound = false;
    var twitterSettings = Helper.LoadSetting<TwitterAccess>(Constants.TwitterAccess);
    if ((twitterSettings != null &&
        !String.IsNullOrEmpty(twitterSettings.AccessToken) &&
        !String.IsNullOrEmpty(twitterSettings.AccessTokenSecret)))
    {
        credentialsFound = true;
    }

    RootFrame.Dispatcher.BeginInvoke(delegate
    {
        RootFrame.Navigate(credentialsFound
                                ? new Uri("/Views/MainPage.xaml", UriKind.Relative)
                                : new Uri("/Views/TwitterAuthPage.xaml", UriKind.Relative));
    });
}

 

We now have to make a minor change to TwitterAuthPage.xaml.cs in the “RequestAccessTokenCompleted”.  We use to just go back, but since this page can now be the first page, if we successfully get the token and there is no back history load the MainPage.xaml” file:

 

private void RequestAccessTokenCompleted(RestRequest request, RestResponse response, object userstate)
{
    var twitteruser = new TwitterAccess
        {
            AccessToken = GetQueryParameter(response.Content, "oauth_token"),
            AccessTokenSecret = GetQueryParameter(response.Content, "oauth_token_secret"),
            UserId = GetQueryParameter(response.Content, "user_id"),
            ScreenName = GetQueryParameter(response.Content, "screen_name")
        };

    if (String.IsNullOrEmpty(twitteruser.AccessToken) || String.IsNullOrEmpty(twitteruser.AccessTokenSecret))
    {
        Dispatcher.BeginInvoke(() => MessageBox.Show(response.Content));
        return;
    }

    Helper.SaveSetting(Constants.TwitterAccess, twitteruser);

    Dispatcher.BeginInvoke(() =>
        {
            if (NavigationService.CanGoBack)
            {
                NavigationService.GoBack();
            }
            else
            {
                NavigationService.Navigate(new Uri("/Views/MainPage.xaml", UriKind.Relative));
            }
        });
}

 

Now we can remove the check in MainPage.xaml.cs that we used to see if credentials were entered.  The new MainPage_Loaded method looks like this:

private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    if (!App.ViewModel.IsDataLoaded)
    {
        App.ViewModel.LoadData();
    }
}

That’s it, if you launch the app for the first time, the Twitter authorization page will show and hitting back will now exit the app.  Launching after credentials have been stored will bring up the MainPage.xaml as it did before.

The source code is available at http://twitt.codeplex.com/

Sam

14 comments:

  1. Hey Sam,

    I just purchased your Feed Reader App yesterday. When I try to sign in to Google Reader I get the following error message: The remote server returned an error: NotFound.

    Can you please help me, I really want to use your app!

    Best Regards!
    Jan

    ReplyDelete
  2. Hi Jan,
    Absolutely I'd like to help! Can you email me at wpfeedreader@gmail.com and we can figure out what's up. If you have time as well would you mind trying to create a new google reader account at http://wwwgoogle.com/reader then trying that account on Feed Reader, that will help us determine if it's something specific to your account or not?

    thanks,
    Sam

    ReplyDelete
  3. Hey Sam,

    Extremely detailed and well written.Great work !

    I stumbled upon your blog while doing some research about windows 7 phone application development. I am currently a graduate student at State University of New York,Binghamton. I am working on my master's termination project which involves developing a social networking app.

    Is it possible for you to tell me any helpful material or a book which I can use for win 7 phone development. Since I am a newbie on this platform it is little hard to follow the logic behind the code and I am not going to just replicate the code.

    Please do reply
    Regards,
    Ameya

    ReplyDelete
  4. Hi Ameya,
    A great place to start is the Microsoft Phone site: http://create.msdn.com they've got a ton of info and step by step guides on building apps.
    Another place to get great links is the reddit site: http://www.reddit.com/r/wp7dev/

    Best of luck and also follow #wp7dev tag on Twitter. Best of luck

    Sam

    ReplyDelete
  5. Thanks a lot sam ! I do have experience in C# development but totally new to phone platform. If it's okay I will keep in touch if I come across any major difficulty

    thanks a lot and again it was extremely helpful to read the posts about twitter app development.

    Regards,
    Ameya

    ReplyDelete
  6. You bet Ameya!
    I actually got a new job as a Program Manager on the Silverlight team at Microsoft at the beginning of the month, so if I can't answer any questions I'm sure I can forward them on.

    ReplyDelete
  7. That's great Sam. Thanks a lot. I also came down to Seattle for interview at Microsoft but didn't make it. Hopefully second time is the charm :-)

    Regards,
    Ameya

    ReplyDelete
  8. This comment has been removed by the author.

    ReplyDelete
  9. This comment has been removed by the author.

    ReplyDelete
  10. Hey Sam, I was just curious why in the Twitt source code you are calling MessageBox using Dispatcher.BeginInvoke, for example: Dispatcher.BeginInvoke(() => MessageBox.Show("error calling twitter")

    Is there a performance reason for this? Normally I just open the MessageBox without the Dispatcher.

    Just curious, thanks.

    ReplyDelete
  11. Hi Ryan,
    That's just to get back to the UI thread to show a messageBox. It will throw an expeption if you try to make some calls off of the UI thread, sot Dispatcher.BeginInvoke sends it back to that thread.

    Hope that's helpful.
    Sam

    ReplyDelete
  12. The twitter app demonstration is awesome.. I have a small doubt regarding Google login in my wp7 app can u please help out with it? The problem is that am able to login to Google account through my app... but am not receiving the User Id from Google..Is there anything particular that i will have to do to receive the user id?

    ReplyDelete
  13. hi i know this is a older blog but i reference to it here and there and maybe its because im building for windows phone 8 but the sample data wont take also while follow you complete tutorial i get "twitter error:NotFound" when running on the phone any help would appreciated thanks.

    ReplyDelete
  14. Any manner to spare back the Previewbuffer as a stream or any method to apply channels straightforwardly to the a film bolster and recovery it as a Mp4? I have a little channel I apply to the snapshot cushion and works exceptionally pleasant yet I need to have the capacity to spare the outcome as a film.mobile app development // mobile app developers // iPhone app maker

    ReplyDelete