Monday, September 20, 2010

In parts one and two I showed you how to create a new Windows Phone 7 Panorama Package. In part two we added oAuth to authenticate the user with Twitter. This is where the fun stuff happens. I’ll show you how to allow a new user to send a tweet.
We’ll be adding a new xaml page with a textBox for the tweet and an application bar with a save and cancel button.
Right click on the “Views” folder in the solution. Select “Add” then “New Item”. Pick the “Windows Phone Portrait Page” template and give the page a name, I’ll name the page “TweetPage.xaml”. Hit the “Add” button when done.
In the TweetPage.xaml file, change the “ApplicationTitle” to “Twitt” and the “PageTitle to “new tweet”. Also remove the applicatoin bar code that is at the bottom. I”m going to show you how to add it via code. Your file should look like this:

Compile and run the app to ensure that pressing the new button opens our “new tweet” page:. Let’s now add the TextBox and a couple TextBlock labels to our new “TweetPage.xaml” where the user will enter their tweet. We’ll add the new code inside the “ContentPanel” “Grid” node.

I’ve added one TextBlock for a title above the control to tell the user to “tap to edit”. I’ve also added a seond TextBlock to update the number of characters remaining, since tweets can only hold a maximum of 140 characters.
I’ve set the “InputScope” property to “Text” on the TextBox control. Setting to “Text” will show the user suggested words as they type them on top of the keypad. I’ve also added the “MessageTextboxKeyUp” event handler. I want to dismiss the keypad if the user hit the “Enter” key. For this to work you also need to set “IsTabStop” property to “true”.
I’ve also hooked up the “TextChanged” Event Handler so that as users type I can update the characters left TextBlock that I added. Here’s what the code behind looks like:

I’ve made a helper method called “UpdateRemainingCharacters” which I also call from the constructor to set the text as well as being called from “TweetTextBoxTextChanged”.
Running the app, the “new tweet” page should now look like this:
If you select the TextBox and start typing you should see the keypad and suggested words I previously mentioned:
Next, we’ll add the application bar to the bottom for our “tweet” and cancel buttons. In the TweetPage.xaml.cs, add the following new “CreateApplicationBar” method. I enclosed it in “#region” to keep my code cleaner.
public TweetPage() { InitializeComponent(); CreateApplicationBar(); UpdateRemainingCharacters(); } #region ApplicationBar private void CreateApplicationBar() { ApplicationBar = new ApplicationBar { IsMenuEnabled = true, IsVisible = true, Opacity = .9 }; var save = new ApplicationBarIconButton(new Uri("/Resources/Images/check.png", UriKind.Relative)); save.Text = "tweet"; save.Click += SaveClick; save.IsEnabled = false; var cancel = new ApplicationBarIconButton(new Uri("/Resources/Images/cancel.png", UriKind.Relative)); cancel.Text = "cancel"; cancel.Click += CancelClick; ApplicationBar.Buttons.Add(save); ApplicationBar.Buttons.Add(cancel); } private void CancelClick(object sender, EventArgs e) { if (NavigationService.CanGoBack) NavigationService.GoBack(); } private void SaveClick(object sender, EventArgs e) { } #endregion In “CreateApplicaitonBar” I add two buttons, the first one is for sending the tweet to Twitter. I set the “IsEnabled” property to “false.” We need to check if the user has validated their account before we enable this button. Notice I’m using two images “Resources/Images/check.png” and also “Resources/Images/cancel.png”. We’re going to need to go get these two images.
Application icons are installed with the development tools and located here: C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.0\Icons The two icons we need are located at \Icons\dark\appbar.cancel.rest.png and \Icons\dark\appbar.check.rest.png. We need to add these two icons to our “Resources/Images” folder. Right click on “Images”, select “Add” and then “Existing Items” and add the two files. Let’s rename them to “check.png” and “cancel.png”. Right click on each one and select “Rename”. Try running the app now, and openeing the “new tweet” page, you should see this: The icons are not showing up. You need to set each icon as a “content” type instead of the default “resource”. To do this, right click on each image file and select “Properties” and set the “Build Action” to “Content”.
Now run the app and the page should now look like this:
Try the cancel button. It should navigate back.
We now need to check if the user has been authenticated with Twitter and if so, enable the “Tweet” icon on the application bar. I’m going to load the saved settings and check if the “AccessToken” and “AccessTokenSecret” exist, if so enable the first button:

Now run the app. If the “Tweet” button is still disabled on the “new tweet” page, go back to the main page and ensure you hit “Account Settings” to authenticate your Twitter account. Note: every time you close the emulator down the Isolated Storage is wiped out. You’ll have to re-authenticate every time you reload the emulator. However, if you just exit the app and don’t close the emulator you won’t have to do this.
Once you’re authenticated you should get this screen. The “Tweet” button however still won’t do anything, we’ll tackle that next.
When we hit the “Tweet” button, we’re going to want a progress bar to show something is going on. In the TweetPage.xaml above the “TitlePanel” I’ve added a ProgressBar. I’ve set the “Visibility” property to “Collapsed” so it is off by default. For performance reasons you should also set “IsIndeterminate” to “False” when it’s not visible,

I’m now going to create a “TwitterHelper” class to wrap all of our calls to Twitter. Under the “Common” folder create a new class (Right click folder, “Add” –> “Class”:
Here’s the code for our “TwitterHelper” class:
using System;using System.Net;using System.Windows;using Hammock;using Hammock.Authentication.OAuth;using Hammock.Web; namespace Twitt.Common{ public class TwitterHelper { private readonly TwitterAccess _twitterSettings; private readonly bool _authorized; private readonly OAuthCredentials _credentials; private readonly RestClient _client; public event EventHandler TweetCompletedEvent; public event EventHandler ErrorEvent; public TwitterHelper(TwitterAccess settings) { _twitterSettings = settings; if (_twitterSettings == null || String.IsNullOrEmpty(_twitterSettings.AccessToken) || String.IsNullOrEmpty(_twitterSettings.AccessTokenSecret)) { return; } _authorized = true; _credentials = new OAuthCredentials { Type = OAuthType.ProtectedResource, SignatureMethod = OAuthSignatureMethod.HmacSha1, ParameterHandling = OAuthParameterHandling.HttpAuthorizationHeader, ConsumerKey = TwitterSettings.ConsumerKey, ConsumerSecret = TwitterSettings.ConsumerKeySecret, Token = _twitterSettings.AccessToken, TokenSecret = _twitterSettings.AccessTokenSecret, Version = TwitterSettings.OAuthVersion, }; _client = new RestClient { Authority = "http://api.twitter.com", HasElevatedPermissions = true }; } public void NewTweet(string tweetText) { if (!_authorized) { if (ErrorEvent != null) ErrorEvent(this, EventArgs.Empty); return; } var request = new RestRequest { Credentials = _credentials, Path = "/statuses/update.json", Method = WebMethod.Post }; request.AddParameter("status", tweetText); _client.BeginRequest(request, new RestCallback(NewTweetCompleted)); } private void NewTweetCompleted(RestRequest request, RestResponse response, object userstate) { // We want to ensure we are running on our thread UI Deployment.Current.Dispatcher.BeginInvoke(() => { if (response.StatusCode == HttpStatusCode.OK) { if (TweetCompletedEvent != null) TweetCompletedEvent(this, EventArgs.Empty); } else { if (ErrorEvent != null) ErrorEvent(this, EventArgs.Empty); } }); } }} I’ll walk through this code now: In the constructor, we take in the TwitterAccess object. This was already loading in our “TweetPage” so we will pass it through. This object contains the User Tokens. If the tokens were passed in successfully we set an “_authorized” member variable to true. This will be used to ensure we’ll have stored credentials when we make calls to the class methods. The constructor also sets up the “_credentials” and “_client” objects as they are needed for all authorized calls to Twitter. Next is the “NewTweet” method. This is the method we’ll call when the user presses the “Tweet” button. It will first check that we are authorized and then make the call. Last in this file, is the “NewTweetCompleted” Callback method, which is called when the Twitter call is completed. We need to check if the call was successful or not. I set up two different Events to fire back, one for a successful call and one for a failed call. All we have left is the “TweetPage.xaml.cs” code that makes this call and hooks up the two event handlers. Here is the code:

The first thing this method does is turns on the ProgressBar by setting the “Visibility” property to “Visible” and also turns on the “IsIndeterminate” property to “true”. We then setup the two callback event handlers (one for success and one for failed calls). Both will turn the progressbar off. Failed calls will also display an error message. Successful calls will navigate back to the previous page. That’s it! We can now tweet from the app. Next Part of this series I’ll show how to get friend statuses, mentions, direct messages and favorites. You can find the source code for part 3 here: http://twitt.codeplex.com/ Sam

Step 1: Add Hammock Library to our project

Update 5/18/2012: Note: Hammoc is no longer hosted on Codeplex, the best way to add it is using NuGet in Visual Studio.

Hammock is an open source REST library for .NET that simplifies calling RESTful services. All we have to do is download the file from Codeplex and add it to our solution. The project is located at: http://hammock.codeplex.com/ .
Download the latest binaries. There is a link on the right side of the page:
I just downloaded the zip file to my desktop. Unzip the file, then browse to find the Windows Phone 7 dll. At the time of this post, there was only a CTP build but will still work with the RTM version of the WP7 tools.
Next step is to copy “Hammock.WindowsPhone.dll” and “Hammock.WindowsPhone.pdb” into our solution. In my case, I created a new directory called “Hammock” under my Twitt project and copied the two files over:
There’s one additional step you need to do since these files were downloaded off the web and Windows doesn’t trust them.
Right click on the file and select “Properties”. Notice the “Unblock” button at the bottom right. Click it then hit “OK”. Do the same for the second file.
Next step is to add the dll to our solution. Load your “Twitt” solution that you created in Part 1. In the Solution Explorer locate the “References” folder, right click followed by “Add Reference”, Hit the “Browse” tab and navigate to the location you put the Hammock dll.
Select it and hit “OK”. You should now see Hammock.WindowsPhone under the Refereces folder:
You can try rebuilding the solution to make sure the compiler doesn’t complain.

Step 2: Setup a twitter dev application

You now need to register your app with Twitter. Go to http://dev.twitter.com/apps . If you don’t have an existing Twitter account create one and you should be able to register a new app:
You’ll get a screen like this next:
Give your app a name & description. If you have a website, provide one. I just put a fake URL in there for now. Ensure “Application Type”’ is “Browser”. Make “Callback URL” something that you’ll remember as we will need this in our app. I chose http://www.bing.com. Set Access Type to “Read & Write” so you can post tweets. I also specified the application icon I created earlier but you can leave that as the default icon.
Click “Register Application” at the bottom and if all was successful you’ll get a new Consumer Key and Consumer Secret. You do need to keep these secret and if they are compromised you can regenerate new ones. I’ll show the ones the issues my app and then change them :-)
That’s it! We’re now done with Twitter. A coding we will go…
Notice my Consumer key was: gOsH5beAiw138xyj29A5AA
and my Consumer Secret was: 8NZNamErHj8YkpLUQZQVipC1p4KOu3AYYDN3pWQ
We’re going to need these later, so keep them handy. You can log back into Twitter at any time to get these.

Step 3: Setting up oAuth

We’re going to need to add a new page to our application and a button to get to this new page. So let’s start there.
Open up the MainPage.xaml and examine the xaml a bit for the Panorama control. Notice there are two Panorama items:

I put it in a StackPanel because we’re going to add more stuff here later.
I also added a Click event and when I typed it, it automatically created my Code behind in the MainPage.xaml.cs file that looks like this:

private void Button_Click(object sender, RoutedEventArgs e){
}

Add the following Code to navigate to the new page that we will create

Now we should go create that page under the “Views” folder. Right Click on it and select “Add” –> “New Item”. Select “Windows Phone Portrait Page” and give it the same name we have above “TwitterAuthPage.xaml” then hit the “Add” button.
Run the app now and you should now have a third Panorama item:
Select the new “Account Settings” button and you should see our new page:
Next ,we will add the Web Browser Control to the page. The way oAuth is going to work is our app will pass our client key’s to Twitter and Twitter will return a web page where the user will be prompted for their user name, password and to accept granting access to this app. This way the user never enters in credentials into the app, where a malicious app developer could hijack those credentials or the app could get compromised. Once Twitter is successful they will redirect to a web page of ours with a token in the query string parameter. (Remember we used http://www.bing.com for our callback). We then need to extract this token and make a final call to Twitter to get the set of client key’s which our app will then store and use for all authorization calls to Twitter. That made perfect sense right? OK, well what about that return forward to bing.com? This is the trick I had to figure out. We need to trap the navigation event to www.bing.com , extract the token, then cancel it and continue on in our process.
Hopefully you can follow better in code. I’m going to dump a bunch of code here and won’t explain every detail of the Hammock call but it should be easy to figure out.
First we need to add the browser control to our new xaml page we created. I’m also going to add a progressbar and default it to “Collapsed”.
Here’s what the changes look like in TwitterAuthPage.xaml. Notice I’ve added two event handlers one for Navigated and another for Navigating:

We’re going to need a helper class for some settings. Under the project add a new folder called “Common,” right click that and “Add” a new “Class” called TwitterSettings.cs
Make this class look like this. Don’t forget to substitute your own Consumer Key and Secret:

There are a few things to note above. The OnNavigatedTo method is invoked whenever this xaml page is Navigated to. This method calls GetTwitterToken.
You can then see the magic of Hammock in wrapping the REST calls to Twitter. Notice the request object sets the path to “/request_token”. It’s requesting a token from Twitter. Once completed, the TwitterRequestTokenCompleted method is invoked where we extract the auth token and auth secret. The return method will then navigate to a new Twitter Authorize URL in the browser control with these tokens attached. If all is good it will redirect us back to http://www.bing.com with a new token attached as a query string parameter.
In BrowserControl_Navigating we check to see if we are navigating to our callback URI if so we cancel the navigation, grab our token and make a final call to Twitter for the users Access Token.
Finally in RequestAccessTokenCompleted we grab the Access Token and Secret and store them in a new object called TwitterAccess. This was also defined in the TwitterSettings.cs file, followed by saving this object to Isolated Storage.
There’s still one Helper class we need to create that will help load and store our Isolated Storage files. We need to store our user tokens in Isolated Storage so that we don’t have to get them again.
Create another new class under the “Common” folder called Helper.cs
This class is going to use “DataContractSerializer” which requires us to add a new reference to “Systm.Runtime.Serialization
Here’s the code for Helper.cs file:

There are a couple other helper methods in here we’ll be using later, like DeleteFile, LoadSetting and ParseDateTime. One other note: you may notice I have a thread lock around reading and writing my files. I needed thread safety and just threw a quick lock around them. I will change this to a reader-writer lock in the future, but this should do for now.
We’ll need one more Constants class to make this all work. Create another new class under the “Common” folder called “Constants.cs” and add the following:
namespace Twitt.Common{ public class Constants { public static string TwitterAccess = "TwitterAccess"; }}
This will be used for our file names.
You should be able to compile and run now. Then navigate to our new page, you should get a Twitter web page in the browser control:
Enter in some valid credentials, then hit the “Allow” link. If the call was successful you’ll see this screen:
You don’t want to hit the back button here since we’re not done. When authentication is complete the code will go back for us to our settings panorama item.

We are now authorized and can go ahead and start reading lists and sending Tweets.

Friday, September 17, 2010

In this series, I’m going to show how to build a ‘real’ twitter app. One that uses oAuth to authenticate with twitter, can get your friend statuses, mentions and direct messages. It will also have the ability to Tweet, Re-Tweet and view links from tweets. I’ll show you how to localize it into the 5 languages that Windows Phone 7 Marketplace supports and how to support tombstoning (ability to restore state when the app gets interrupted by a phone call for example or the user hitting the start button then back again). I’ll also show you how to work with Isolated Storage and the MVVM pattern.

If you saw my first post, I mentioned I was new to both Windows Phone Development and Silverlight development. I’ve learned a great deal along the way and hope to share what I’ve learned. I also have a lot to learn and hope that some of you will provide input on things I can improve.

I plan to make this blog very detailed so it could even beginners. I’ll just assume you know some c#. Hopefully more advanced folks can just skip some of these details.

We’re going to make this a “Panorama” app, You could choose Pivot App instead. The main difference is that the Panorama has a large ‘panorama’ background image. I think the design looks great, however one draw back is the default layout gives you less room for your content than a pivot control. The title area takes up much more space. But I’ll leave it up to you to pick one.

You’ll want to hit the typical “File” –> “New” –> “Project” and give your app a name as well as a Location to store it. I picked “Twitt” as my app name.

Hit “OK”

Wait a few seconds for the magic to happen, then build the solution. Before you run it, there’s an important drop down at the top of Visual Studio where you can pick the target of where you want it to run. It has two options, the emulator or a phone device. Make sure it’s set to emulator:

Now you can run the app. The emulator will launch; this takes a few seconds for the emulator to start if it’s the first time before your app is deployed. You don’t need to shut down the emulator when you’re done. In fact, just hit the “back” button on the bottom of the emulator and the app will exit or you can just stop debugging from within Visual Studio. This will speed up your next launch if the emulator is kept running. When you run it, you should see something like this:

Try swiping on the screen to move to the next panoramic item:

Did you notice those funky looking numbers along the right edge? Those are frame rate counters. Open up the App.xaml.cs file and look at the constructor:

// Show the areas of the app that are being redrawn in each frame. //Application.Current.Host.Settings.EnableRedrawRegions = true;

// Enable non-production analysis visualization mode, // which shows areas of a page that are being GPU accelerated with a colored overlay. //Application.Current.Host.Settings.EnableCacheVisualization = true; }

// Standard Silverlight initialization InitializeComponent();

// Phone-specific initialization InitializePhoneApplication(); }

Notice the “EnableFrameRateCounter” property is set to true during debugging. If you don’t care about this, you can set it to false or just ignore,. It won’t appear when you’re not debugging the app.

Here’s a look at all the files that were created when you created the solution:

Under “Properties” you’ll see a few interesting files. The AppManifest.xml doesn’t contain very much and in fact I’ve never had to touch it. Assembly info contains information about the assembly that will be created such as the app title, version, etc…

Last in “Properties” is the WMAppManifest.xml file. It looks like this:

The <App> node contains some app specific information that you can change if you like.

The <IconPath> node points to the icon that will appear for the installed app. This icon is a 62x62 pixel icon and you can see the default “ApplicationIcon.png” file exists at the root of the project.

The <Capabilities> section is important, it tells the OS what capabilities of the phone your application will be using. We won’t be using most of the ones listed except for the web browser control and networking layer. So I removed the rest of them:

Notice the <DefaultTask> node. It points to Mainpage.xaml. This is the first xaml page that will load when the app launches. I personally like to put all the view xaml files in a folder called “Views”. Right click on the project and add a folder called “Views”. Then move the MainPage.xaml and MainPage.xaml.cs into this folder. It should look like this:

Now we have a “Views” directory and also a “ViewModels” directory that will contain the viewModels that go with each view (more about that in a future post).

Since we made this change we also have to change <DefaultTask> node we saw above to point to this new MainPage.xaml location, otherwise it won’t find it and will throw an exception when you run it. Try running it if you don’t believe me!

Since we moved the MainPage.xaml out of the root and into a new folder and since the system is using relative paths, we’ll need to update the path for this image. Here’s an addition I usually like to do with most apps. Create a “Resources” folder for images and any other resources, such as localized resource files (more on those in a future post).

So once again right click on the project and “Add” –> “New Folder” and call it “Resources”. Then add a child folder to this one called “Images”. Now move the PanoramaBackground.png to the “Resources/Images” folder. Your structure should now look like this:

We could also move the other images there but I’ll leave them at the root for now and leave the App.xaml there.

Now we can change the MainPage.xaml code to point to this new location:

You may be wondering what the Background.png image is for. This is a 173x173 pixel image that shows up on the Windows Phone start screen if the user “pins” the app. To check this out, go back to the emulator. As long as you didn’t close it, the app will still be on the emulator and you can run it from there. You should see this screen:

Hit that top right arrow and as long as you’ve run the app at least once without shutting down the emulator you should get this:

There’s our “Twitt” app and that icon you see is the “ApplicationIcon.png” we talked about. Now hold down the mouse button on “Twitt” and you will get a pop-up menu:

Select “pin to start” and it’ll take you back to the start page:

And voila, there’s the “Background.png” image. Notice the text title that says “Twitt”. You may want to remove the text and have an icon that has the name in the image. To remove the name (or change it for that matter), go back to the WMAppManifest.xml and locate the title node:

By the way, when you compile a Windows Phone 7 app (or Silverlight app) you get a “xap” file (pronounced zap) that is really just a zipped file. Go look in the output directory of our solution and if you change the extention to .zip you can then unzip it and see what’s inside. This one single file gets deployed to the phone.

Once you’ve re-run the app, exit the app. Notice the text is still there? It doesn’t update the pinned item for some reason when you redeploy, but if you “unpin” it then “pin” it again it will update and you’ll see the title is now gone:

Another neat thing about this image is its supported transparency. If you make an icon with a transparent background it will pick up the user’s “accent” color and apply that to the background. In this case it would be blue and match the Internet Explorer icon shown in the image.

The last image to look at is the SplashScreenImage.jpg. This is the image that comes up briefly while the app is starting. Notice it’s a jpg image and not a png image. This is for performance reasons. JPG’s are lighter weight and you don’t want heavy processing going on like transparency while starting up the app. In fact, if your app takes too long to start, it’s possible the OS will kill it before it completes.

The default SplashScreen looks like this:

Right now our 3 images look pretty plain (AppliationIcon.png, Background.png and SplashScreenImage.jpg). I’ll leave this as a side exercise but what I did is open each file up in Paint.Net . You can use your favorite image editor instead or even Microsoft Paint.

I changed my graphics to look like these:

Most people probably leave these details until the end, but sometimes it’s nice to get these out of the way early on. I also think it looks better as you start showing people, since it gives it a real app feel. You might also want to change the panoramic background but I decided to leave mine as is.

Let’s do one last thing, which is to set our app name in the MainPage.xaml instead of the default “my application”.