Discussing the nuts and bolts of software development

Friday, February 25, 2011

 

Windows Phone 7 Isolated Storage Explorer & Open Source Project

Simplifying WP7 local data storage development and testing

Written by: Anthony Hooper and Romeo Dumitrescu

One of the biggest challenges for developing any advanced Windows Phone 7 applications is not using or manipulating the isolated storage, but rather having to continuously set up test and development data over and over again as new features are added or bugs are found and fixed.  Although the WP7 development tools Microsoft has provided are arguably the best of class, there currently is no easy way to explore, load, or export local data in a WP7 device or emulator that is developer friendly.  Until now.


Enter the WP7 Isolated Storage Explorer.  Both a stand alone tool (that connects either to an emulator or a tethered device) or a Visual Studio 2010 plug-in that enables developers and QA specialist or testers to explore, save, and even upload data to the isolated storage.

Lets first explore why the isolated storage is important for WP7 applications.  Relying heavily on loading and storing data from the cloud (web services) results in slow loading and sluggish response time of the application.   It’s a best practice to cache some data locally and in many situations much of the data in a mobile application can be stored locally, something many application do not do.

So how does the WP7 isolated storage explorer enter into the development cycle?  Simply put, it facilitates iterative development and testability of your WP7 applications by facilitating saving, loading and exploring any isolated storage files associated with your WP7 applications.  It will speed up debugging edge cases by enabling developers to load isolated storage cache files to the emulator or device, it will empower QA/Test specialists by enabling them the power to explore local data files to help identify critical bugs.  Furthermore, it will speed up testing and feature development by enabling testers and developers the ability to preload their devices/emulators with dev and test data to short cut recreating use cases.


How do you get started?

            // Code to execute when the application is launching (eg, from Start)
       // This code will not execute when the application is reactivated
       private void Application_Launching(object sender, LaunchingEventArgs e)
       {
            IsolatedStorageExplorer.Explorer.Start("localhost");
       }

       // Code to execute when the application is activated (brought to foreground)
       // This code will not execute when the application is first launched
       private void Application_Activated(object sender, ActivatedEventArgs e)
       {
            // This will restore the state of the explorer and the hostname after
            //  reactivating the application
            Explorer.RestoreFromTombstone();
       }

The connected application will show up in the application drop down list in the WP7 Isolated Storage Explorer desktop client. To see the Visual Studio integrated client: In Visual Studio 2010, click on the View > Other Windows, select WP7 Isolated Storage Explorer.

Finally, why did we start this project? It started as one of our developer's aggravations with the MS provided SDKs. Not that they weren't fantastic (they were very complete) but local storage was difficult to work with. Furthermore, Macadamian believes in efficient, predicable testability of all applications we build. We felt that this was missing from the SDKs provided by Microsoft and hope that this project/tool can help the WP7 developer community. There is nothing like a little healthy competition on the mobile marketplace!

Wednesday, February 09, 2011

 

Nokia and Microsoft to Join Forces? by Martin Larochelle

Last week I attended a presentation by Nokia about how to do business with them. I was planning to write a blog about how to develop for their phones and how to publish applications to the Ovi Store.


I concluded that if one has many C++ developers, the Nokia phone is quite accessible. Most of their presentation was focused around how Qt can now be used to develop for all of their platforms (Symbian, Maemo, MeeGo). This is great for us, because we did a couple of projects with Qt in the past six months. They followed with a walk-through of publishing apps to the Ovi Store. Bottom line, the review process takes 7 to 9 business days and it is rejecting slightly over 30% of the submissions on the fist pass.


Today, a Nokia internal memo was leaked,the contents of which indicated that things could all change on Friday. The memo revealed that the N9 should be the first Nokia device to ship with MeeGo. "at this rate, by the end of 2011, we might have only one MeeGo product in the market". In their presentation, Nokia had hinted that their CEO would make an announcement at MWC, which most of us assumed to be their anticipated MeeGo Tablet. But given the contents of the memo and the fact that the CEO only expects one MeeGo device to ship this year, it now seems unlikely.


The memo will fuel the rumour that Nokia would move to WP7 for its phone platform. In insight, we learned how the Nokia Ovi Store could be a great asset to get WP7 off the ground.


Possibly the biggest asset that Nokia has is the global reach of its platform. Nokia covers 170+ counties with credit card payment and 99 countries with carrier billing. Their store is translated into 30 languages and their application approval process includes a moderation process that takes into account the regional and culture differences of each country published to.


The most surprising statistic which they've released is that carrier billing has increased app sales by up to 13x in some markets. In comparison, Android has carrier billing in two countries and the other competitors have none. These agreements take time to negotiate, and most carriers want to take 50% of the app price. If Nokia brings that to another ecosystem, it would increase the app sales drastically.


Instead of WP7 it would be easier for Nokia to go with Android and have their own application market for their phones. But will developers really want to submit their apps on all these application market clones? WP7 seems like the most accessible choice.


On the other hand, WP7 is struggling. It did not even surpass Windows Mobile in Q4. Although Microsoft shipped 2 million phones, it took almost two months for our biggest WP7 fan to find the one he wanted. What if Nokia moved to WP7 and started distributing massive amounts of WP7 world-wide? It would be a huge gain for Microsoft, having the potential to give them 30% of the World’s smartphone market shares. These potential gains could justify an exclusive deal with Nokia.


According to their memo, Nokia is "standing on a burning platform", which they plan to evacuate on Friday. Will they save the value they have, partner up with Microsoft, and create an ecosystem that can compete with iPhone and Android?


Tuesday, February 01, 2011

 

Pass Me the Data, by Rob Woods

You've written the Hello Android app, then created your own simple app. Now you've created a much more complicated app with several activities. You may need to be able to pass data between your activities. In this post, I will take you from the basics of passing simple data types between activities, right up to making your own custom objects parcelable so they can also be passed along with the same ease as a simple data type.
If you feel that you need a bit more background on this subject matter before reading further, here is a helpful article on Android application development.

Before we start passing data around, first you will need to understand how an activity is launched. To launch a new activity, you would create an Intent and pass it to the Activity method startActivity().

Illustration:
"Intent newIntent = new Intent(Context, Class);
startActivity(newIntent);"

Now lets say you have a listactivity, and whenever a user taps on an entry in the list, you want to launch a new activity that does something with the data from that list entry. The most basic scenario for passing data is to attach an extra to the intent in the form of

"newIntent.putExtra(name,value);"

Where name is a String that is used to "tag" your data and value is the actual data object you are passing to the intended activity. Value can be many different types, including String, int, Boolean, etc. You can see the complete list of putextra methods here.

Here's an example from the callingaActivity.
"Intent newIntent = new Intent(this, SomeActivity.class);
newIntent.putExtra("MAGIC_NUMBER", 42);
startActivity(newIntent);"

Now on the called activity side (receiving the Intent), in your activities onCreate() method, you will need to retrieve the extra data from the intent. You can do this by calling getIntent() to get the intent that started the activity, then getIntExtra(name, default). This is if you passed an int value, if you passed a different type, you would use the corresponding method for that type.

For example:
"int magic_number = getIntent().getIntExtra("MAGIC_NUMBER", 420);"

Note that the default value is used if the tag "MAGIC_NUMBER" had no value assigned to it. This is great if you are just passing one piece of data using a basic data type, but if you are passing more data than just a single type, you might want to consider using Bundle.

Basically, a Bundle is just a mapping of tag-data pairs grouped together into one passable object. Let's say that you had a contact list and when the user taps a contact, you want to pass the name, id and phone number to the called Activity. You could do so like this:

"Intent newIntent = Intent(this, ContactDetails.class);
Bundle extras = new Bundle();
extras.putString("CONTACT_NAME", name);
extras.putInt("CONTACT_ID", id);
extras.putString("CONTACT_NUMBER", number);
newIntent.putExtras(extras);
startActivity(newIntent);:

And on the receiving Activity:

"Bundle extras = getIntent().getExtras();
String name = extras.getString("CONTACT_NAME");
int id = extras.getInt("CONTACT_ID");
String number = extras.getString("CONTACT_NUMBER");"

Now lets say you've created your own data class with several different types of data representing the class:

"public class Dog extends Object {
private String mType;
private String mName;
private int mId;

public Dog(String type, String name, int id) {
mType = type;
mName = name;
mId = id;
} "

You could pass each piece of data separately by adding 4 tag-data pairs to a Bundle and passing the Bundle. However, a smarter way of doing this is to implement the parcelable interface in your Dog class. The parcelable interface has 2 methods which are needed to implement, describeContents() and writeToParcel(Parcel, int).

"@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mType);
dest.writeString(mName);
dest.writeInt(id);
}"

Using this method, you must add each of your data types to the Parcel with the correct write method for its data type.

If your class has child classes, you can use the describeContents() method to differentiate between child classes so that when you unparcel your parceled object, you can create the correct child object.

This is only half of the solution. Now that you have the facilities to write your object to a parcel, you also need to be able to rebuild your object in the called activity. First you will need a new constructor for your class. One that takes a parcel object and can populate it's data members from it;

'public Dog(Parcel dest) {
mType = dest.readString();
mName = dest.readString();
mId = dest.readInt();
}'

Note the order.
You must read your data types from your parcel in the same order you wrote them. Essentially you're flattening your data into one data stream, then reading it back on the other side.

Finally, you will need to create a parcelable creator in your class that will trigger your new parcelable constructor when needed:

"public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
@Override
public LocalContact createFromParcel(Parcel source) {
return new LocalContact(source);
}

@Override
public LocalContact[] newArray(int size) {
return new LocalContact[size];
}
};"

One last thing I'll leave you with is the concept of chaining your parcelable objects. Lets say your Dog class has a custom object as one of its data members. You need to make sure that class also implements the parcelable interface. In order to support parcelizing your custom object inside your Dog class, you will need to change 2 methods.
First, Dog's writeToParcel(Parcel, int) method needs to tell your custom object to write itself to the parcel.
To do this, we can call writeParcelable(Object, int). This method will invoke your custom classes writeToParcel method:

"@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mType);
dest.writeString(mName);
dest.writeInt(id);
dest.writeParcelable(dogTag, flags);
}"

Here dogTag would be your custom class that could implement say, a phone number and address for where the dog lives. Second Dog's parcel constructor. Here we will call readParcelable(Classloader) to get the custom objects parceled data:

"public Dog(Parcel dest) {
mType = dest.readString();
mName = dest.readString();
mId = dest.readInt();
dogTag = dest.readParcelable(DogTag.class.getClassLoader());
}"

This should get you passing your data around to your activities!

Labels: , , , , , , , , , , , , ,


Thursday, August 05, 2010

 

Three Ways to Run Multiple Versions of Internet Explorer and Firefox

Recently I worked on a project that had to support six different browsers; three versions of Firefox (1 through 3) and three versions of Internet Explorer (6, 7, 8). Right away this raised a few questions, and one of the more interesting ones was about testing:

What is the optimal environment for testing two browsers at three versions each?

This is an interesting issue because browsers are not designed to allow more than one version to be installed at once. This makes sense for users — it would be confusing and insecure for them to use an older version by accident — but it's traditionally a big hassle for web developers. It's important for us to be able to test our changes on multiple browsers because different versions of the same browser may not render the same code the same way, and it's important to catch and fix these bugs.

To answer this question, our team of myself (a developer) and two quality assurance experts did some brainstorming and each of us actually came up with our own solution. Here are the three options we considered:

Multiple VMs

This was our senior QA's suggestion. Set up three virtual machines, and on each machine, install a different version of Internet Explorer and Firefox.

Advantages:

Disadvantages:

VM Snapshots

This was our other QA's suggestion, which I thought was quite novel. The process goes like this: create a virtual machine and install IE6 and FF1, then take a snapshot (something the VM can revert to upon request). Now, upgrade the browsers to IE7/FF2 and take another snapshot, and perform the final upgrade to IE8/FF3 and take a third snapshot. By toggling between the three snapshots, all six browsers can be tested using only one VM.

Advantages:

Disadvantages:

Hack it Together

Predictably, this was the developer's solution (mine). I've used a slightly-unstable beta product called IETester in the past, which allows testing multiple versions of Internet Explorer simultaneously. This meant all I needed was a solution for Firefox, and after some searching I found an outline of how to install multiple versions of FF.

Advantages:

Disadvantages:

Given these options, we decided that the best match for our project's needs was to use VM Snapshots on the quality assurance side, and the hacked-together solution on the development side. The low overhead was a big plus, especially for development, and it was important that QA was able to reliably test real versions of each browser. This worked out well for us, and I would definitely use such methods again.

Have you used these or similar solutions in the past? Are there other solutions out there that we don't know about? Let us know in the comments.

Labels: , , ,


Tuesday, March 02, 2010

 

RIATest: Automating Custom Components

RIATest is a GUI test automation tool for Adobe Flex applications. RIATest does for your GUI what FlexUnit does for your code, and it is available on Windows and Mac OS X. RIATest has number of useful features which can be very helpful, such as component inspector, script debugger, and synchronization capabilities. You can find the full list of features here.

When you specify actions that must be performed on your application the first thing you specify is what component you want to be located by RIATest so that an action can be performed on it. RIATest has few ways of locating components. One of the ways is locating component by label e.g. button with "Save" label can be located following way:

FlexButton("Save")

Component can be located in a same manner using components automatationName. You can also locate component using its automationIndex:

FlexButton("index:0")

In most of the cases you are getting every component which you need in the inspector, so you can easily locate those components. In case you derive a custom class from built-in container-type classes you usually do not need to do anything special to make children of your custom component available for automation since this is done by the automation delegate of base class.

However sometimes you implement a custom component that contains other components but your custom component is not derived from Container built-in class. If that is the case you need to expose components contained in your custom class. You will need to perform some additional steps to access them.

Let's discuss one exact example. Here we have a CustomPanel with a button added in its title bar. You will notice that the button which you just added is not visible in the inspector:


So what we can do? We need to implement automation delegate class for our custom component. Exposing child components is done by implementing numAutomationChildren/getAutomationChildAt pair of functions. numAutomationChildren function must return the number of children component for your custom class, getAutomationChildAt must return the child at the specified index. This means we need to implement automatation delegate class for our custom component to make Switch button accessible from RIATest.

numAutomationChildren

In our case we will need to return the number of children which are implementing IAutomationObject plus Switch button:
override public function get numAutomationChildren() : int {
    var count:int = 0;
    for(var i:int=0; i < comp.numChildren; i++) {
        if (comp.getChildAt(i) is IAutomationObject)
            count++;
    }
    return ++count;
}

getAutomationChildAt

getAutomationChildAt will need to return the child with a given index in case of index < numChildren and return Switch button in case of index == numChildren
override public function getAutomationChildAt( index : int ) : IAutomationObject {
    if (index >= 0 && index < comp.numChildren )
        return comp.getChildAt(index) as IAutomationObject;
    if(index == comp.numChildren)
        return comp.button;
    return null;
}

We will also need to implement init method in order to register our delegate class:
public static function init( root : DisplayObject ) : void {
    Automation.registerDelegateClass( CustomPanel, CustomPanelAutomationImpl);
}

The only thing left to do is to include our delegate into build, include your delegate class using additional compiler arguments:

-includes CustomPanelAutomationImpl

As you can see from the screenshot now Switch button is getting displayed in the inspector, so you can easily locate it:

FlexPanel("index:0")->FlexButton("Switch")=>click();

You can download source code of this project from here.

Friday, September 18, 2009

 

Maven Compiler Tips and Tricks

Apache’s Maven is a great tool for managing a build environment: it keeps track of all project dependencies and provides a number of configurable build phases which can add depth to the build process. Building a project from the ground-up with Maven is a sure-fire way to keep it well organized and easy to maintain – but what about adding Maven on to an existing project, or worse, merging a non-Maven project into a project that already relies on Maven?

What follows is a look at some of the lessons I’ve learned from tweaking compiler plug-ins and digging through search results to debug various Maven-related issues. Hopefully it will be useful to the next developer who happens to hit similar issues, and if you have tips of your own be sure to leave a comment.

The maven-compiler-plugin <include> property

When overriding the default maven-compiler-plugin, the <include> tag may be used to force the compiler to include extra files into the build. There are a couple of interesting points to note here:

It is a filter. Many things in Maven expect a path to a directory, but not the <include> tag. If you have some extra java classes in src/main/java and you pass that to <include> it will fail silently – what you actually want is src/main/java/**/*.java.

It is for the compile-phase only. By default, in addition to using the maven-compiler-plugin during the compile phase, Maven will also use it during the test-compile phase. Most properties will apply to both, but <include> is not one of them; the test-compile phase requires a separate property, <testIncludes>, for any includables it requires[1].

The generate-sources and generate-resources phases

These phases are great for adding source (.java) and resource (.class) files to the compiler before the compile phase occurs. The snippet below shows how to use mojo's build-helper-plugin to add some obscure .class files to the classpath:

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>add-resource</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>../obscure/classes</directory>
</resource>
</configuration>
</execution>
</executions>
</plugin>

Now any .class files in ../obscure/classes (or any subdirectories) will be added to the classpath.

The same plug-in is used for adding .java files, simply tweak the generate-resources and add-resource values to generate-sources and add-source, and the <resources> and <resource> properties to <sources> and <source>.

The maven-compiler-plugin <compilerArgument> property

The <complierArgument> tag may be used to pass command-line arguments directly to the java compiler. Two examples:

<classpath> seems like it would let you add resources to the classpath, but near as I can tell, these aren’t actually used. Maven seems to prefer managing its own classpath, though we can still add/remove entries by overriding the default generate-resources phase (as explained above).

<sourcepath> is a great way to specify multiple source directories for compilation. It takes a semicolon-delimited list of top-level directories containing java files to compile. Alternately, an override of the generate-sources phase may be used here as well.

One gotcha with regards to sourcepath: to get this to work, I had to manually set <fork> to true on the maven-compiler-plugin. In fact, this gets even worse: when <fork> is true, Maven will use the %PATH% environment variable to determine which JRE to use, and this will fail with a totally non-descript error if the path to your JRE contains any spaces – very annoying to track down. This is actually a bug in Maven, logged here (http://jira.codehaus.org/browse/MCOMPILER-30).

The <sourceDirectory> property

A minor but important tag when playing around with various sources and resources, the <sourceDirectory> tag may be used to set the base directory for including java source files. It defaults to src/main/java, but I found when playing around with a lot of sources spread around various directories, it was easiest to set it to the current directory as follows:

<build>
<sourceDirectory>.</sourceDirectory>
{...}
</build>

Other useful debugging hints

When running into problems, it’s always good to have a few debug flags around to get a little more information out of Maven, which is generally not great at telling you what might be wrong.

Specifying the -e flag while running Maven will print out any exceptions Maven encounters, with the corresponding stack trace.

The <verbose> tag may be added inside any plug-in’s <configuration> property and when toggled to true (default is false) it will print some extra information, including the sourcepath and classpath being used by Maven’s compiler.

Specifying the -X flag while running Maven will document all kinds of intermediate steps Maven takes during the build – much more than -e and <verbose>.



[1] This makes perfect sense, of course: it’s unlikely that you’ll want the same includables for both the normal compiler and the testing compiler. It’s just counter-intuitive compared to the rest of the <configuration> properties.

Labels: , ,


Friday, July 17, 2009

 

Here I am!

This application allows you to send URL link with your location through SMS message. Receiver will be able to see your location on the map(Google Maps) by simply clicking on the link. First thing we need to do is to get our location using GPS. Android SDK has set of classes and interfaces which makes dealing with location services quite easy. Another positive thing is that SDK is well documented. We need to get an instance of LocationManager:
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Now that we have location manager we need to request location updates from it. The location is requested using requestLocationUpdates method, it registers the current activity to be notified periodically by the named provider. In our case provider is GPS. For tracking location changes we are using LocationListener which is for receiving notifications from the LocationManager when the location has changed.

lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, 
                new LocationListener() {
                    public void onLocationChanged(Location location) 
                    {
                        double lat = location.getLatitude();
                        double lng = location.getLongitude();                        

                        latitude.setText( Double.toString( lat ) );
                        longitude.setText( Double.toString( lng ) );
                    }

                    public void onProviderDisabled(String provider){}
                    public void onProviderEnabled(String provider){}
                    public void onStatusChanged(String provider, int status,Bundle extras){}
        });

Just getting last known location...
Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
Good! We got the location. Now we just need to generate the URL and send SMS. Android offers full access to SMS functionality from within your applications with the SMSManager. We are geeting a reference to the SMS Manager using the static method SmsManger.getDefault. For sending SMS message use sendTextMessage, which allows you to send SMS message by specifying text message and receiver's phone number.
final SmsManager sm = SmsManager.getDefault();
String phoneNumber = number.getText().toString();
String URL = "http://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=";
URL += latitude.getText() + "," + longitude.getText(); 
sm.sendTextMessage(phoneNumber, null, URL, null, null);
That's it! Just one note - in order to send SMS message and request GPS location application require following two permissions:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.SEND_SMS"/> 

Thanks to my friend Aaron Olson from Macadamian for the help in testing this code.

Source

Labels: , ,


This page is powered by Blogger. Isn't yours?