Discussing the nuts and bolts of software development

Monday, April 02, 2012

 

Real-time face detection with Android


In this post I will show you how to use the still image FaceDetector class from the Android SDK to achieve (mostly) real-time face detection.  The following method was used in the creation of the MonkeyCam application.

Since its first release, the Android SDK has made available the FaceDetector class, which “identifies the faces of people in a Bitmap graphic object”.  By using the FaceDetector on preview frames from the camera, we approximate the real-time face detection.  For example in the MonkeyCam application we achieved a rate of slightly over one second per frame which is in the same range as other solutions found around the Internet using more complex solutions like third party computer vision libraries.  Short of using the NDK to do GPU programming for the face detection algorithm this was a very usable compromise.

Read more »

Labels: , , , , , , ,


 

Disabling the console switching keys for Android

Some time ago I was doing development on an Android phone and using a BlueTooth keyboard I came across an intriguing behaviour.  Hitting the Alt+Left or Alt+Right key combo, the phone would seemingly stop working and give all the symptoms of a frozen device, no more animated wallpaper and unresponsive touchscreen.  This stems from a functionality inherited from Linux for the desktop.  In this article I will describe the origin of the issue, how to recover from it and how it can be fixed at the kernel level.


Background information

In Linux there exist some special key combinations that are handled at the kernel level.  In this article we'll be looking at the console key combinations, specifically:
* Alt refers to the left Alt key on the keyboard


Let's start with Alt+F1 through F12; these allow accessing the tty's.  On a typical Linux installation Alt+F1 through F6 allows the user to switch between tty1 through tty6 respectively directly and Alt+F7 (F1 in Fedora) is a special tty in which the graphical interface runs.  This can change from distro to distro.

Read more »

Labels: , , ,


Thursday, March 29, 2012

 

Surviving the transition between SVN and Git

A guide for the commandline-adverse

As a Microsoft ‘fanboi’ I was at first rather unhappy when the people promoting Git kept insisting that “the command-line is where there power is at” and that “GUIs aren’t good enough”.
They were, in part, right; but there’s a lot you CAN do with the right GUI. I for one am a fan of TortoiseGit (http://code.google.com/p/tortoisegit/)
In this blog post I’ll outline a few common operations that you can do using a combination of Git Bash and Tortoise Git, and a few that are best done in Bash alone (don’t worry, we’ll try to keep the use of Bash to a minimum; Note however that that it will probably be helpful if you were already familiar with basic git concepts (branch, commit, rebase, etc)

Read more »

Labels: , ,


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.

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