Getting started with the Android SDK

by Randall 11/1/2009 11:07:00 PM

After putting off Android for quite some time, I finally decided to dig in.  I must admit, however, that it was Verizon's clever marketing campaign in coordination of the upcoming launch of the Verizon Droid that motivated me enough to do it.  For the last year or so I've had friends and family memers mention on occasion that I 'should' be developing applications for the iPhone (perhaps they're all thinking that I'll strike gold and share some moola), but I never could motivate myself.  First of all, I'm not an Apple fanboy.  Secondly, I don't own a Mac so that kind of kills it.  Apple has seen to it to exclude Windows developers from getting in on the action.  Android and Google is a completely different story.

The Android SDK plugs into the Eclipse IDE quite seamlessly.  I was able to get Eclipse and the Android SDK installed, updated, configured, and ran my initial "Hello World" application within about an hour.  Since Eclipse runs on Windows (as well as Linux and Mac), I was able to dig right in.  Kudos to Google.

Let's see what it's all about.

The best place to start is right here: http://developer.android.com/sdk/index.htm

I'm not going to reproduce their work, so let's get right to how things look (this is running on a fresh install of Windows 7) ...

Running the AVD



... still booting ... 



... and still booting ... 



The whole bootup process takes far too long.  I have yet to be able to find a way to shorten it.  Unfortunately, every time you make a code change and want to run your application, you must wait for about 1 min or so for the AVD to fire up.  Unless I've just not found it, this is a step back from developing against the .Net CF as the emulators there enter a standby mode when you stop debugging.  ***EDIT*** You do not need to shut down the emulator in order to deploy new code.  Simply minimize the AVD, make your code changes, then run the application via Eclipse.  The updated application will run correctly.

"Hello, Android!"

According to Google's "Hello World" tutorial, you can simply change this:


to this ...


... and Voila! But this DOES NOT work. At first glance it (seemingly) works, but change the argument of setText to "Howdy, Android" and you will still get "Hello, Android" when you run the AVD. I tried several times recompiling my code. Nothing worked.

To resolve this, you need to understand that Android applications support two ways of building the user interface: through code and XML files1. If you browse to 'res/layout/main.xml' and "Open with XML Editor", you'll see the following:


The key here (literally) is in the @string/hello. Now open 'strings.xml' and find the Resource Element called 'hello' which is being referenced here. If you change the value here to something else, it will work.

 

Run your application again (and wait, and wait, and wait) ...

 

Nothing dramatic yet.  Just getting up and going.  Perhaps someone else had or will have the same issue and this will help.  Tell me if you know how to speed up running the apps on the AVD.

More to come on this.

Sources: 1. "Getting Started with Android Development Using Eclipse", September 15, 2008, Wei-Meng Lee, http://www.devx.com/wireless/Article/39101

 

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

Internet Explorer is Driving Me Mad

by Randall 6/2/2009 3:04:00 PM

Currently I'm trying to learn jQuery and jQueryUI.  Both libraries are supposed to foster compatibilty between all browsers.

Why is it that once again IE is the bastard child?

Firefox gets it right.

 

Safari gets it right.

 

Chrome joins the club by rendering the page correctly.

 

  Here comes IE ...

 

Here are the choices for the question I pose in the IE screencap:

  1. Normal abnormal behaviour
  2. My problem
  3. Microsoft bullshi*
  4. Ignoring W3 standards
  5. All of the above

If you chose 5, you guessed it.

Unfortunately the worst part is answer #2.  At least it keeps me busy.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , , ,

Mission Accomplished

by Randall 5/31/2009 8:21:00 AM

I started this blog with the sole intent of sharing things that I have found useful.  While I've not done a very good job of posting regularly, I've also purposely not posted things just to say that I 'post regularly'.

I was browsing my StatCounter statistics this morning, when I noticed something that made me smile.  Someone in a forum referred to my NUnit tutorial in their post as a good intro. 

 

(By the way, if you're unfamiliar with StatCounter, I suggest you check it out)

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

jQuery & Visual Studio 2010 Beta

by Randall 5/29/2009 2:30:00 PM

Today I decided to check out the jQuery support within Visual Studio 2010.  I had been having difficulty in getting IntelliSense to work correctly in Visual Studio 2008 SP1 as described by Scott Guthrie here.  Turns out that VS wasn't allowing jQuery and jQuery UI to play along nicely.  If I removed the script include for jQuery UI, IntelliSense would begin functioning for jQuery as it was supposed to. However, I'm currently trying to learn both of them so I want it to work properly.

After firing up Visual Studio 2010 Beta, I created a new Web Application Project: 



By the way, you might be happy to see that the option for a website has been removed and you're now forced to choose a web application project.  Personally I'm glad to see this.

Getting back to it, I immediately went into my code behind and started typing up a script block - I didn't see anything any jQuery IntelliSense at all.  DOH.  jQuery is SUPPORTED, not PROVIDED.  After including the scripts for jQuery and jQuery UI, IntelliSense began working beautifully providing support for both.

For jQuery ...

 

... and for jQuery UI ... 

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Supressing Submit Behaviour

by Randall 3/30/2009 10:39:00 AM

Yesterday I needed to supress the submit functionality of some HtmlInputImage controls (aka <input type="submit" ... /> ) and found the answer with a bit of Googling.  I'm posting it here with what is (hopefully) a better heading for the solution.   Perhaps Google will index this page and make it easier for someone else to figure out.

In your form tag, use the following:

<form id="form1" runat="server" onsubmit="return false"

This will prevent the standard submit behaviour and allow your onclick JavaScript to run as you expected. 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Hilarious

by Randall 2/3/2009 10:07:00 AM

I ran across this today while doing some reading on CSS ...

http://giveupandusetables.com/ 

Enjoy. 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

This Was Probably Sheer Luck ...

by Randall 7/31/2008 1:11:00 PM

I just spent part of two days battling an exception while waiting on a response from a web service. 

    ---> System.Net.WebException: The server committed a protocol violation. Section=ResponseStatusLine at System.Web.Services.Protocols.WebClientProtocol.GetWebResponse(WebRequest     request)

   at System.Web.Services.Protocols.HttpWebClientProtocol.GetWebResponse(WebRequest request)

   at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters) 

I found all sorts of suggestions to fix the issue.  Most of them involved adding the following information to your web.config:

    <system.net>
        <settings>
            <httpWebRequest useUnsafeHeaderParsing="true" />
        </settings>
    </system.net> 

No luck.

I even found a post that suggested you override the WebRequest method within your proxy class (seems like a bad idea because if you ever regenerate your proxy class ... well, you know what'll happen to your "fix").

protected override WebRequest GetWebRequest(Uri uri)
{
     HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(uri);

     request.ProtocolVersion = HttpVersion.Version10;

     return request;
} 

Anyway, after neither of those solutions had worked, my Google resources were running low.  I kept noticing that all of the posts mentioned .Net 1.1 ...

So I changed the webservice to use 2.0 (this is a COTS product and installs to 1.1 by default) and voila.  No more nasty gram.

Perhaps this will help someone.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Fixes

String.Format Shortcut

by Randall 6/24/2008 5:19:00 PM

Well, I feel like I have totally missed the boat on something.

I love using string.Format() in order to construct messages and other things that need to be written to the console, etc.  For example:

    string msg = string.Format("I can't believe it's {0} already!", DateTime.Now.Date.ToShortDateString());
  Console.WriteLine(msg);

Anyway.  I just learned that the line above can be written as:

    Console.WriteLine("I can't believe it's {0} already!", DateTime.Now.Date.ToShortDateString());

Seems as if the compiler can determine that you're formatting a string and will infer the string.Format() function.

Too bad it can't infer the following:

    string msg = "I can't believe it's {0} already!", DateTime.Now.Date.ToShortDateString();

Currently rated 1.0 by 1 people

  • Currently 1/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Getting Started With TestDriven.Net PlugIn & Unit Testing With NUnit Tutorial

by Randall 6/18/2008 10:42:00 AM

(You can download a Word version of this tutorial here.) 

In case you've been using NUnit (or some other testing framework) and NCover as stand-alone applications, you need to check out a plug-in for Visual Studio 2005/2008 called TestDriven.Net.

For those of you who have yet to even get started with Unit Testing - let's take a small project, create some unit tests, and show how this plug-in (along with NUnit and NCover) can increase the quality of your code.

*Disclaimer*  This demo will not implement the TDD methodology.  There is another school of thought that says you write a test before writing any code.  However, the purpose of this entry is to show you how easy it is to get started with unit testing.  How you choose to apply it to your projects will, of course, be left to you.  Furthermore, in-line SQL is used in this demo for purposes of simplicity and the connection string is embedded in the code.  Of course you'd ALWAYS want to put the connection string in your App.config or Web.config.  You know that.

Source code for the example project is located here (without the unit tests if you'd like to complete them youself) and the fully completed source code is available here.  The script for generating the single table is here - you'll simply need to create a database called 'DogsDB' and update your connection string.  I've marked the location of the connection string with a 'TODO' comment.  You can find that by looking in Visual Studio's Task List (hit CTL+T).

Dogs Application

So we have this little application that will allow us to manage all of the dogs in a kennel (or whatever).  We have all of our code in-place that will perform the normal CRUD operations and provide functionality to the UI.  How do we know that it will work?  I suppose before I stated doing unit testing I would simply have hooked in whatever user controls I needed and ran the application.  For really simple projects (such as this one) yes, that can work.  However, when you begin working on large-scale applications and creating very large APIs that will break other applications when they fail - unit testing will save your a$$.

At this point we'll be working with the unfinished sample.

If you haven't downloaded NUnit yet, you'll need to do that before going to the next step.  You can download it here

Let's add a new project to our solution - a class library - and call it 'UnitTestingDemo.UnitTests'.  This will be the container for all of our unit tests. 

 At this point, we'll need to add a reference to the NUnit framework.  So go ahead and add the reference - you'll find the asembly under the .Net tab of the 'Add Reference' dialog. 

Now we want to start writing tests for our business layer.  You could write tests that touch your DAL directly, but theoretically your BLL should expose all of your DAL.  However, if there are private methods within your DAL, you'll need to write tests to address those issues.  For this example, we'll just be testing the public layer which is in the BLL.

Let's go ahead and stub out our tests based on what's in the BLL.

In the project we just created, rename Class1.cs to DogLayerTests.cs and add a using statement for NUnit.Framework.  Your class should now look like this ... 

We want to base all of our tests on what's in our BLL.  One of the easiest ways to do this is to simply copy & paste our BLL methods into our test class. 

  1. remove all of the code from within each method
  2. rename each method to reflect that it's a test (add '_Test' to the end of each method's name)
  3. change every return type to void
  4. remove all parameters from each method's signature

When you're done, DogLayerTests should look like this ...

 

In order for NUnit to know that you want this class and its methods to constitute a suite of tests, you must 'decorate' the class and its methods with a couple of attributes.  At the class level, NUnit expects the [TestFixture] decorator and the [Test] decorator at the method level.  Go ahead and add those now.  Your code should now look like this ...

(If you don't see [Test] and [TestFixture] in IntelliSense, you either forgot to add the assembly reference to NUnit.Framework or you forgot to add the using for the namespace.) 

  Since we're starting with an empty database, the first thing we probably want to test is the ability to save a dog to the database.  Since NUnit will run your tests in alphabetical order, you can simply rename your methods numerically to fix that issue.  However, I think by definition each unit test should be able to run without any dependencies on other tests.  But if the database is empty, and you can't guarantee there will be any data to load, I'm not sure what else we can do.

I want to conduct my tests in the following order: Save, Get, Get All, Delete.  I'll letter my tests accordingly using A, B, C, & D as prefixes on the method names. 

Let's go ahead and write the test code for A_Dog_Save_Test.  We'll need to add two project references, one for the BLL and another for the Data Objects.  Do this and add your using statements for both namespaces. Because we're using the Color object in the System.Drawing namespace, you'll also need to add a reference to System.Drawing in your UnitTests project.  Go ahead and do that now also.

Once we start coding our test for the Save functionality, we can see that within that test, we'd like to have a way to verifiy that the object was saved.  Yes, the method itself will return a bool value, but we still want to know.  Based on that observation, we'll make the newly-created Dog a private member within the class so that other methods can perform tests based on it.

    [TestFixture]
    public class DogLayerTests
    {

        private DogLayer _dogLayer = new DogLayer();
        private Dog _dog = null;

        [Test]
        public void A_Dog_Save_Test()
        {

            this._dog = new Dog();
            this._dog.Id = System.Guid.NewGuid();
            this._dog.Name = "Fido";
            this._dog.Breed = "Mutt";
            this._dog.HairColor = System.Drawing.Color.Brown;
            this._dog.Age = 7;

            Assert.That(this._dogLayer.Dog_Save(this._dog) == true);

        }

    ...

    } 

We want all of the other tests to fail since they don't contain any code.  In order to make that work, insert the following into each of the remaining test methods.

Assert.That(true == false);

This will force the rest of our tests to fail; this is desirable. 

Now we'd like to run our test in order to determine if everything is working.  Since you have NUnit now, you can run your tests.  However, this article is about working with the TestDriven.Net plug-in, so you'll need to download that now.  You can download it here.  (Don't forget to save your solution and exit Visual Studio prior to running the installer.)  Once you have completed the installation, re-open the solution and continue.

Right-click on your test class and select 'Run Tests'. (We'll explore some of the other menu items later.)

 Your test will fail (there's an error that we'll flush out next). 

Debugging Using the Test Driven .Net Plug-In

Since our test failed and we have a bug, we want to be able to step through our test just like we'd normally step through using the debugger.  In order to do this, place a breakpoint at the test's call to the Save method.  Right-click on the test project again, but this time select 'Test With --> Debugger'.  You can now step into your code - eventually you'll find that we're missing a closing paren in our SQL insert statement.

Change

sb.AppendLine(string.Format("'{0}',", value.HairColor));

to

sb.AppendLine(string.Format("'{0}')", value.HairColor)); 


Re-run your tests.  The Save test will now pass and you'll see this in the Output window ... 

Congratulations.  You have just written your first unit test.

For the sake of brevity (too late, I know) here's the code for the rest of the test methods:

(Note that I have added more code in the first test to create multiple dogs which will be loaded by the Dogs_Get() test)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using NUnit.Framework;

using UnitTestingDemo.DataObjects;
using UnitTestingDemo.BLL;

namespace UnitTestingDemo.UnitTests
{

    [TestFixture]
    public class DogLayerTests
    {

        private DogLayer _dogLayer = new DogLayer();
        private Dog _dog = null;

        [Test]
        public void A_Dog_Save_Test()
        {

            this._dog = new Dog();
            this._dog.Id = System.Guid.NewGuid();
            this._dog.Name = "Fido";
            this._dog.Breed = "Mutt";
            this._dog.HairColor = System.Drawing.Color.Brown;
            this._dog.Age = 7;

            Assert.That(this._dogLayer.Dog_Save(this._dog) == true);

            // create 5 dogs and save them all
            for (int i = 0; i < 5; i++)
            {
                Dog tempDog = new Dog();
                tempDog.Id = System.Guid.NewGuid();
                tempDog.Name = string.Format("Name{0}", i.ToString());
                tempDog.Breed = string.Format("Breed{0}", i.ToString());
                tempDog.HairColor = System.Drawing.Color.Brown;
                tempDog.Age = i;

                Assert.That(this._dogLayer.Dog_Save(tempDog) == true);

            }

        }

        [Test]
        public void B_Dog_Get_Test()
        {

            Assert.That(this._dog != null);

            // attempt to retrieve the dog to ensure that it was saved ...
            Dog tempDog = this._dogLayer.Dog_Get(this._dog.Id);

            Assert.That(tempDog != null);

            // check as many properties as you'd like
            Assert.That(this._dog.Name == tempDog.Name);
            Assert.That(this._dog.Breed == tempDog.Breed);

        }

        [Test]
        public void C_Dogs_Get_Test()
        {
            List<Dog> dogs = this._dogLayer.Dogs_Get();
            Assert.That(dogs != null);
            Assert.That(dogs.Count > 0);
        }

        [Test]
        public void D_Dog_Delete_Test()
        {
            // get all of the dogs in the database
            List<Dog> dogs = this._dogLayer.Dogs_Get();
            Assert.That(dogs != null);
            Assert.That(dogs.Count > 0);

            // delete all of them
            foreach (Dog dog in dogs)
            {
                // delete the dog
                Assert.That(this._dogLayer.Dog_Delete(dog.Id) == true);

                // attempt to load the dog - it should fail (return null)
                Assert.That(this._dogLayer.Dog_Get(dog.Id) == null);
            }

        }

    }

}

Run your tests again.  Oh no.  Another bug (actually two within the same method).  This time I'll leave it up to you to decipher - but it's in the DAL. ;) (*Hint* Make sure your reader has rows before attempting to read from it and ensure that method will always return a value.)

Now that all of our tests have passed with flying colors, we're good to go, right?  Well yes and no.  Yes all of our tests passed, but how much of our code did we test?  Are we testing everything that will get called during its use?  This brings us to the next part.

Verifying Test Coverage With NCover

NCover is a code-coverage tool that is available as a stand-alone product but which is also packaged with the Test Driven .Net plug-in you downloaded earlier.  What exactly is code-coverage you ask?  Well, it's just a way of showing you whether or not your lines of code were actually used based on the tests you have written.  NCover will show you line-by-line what code was 'touched' and even provide a percentage of the lines of code within a method that were used by your test.  Determining the 'correct' percentage of appropriate code coverage is an entirely difference discussion on its own, but I attempt to get 100% coverage within my business and data access layers.  Some things, such as your data objects, might not get 100% coverage.  What is and isn't a good level of coverage will be left for you to research and determine.

Let's get started.

Since all of our tests passed, let's determine how good of a job we did in contructing our test classes (based on code coverage).  Right-click on your test project and select 'Test With --> Coverage'.  

NUnit will run the tests, then NCover will launch and show you the results. 

Looks pretty good, right?  I mean we have 100% in our business layer.  Remember though that this BLL isn't really doing anything in this application - it's really acting as a pass-through to our DAL.  Speaking of - we only have 29% coverage there.  Let's take a look and see what the problem is.

Looks like our BaseDal is skewing our results.  If you're like I am, you have a generic SQL base DAL from which all of your other object-specific DALs inherit.  This class should have been tested within some other solution (as a matter of fact, it was).  Since we've already unit tested that class in another test suite, we'll focus our efforts on obtaining 100% coverage within our DogDal.

Looks like everything is at 100% except for the Dog_Save method.  Let's take a look and see what the issue is ... 

Well, look at that.  We never attempted to update a previously-existing dog.  How do we know?  The red lines of code were never touched.  If you think back to our tests, we only saved new dogs - we never updated any of them.

While we thought we were ok because all of our tests passed, it's clearly evident now that we didn't do the best job we could when writing our tests.  This is why these tools are invaluable - because we all make mistakes.  True, our update method probably works - but you need to adopt the attitude of 'I want to KNOW that it works'.  Never assume anything, as you know. 

Let's go back and fix our tests.  In the first test where we were saving new dogs, let's add a few more lines of code that will update each of the dogs we just created and saved.  Your test method A_Dog_Save_Test should now look like this ...

        [Test]
        public void A_Dog_Save_Test()
        {

            this._dog = new Dog();
            this._dog.Id = System.Guid.NewGuid();
            this._dog.Name = "Fido";
            this._dog.Breed = "Mutt";
            this._dog.HairColor = System.Drawing.Color.Brown;
            this._dog.Age = 7;

            Assert.That(this._dogLayer.Dog_Save(this._dog) == true);

            // create 5 dogs and save them all
            List<Dog> dogs = new List<Dog>();
            for (int i = 0; i < 5; i++)
            {
                Dog tempDog = new Dog();
                tempDog.Id = System.Guid.NewGuid();
                tempDog.Name = string.Format("Name{0}", i.ToString());
                tempDog.Breed = string.Format("Breed{0}", i.ToString());
                tempDog.HairColor = System.Drawing.Color.Brown;
                tempDog.Age = i;

                Assert.That(this._dogLayer.Dog_Save(tempDog) == true);

                dogs.Add(tempDog);

            }

            // update all 5 of the newly-created dogs
            foreach (Dog dog in dogs)
            {
                dog.Name = string.Format("{0}_Updated", dog.Name);
                // save the dog - this will be an update now
                Assert.That(this._dogLayer.Dog_Save(dog) == true);
            }

        }

Re-run all of your tests using NCover as we just did.  They should all pass and NCover will show you the new results.  Drill down into the DogDal and look at the code coverage percentage ... 

Congratulations.  You now have 100% code coverage within your DogDal.  This is what we wanted.

Wrap-Up

While writing your unit tests, running them, fixing them, analyzing your code coverage, and adjusting your tests all takes time - the benefit in the long run will blow your mind.  As the weeks progress and you become more removed from the code you just wrote, having a series of tests to run will provide some much-needed peace of mind.  Developing software is tough enough without worrying about breaking code that you have previously written.

With that being said, I challenge you on your next project (or even your existing project(s) to implement unit testing.  It will change the way you develop software.  Frankly I don't know how I called myself a 'professional' developer before I began doing this.


kick it on DotNetKicks.com

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , , , ,

Powered by BlogEngine.NET 1.3.1.0
Theme by Mads Kristensen

About the author

Name of author Randall Sexton
Currently a .Net developer for Bechtel Corporation in Oak Ridge, TN.

E-mail me Send mail

Calendar

<<  February 2010  >>
MoTuWeThFrSaSu
25262728293031
1234567
891011121314
15161718192021
22232425262728
1234567

View posts in large calendar

Pages

    Recent comments

    Don't show

    Authors

    Categories


    Logo Credit

    My logo was taken from CodingHorror.
    Jeff Atwood © Copyright 2007

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    © Copyright 2010

    Sign in