How to shorten an url with Bitly asynchronously on Windows Phone

bitly_logo

It was only yesterday when I decided to shorten shared links in UniShare. The reason is not Twitter as suggested by some of my users, but other networks like LinkedIn, that have text length limits as well.

After digging into the Bitly API, I created a little helper that returns the a shorten Bitly-url. In case this is not possible for whatever reason, it returns the long url that was tried to be shortened.

Before we can start to write some code, we need to get our generic access token for the Bitly API. Log in to your Bitly account, and click on ‘Settings’, and choose the ‘Advanced’ tab. If you already verified your mail address, you are nearly done. Enter your password and click on the ‘Generate Token’ Button:

Screenshot (388)

This is one of the constants we need soon. In your project, generate a new class called BitlyHelper. Declare the following constant strings:

private const string bitlyGenericAccessToken = "your_generic_access_token";
private const string base_url = "https://api-ssl.bitly.com/v3/shorten?access_token={0}&longUrl={1}&format=txt";

The base_url string contains the url we are calling, setting our generic access token as well as the long url we want to share. As we are only interested in getting the shortened url, we need to add the ‘format=txt’ part at the end.

The next step is to create an async Task that returns the HttpResponseMessage:

        /// <summary>
        /// Task that starts the async request for the HttpResponseMessage
        /// </summary>
        /// <param name="longUrl">the url to shorten</param>
        /// <returns>the HttpResponseMessage that contains the shortened url</returns>
        private async Task<HttpResponseMessage> getShortUrl(string longUrl)
        {
            //do not forget to UrlEncode the longUrl!
            string request_url = string.Format(base_url, bitlyGenericAccessToken, System.Web.HttpUtility.UrlEncode(longUrl));

            HttpClient client = new HttpClient();
            client.DefaultRequestHeaders.IfModifiedSince = DateTime.Now;

            //get the response from the Bitly API
            return await client.GetAsync(new Uri(request_url));
        }

The only important thing we think of here is to UrlEncode our long url, using the System.Web.HttpUtility.UrlEncode() method. If we would not do that, we would get an error on some links from the Bitly API. The rest is pretty straight forward to any other HttpClient usage.

To get our BitlyHelper to be helpful, we are creating another Task that detects the HttpStatusCode of our HttpResponseMessage and returns the shortened url:

        /// <summary>
        /// gets the shortened url out of the HttpResponseMessage
        /// </summary>
        /// <param name="longUrl">the url to shorten</param>
        /// <returns>the shortened url as string</returns>
        public async Task<string> GetShortenedUrl(string longUrl)
        {
            string short_url = string.Empty;

            //using try/catch to avoid Exceptions
            try
            {
                var response = await getShortUrl(longUrl);

                if (response.StatusCode == HttpStatusCode.Ok)
                {
                    short_url = await response.Content.ReadAsStringAsync();
                }
                //on error StatusCodes, just return the longUrl
                else
                {
                    short_url = longUrl;
                }
            }
            catch
            {
                short_url = longUrl;
            }

            return short_url;            
        }

In case the HttpStatusCode is not OK (200), we are simply returning the long url. To avoid any Exceptions, we are doing the same in case there is one. This way, we are keeping it as simple as possible while keeping our desired functionality.

The usage is very simple:

BitlyHelper bitly = new BitlyHelper();
var shorturl = await bitly.GetShortenedUrl("http://yourlongurl.com");

If you want more advanced features, you can perform the whole oAuth dance with your users and get some more features into your app (read more in the API docs). If you just need to shorten the url, this BitlyHelper is all you need.

As always, I hope this is helpful for some of you.

Happy coding!

Helper class to handle In-App-Products (IAP) licenses on Windows Phone (SL)

Like a lot of other apps, also UniShare got hit by an outage in the licensing system of the Windows Phone Store recently.

There was a workaround to get the licenses back from the store, but even with that, users have left negative votes (even after I posted the workaround and also wpcentral wrote about it a few days later).

The problem with those negative reviews: they tend to remain, even after responding to them (if possible) or having conversation with the users via mail. I totally understand users that are annoyed by such facts – I got hit by it as well with other apps I am using regularly. So I was thinking about a better solution as the recommended way by Microsoft, which says you should check it on every app start.

Rob Irving posted about his solution at the same day wpcentral wrote about it, which is one possible solution. His motive was the same as my solution – improving the user experience with the IAP’s.

However, I am preferring to check the licenses against the Store from time to time to make sure that the licenses are still correct.

Here is my solution (for durable IAP):

First, let’s we need to declare an object for the ListingInformation, which will hold the information that the store returns for our IAP:

ListingInformation IAPListing;

Then, we  need to create these two classes:

        public class IAP
        {
            public string Key { get; set; }

            public string Name { get; set; }

            public string Price { get; set; }

            public ProductType Type { get; set; }

            public string Description { get; set; }

            public string Image { get; set; }

            public bool IsLicenseActive { get; set; }
        }

        public class IAPToSave
        {
            public List<IAP> IAPListToSave { get; set; }

            public DateTime date { get; set; }
        }

The class IAP is the class/model that holds a single IAP item information. The second class is needed for saving the fetched IAP information (we’ll see later how I did it).

Now we have prepared these, we can finally go to the store and fetch the IAP list. I created an async Task that returns a List<IAP> for it:

        public async Task<List<IAP>> GetAllIAP()
        {
            var list = new List<IAP>();

            IAPListing = await CurrentApp.LoadListingInformationAsync();

            foreach (var product in IAPListing.ProductListings)
            {
                list.Add(new IAP()
                {
                    Key = product.Key,
                    Name = product.Value.Name,
                    Description = product.Value.Description,
                    Price = product.Value.FormattedPrice,
                    Type = product.Value.ProductType,
                    Image = product.Value.ImageUri.ToString(),
                    IsLicenseActive = isPackageUnlocked(product.Key)
                });
            }
            return list;
        }

To immediately check if our user has already purchased the item, we are getting a Boolean for it. While we are getting the data from the store, we are using this to fill our IAP class with the desired value (see IsLicenseActive property in the IAP item above).

        public bool isPackageUnlocked(string productKey)
        {
            var licenseInformation = CurrentApp.LicenseInformation;

            if (licenseInformation.ProductLicenses[productKey].IsActive)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

Now we have already all data that we need to display all IAP in our app. The usage is fairly simple:

var iapHelper = new IAPHelper();
var iapList = await iapHelper.GetAllIAP();

You can now bind the iapList to a ListBox (or your proper control/view). Next thing we are creating is our helper that performs the purchase action and returns a result string to display in a message to the user in our IAPHelper class:

        public async Task<string> unlockPackage(string productKey, string productName)
        {
            var licenseInformation = CurrentApp.LicenseInformation;

            string response = string.Empty;

            if (!licenseInformation.ProductLicenses[productKey].IsActive)
            {
                try
                {
                    //opening the store to display the purchase page
                    await CurrentApp.RequestProductPurchaseAsync(productKey);

                    //getting the result after returning into app
                    var isUnlocked = isPackageUnlocked(productKey);

                    if (isUnlocked == true)
                    {
                        response = string.Format("You succesfully unlocked {0}.", productName);  
                    }
                    else
                    {
                        response = string.Format("There was an error while trying to unlock {0}. Please try again.", productName);
                    }
                }
                catch (Exception)
                {
                    response = string.Format("There was an error while trying to unlock {0}. Please try again.", productName);
                }
            }
            else
            {
                response = string.Format( "You already unlocked {0}", productName);
            }

            return response;
        }

You may of course vary the messages that are displayed to the user to your favor.

The usage of this Task is also pretty straight forward:

var iapHelper = new IAPHelper();
string message = await iapHelper.unlockPackage(((IAPHelper.IAP)IAPListBox.SelectedItem).Key, ((IAPHelper.IAP)IAPListBox.SelectedItem).Name);

After that, we need to refresh the LicenseInformation by using GetAllIAP() again to refresh the iapList and of course our ListBox.

My goal was to save the LicenseInformation of my IAP for a limited time so the user is protected for future outages (or situations where no network connection is available). That’s why we need to add another Task to our IAPHelper class:

        public async Task<string> SerializedCurrentIAPList(List<IAP> iaplist, DateTime lastchecked)
        {
            string json = string.Empty;

            IAPToSave listToSave = new IAPToSave() { IAPListToSave = iaplist, date = lastchecked };

            if (iaplist.Count != 0)
            {
                json = await Task.Factory.StartNew(() => JsonConvert.SerializeObject(listToSave));
            }
            return json;
        }

As you can see, now is the point where we need the second class I mentioned in the beginning. It has one property for the List<IAP> and a DateTime property that we are saving. I am serializing the whole class to a JSON string. This way, we are able to save it as a string in our application’s storage.

The usage of this Task is as simple as the former ones:

var savedIAPList = await iapHelper.SerializedCurrentIAPList(iapList, DateTime.Now);

The last thing we need to create is an object that helps us indicating if a refresh of the list is needed or not. Like I said, I want to do this action time based, so here is my way to get this value:

        public bool isReloadNeeded(DateTime lastchecked, TimeSpan desiredtimespan)
        {
            bool reloadNeeded = false;

            var now = DateTime.Now;

            TimeSpan ts_lastchecked = now - lastchecked;

            if (ts_lastchecked > desiredtimespan)
            {
                reloadNeeded = true;
            }

            return reloadNeeded;
        }

This method just checks if the desired TimeSpan has passed already and returns the matching Boolean value. The usage of this is likewise pretty simple:

var savedlist = await Task.Factory.StartNew(() => JsonConvert.DeserializeObject<IAPHelper.IAPToSave>(App.SettingsStore.savedIAPList));

if (iapHelper.isReloadNeeded(savedlist.date, new TimeSpan(96, 0, 0)))
{
   //reload the list and perform your actions
}
else
{
   //use savedlist.IAPListToSave and perform your actions 
}

This way, we are able to make sure that all IAPs are available for a minimum of time and protect our users against store outages.

For your convenience, you can download the whole class right here. Just replace NAMESPACE with yours and you are good to go.

Note: I know that this approach does not follow the recommended way of Microsoft. It is up to us to deal with bad reviews if something on the store part is not working. This is my approach to avoid negative reviews because of store outages (at least for a limited time). However, like always, I hope this post is helpful for some of you.

Happy coding!

Prevent accidentally exit of your Windows Phone SL app (with Telerik RadMessageBox or Toolkit CustomMessageBox)

preventExit

After finally being able to use my dev center account again after three long weeks, I am back into UniShare development. One of the most requested fixes was to not exit the app when users are not at the compose pivot.

Of course I am listening and I found a solution that should fit nearly all possible scenarios. Here is what I did:

        //handle back key press to prevent accidentally exit of the app
        protected async override void OnBackKeyPress(CancelEventArgs e)
        {
            //get the base handler
            base.OnBackKeyPress(e);

            //go back to the first pivot on all other pivots
            if (MainPivot.SelectedIndex != 0)
            {
                MainPivot.SelectedIndex = 0;
                e.Cancel = true;
            }
            //handle app exit
            else if (MainPivot.SelectedIndex == 0)
            {
                //cancel the back button press
                e.Cancel = true;

                //check if bool isExitQuestionCheckBoxChecked is false and the message needs to be displayed
                if (isExitQuestionCheckBoxChecked == false)
                {
                    //show the message box
                    MessageBoxClosedEventArgs args = await RadMessageBox.ShowAsync("Do you really want to exit the app?", MessageBoxButtons.YesNo, null, "don't ask me again, just exit next time", false, true);
                    if (args.ClickedButton == null)
                    {
                        //save check box value (use IsolatedStorage on earlier versions of Windows Phone)
                        App.SettingsStore.isExitQuestionCheckBoxChecked = isExitQuestionCheckBoxChecked;
                        //go back to the app
                        return;
                        
                    }
                    if (args.ButtonIndex == 0)
                    {
                        //set the check box value
                        isExitQuestionCheckBoxChecked = args.IsCheckBoxChecked;
                        //save check box value (use IsolatedStorage on earlier versions of Windows Phone)
                        App.SettingsStore.isExitQuestionCheckBoxChecked = isExitQuestionCheckBoxChecked;
                        //exit the app
                        Application.Current.Terminate();
                        
                    }
                    if (args.ButtonIndex == 1)
                    {
                        //set the check box value
                        isExitQuestionCheckBoxChecked = args.IsCheckBoxChecked;
                        //save check box value (use IsolatedStorage on earlier versions of Windows Phone)
                        App.SettingsStore.isExitQuestionCheckBoxChecked = isExitQuestionCheckBoxChecked;
                        //go back to the app
                        return;
                    }
                }
                //check if bool isExitQuestionCheckBoxChecked is false and the app should be exited
                else if (isExitQuestionCheckBoxChecked == true)
                {
                    Application.Current.Terminate();
                }
            }
        }

 

Let me explain. The first thing I am checking is if the current PivotItem is the one I want to display the message. If not, I am moving the Pivot to it.

The next step is to show the MessageBox and handle the buttons and the CheckBox. If no button is pressed, the codes saves the value false and goes back to the app.

If the Yes-button is pressed, the code saved the value of the CheckBox and exits. Same happens for the No-button.

If the user presses the back button the next time, the isExitQuestionCheckBoxChecked boolean gets checked – if the user does not want the message and checked it, the app exits as expected.

The above snippet uses the RadMessageBox.

When we use Toolkit’s CustomMessageBox, we need a slightly different approach. First, we do not override the OnBackKeyPress event – instead, we declare a new BackKeyPress event in the page’s constructor:

public MainPage()
{
    InitializeComponent();     
    BackKeyPress += MainPage_BackKeyPress;
}

 

Then, add this code to the newly generated event handler:

        //handle back key press to prevent accidentally exit of the app
        void MainPage_BackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)
        {
            //go back to the first pivot on all other pivots
            if (MainPivot.SelectedIndex != 0)
            {
                MainPivot.SelectedIndex = 0;
                e.Cancel = true;
            }
            //handle app exit
            else if (MainPivot.SelectedIndex == 0)
            {   
                ////check if bool isExitQuestionCheckBoxChecked is false and the message needs to be displayed
                if (isExitQuestionCheckBoxChecked == false)
                {
                //generate a CheckBox as Content
                CheckBox chkbox = new CheckBox()
                {
                    Content = "don't ask me again, just exit next time",
                    Margin = new Thickness(0, 14, 0, -2)
                };

                //generate msg and handle the result
                CustomMessageBox msg = new CustomMessageBox()
                {
                    Title = "Attention",
                    Message = "Do you really want to exit the app?",
                    Content = chkbox,
                    LeftButtonContent = "yes",
                    RightButtonContent = "no"
                    
                };

                msg.Dismissed += (s1, e1) =>
                    {
                        switch (e1.Result)
                        {
                            case CustomMessageBoxResult.LeftButton:
                                //save check box value
                                isExitQuestionCheckBoxChecked = (bool)chkbox.IsChecked;

                                //save the check box value
                                if (IsolatedStorageSettings.ApplicationSettings.Contains("isExitQuestionCheckBoxChecked"))
                                {
                                    IsolatedStorageSettings.ApplicationSettings.Remove("isExitQuestionCheckBoxChecked");
                                }
                                IsolatedStorageSettings.ApplicationSettings.Add("isExitQuestionCheckBoxChecked", isExitQuestionCheckBoxChecked);

                                IsolatedStorageSettings.ApplicationSettings.Save();

                                //exit the app
                                Application.Current.Terminate();
                                break;
                            case CustomMessageBoxResult.RightButton:
                                //save check box value
                                isExitQuestionCheckBoxChecked = (bool)chkbox.IsChecked;

                                //save the check box value
                                if (IsolatedStorageSettings.ApplicationSettings.Contains("isExitQuestionCheckBoxChecked"))
                                {
                                    IsolatedStorageSettings.ApplicationSettings.Remove("isExitQuestionCheckBoxChecked");
                                }
                                IsolatedStorageSettings.ApplicationSettings.Add("isExitQuestionCheckBoxChecked", isExitQuestionCheckBoxChecked);

                                IsolatedStorageSettings.ApplicationSettings.Save();

                                //go back to the app
                                break;
                            case CustomMessageBoxResult.None:
                                break;
                            default:
                                break;
                        }
                    };
                    //show message
                    msg.Show();

                    //cancel all BackKey events
                    e.Cancel = true;

                }
                //check if bool isExitQuestionCheckBoxChecked is false and the app should be exited
                else if (isExitQuestionCheckBoxChecked == true)
                {
                    Application.Current.Terminate();
                }
            }
        }

 

This code is taken from a Windows Phone 8 project and does the same as the first snippet by using the Windows Phone Toolkit.

As always, I hope this is helpful for some of you.

Happy coding, everyone!

How to create an Extended Splashscreen for Universal Apps

Recently, I started to create a real world app to demonstrate the usage of my WordPressUniversal library. While I was working on it, I also decided to extend the Splahscreen which is mandatory for universal apps.There are several reasons to extend the splash screen, the most obvious is to hide initial data loading.

The only sample I found had a separate solution for the Windows and the Windows Phone application, and I decided to put them together to use the advantages of the Shared project that comes with every universal app.

The first step is to add your Splashscreen images to both projects. To do so, open their Package.appxmanifest files and go to the ‘Visual Assets’ tab. Add your images:

Screenshot (371)

Now add a UserControl to your shared project and rename the control type to “Grid” in the XAML file. After that, let us design the UI that is shown to the user when he starts our app:

<Grid.RowDefinitions>
    <RowDefinition/>
    <RowDefinition Height="180"/>
</Grid.RowDefinitions>

<!--Windows needs a Canvas-->
<Canvas x:Name="Win_Splash_Img" 
        Grid.Row="0" 
        Grid.RowSpan="2" 
        Visibility="Collapsed">
    <Image x:Name="extendedSplashImage_Win" 
           Source="Assets/SplashScreen.png"/>
</Canvas>

<!--Windows Phone needs a Viewbox-->
<Viewbox 
    x:Name="WP_Splash_Img"
    Grid.Row="0" Grid.RowSpan="2" 
    Visibility="Collapsed">
    <Image x:Name="extendedSplashImage_WP" 
           Source="Assets/SplashWindowsPhone.png"/>
</Viewbox>

<!--this StackPanel holds our ProgressRing that is telling the user we are doing some work-->
<StackPanel 
    Grid.Row="1" 
    HorizontalAlignment="Center">
    <ProgressRing x:Name="progressRing" 
                  IsActive="True" Margin="0,0,0,12" 
                  Foreground="White" 
                  Background="Black">            
    </ProgressRing>
    <TextBlock x:Name="progressText" 
               Style="{StaticResource TitleTextBlockStyle}" 
               TextAlignment="Center" 
               HorizontalAlignment="Center">
 </TextBlock>
</StackPanel>

This XAML code is the base for our extended Splashscreen. It defines a row height of 180 to place the StackPanel that holds the ProgressRing at the bottom of our control. The main difference here is that Windows Apps use a Canvas while Windows Phone uses Viewbox to hold our Splashscreen Image. We need to set the Visibility on both to collapsed as our code decides which one will be displayed on Launch.

In our code page, we have a bit more work to do. Let’s go through it step by step:

Make sure you have added the following Namespaces:

using Windows.ApplicationModel.Activation;
using Windows.UI.Core;
using ExtendedSplash.Common;

Note: if you do not have a Common folder in your Shared Project, you can add it manually and copy the classes from the demo project attached to this project. Don’t forget to change the Namespaces of the classes to your project name after you added them.

The next step is to declare some objects that we need for the extended Splashscreen:

internal Rect splashImageRect; 
internal bool dismissed = false; 
internal Frame rootFrame;
private SplashScreen splash;

The Rect is used to place the Splashscreen Image in it and will be sized by our code which we will add later. The dismissed bool is used to determine when the system Splashscreen gets dismissed. The rootFrame is used for the navigation to our first application page, while the splash is used to read the needed values for placing our image into the Rect.

After we have declared those objects, we need to overload the main class of our control:

public ExtendedSplash(SplashScreen splashcreen, bool loadstate)

The splashcreen tells us the coordinates and the height of the splash image. You can use the loadstate bool to determine data that needs to be restored by the SuspensionManager, if needed.

As users are snapping our apps or rotating the device, we need to handle this. To do so, we need to add the following line to our constructor:

Window.Current.SizeChanged += new WindowSizeChangedEventHandler(ExtendedSplash_OnResize);

Add this code to handle the resizing:

if (splash != null)
{
    splashImageRect = splash.ImageLocation;
    PositionImage();
}

If the user causes the WindowSizeChanged event to fire, the splash will be loaded again and submits new coordinates to our splash object. To properly handle the positioning, we are using the PositionImage() method:

        void PositionImage()
        {
#if WINDOWS_PHONE_APP
            extendedSplashImage_WP.SetValue(Viewbox.HeightProperty, splashImageRect.Height);
            extendedSplashImage_WP.SetValue(Viewbox.WidthProperty, splashImageRect.Width);
#else
            extendedSplashImage_Win.SetValue(Canvas.LeftProperty, splashImageRect.X);
            extendedSplashImage_Win.SetValue(Canvas.TopProperty, splashImageRect.Y);
            extendedSplashImage_Win.Height = splashImageRect.Height;
            extendedSplashImage_Win.Width = splashImageRect.Width;
#endif
        }

As you can see, we use the preprocessor directive WINDOWS_PHONE_APP to declare the height and width of the Viewbox. If it is not running on Windows Phone, we are setting the canvas coordinates and size via this method. This is not the only point where we need this method, as you will see later in this post.

Let’s go back to our constructor and add this line to load the system’s Splashscreen values into our object:

splash = splashcreen;

Now that we have these values, we are finally able to receive the coordinates and declare which Splashscreen will be used:

            if (splash != null)
            {
                //handle the dismissing of the system's splash 
                splash.Dismissed += new TypedEventHandler<SplashScreen, Object>(DismissedEventHandler);

                //get the system's splashscreen values
                splashImageRect = splash.ImageLocation;

                //decide which control is used to display the splashscreen image and size the progressRing
#if WINDOWS_PHONE_APP
                Win_Splash_Img.Visibility = Visibility.Collapsed;
                WP_Splash_Img.Visibility = Visibility.Visible;
                progressRing.Height = 50;
                progressRing.Width = 50;

#else
                Win_Splash_Img.Visibility = Visibility.Visible;
                WP_Splash_Img.Visibility = Visibility.Collapsed;
                progressRing.Height = 70;
                progressRing.Width = 70;
#endif
                //position and size the image properly
                PositionImage();

            }

 

Let me explain what I have done here. First we need to check if our splash object has a value. Then, we need to handle the Dismissing of the system’s Splashscreen with this TypedEventHandler:

private void DismissedEventHandler(SplashScreen sender, object args)
{
    dismissed = true;
}

After that, I am declaring when to show Windows Phone’s Viewbox and Windows’ Canvas as well as setting the size of the ProgressRing. The last step is to position and size the image again with our PositionImage() method. This will cause the app to switch to our extended Splashscreen.

Now we have to declare a new Frame instance and begin to load our data:

// this frame acts as navigation context
rootFrame = new Frame();
//start loading your data:
LoadData();

For this demo, I used a delay to keep the ProgressRing spinning:

async void LoadData()
{
    progressText.Text = "sleeping, please wait until I wake up...";
    //using a delay to keep the progress ring spinning for this demo
    await Task.Delay(TimeSpan.FromSeconds(5));
    //Navigate to the first application page after all work is done
    rootFrame.Navigate(typeof(MainPage));
    Window.Current.Content = rootFrame;
}

That’s all of the code we need inside our ExtendSplash control. If you now build the project, it will compile, but nothing will happen. other than going directly to the MainPage.

We need to add some additional code to our App.xaml.cs in the OnLaunched event:

//only show the splash if the app wasn't running before
if (e.PreviousExecutionState != ApplicationExecutionState.Running)
{
    //check the loadstate if necessary
    bool loadState = (e.PreviousExecutionState == ApplicationExecutionState.Terminated);
    //create a new instance of our ExtendedSplash
    ExtendedSplash extendedSplash = new ExtendedSplash(e.SplashScreen, loadState);
    //declare our extendedSplash as root content
    rootFrame.Content = extendedSplash;
}

If you hit the debug button, you should have similar results to these:

Screenshot (374)

Screenshot (375)

For your convenience, I created a small demo project. Download it here.

As always, I hope this blog post is helpful for some of you. If you have questions or feedback, feel free to leave a comment below.

WordPressUniversal – a PCL library for WordPress based C# mobile apps

WP_CSharp_Lib

As I have already developed a news reader app for my blog, I got asked quite a few times if I want to share my code to help others creating their apps. As I need to redesign my blog reader to match the latest OS features of Windows and Windows Phone, I decided to create my WordPressUniversal library.

Automattic, the company behind WordPress, integrated a powerful JSON API into their JetPack plugin. My library is based on this API. Please make sure the JSON API is active on the blog you are developing your app for.

The library currently provides the following features:

  • getting a list posts or pages
  • getting a list of all categories
  • getting a list of comments for the site and single posts
  • supports Windows Phone 8 & 8.1 Silverlight, Windows Phone 8.1 RT, Windows 8, Xamarin.iOS and Xamarin.Android

The library deserializes all data into C# objects you can immediately work with.

It is still a work in progress, but as it provides already a bunch of options to get you started, I am making this public already.

I am constantly working on the library, so be sure to follow the project along.

Note: JetPack’s JSON API does not support guest commenting at the moment. I already reached out to Automattic to (hopefully) find a solution for this. If you cannot wait, Disqus has a portable solution for Windows Phone apps.

Please make sure to see the documentation on my GitHub page.

If you have any questions, idea, wishes for me, just post a comment here or ping on Twitter.

Happy coding everyone!

Book review: iOS Development with Xamarin Cookbook (Dimitris Tavlikos)

I love to learn and expand my knowledge. Because of this, I was absolutely happy when I was asked for a book review about Dimitris’ iOS book.

The book is a huge collection of iOS recipes using Xamarin. The first three chapters are going deeply into the UI of an iOS application, looking on a lot (almost all) possible aspects of UI elements. What I like very much is that the author shows the code, usually with a step by step guide, and after that delivers a detailed explanation why something works in the way it does.

The next two chapters are all about creating and displaying data, files and sqlite, providing the same experience as the first chapters.

The sixth chapter is all about consuming services, such as web services, REST services or even WCF services (I wasn’t even aware of this being possible). Very good starting point for so many app ideas.

So far, the book shows already a lot of what we can do with Xamarin. But modern apps often contain media content: videos, photos, capturing media – this is what chapter 7 is all about.

Like all modern Smartphone operating systems, iOS provides some methods to let our apps interact with the OS. The 8th chapter is all about those interactions, like contacts, mail and more and has the matching real world scenarios.

The most usable apps use a device’s sensors, touch and gestures. Of course, with Apple being the leader in this space for a long time (we just need to be fair in this point), iOS has a lot of APIs for these. Chapter nine has some good recipes to help us with improving our app’s UX.

If your app needs location services and maps, chapter 10 is your friend. It shows you how to interact with Apple’s map services, add annotations and a lot more.

Users love when apps have some nice animations when something changes in an app. iOS provides a lot of options, and chapter 11 explains a lot about animations and drawing methods.

One of the most important parts when developing an app is lifecycle handling. As with any other OS, also iOS has its specific methods to handle the lifecycle. Background operations are part of this handling. In chapter 12, Dimitri tells us a lot about handling the states of an app as well as background operations.

Chapter 13 consists of tips and recipes for localization of an iOS app.

One of the most important steps when creating an iOS app is deploying the app. Apps should of course be tested on real devices, and this what chapter 14 is about – but not only. Also the required steps to prepare and app for submission as well as the submission to the store are explained.

The final chapter contains some additional recipes that can make your app more valuable like content sharing or text-to-speech.

Conclusion

I only began with Xamarin.iOS a few month ago. This book provides a great insight into development for iOS using the Xamarin IDE. As I said already, I like the approach of showing code first and then explaining what it does exactly and provide additional info if suitable. This book is absolutely worth every single cent if you want to start with iOS and Xamarin.

If you’re interested in the book, you’re just a click away: http://bit.ly/1tnxmGX

Note: This post was completely written on my phone. If you find typos, you can keep them ;-).

Book review: Learning Windows Azure Mobile Services for Windows 8 and Windows Phone 8 (Geoff Webber-Cross)

During the last months, I used the few times of my spare time when I wasn’t in the mood for programming to read Geoff’s latest book for diving deeper into Azure Mobile Services. Geoff is well known in the community for his Azure experience, and I absolutely recommend to follow him! I am really glad he asked me to review his book and need to apologize that it took so long to get this review up.

The book itself is very well structured with a true working XAML based game that utilizes both Windows 8 and Windows Phone 8 and connects them to one single Mobile Service.

Even if you are completely new to Azure, you will quickly get things done as the whole book is full of step-by-step instructions. Let’s have a quick look on what you will learn while reading this book:

  1. Prepare your Azure account and set up your first Mobile Service
  2. Bring your Mobile Service to life and connect Visual Studio
  3. Securing user’s data
  4. Create your own API endpoints
  5. use Git via the console for remote development
  6. manage Push Notifications for both Windows and Windows Phone apps
  7. use the advantages of the Notification hub
  8. Best practices for app development – some very useful general guilty tips!

I already use a Mobile Service with my Windows Phone App TweeCoMinder. I have already started a Windows 8 version of that app, which basically only needs to be connected to my existing Azure Mobile Service to finish it.

Screenshot (359)

While reading Geoff’s book, I learned how I effectively can achieve this and also improve my code for handling the push notifications on both systems. The book is an absolutely worthy investment if you look into Azure and Mobile Services and has a lot of sample code that can be reused in your own application.

As this is my first book review ever, feel free to leave your feedback in the comments.

You can buy the book right here.

Happy coding, everyone!

Save and load multiple selected items with Telerik’s RadListPicker on Windows Phone 8 & 8.1

wp_ss_20140706_0005

While I am continuing to add new features to my current main project UniShare, I am facing also problems that I never had before in my other apps.

One of those problems is to save and load multiple selected items on Telerik’s RadListPicker control. While the control itself is pretty easy to use, there is no documentation and also no blog posts on how to save and load those selected items.

If you are using Windows Phone Toolkit’s ListPicker, you should be fine by following this post I found during research for a solution. If you are using Telerik’s control like I am, this post is for you.

The main problem we have is that the SelectedItems property cannot be set directly. It has only a get accessor, which results in an error from Visual Studio if you try to set it. Luckily, there is still a way to set the saved  SelectedItems.

You need two things before we can go on: of course Telerik’s Windows Phone UI controls, and JSON.net, which we are using to serialize and deserialize our SelectedItems.

We are going to start with adding a ListPicker to our page:

            <telerikInput:RadListPicker 
                x:Name="TestPicker" Header="select items" 
                OkButtonIconUri="/Assets/PickerOK.png" 
                CancelButtonIconUri="/Assets/PickerCancel.png" 
                SelectionMode="Multiple" 
                SelectionChanged="TestPicker_SelectionChanged">
                <telerikInput:RadListPicker.PopupItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding name}" Margin="16 0 0 0" TextWrapping="Wrap"></TextBlock>
                    </DataTemplate>
                </telerikInput:RadListPicker.PopupItemTemplate>
                <telerikInput:RadListPicker.PopupHeaderTemplate>
                    <DataTemplate>
                        <TextBlock Text="choose item:" Margin="16 0 0 0" TextWrapping="Wrap" Style="{StaticResource PhoneTextTitle2Style}"></TextBlock>
                    </DataTemplate>
                </telerikInput:RadListPicker.PopupHeaderTemplate>
            </telerikInput:RadListPicker>

Pretty easy to use, right? Until now, our RadListPicker does nothing except being there. We need to hook up some code to it.

First we declare a data class for our RadListPicker ItemsSource:

        public class PickerItems
        {
            public string name { get; set; }
        }

After that, we need to get some items into our ListPicker. For this demo I am using static items, but this works also with dynamic ones:

public MainPage()
        {
            InitializeComponent();

            pickerSource = new List<PickerItems>();
            pickerSource.Add(new PickerItems() { name = "item 1" });
            pickerSource.Add(new PickerItems() { name = "item 2" });
            pickerSource.Add(new PickerItems() { name = "item 3" });
            pickerSource.Add(new PickerItems() { name = "item 4" });
            pickerSource.Add(new PickerItems() { name = "item 5" });

            TestPicker.ItemsSource = pickerSource;
            //registering the SummaryForSelectedItemsDelegate event
            TestPicker.SummaryForSelectedItemsDelegate += TestPicker_SummaryForSelectedItemsDelegate;
        }

“pickerSource” is just a List<PickerItems> that is defined globally for the page. Noticed the registration of the SummaryForSelectedItemsDelegate object? Awesome, because we are continuing with exactly that:

        //getting the string that is displayed when our ListPicker is not expanded
        private object TestPicker_SummaryForSelectedItemsDelegate(System.Collections.IList list)
        {
            string summary = string.Empty;

            for (int i = 0; i < list.Count; i++)
            {
                //getting the last item
                bool isLast = i == list.Count - 1;
                //generating the string
                PickerItems groupItem = (PickerItems)list[i];
                summary = String.Concat(summary, groupItem.name);
                summary += isLast ? string.Empty : ", ";
            }

            if (summary == string.Empty)
            {
                summary = "none";
            }

            return summary;
        }

This object is used to get the text that is displayed in the RadListPicker while it is not expanded.

Of course we need to handle the changed selection, that’s why we hook into our TestPicker’s SelectionChanged event:

        private void TestPicker_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

            //saving the selected items
            if (TestPicker.SelectedItems.Count == 0)
            {
                //WP8.1
                //App.SettingsStore.selectedItemsString = string.Empty;

                //WP8
                App.selectedItemsString = string.Empty;
            }
            else
            {
                //WP8.1
                //App.SettingsStore.selectedItemsString = JsonConvert.SerializeObject(TestPicker.SelectedItems);

                //WP8
                App.selectedItemsString = JsonConvert.SerializeObject(TestPicker.SelectedItems);
            }

            //WP8
            if (IsolatedStorageSettings.ApplicationSettings.Contains("selectedItemsString"))
            {
                IsolatedStorageSettings.ApplicationSettings.Remove("selectedItemsString");
            }
            IsolatedStorageSettings.ApplicationSettings.Add("selectedItemsString", App.selectedItemsString);
        }

If we do not have selected items, we are going to save an empty string. Otherwise, we just serialize the selected items (which are an IList<PickerItems>) and save this code to our IsolatedStorage (on WP8) or ApplicationDataContainer (on WP8.1). This way, we can save the selected items without any trouble.

Until now, we only saved our items. Of course we want our app to select those saved items if our users return to this point in our app. The solution to this is a mix of JSON deserialization and LINQ. Add this code to your OnNavigatedTo event:

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            //WP8.1
            //if (App.SettingsStore.selectedItemsString != string.Empty)
            //WP8
            if (App.selectedItemsString != string.Empty)
            {
                try
                {
                    //WP8.1
                    //var selectedItems = JsonConvert.DeserializeObject<List<PickerItems>>(App.SettingsStore.selectedItemsString);
                    //WP8
                    var selectedItems = JsonConvert.DeserializeObject<List<PickerItems>>(App.selectedItemsString);

                    foreach (var item in selectedItems)
                    {
                        //using LINQ to get the matching item from pickerSource
                        var selectedItem = pickerSource.Where(x => x.name == item.name).Single<PickerItems>();
                        //getting the index
                        int index = pickerSource.IndexOf(selectedItem);
                        //setting the item as selected
                        TestPicker.SelectedItems.Add(pickerSource[index]);
                    }
                }
                catch { }
            }

        }

Let me explain what I have done in there. First, I checked if there are selected items by checking if the saved string is empty. If not, I am deserializing the saved JSON string into a List<PickerItems>.

In the next step, we are iterating with a foreach loop over this List<PickerItems>. We are looking for each item that is in this list, and if it exists, we pick up this item from our pickerSource. This item has its own index position within the pickerSource List<PickerItems>. We assign this position as a an integer value to a local object in the foreach loop.

The most important point is the last step: adding the item to the SelectedItems IList<PickerItems>. After adding all items, our SummaryForSelectedItemsDelegate automatically reflects those changes. Bonus: this way, also the order of the selected items is still the same as at the time the user selected those items (which can be a case).

wp_ss_20140706_0004

If you do not want this, you should sort the SelectedItems before saving them. I wrapped the code in a try catch blog to avoid serialization exceptions for this demo project, you should handle/avoid them of course in a real world app.

Once one figured these steps out, pretty easy to solve. And finally, it is also documented by a blog post. As always, I hope this is helpful for some of you.

For your convenience, you can RadListPickerMultiSelect.

Until the next post, happy coding!

Using BugSense to track errors and events in a Windows Phone app

BugSenseWhy BugSense?

Errors/exceptions are annoying and helpful at the same time. They can annoy you while creating your app. At the same time, they help you to improve the quality of your app (most of the time, that is). They annoy your users, if they lead to crash your app. At the same time, they are a good chance to get in contact with your users – for example you could catch unhandled exceptions and ask the user to send it over to you.

But what if your users choose to ignore the error? How should you improve your app’s quality? What if the only thing you get are bad reviews? Pretty hard task, especially if you have a completely new app. I had that situation over and over again – and of course, I was annoyed of that fact.

So I researched the internet for solutions. Google Analytics is one service that works and is mostly used in enterprise apps. I use it in the app I am developing for my 9to5 job on Windows Phone and Android, but I only am able to use it on Windows Phone due to a third party library. If the developer chooses to not continue his efforts, at one point it will stop working or at least needs manual maintenance from my part  (looking at you, TweetSharp).

BugSense was the second alternative I had a look on. They are  a big player in the mobile monitoring market, and have a very good basic model, that fits perfectly for the average developer (500 errors per month, 350000 data points per month for free) to get started, and their first pricing stage if you have more apps comes close to what indie developers like I am need to maintain more than one app.

On top, there is often the possibility to gain promo codes that unlock some of the functionalities for free for a limited time (like DVLUP promo codes etc.).

I can only recommend to give it at least a try. On major point on the plus side was the fact that BugSense also has a Windows Phone app that helps you to keep up to date with the errors and insights while you are on the go.

Setting up an app is also pretty easy, be it tracking errors or tracking events. Let’s have a look at the code.

Error handling

The first thing you’ll need to to install is the BugSense SDK either via Nuget (‘BugSense.WP8′ for WP 8.0 / 8.1 Silverlight, ‘BugSense.WP81′ for WP 8.1 Runtime) or you can download the package manually here and import the dll for SL projects.

Next step is to authorize your app in your app’s constructor:

public App()
{
    //connect your app to the BugSense API’s
    BugSenseHandler.Instance.InitAndStartSession(new ExceptionManager(Current), RootFrame, "");
}

For WINPRT projects, you’ll leave the Rootframe parameter out.

The official documentation says you don’t need the UnhandledException handler any longer and can remove it. In a real Windows Phone app, this could lead to crashes from exceptions by the BugSense handler that are not caught without any error logging – thanks to Sara Silva for pointing me to that (follow her!). I’ll leave it up to you if you leave it there to handle those errors or if you are fine with your app being crashing in this case.

I am also telling you what I did: I left the UnhandledException handler in there because my users are already used to another thing I used before: Telerik’s RadDiagnostics, which enables users to send those error messages via mail. I left it there for two reasons:

  • to keep the interaction with my user that I already had when an error showed up
  • to prevent my app from crashing – no matter if the error comes from BugSense or my code

For error logging, there is only one point left to do. After my experience, error logging only works after registering a new instance of the BugSense handler (I am doing this in my first page’s Loaded event):

BugSenseHandler.Instance.RegisterAsyncHandlerContext();

That’s all, now all your errors are collected into your BugSense account.

Event tracking

If you want to track events in your app, BugSense is helpful on that task, too. The easiest way to achieve is this one:

await BugSenseHandler.Instance.LogEventAsync(“");

Conclusion

With BugSense you don’t need a complex setup to collect errors and track events remotely from your users devices. Pricing is moderate, and you even have a mobile app that allows you to keep track of errors when your are not on your dev machine. BugSense has a lot more options, for getting started, I hope this post is helpful for some of you.

Until the next post, happy coding!

How to load a list of a user’s twitter friends/followers in your Windows Phone app

TwitterFriendsList_WP_Blog During the last days, I was adding a new function to UniShare that suggests users the Twitter handles while typing in some text. The base of this new function is a list of the user’s twitter friends. In this post, I am going to show you how to generate this list and save it for further use. First thing I need to talk about: you can only load a maximum of 3000 friends at once due to the rate limit on Twitter’s part. At the end of the post, I’ll give you also an idea how to continue this after the first 3000 users were loaded. For the most scenarios, 3000 should be enough to cover the major part of your users. To be able to load all friends we first create a Task that fetches 200 entries of our user’s friends list. To be able to perform paging through all entries, Twitter uses so called cursors, which are 64-bit signed integers (long). You can read more about that here on Twitter’s API documentation. Let’s have a look on this Task:

        private async Task<string> TwitterFriendsListString(long twitterCursor)
        {
            ShowProgressIndicator("generating mention suggestion base...");

            //needed for generating the Signature
            string twitterRequestUrl = "https://api.twitter.com/1.1/friends/list.json";

            //used for sending the request to the API
            //for usage of the url parameters, go to https://dev.twitter.com/docs/api/1.1/get/friends/list
            string twitterUrl = string.Format("https://api.twitter.com/1.1/friends/list.json?cursor={0}&screen_name={1}&count=200&skip_status=true&include_user_entities=false", twitterCursor, App.SettingsStore.twitterName);

            string timeStamp = GetTimeStamp();
            string nonce = GetNonce();

            string response = string.Empty;

            //we need to include all url parameters in the signature
            //IMPORTANT: Twitter's API demands them to be sorted alphabetically, otherwise the Signature will not be accepted
            string sigBaseStringParams = "count=200";
            sigBaseStringParams += "&" + "cursor=" + twitterCursor;
            sigBaseStringParams += "&" + "include_user_entities=false";
            igBaseStringParams += "&" + "oauth_consumer_key=" + twitterConsumerKey;
            sigBaseStringParams += "&" + "oauth_nonce=" + nonce;
            sigBaseStringParams += "&" + "oauth_signature_method=HMAC-SHA1";
            sigBaseStringParams += "&" + "oauth_timestamp=" + timeStamp;
            sigBaseStringParams += "&" + "oauth_token=" + App.SettingsStore.twitteroAuthToken;
            sigBaseStringParams += "&" + "oauth_version=1.0";
            sigBaseStringParams += "&" + "screen_name=" + App.SettingsStore.twitterName;
            sigBaseStringParams += "&" + "skip_status=true";
            string sigBaseString = "GET&";
            sigBaseString += Uri.EscapeDataString(twitterRequestUrl) + "&" + Uri.EscapeDataString(sigBaseStringParams);

            string signature = GetSignature(sigBaseString, twitterConsumerSecret, App.SettingsStore.twitteroAuthTokenSecret);

            string authorizationHeaderParams =
                "oauth_consumer_key=\"" + twitterConsumerKey +
                "\", oauth_nonce=\"" + nonce +
                "\", oauth_signature=\"" + Uri.EscapeDataString(signature) +
                "\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"" + timeStamp +
                "\", oauth_token=\"" + Uri.EscapeDataString(App.SettingsStore.twitteroAuthToken) +
                "\", oauth_version=\"1.0\"";

            HttpClient httpClient = new HttpClient();

            httpClient.DefaultRequestHeaders.Authorization = new HttpCredentialsHeaderValue("OAuth", authorizationHeaderParams);
            var httpResponseMessage = await httpClient.GetAsync(new Uri(twitterUrl));

            response = await httpResponseMessage.Content.ReadAsStringAsync();

            return response;
        }

As you can see, we need to create our signature based on the url parameters we are requesting. Twitter demands them to be sorted alphabetically. If you would not sort them this way, the Signature is wrong and your request gets denied by Twitter. We are overloading this Task with the above mentioned cursor to get the next page of our user’s friends list. If you need the GetNonce() and GetSignature() methods, take a look at this post, I am using them for all requests to Twitter. Now that we have this Task ready to make our requests, lets load the complete list. First, declare these objects in your page/model:

        public List<TwitterMentionSuggestionBase> twitterMentionSuggestionsList;
        public long nextfriendlistCursor = -1;
        public string friendsResponseString = string.Empty;
        public string friendsJsonFileName = "twitterFriends.json";

Then we need to create a loop to go through all pages Twitter allows us until we are reaching the rate limit of 15 requests per 15 minutes. I using a do while loop, as this is the most convenient way for this request:

            //to avoid double entries, make sure the list is we are using is empty
            if (twitterMentionSuggestionsList.Count != 0)
            {
                twitterMentionSuggestionsList.Clear();
            }
            //starting the do while loop
            do
            {
                //fetching the Json response
                //to get the first page of the list from Twitter, the cursor needs to be -1
                friendsResponseString = await TwitterFriendsListString(nextfriendlistCursor);

                //using Json.net to deserialize the string
                var friendslist = JsonConvert.DeserializeObject<TwitterFriendsClass.TwitterFriends>(friendsResponseString);
                //setting the cursor for the next request
                nextfriendlistCursor = friendslist.next_cursor;

                //adding 200 users to our list
                foreach (var user in friendslist.users)
                {
                    //using the screen name ToLower() to make the further usage easier
                    TwitterMentionSuggestionsList.Add(new TwitterMentionSuggestionBase() { name = "@" + user.screen_name.ToLower() });
                }

                //once the last page is reached, the cursor will be 0
                if (nextfriendlistCursor == 0)
                {
                    //break will continue the code after the do while loop
                    break;
                }
            }
            //the while condition needs to return true if you would set up a Boolean for it!
            while (nextfriendlistCursor != 0);

As long as the cursor is not 0, the loop will load the json string with 200 entries. The class you’ll need for deserializing can be easily generated. Just set a breakpoint after the call of our Task, copy the whole response string and go to http://json2csharp.com to get your class. The TwitterMentionSuggestionBase class only contains a string property for the name and can be extended for you needs:

    public class TwitterMentionSuggestionBase
    {
        public string name { get; set; }
    }

Of course we need to save the list for further use. The code I use is pretty much the same you’ll find when you search for “saving json string to file” with your favorite search engine and works with Windows Phone 8 and 8.1:

            //saving the file to Isolated Storage
            var JsonListOfFriends = JsonConvert.SerializeObject(twitterMentionSuggestionsList);
            try
            {
                //getting the localFolder our app has access to
                StorageFolder localFolder = ApplicationData.Current.LocalFolder;
                //create/overwrite a file
                StorageFile friendsJsonFile = await localFolder.CreateFileAsync(friendsJsonFileName, CreationCollisionOption.ReplaceExisting);
                //write the json string to the file
                using (IRandomAccessStream writeFileStream = await FriendsJsonFile.OpenAsync(FileAccessMode.ReadWrite))
                {
                    using (DataWriter streamWriter = new DataWriter(writeFileStream))
                    {
                        streamWriter.WriteString(JsonListOfFriends);
                        await streamWriter.StoreAsync();
                    }
                }
            }
            catch
            {

            }

This way, we can easily generate a friends list for our users, based on their Twitter friends. Some points that might be helpful:

  • users with more than 3000 friends will receive an error after reaching this point on our task. Catch this error, but continue to save the already loaded list. Save the latest cursor for the next page and prompt the user to continue loading after 15 minutes to continue loading.
  • if you want to have a list with more details about a user’s friends, extend the TwitterMentionSuggestionBase class with the matching properties.
  • this code can also be used to determine the followers of a user, you just need to change the url parameters as well as the signature parameters according to the matching Twitter endpoint

As always, I hope this is helpful for some of you. Until the next post, happy coding!