Category: Code


Scenario

My latest adventure took me towards developing a location tracking application using PhoneGap. The goal was to continuously monitor the location of the user (obviously the user had to permit the app for doing so – Privacy alert!) and share the info with the peers. This required interacting with the iOS Location Services to get the current location coordinates of the user and then sending them over to the backend server via an ajax call, etc. While this sounds easy, I had to go thru various obstacles to reach the right solution. I am going to divide the solution in a series of blog posts to throw light on all situations faced and the good/bad solution choices then finally how the goal was achieved.

What is PhoneGap?

In case you didn’t know, PhoneGap is a framework that allows cross-platform web application development for mobiles using HTML5, JS, CSS3 and without requiring the developer to have experience with the native language of the targeted platform.

Basic Approach

Ever since PhoneGap v3+, it has become much easier to access a device’s native functionalities. PhoneGap is based on Apache’s Cordova project which is a set of APIs (adhering to W3C HTML5 specs) that enables accessing the native device features directly from javascript accomplished via “Plugins”. A plugin is a piece of native and javascript code bundled together, the native code exposes an interface i.e. methods that access the device features and the javascript code is used for enabling invocation of the exposed interface thru user-defined JS code. Depending on the platform the native language varies e.g. Objective C for iOS and Java for android, etc. In this blog, we’ll consider the strictest platform to code for iOS 7. 🙂

Getting Started

To get started, install Node.JS followed by PhoneGap module (which internally installs Cordova) as show here. I had PhoneGap 3.3.0, Xcode5 and command line tools installed on my machine while writing this blog post. Now, if you follow the documentation provided by PhoneGap like a good student you would execute the following commands:

Install PhoneGap

sudo npm install -g phonegap

Create a PhoneGap app

phonegap create MyAppFolder "com.myorg.loctracker" "My Location Tracker"

Add iOS as platform

cd MyAppFolder
phonegap build ios

Add Geolocation plugin

phonegap plugin add org.apache.cordova.geolocation
cd www
vi config.xml

Add the following lines in the file at the bottom (but as a child of widget tag) and save the file:

<feature name="Geolocation">
   <param name="ios-package" value="CDVLocation" />
   <param name="onload" value="true" />
</feature>

Thats it for the configuration part. Now lets just run the app for the first time by:

phonegap run ios

This would automatically launch the iOS simulator with the basic PhoneGap app running on it, that looks like this:

PhoneGap Basic Installation

PhoneGap Basic Installation

The code you see comes from www/index.html page hosted on a native UIWebView control. The cool thing here is you actually have a web app running on your iOS as a native app without actually requiring the code to be hosted on an external server.

Now you have the basic app running. I encourage you to explore the code added in the “plugins” folder to understand the code structure, to given an overview, the native code will be present inside the “plugins/org.apache.cordova.geolocation/src/ios” directory and javascript is at “plugins/org…/www” directory. The Xcode project is located at “platforms/ios/” directory, you’ll need this later.

Congratulations, you now officially know how to create PhoneGap app for iOS. Feel free to explore the API documentation. In the next post, I’ll cover the following:

  • Life cycle of a phonegap app
  • Getting geolocation coordinates on-demand
  • Monitoring location change in realtime

Stay tuned!

Advertisements

I recently was working on making a webpage compatible with the portable devices specifically iPhone & iPad. And when I say compatible, there are only 2 things to keep in mind:

  1. The graphical elements should maintain the layout or gracefully adjusted to remove the horizontal scroll.
  2. The functionalities are preserved – this would include all the dynamic aspects like server side calls, animations, etc.

For the first requirement, we have a really great solution – “Twitter Bootstrap”. Just add it to any page and making it responsive becomes super easy. Of course, it does require the programmer to still have a sense of a front-end designer i.e. just putting the framework in place is not going help, it requires some effort still. I am going to refrain from going into details about the styling aspect in this post and talk about the issues I dealt in terms of functionality.

The second requirement is tricky and get really annoying at times. Some components required replacing, tweaking while somethings were not supported at all. Below, I’m going to mention all the challenges I faced:

  • Custom scrolling solution like jquery.slimScroll had some rendering/processing issues, though iScroll is a good replacement.
  • If you are using text controls than the virtual keyboard can create mayhem for your user experience, the primary reason is when the keyboard opens, the page automatically scrolls up but the original position fails to restore when the keyboard is closed.
  • Sounds & Videos – while on the desktop you can play these as and when required i.e. on page load, based on an event, the iOS web engine only allows the playing of these files as consequence of a user action ONLY. This can totally ruin your UX if you have a auto-playing media files.
  • If the user puts the browser in the background or is working with multiple tabs, then in pre-iOS 7 devices, the pages state will be lost i.e. when the user goes back to the page it’ll open up like you hit refresh. While the query string params in the URL are retained, the post params are lost. In iOS7, I guess there’s a better handling of this particular case where the page is kept in memory but maybe its only for a limited time.

One good thing is jQuery works nicely and the socket.io also is not blocked although Apple only wants to use APNS for their push notifications but then again when the browser is in the background, the page is dead and no processing is done.

How do we handle these cases where we dont want to create a Native App due to lack of time, resources, experience, etc? Well one solution can be PhoneGap, it allows you convert your existing web app into a iOS installable application. Please see that it doesnt cover all the cases mentioned above directly, you would still have to write some native code as an hybrid solution but it reduces a lot of pain. Also, you’ll have to go thru Apple Developer Program and App publishing guidelines to ensure the app is available at the AppStore. It sounds like more of a mess but its a one time investment, for a solution that works!

 

Xaml Spy usage problem

XAML Spy (previously known as Silverlight Spy) is quite famous with Silverlight development groups to investigate into existing XAML based applications. It provides quite an insight to the developer if not the exact solution for a given scenario. I have used the older version ‘Silverlight Spy’ multiple times in the past to get the details of how the Pivot Viewer control works, etc. But with XAML Spy released, I felt a need to have a hands on experience to see the changes. So, I downloaded the tool, added my application (built in Silverlight 5) but the XAML Spy didn’t detect the application…I tried checking the app for errors but nothing, the app was running perfectly in Visual Studio. So, I thought about using the older version of Silverlight Spy and to my amazement, the app was detected and I was able to explore the XAML as well! Now, whats going wrong?

I was about to send a mail to the support but I thought to doing what us developers are not used to or just don’t want to do…Read the Tutorials :), I stumbled around the page Manually connect a Silverlight app (having no idea what it means), but followed it and Eureka…XAML Spy now detected my application.

Although its working, my question to the First Floor Software team is why such a requirement? Why does the customer require to modify their codes? What to do when the app is not really yours and you cant modify it?

In the past, many times I have come around a situation where I want to load a completely different set of facets in the Pivot Viewer without really instantiating a new instance of it! While in the Pivot Viewer’s first version it was relatively simpler (by just loading a different cxml) but in the second version it didn’t work right, when I was using the client-side loading of items. There was always something that didn’t work example the filter pane wouldn’t show the facets of the new collection, etc. But, there’s a very simple solution for this (actually it was too simple to be believable for the first time…at least for me), so here it is…before you set the new PivotProperties and the Templates, just write down the following 3 lines:

ItemPivot.ItemsSource = null;
ItemPivot.PivotProperties.Clear();
ItemPivot.ItemTemplates.Clear();

Thats it! And you’ll never face a problem in loading a new set of items following a different structure again! Kapish? 🙂

In Silverlight 5 (and may be earlier), you would face a real frustrating issue when using ChildWindows…the problem is as soon as you close a ChildWindow the application would freeze. Well, the solution is pretty simple it requires you to copy-paste the following piece of code to your ChildWindow’s class:

protected override void OnClosed(EventArgs e)
{
   base.OnClosed(e);
   Application.Current.RootVisual.SetValue(IsEnabledProperty, true);
}

Code Source: Silverlight Community

While I am not the guy who found it, but I sure have used it a lot of times and trust me, it does work.

Cheers! 🙂

Pivot Viewer v2: Custom actions on items

A good post here by “Good Coffee Good Code” guy explains the complete process and provides a sample solution here. Download and check it out!

In Pivot Viewer v2, sorting of multivalued facets is not taken care of automatically (i.e. if you are binding items in the non-cxml way). I took the sample provided at the end Pivot Viewer’s documentation here and changed the Employee class to:

public class Employee
{
	public Employee(string firstname, string lastname, DateTime? birthDate, string department, string office, string title, string officePhone, string personalPhone)
	{
		FirstName = firstname;
		LastName = lastname;
		Birthdate = birthDate;
		Department = new List<string> { department, "D1", "D2", "D3", "D4", "D5" };
		Office = office;
		Title = title;
		OfficePhone = officePhone;
		PersonalPhone = personalPhone;
	}

	public string FirstName { get; set; }
	public string LastName { get; set; }
	public DateTime? Birthdate { get; set; }
	public List<string> Department { get; set; }
	public string Office { get; set; }
	public string Title { get; set; }
	public string OfficePhone { get; set; }
	public string PersonalPhone { get; set; }
}

i.e. the “Department” variable is now of List<string> type. Then, I added “Department” as a Filterable Pivot Property in the xaml like:

<sdk:PivotViewerStringProperty Id="Department" Options="CanFilter" DisplayName="Department" Binding="{Binding Department}" />

The result was when I tried to sort on this property, it threw an error:

“Failed to compare two elements in an array. At least one object must implement IComparable”

As the error explains, the error comes because the List object doesn’t have an implementation for IComparable due to which the sorting is not supported. It kind of makes sense too since a generic sorting criteria of how a List object is compared with another cant be decided. To make this work, I created a custom class that inherits the List object and has an implementation for the IComparable interface. For the sorting comparison, I did it according to the number of items in an object compared with the other. I know its not going to be correct in most of cases, but hey…its just a feasibility shown here, you can sophisticate the sorting mechanism as much as you like! 🙂 The custom class goes like:

/// <summary>
/// Custom class to support multivalued facets sorting
/// </summary>
public class StringFacets : List<string>, IComparable
{
	#region Implementation of IComparable

	/// <summary>
	/// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
	/// </summary>
	/// <returns>
	/// A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has these meanings: Value Meaning Less than zero This instance precedes <paramref name="obj"/> in the sort order. Zero This instance occurs in the same position in the sort order as <paramref name="obj"/>.Greater than zero This instance follows <paramref name="obj"/> in the sort order.
	/// </returns>
	/// <param name="obj">An object to compare with this instance. </param><exception cref="T:System.ArgumentException"><paramref name="obj"/> is not the same type as this instance. </exception>
	public int CompareTo(object obj)
	{
		//PUT YOUR SORTING LOGIC HERE
		var stringFacet = obj as StringFacets;
		if (stringFacet == null)
			return -1;

		if (stringFacet.Count < this.Count)
			return -1;
		
		if (stringFacet.Count == this.Count)
			return 0;
		
		if (stringFacet.Count > this.Count)
			return 1;

		return -1;
	}

	#endregion
}

 

And the class is to be used as follows in the Employee class:

public StringFacets Department { get; set; }

 

Now, when you will try to sort the items based on the  “Department” category, it would work like a charm. The code is available at https://skydrive.live.com/embedicon.aspx/Blog/SLPV2_Sorting.rar?cid=e24ef727df20622d&sc=documents.

If you would like to share any improvement, its going to be awesome!

Pivot Viewer v2 (released as a part of SL 5 RC) is one of smartest improvements done by MS to its own products. However, there are still somethings which are not very clearly available. For instance, sorting multivalued facets, custom actions, etc. In this series of blogs, I am going to explain to you how one can do the tasks which were quite easy in the old version of Pivot Viewer but not so straight forward in this version and then later I’ll take you through how you can harness the power of this newer version of the super awesome product. The series will evolve as follows:

Stay tuned!

Silverlight 5 Toolkit is here!

Good news for all those facing problems with SL5 RC projects and the SL4 Toolkit issues! The Toolkit for SL5 RC projects is available here.

Happy coding! 🙂

After playing with Pivot Viewer for long time, I decided to take one more step of going towards a decentralized approach i.e. storing data in different servers. So, I created 3 servers, one for images another for data (about facets) and one server for Pivot Viewer JIT Collection generation. Everything was well set and all communication working fine and suddenly I couldn’t see images any more in the Pivot Viewer. I checked all the images that my images were accessible from my machine, the data was going to the JIT server properly and also checked all the possible options where an exception could be raised and I didnt find anything…and still no images!

Then I compared the CXML files from the version before and this new setup and I found out that there was no information about the images and I was really pissed…as to what in the world went wrong? Then it struck into my mind to try an access the images on the server where the CXML is being generated and BINGO! The error was even though the images existed and were accessible from the my machine…they were not accessible on the JIT server and as soon as I enabled the access of the images on this server, the images started to show up on the pivot viewer as well.

Come to think about it, its pretty logical and I should have known that this would happen but I didn’t realize until I faced the issue. And sharing this, might help some other poor soul like mine was for the last 2 days.

Cheers!