Monday, January 30, 2012

Multiple Click Handlers on a List View Row in Android

Recently a reader asked a interesting question. The reader asked how to handle multiple buttons within a list view item, while still being able to scroll the list and click on the list item itself. In Android, when you introduce a view that has drawable states to to a list view, any touch events that the list view would normally handle no longer work, because all touch events are now being used by the new view that was added.


This is actually by design in Android. Any time a click-able view comes into place, it takes presidents over any touch events below it. There is a way to get it working the way your expecting, where you can click on the buttons while having touch events handled by the list view. Here is one way you could do it:


First, you need to set your ListView to allow focus-able views. This lets you set which views can be focused on a given list item. Add this line to your activity where you are setting up your list view (probably onCreate or onResume):

   1: getListView().setItemsCanFocus(true); 

Next, in your List View Adapter’s getView method, where your setting up your buttons, you need to add a few lines to each view that you want to be clickable. In your case, it would be each button, and the main layout View that was inflated. You just add the three lines below to each of those views (your two buttons, and your main layout).

   1: v.setClickable(true);
   2: v.setFocusable(true);
   3: v.setBackgroundResource(android.R.drawable.menuitem_background);  

Hope that helps! Let me know if it works out for you.

Monday, January 23, 2012

Tutorial: Scraping HTML Pages with HtmlCleaner

Parsing a web page for some specific data you’re looking for can be a huge pain to due. With all the bad types of HTML out there, it can be very difficult to come up with a strategy that will work for all types of pages you want to encounter.

Luckily, this task has been accomplished many times before, and there are several good libraries one can use to get the job done.

The best strategy I have found is to use HtmlCleaner in conjunction with XPath query language. There really is no need to write out gain functions to parse through HTML or XML using the XMLPullParser. The code that I’m going to explain is much, much simpler and easier to maintain.

Steps to do so:

  1. Set up your tag node
  2. Load the page in
  3. Use XPath to pull out your information as Nodes
  4. Parse out the information you need.

For example, say you’re a pretty serious Starcraft 2 player and you’re looking to get all of the build info out of Team Liquid’s Wiki. You can see an example here, where you see a table containing information about a given build order. We’ll start with this page and grab all of the info within that table. HtmlCleaner can help you out with this task. Here’s how you do it:

First, you need to load up HTMLCleaner and give it the URL you’re looking to scrape. In this example, we’re just using the URL from above (http://wiki.teamliquid.net/starcraft2/3_Gate_Robo).

   1: CleanerProperties props = new CleanerProperties();
   2:  
   3: // set some properties to non-default values
   4: props.setTranslateSpecialEntities(true);
   5: props.setTransResCharsToNCR(true);
   6: props.setOmitComments(true);
   7:  
   8: //**Load up the web page
   9: //HtmlCleaner reads in the html and formats the info to ensure its a properly formatted XML document.
  10: //When its finshed, it returns the root node of your document
  11:  
  12: TagNode tagNode = new HtmlCleaner(props).clean(new URL(
  13:         http://wiki.teamliquid.net/starcraft2/3_Gate_Robo));

Now that we have the root node of your newly formatted XML document, we can use XPath to query the document for specific information. For starters, we’ll grab the first header of the HTML Document, as that contains the build name. The following code finds out the title and simply prints it out to the console.

   1: Object[] nodes = tagNode.evaluateXPath("//h1[@id='firstHeading']");
   2:  
   3: TagNode Headernode = (TagNode)nodes[0];
   4: System.out.println("Build Title: " + Headernode.getText());
   5: System.out.println("------------------------------");

Next, we want the actual build order information. The build order itself is contained within a tag named “collapsible table”. Knowing that, we can query our root node for the data, just like we did for the title of the document a minute ago.

   1: nodes = tagNode.evaluateXPath("//table[@class='wikitable collapsible']");

This line gives us the table we’re looking for in our object array called nodes. But the table itself isn’t very interesting to us. We need the actual data inside it. Luckily, we can use XPath on our table node object and get the information we’re looking for out of it. By looking at the table more closely, each line in the table is divided by the “li” tag. Also, Some of the table text is within links, which could be the “a” tag.

   1: //this line checks if we returned a table object from the above line. If not, we see if there is a collapsed version of it instead
   2: if(nodes == null || nodes.length == 0){
   3:     nodes = tagNode.evaluateXPath("//table[@class='wikitable collapsible collapsed']");
   4: }
   5:  
   6: //grab the Table node
   7: TagNode node = (TagNode)nodes[0];
   8:  
   9: //Look for the invididual rows within the table
  10:  
  11: nodes = node.evaluateXPath("//li");
  12:  
  13: //print out our contents!
  14: for (int i = 0; i < nodes.length; i++) {
  15:     System.out.print(((TagNode)nodes[i]).getText());
  16: }

And that’s it! With the above code, you should see the following output:

Build Title: 3 Gate Robo &nbsp;
------------------------------
9/10 - Pylon (1)
13/18 - Gateway (1)
15/18 - Assimilator
16/18 - Pylon (2)
18/26 - Cybernetics Core
19/26 - Zealot
22/26 - Pylon (3)
23/26 - Stalker
25/34 - Warpgate research
25/34 - Assimilator (2)
26/34 - Gateway (2)
27/34 - Sentry
30/34 - Pylon (4)
30/34 - Gateway (3)
31/34 - Robotics Facility

Here’s the above code all in one place.

   1: CleanerProperties props = new CleanerProperties();
   2:  
   3: // set some properties to non-default values
   4: props.setTranslateSpecialEntities(true);
   5: props.setTransResCharsToNCR(true);
   6: props.setOmitComments(true);
   7:  
   8: // do parsing
   9: TagNode tagNode = new HtmlCleaner(props).clean(new URL(
  10:         "http://wiki.teamliquid.net/starcraft2/3_Gate_Robo"));
  11:  
  12: Object[] nodes = tagNode.evaluateXPath("//h1[@id='firstHeading']");
  13:  
  14: TagNode Headernode = (TagNode)nodes[0];
  15: System.out.println("Build Title: " + Headernode.getText());
  16: System.out.println("------------------------------");
  17:  
  18:  
  19: nodes = tagNode.evaluateXPath("//table[@class='wikitable collapsible']");
  20:  
  21: if(nodes == null || nodes.length == 0){
  22:     nodes = tagNode.evaluateXPath("//table[@class='wikitable collapsible collapsed']");
  23: }
  24:  
  25: TagNode node = (TagNode)nodes[0];
  26:  
  27: nodes = node.evaluateXPath("//li//a");
  28:  
  29: Object[] nodes1;
  30:  
  31:  
  32: nodes1 = node.evaluateXPath("//li");
  33:  
  34:  
  35:  
  36: for (int i = 0; i < nodes1.length; i++) {
  37:     System.out.print(((TagNode)nodes1[i]).getText());
  38: }

Monday, January 16, 2012

Learning iOS from an Android Developer’s Perspective – Part 1

androidvsiosOver the last year or so, I have spent most of my programming time (at work and at home) improving my skills with Android. I picked up Android because, at the time, I didn’t have access to a Mac, and I really didn’t like the idea of having to pay Apple just to develop software for iOS (although it would have been nice to write some apps for my iPod Touch). Once Android came around and it started to turn out to be a real competitor to iOS, I jumped in.

Within the last few months, I have had the need to convert over some iOS code over to Android. Even though I have a decent amount of experience with C programming, understanding what is going on in a simple Iphone application took more time and too many questions to be worth while.

I’m sure the opportunity to check out some iOS code will come up again. So recently I picked up a cheap Mac Mini and this iOS book. My goal is to be able to understand iOS well enough to  convert between the two dominate technologies with ease. After reading the BNR’s iOS book, here are my initial thoughts about iOS:

Initially, iOS is easier to pick up

The Model View Controller pattern that iOS follows is much simpler and easier to grasp than Android’s Activities/Services. This model allows anyone to pick up the SDK and understand what the basic meaning behind any given object is. However, the ease of the iOS model is offset by Objective C’s syntax.

Even the most basic Hello World problems for iOS contain a ton of braces. It’s very daunting to look at, if you’re coming from a Java background. After a bit of time, and once you grasp the idea that objects are sending “messages” back and forth and braces are used to send any sort of message, the syntax of Objective C becomes much clearer.

UI Design is much simpler

Creating UIs in iOS is really straight forward. But having to manually connect Views in an xib file (what iOS uses to store UI details) to your source files before run time is pretty nice. It removes a good amount of boiler plate code that Android has, which involves initially hooking up to your UI.

Designing UIs is obviously going to be much easier for iOS just because of the device count. You’re only looking at a one screen size for the Iphone and one for the iPad. Coming from Android, this is a huge plus. Designing interfaces for a countless number of devices can soak up a ton of time. Having manageable hardware differences between all iOS devices is certainly a big strength of the platform from the perspective of a developer.

Memory Management isn’t so bad

Memory Management is always brought up as a negative about iOS. From my initial thoughts, it really doesn’t seem that bad. For iOS, every object that you create has a counter. An Object’s memory counter is a simple count of how many objects are actually using your object. Objects that have a memory count of zero are reclaimed, and their memory is recycled.

It’s certainly nice to not have to worry about memory so much in Android, but as long as you keep track of your retain counts for a particular object, you should be good to go. Encapsulation is required to keep memory managed correctly for iOS. You always need to know where you are in a given program.

Everything isn’t so rosy with iOS, though. Android does have some key benefits over Apple’s system. Stay tuned for Android’s strengths over iOS.

Thursday, January 12, 2012

Dependency Injection for Android with Google’s Roboguice

For most developers, writing Android apps means writing a ton of Java. On large projects, trying to keep patterns straight can be pretty difficult. Useful frameworks for Android are few and far between, which leaves the programmer to pick up a lot of the details of the system. Far too many bugs are created this way.

The other day, I came across Roboguice, a port of Google's Guice framework over to Android. If you've never heard of it, it’s a simple framework to streamline Dependency Injection within Android. The framework still seems to be a hidden gem. I couldn’t find many developers that even knew it existed.

What is Dependency Injection, really?


In short, Dependency Injection is a way to decouple specific types of objects in your code. It allows your program to be far more modular with minimal extra effort. If you have ever heard of the Factory, then you have at least a faint idea of what Dependency Injection is.

What is Roboguice… and what’s up with the name?


Roboguice is actually just an implementation of Google's Guice within Android – sorry, I don’t have a clue why they picked the name. It lets an application have all the benefits of Dependency Injection with just a handful of lines of code. In Google's words, "Guice alleviates the need for factories and the use of new in your Java code." Like everything else Google related, an IO video gives a pretty good idea about it.



Instead of creating handfuls Factories for every object that needs Dependency Injection, you can simply use RoboGuice to bind a particular sub type to a base type, which removes the need to have a Factory class for every type of object that could possibly be changed out in a program. Of course there are other benefits to using the framework, but this is the major benefit that many developers, beginners and experts alike, would see very quickly. Using the framework is actually pretty easy. I would say the heart of the framework can be described with the following line of Java code.+
bind(BillingService.class).to( RealBillingService.class);
These bind method calls are used within a new type of class called Modules. What this line means is, during runtime, any instance of BillingService that is marked correctly  should actually be RealBillingService. This one line barely scratches the surface though. You can see the rest of this example, which includes how to build modules and using the @Inject method, here.
Using this framework decreases the amount of objects you need to create within the program. Any factory objects that are used within the project can be replaced. Any object that doesn’t have to be created saves valuable processor cycles and battery power for the user. All for the cost of adding a few libraries to your project, and actually making your code easier to understand in the process. Sounds like a no brainer to me.

Wednesday, January 11, 2012

ACRA–Easy Crash Log Reporting for Android

 

When I was looking at third party libraries for Android the other day (check out this link to find some interesting libraries; they may make your life easier), I stumbled across a pretty nice library for getting crash reports from your applications when they are out in the field.

ACRA generates all of the crash information you need--from device specs to log cat output during the crash. It uploads all of this info to a specified Google Doc Form. It even allows the user to input a simple message to the crash report before it gets sent out.

This tool is great for small testing groups. It allows you to grab all the info you need about a crash without trying to pry it out of your testers. But ACRA doesn’t scale very well, though. More than a handful of testers sending crash reports this way would become pretty difficult to sort and find the information if needed quickly.

Tuesday, January 10, 2012

Programming Mobile Now Available on Android

You can now download the Programming Mobile app on the Android market for quick access to programmingmobile.com.

Click here to download.

image

Monday, January 9, 2012

Multicast and Android – A Big Headache

You may want to rethink any apps that require multicast on Android.
Multicast allows one device to send out a message to every other device on a network (usually a LAN). This allows devices to send out messages to a network without knowing who is listening on the other end. Ever wonder how Windows knows when your Xbox is hooked up or vise versa? Multicast is the key. Without multicast, a device has no idea what other devices are on a network.
Multicast works fine on most low-end routers you would buy at any store (which is probably why this problem hasn’t been addressed already). Once you get a bit higher up, you see many routers implementing IGMP, which causes a big problem in Android.
IGMP
The Internet Group Manager Protocol is a standard for handling multicast packets over a network. IGMP allows filtering of multicast traffic over a network. The idea is that all multicast traffic doesn’t need to be transmitted. Only traffic that something is actually listening for should be sent out. This is were IGMP comes in.
Using IGMP, devices can notify the network (usually a router of some kind) that its listening for specific multicast messages. As long as the router knows someone is currently looking for a specific message, it forwards them on.

What does this really have to do with Android?

After some in-depth testing with WireShark and tcpdump with a handful of rooted Android devices, it looks like not all Android devices fully, or maybe correctly, support IGMP. It also seems that only Android version 2.2 has any consistency in supporting the protocol. And even then, not all 2.2 devices did. The problem isn’t manufactor specific either. IGMP was missing on different HTC, Samsung, and Motorola devices of all android version from 2.1 up to 3.2.
Check out all the latest bugs filed on Android about Multicast. Some of the older bugs have been closed. But it seems Android’s IGMP support may still have some problems. Even worse, this could be dependent on the manufacture of a unique device’s build of Android. If that really is the case, there is little hope of getting consistent support on old devices.

Sunday, January 1, 2012

Working 40 hours a Week is Nothing if You Enjoy what You’re Doing - Looking Back on 2011

I finally got out of college and moved into my first full-time job. Many people say that in the first 6 months of your first job, you’ll learn more than you did in most of your college years. Boy were they right.

I’ve learned a great deal about software development in the real world in the past few months. I’ve been lucky enough to be a major part of a team through a full development cycle on some highly visible projects. I’ve also had a chance to start a project from scratch and watch what it turns into, learn what type of problems come up, and see how problems are solved. From the experience I have already taken in, I have plenty of things I would like to improve next time I get the chance.

Here are some lessons learned:

  1. Communication is key in solving problems.
  2. Ask questions! Even dumb questions have a chance to uncover a situation that no one else has thought of yet.
  3. When no one else will step up and get things done, take the opportunity yourself. You’ll be glad you did later.
  4. Be open and willing to accept any comments anyone has about your work.
  5. Keep your own comments to yourself unless explicitly asked for them.
  6. Learn everything you can. You never know what solution you will find today that will help you later on.
  7. Working 40 hours a week is nothing if you actually enjoy what you’re doing

Team dynamics are a very interesting part about industry software development. Discovering how other people work and what they require to get things done is a pretty difficult process. It’s also absolutely essential to producing great quality products, though. Understanding team dynamics allows you to see different perspectives on how to go about programming, which is never a bad thing.

With the above in mind, there is a bit of a grey area that is also important to note. It is still important to not let your coworkers determine how you perform. It’s very easy to get bogged down with what everyone else is doing. You shouldn’t let anyone else’s work ethic or problems determine how you do your job. Simply do the best you can, and you won’t have any problems.

So what should I accomplish this year?

  • Figure out the key to marketing Android Apps. I still haven’t found the key to getting the word out about my two applications (RB Recorder and Work Tracker).
  • Learn what all the fuss about HTML5 really is-- and if it’s really going to go anywhere.
  • Move into iOS programming.

Happy New Years!