Tony Lukasavage

Caffeine. Whiskey. Code. Mostly the last one.

NerdKits under my Christmas Tree!

Time to dive into the world of embedded programming head long with one of my favorite Christmas gifts: my NerdKit. What’s a NerdKit? Well its basically a starter kit for bridging programming with the real world through electronics, an API, and a thorough guide for getting started. You might have also heard of Arduino, which is a similar and uses open source technology for embedded programming.

What can you do with it? Well, thats what I aim to find out. In the meantime, though, you can check out the “Projects” page of the NerdKits site for some pretty damn cool projects that include:

  • iPhone controlled RC Car
  • Morse Code decoder
  • Digital thermometers
  • Spark generator
  • Computer controlled robotics and devices

So for all you SavageLook.com faithful there’s sure to be some NerdKit guides and demos to come. Here’s hoping I haven’t forgotten every bit of electrical engineering I learned in college. Forget it, I drank that knowledge clean outta my head. I guess 3 hours/week of EE can’t compete with 12 hours/week of beer pong. Oh well, should be fun anyway!

Oh and be sure to follow @nerdkits on twitter for all kinds of cool updates, demos, and tutorials!

Fixing VirtualBox Guest Additions for Ubuntu 10.10

So I have a Centos server project for which I need to do some C++ development. I thought it would be logical to use Centos as my development desktop, inside VirtualBox. This line of thinking was unfortunately flawed as Centos sucks as a desktop. Don’t get me wrong, I wouldn’t build a server anymore that wasn’t running Centos, but the desktop is just hopeless.

Enter Ubuntu 10.10. It was quick, simple, and straightforward to install and get running. Things actually worked like you would expect they would, you know, like a normal desktop OS. I installed Eclipse and all the necessary C++ libraries I needed. Now it came time to build the Guest Additions in VirtualBox for Ubuntu…

Well, it appeared to work, but I couldn’t use the auto-resize functionality of VirtualBox to change the size of the desktop. Also, the screen resolution was stuck at 800x600. As it turns out, the built-in guest additions for Ubuntu 10.10 don’t work correctly. In order to fix the situation you just need to execute the following on the command line:

1
2
3
sudo apt-get update
sudo apt-get install build-essential linux-headers-$(uname -r)
sudo apt-get install virtualbox-ose-guest-x11

This will install the latest VirtualBox guest additions for Ubuntu 10.10. All you have to do now is restart your VirtualBox instance of Ubuntu and you’ll be all set. You can now adjust your screen resolution to your liking and the VirtualBox auto-resize of the Ubuntu guest display will be working.

Happy Ubuntu’ing!

Programmers: Why do we do it?

Every now and again when suffering through a movie my wife has chosen, I manage to find one thing I really like about it. This time the form of torture was “The Kids Are All Right”. Fantastic acting, spectacularly unentertaining story. Anyway, while I was daydreaming about code, I heard this exchange that probably went right over the heads of most viewers. Not the viewers fault, they were probably still reeling from the rough Mark Ruffalo on Julianne Moore action in the prior scene.

Gardener: “I have allergies.” Jules: “Then why are you a gardener?!” Gardener: “Because I love the flowers.”

And then they fly right past that line, but that’s the one good thing I took from this movie. Sometimes the things we love don’t make sense and can downright make us miserable, but it doesn’t make us love them any less.

In my head this philosophy plays so easily into the mind of programmer. There’s so much to dislike about programming:

  • Entire days spent chasing bugs
  • Short deadlines
  • Constantly having skillsets superseded by new technology
  • No appreciation for the work it takes outside other developers
  • The elitist nature of many in the developer community
  • Moronic clients
  • Late nights, long hours in front of a glowing screen
  • The constant inkling that some 14 year Japanese kid already did this better than you
  • The lottery-esque likelihood of independent success

And that’s just a few. I’m sure I’ll hear a few more in the comments.

Then why do we do it? What is there to love about programming? What is it about crafting together mountains of syntax that makes us come back to it every day? I know for most of us there’s a paycheck attached to it, but for plenty of us that’s not the root.

I may be getting too romantic even for my own tastes, but I think its the fact that those who truly love programming see it as an art form. Its not just a technical pursuit, but one that allows the leveraging of one’s unique talent and views. You bring a form of personal expression into your work. You invest yourself physically and mentally in what you do. You suffer and toil, using code as your medium, just as other artists craft with paint or stone. You have a personal association and pride with its creation. The code and its results represent you.

What do you think? Is there really a right-brain satisfaction achieved through a love of programming. Is it more than ones and zeros doing an assigned task? I think so. Otherwise, why bother?

Android SDK Windows Installer + JDK 64 bit = FAIL

Just a quick tip, when installing the Android SDK via Windows installer with the 64 bit JDK installed, you may get a “Java SE Development Kit (JDK) not found” error.

The problem is that the Android SDK is not recognizing the 64 bit JDK (duh). In order to work around this, you can do one of two things:

  1. Uninstall the 64 bit JDK and install the 32 bit JDK
  2. Download the Android SDK Windows ZIP file instead of the installer

I’d highly suggest the second option, as it lets you keep the better version of the JDK and doesn’t really require much more work. Just download the ZIP file, extract it where ever you want (C:\android-sdk-windows), and then run the “SDK Manager.exe” to install all the SDK platforms to develop against. After that, add the following 2 directories to your system path (you don’t have to, but it’ll make things easier from the command line):

  • C:\android-sdk-windows\tools
  • C:\android-sdk-windows\platform-tools

Make sure you restart any open command lines to take advantage of the new PATH. That’s it. You are now free to use your favorite workflow, be it native Java or Adobe Air mobile development. Happy Androiding!

Quick Tip - C# property with abstract getter, concrete setter

The Problem

On a recent .NET project I was defining an abstract class in C# when I came upon a unusual case: I needed a property that had an abstract getter, but a concrete setter. In other words, the getter needed to be implemented by all derived classes and the setter does not, in fact its defined in the abstract class. Nothing I like more than a good object oriented programming quandry.

Here’s some code to help make sense of it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public abstract class BaseClass
{
    private string _baseValue;
    public abstract string Value
    {
        get;
        // the "set" will cause a compile error.  You can't define the get or set inside
        // of an abstract property.
        set
        {
            _baseValue = value;
        }
    }
}

The Solution

While the above syntax will generate a compile time error, there is a fairly simple way to work around the issue. Check out this code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public abstract class BaseClass
{
    private string _baseValue;
    protected abstract string ValueGet();
    protected void ValueSet(string baseValue)
    {
        _baseValue = baseValue;
    }

    public abstract string Value
    {
        get
        {
            // as implemented by the derived class
            return this.ValueGet();
        }
        set
        {
            // as implemented by BaseClass, or derived class override
            this.ValueSet(value);
        }
    }
}

Here we delegated the setting and getting of the property to separate protected methods within BaseClass. Now that 2 methods are used we can assign whether or not they are abstract separately. The getter must be implemented by the derived classes, the setter may or may not be.

And that’s it. Obviously this code also works vice versa, with the setter being abstract and the getter being concrete. It’s nice because from the perspective of someone using your code, nothing changes with regards to the public Value property. The use of protected methods to defer overriding and abstraction help you avoid writing any unnecessarily redundant code in your derived classes. It’s a nice little trick to have in your pocket.

Happy C# OOP’ing!

Offline packet capture analysis with C/C++ & libpcap

The Overview

At the request of one of my faithful readers in my original article on packet capture with libpcap, I decided to post a guide to offline packet capture processing. Why is this useful? Because popular packet capture programs like Wireshark or tcpdump can save captures to files that can be processed later. You can then apply your specialized code to these previously captured packets.

The Code

NOTE: This program makes use of the http.cap Wireshark packet capture sample.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <iostream>
#include <pcap.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>

using namespace std;

void packetHandler(u_char *userData, const struct pcap_pkthdr* pkthdr, const u_char* packet);

int main() {
  pcap_t *descr;
  char errbuf[PCAP_ERRBUF_SIZE];

  // open capture file for offline processing
  descr = pcap_open_offline("http.cap", errbuf);
  if (descr == NULL) {
      cout << "pcap_open_live() failed: " << errbuf << endl;
      return 1;
  }

  // start packet processing loop, just like live capture
  if (pcap_loop(descr, 0, packetHandler, NULL) < 0) {
      cout << "pcap_loop() failed: " << pcap_geterr(descr);
      return 1;
  }

  cout << "capture finished" << endl;

  return 0;
}

void packetHandler(u_char *userData, const struct pcap_pkthdr* pkthdr, const u_char* packet) {
  const struct ether_header* ethernetHeader;
  const struct ip* ipHeader;
  const struct tcphdr* tcpHeader;
  char sourceIp[INET_ADDRSTRLEN];
  char destIp[INET_ADDRSTRLEN];
  u_int sourcePort, destPort;
  u_char *data;
  int dataLength = 0;
  string dataStr = "";

  ethernetHeader = (struct ether_header*)packet;
  if (ntohs(ethernetHeader->ether_type) == ETHERTYPE_IP) {
      ipHeader = (struct ip*)(packet + sizeof(struct ether_header));
      inet_ntop(AF_INET, &(ipHeader->ip_src), sourceIp, INET_ADDRSTRLEN);
      inet_ntop(AF_INET, &(ipHeader->ip_dst), destIp, INET_ADDRSTRLEN);

      if (ipHeader->ip_p == IPPROTO_TCP) {
          tcpHeader = (tcphdr*)(packet + sizeof(struct ether_header) + sizeof(struct ip));
          sourcePort = ntohs(tcpHeader->source);
          destPort = ntohs(tcpHeader->dest);
          data = (u_char*)(packet + sizeof(struct ether_header) + sizeof(struct ip) + sizeof(struct tcphdr));
          dataLength = pkthdr->len - (sizeof(struct ether_header) + sizeof(struct ip) + sizeof(struct tcphdr));

          // convert non-printable characters, other than carriage return, line feed,
          // or tab into periods when displayed.
          for (int i = 0; i < dataLength; i++) {
              if ((data[i] >= 32 && data[i] <= 126) || data[i] == 10 || data[i] == 11 || data[i] == 13) {
                  dataStr += (char)data[i];
              } else {
                  dataStr += ".";
              }
          }

          // print the results
          cout << sourceIp << ":" << sourcePort << " -> " << destIp << ":" << destPort << endl;
          if (dataLength > 0) {
              cout << dataStr << endl;
          }
      }
  }
}

The Breakdown

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <pcap.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>

using namespace std;

void packetHandler(u_char *userData, const struct pcap_pkthdr* pkthdr, const u_char* packet);

These are the includes and declarations necessary for reading the packet captures. The first 2 are self explanatory, the following 5 includes might be less so. These are used for parsing and transforming data found in packets. The functions and structures included in these headers are integral to packet processing and are available natively on Linux systems (Ubuntu in this case).



1
2
3
4
5
6
7
8
9
10
int main() {
pcap_t *descr;
char errbuf[PCAP_ERRBUF_SIZE];

// open capture file for offline processing
descr = pcap_open_offline("http.cap", errbuf);
if (descr == NULL) {
  cout << "pcap_open_live() failed: " << errbuf << endl;
  return 1;
}

After entering the main execution, we go straight to opening our target packet capture file, http.cap. To do this we use pcap_open_offline() and give it the capture filename and an error buffer as parameters. If all goes well, we get a pcap_t descriptor returned. If not, check the error buffer for details.



1
2
3
4
5
6
7
8
9
10
    // start packet processing loop, just like live capture
if (pcap_loop(descr, 0, packetHandler, NULL) < 0) {
  cout << "pcap_loop() failed: " << pcap_geterr(descr);
  return 1;
}

cout << "capture finished" << endl;

return 0;
}

Just like in a live packet capture, we use pcap_loop() to set up a handler callback for each packet to be processed. We give it the following:

  • descr - the descriptor we just created with pcap_open_offline()
  • count - 0 (zero), to indicate there is no limit to the number of packets we want to process
  • callback - The name of our packet handler function
  • userdata - NULL, to indicate that we will be passing no user defined data to the callack

When the entire file has been processed, we will print the “capture complete” message and then exit.



1
2
3
4
5
6
7
8
9
10
void packetHandler(u_char *userData, const struct pcap_pkthdr* pkthdr, const u_char* packet) {
const struct ether_header* ethernetHeader;
const struct ip* ipHeader;
const struct tcphdr* tcpHeader;
char sourceIp[INET_ADDRSTRLEN];
char destIp[INET_ADDRSTRLEN];
u_int sourcePort, destPort;
u_char *data;
int dataLength = 0;
string dataStr = "";

Here we define the packet handler callback, as per the libpcap specifications. For more details, check out my original post on packet capture. The following declarations define variables that will help us parse meaningful data out of the packets. These include packet header data, IP addresses, source/destination ports, and payload data.

There’s LOTS more useful information to be analyzed from the average packet. Check out the structure defined in the network includes at the beginning of the code for more details. Actually, it would probably be a hell of a lot easier to just download and fire up Wireshark. It will give you a greater appreciation for what can be learned from a packet.



1
2
3
4
5
    ethernetHeader = (struct ether_header*)packet;
if (ntohs(ethernetHeader->ether_type) == ETHERTYPE_IP) {
  ipHeader = (struct ip*)(packet + sizeof(struct ether_header));
  inet_ntop(AF_INET, &(ipHeader->ip_src), sourceIp, INET_ADDRSTRLEN);
  inet_ntop(AF_INET, &(ipHeader->ip_dst), destIp, INET_ADDRSTRLEN);

I’m not going to delve to deeply into the specifics of network protocols, as that could be a post… check that… that could be a book of its own. Basically here we are parsing the ethernet header from the packet and using its type to determine if it is an IP packet or not. We use the ntohs() to convert the type from network byte order to host byte order.

If it is an IP packet, we parse out the IP header and use the inet_ntop() function to convert the IP addresses found in the IP header into a human readable format (i.e., xxx.xxx.xxx.xxx). In a lot of older examples you’ll see the use of inet_ntoa(), but this is not thread-safe and is deprecated.



1
2
3
4
5
6
  if (ipHeader->ip_p == IPPROTO_TCP) {
      tcpHeader = (tcphdr*)(packet + sizeof(struct ether_header) + sizeof(struct ip));
      sourcePort = ntohs(tcpHeader->source);
      destPort = ntohs(tcpHeader->dest);
      data = (u_char*)(packet + sizeof(struct ether_header) + sizeof(struct ip) + sizeof(struct tcphdr));
      dataLength = pkthdr->len - (sizeof(struct ether_header) + sizeof(struct ip) + sizeof(struct tcphdr));

Similar to above, I use the IP header to determine if this is a TCP packet (they all should be since its a HTTP capture) and then parse out the TCP header. With the TCP header we can then determine the source and destination ports, with ntohs() again, and then determine the contents of the packet payload.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
      // convert non-printable characters, other than carriage return, line feed,
      // or tab into periods when displayed.
      for (int i = 0; i < dataLength; i++) {
          if ((data[i] >= 32 && data[i] <= 126) || data[i] == 10 || data[i] == 11 || data[i] == 13) {
              dataStr += (char)data[i];
          } else {
              dataStr += ".";
          }
      }

      // print the results
      cout << sourceIp << ":" << sourcePort << " -> " << destIp << ":" << destPort << endl;
      if (dataLength > 0) {
          cout << dataStr << endl;
      }
  }
}
}

In the final step of the packet handler we display the results of our rudimentary analysis. First we iterate through the bytes of the payload and save it in a format that is human friendly. If you try to print it out with the non-printable characters in there you will get some very messy results in your console. After this cleanup we simply output the packet data we have extracted and display it in the console.

The Summary

So now that you can process packets offline, what do you want to do with them? I don’t know about you, but aside from obvious applications to network analysis, I’d like to use this data for trending, visualization, or even generative art and sound. But then again I’m weird. What are you gonna do?

Quick Tip: Deserializing XML to objects in C#

The Overview

Here’s a quick example of how you can deserialize XML into C# objects. This will be brief, so feel free to ask questions in the comments for more details.

We are going to write a small class and program to deserialize objects.xml into a MyObject object that can then be used in the main program, Program. Its not rocket science, but it beats the hell out of manually parsing XML to get the information we need.

The Code

objects.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<ArrayOfMyObject>
  <MyObject>
    <name>ObjectName</name>
    <intValue>123</intValue>
    <timestamp>2010-12-15T08:54:11</timestamp>
    <elementNameDifferentThanObjectPropertyName>ridiculously long name</elementNameDifferentThanObjectPropertyName>
  </MyObject>
  <MyObject>
    <name>AnotherObject</name>
    <intValue>235435</intValue>
    <timestamp>2010-12-15T08:59:51</timestamp>
    <elementNameDifferentThanObjectPropertyName>seriously, its way too long</elementNameDifferentThanObjectPropertyName>
  </MyObject>
  <MyObject>
    <name>TheLastObject</name>
    <intValue>6543333</intValue>
    <timestamp>2010-12-15T09:04:43</timestamp>
    <elementNameDifferentThanObjectPropertyName>no way this is gonna be the property name</elementNameDifferentThanObjectPropertyName>
  </MyObject>
</ArrayOfMyObject>

MyObject.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System;
using System.Xml.Serialization;

namespace MyNamespace
{
    public class MyObject
    {
        public string name;
        public int intValue;
        public DateTime timestamp;

        [XmlElement("elementNameDifferentThanObjectPropertyName")]
        public string extraValue;

        public MixOrder()
        {
            name = "";
            intValue= 0;
            timestamp = new DateTime();
            extraValue = "";
        }
    }
}

Notice I used the XmlElement attribute for the XML field with the obscenely long name. XmlElement specifically represents System.Xml.Serialization.XmlElementAttribute. This allows us to assign an element or attribute of the XML to a public property of the deserialized object even if their names don’t match. This is useful in the case of undesirable XML element names that are hard to work with or break coding conventions. Also, and more importantly, as the XML you deserialize changes over time, you can just adjust the name of the XmlElement attribute if necessary without changing the functionality of the object.

Program.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;
using System.Xml;
using System.Xml.Serialization;
using MyNamespace;

namespace TestConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            List<MyObject> myObjects = new List<MyObject>();
            XmlSerializer serializer = new XmlSerializer(typeof(List<MyObject>));
            XmlReader reader = XmlReader.Create("objects.xml");
            myObjects = (List<MyObject>)serializer.Deserialize(reader);

            // now you can perform operations on your list of MyObject objects,
            // no manual XML parsing necessary.

            Console.WriteLine("Press <ENTER> key to exit.");
            Console.ReadLine();
        }
    }
}

I leave the processing of the object up to you, but the process is clear. We create a XmlSerializer that corresponds to the type of our object, create a XmlReader for the XML, then use the serializer to deserialize the XML from the reader. From there you have a successfully populated List list. Do with it what you will.

In the words of the Beastie Boys, “That’s it, that’s all, that’s all there is.” See ya at the next quick tip.

Haters Gonna Hate: The Psyche of the Tech Zealot

Actual comments to a reddit post I made regarding the Adobe Molehill 3D API:

“Since Adobe’s making it, will it use 3x the memory and be 10x slower than webgl?” “Molehill? If it looks like a shitpile….” “HTML5 and CSS3 already do that way better.” “wtf… games are written in C++ or C”

Tech zealots, they are everywhere, particularly on discussion forums where they can make their views tactlessly clear. They have holed up in one camp and anyone using anything but their weapon of choice is clearly a moron. I’m not talking about open minded professionals with conflicting views, just those people highlighted by the pearls of wisdom above.

But why? Why would someone be so vehemently opposed to technologies they obviously have only a stereotyped or passing knowledge of? Insecurity of course, but more specifically:

Lack of Skill and/or Intelligence

This is the most common root cause of mindless scathing comments on technology. The purveyor of bullshit is not smart or motivated enough to speak intelligently on more than one technology topic, so all others aren’t worth discussing. His mind cannot be changed, as this would require a level of decision making and logic that is beyond him.

This person is the manifestation of why the “ignore” function exists on forums and networks.

The one hit wonder

When is your hammer, everything looks like a nail. Aside from the true idiots mentioned above, these are the second most prevalent zealots. They have hitched their wagon to one technology and are going to ride it til the wheels fall off… and maybe even after that. And guess what? You need to agree that it was the right choice.

The best way for a one hit wonder to keep himself relevant and in demand is by increasing the numbers of his clan. Convince others that his tech is the holy grail of software development. He will find any opportunity to insert the technology he knows well into a situation, regardless of how inappropriate it may be, and cite it as the “right” solution.

I’ve had a small, basic website project in a PHP shop be diagnosed by a OHW as needing a C++ web framework. I’ve seen web servers created in Perl (OK, that was me). The point is, add more tools to your toolbox or run the risk that your hammer starts collecting dust.

Lack of experience, or just one bad one

You know the type, the person who used Actionscript once 6 years ago and hinges his beliefs of Flash, Air, and any Adobe product on that experience. They cite shortcomings and problems that no longer exist. They perceive any former weakness as an inevitability that the technology in question will always be a total failure. Windows ME sucked so there’s no sense in trying Windows 7, right?

But this person is not beyond help. As easily as they dismissed the language, there is a chance they will applaud it in the future. The trick is getting them to revisit it. Unless this person gives the technology another try they will continue to perpetuate misinformation.

Fear of being made obsolete or jobless

In this day and age the lifetime tech job doesn’t exist. Even worse, employers are viewing programmers as interchangeable parts of a business; assuming one developer can be swapped out for another. Then how does one remain important? By feigning a high level of expertise.

Unfortunately, the damage done by a developer pretending to know what he’s doing doesn’t end in the office. The guy who fooled your recruiters is a pain in the ass everywhere he goes… especially the internet. What better place is there to pretend you are smarter than someone else than in Internet forums and debates? Its vast, anonymous, and you can pretty much say anything you want.

So this one hit wonder is going to spend his time, as he does in the office, creating this myth of talent and expertise with anyone who will listen. He will unleash a deluge of buzz words. He will weave tales about wildly successful projects, of wildly varying validity. And like at work, he will get just enough people to believe him to make your interactions with him miserable.

Refuse to appear “wrong”

You’ll typically see this when a debate backs one guy into a corner, usually attributed to his own limited knowledge of the technologies in discussion. Lots of diversions and straying from the topic at hand. Dialogs like the following are sure fire indicators of this mentality:

Zealot: Python is just a language for blogs and little hobby websites. You need enterprise level Java for a scalable solution. Normal person: That’s weird, it seems to work for Google and Youtube. Zealot: Yeah, but only for small parts of their site. I’m sure they use a better language for their core. Normal person: Nope, they have both cited that Python is the primary language used in their implementations. Check out this post from the creator of Python about Youtube. Zealot: Python would never work for a REAL business site though.

The zealot here is blindly adhering to his perception that the technology he was bashing was “bad” for the described situation. When proven wrong he then throws out vague, unprovable statements in an effort to remain relevant in the conversation.

Mob mentality

Misery loves company. And the more company the more misery. There’s power in those numbers. A stereotype’s effectiveness is directly proportional to the number of people you can get to believe it. Get enough people to chant “Java is slow,” “Microsoft is evil,” or “C++ is too complicated” and it can be enough to divert a person from a technology before they even try it. And yes, I even dodged Java for a long time because of the first one.

A person allowing themselves to fall victim to this mentality is usually a smattering of many of the above listed mentalities. Not enough personal experience coupled with a strong allegiance to other technologies that designed with similar tasks in mind can easily make you dismissive of another. Be vigilant and open minded. Make your own decisions.

The Open Source / Vendor Zealot

This is a mentality I’m sure you are familiar with. Open source zealots that can’t admit that many commercial products far exceed the capabilities offered by open source alternatives. On the other side of the coin you have vendor zealots who feel that all open source software is invariably buggy, unstable, and inferior to commercial products.

I once brought the idea of converting IIS servers to Apache for our small web presence to one of my bosses. His reply? “Nobody really uses Apache anymore.” It blew me away. The product trusted to run ~60% of the world’s websites was dismissed without a second thought due to misconceptions about open source software.

This mentality is a really tough nut to crack. You take a healthy respect for a technology and compound it with preconceived notions about free/paid alternatives to create unfounded animosity. The worst part is that there’s tons of people who have this mindset and will not only avoid free/paid techs, but slander them as well. Much like fixing phobias, a steady diet of forced exposure to positive events regarding the technology they fear or hate is the road to recovery.

Final Thought

If you fit one or more of the mentalities above, take a deep breath before you start hammering me with inflammatory comments. The fact that you read the article means you are not a terminal case. You may have a valid allegiance to a great technology. But has it blinded you to other opportunities to learn and excel? Have you helped perpetuate myths?

Take a hard look at your own views and you may find yourself a little less angry at me and a little better of a developer in the end.

Create Your Own QR Code

The Generator

Text for QR Code:

The Overview

QR codes are basically just bar codes on steroids. They allow you to encode up to 4,296 characters in a format that can be read by most modern bar code scanning devices. More specifically, QR codes make it much simpler to direct smart phone users to your website (or anywhere else you want).

So why do you want to do this? Here’s a few reasons that range in practicality:

  • Direct mobile phones to personally hosted mobile applications (no need for market fees)
  • Direct users from physical storefronts or magazine articles to your website
  • Leave encoded messages for mobile users
  • To be super cool and trendy

The Code

Here’s the Google Chart API URL you hit in order to create your own QR code. Pop it into a browser and it will return your image. There are more optional criteria you can send, which are detailed in the API’s QR code section. Be sure to change the sections highlighted in RED to the values that fit your needs.

http://chart.apis.google.com/chart?cht=qr&chs=HEIGHTxWIDTH&chl=YOURTEXT

Now let’s say you wanted to copy my website and have your own generator. It’s pretty simple. Here’s the tiny bit of HTML and javascript I used to make it happen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<table>
  <tr>
    <td>
      <strong>Text for QR Code:</strong>
      <form onsubmit="return false;">
        <input type="text" id="qrvalue" value="http://savagelook.com" style="width:250px;"/>
        <button onclick="document.getElementById('qrimg').src = 'http://chart.apis.google.com/chart?cht=qr&chs=150x150&chl=' + document.getElementById('qrvalue').value;">Encode</button>
      </form>
    </td>
    <td>
      <img id="qrimg" src="http://chart.apis.google.com/chart?cht=qr&chs=150x150&chl=http://savagelook.com"/>
    </td>
  </tr>
</table>

And here’s another version from Eric Harrison with no tables

1
2
3
4
5
6
7
8
<div style="padding:15px 50px;">
  <img id="qrimg" src="http://chart.apis.google.com/chart?cht=qr&chs=150x150&chl=http://savagelook.com" style="float:left;margin-right:25px;" />
  <form onsubmit="return false;">
    <input type="text" id="qrvalue" value="http://savagelook.com" style="width:60%;font-size:125%;" /><br />
    <input type="button" style="padding:5px;font-size:125%;margin-top:10px;" onclick="document.getElementById('qrimg').src = 'http://chart.apis.google.com/chart?cht=qr&chs=150x150&chl=' + document.getElementById('qrvalue').value;" value="Encode" />
  </form>
  <br style="clear:both;" />
</div>

As you can see, its not rocket science, but it sure can add a little techie flare. Have fun and be sure to let me know if you add a QR coding to your geek repetoire!

Mobile Development: Native vs. Adobe Air

DISCLAIMER: This article is about Adobe Air as an alternative to native API mobile development. Other mobile frameworks like Appcelerator Titanium and PhoneGap are not discussed.

The overview

So you want to make an iPhone app? Wait, you want to run it on Android too? And any tablet? And any desktop? And you want to be able to reuse the code base for all of them? OK, sounds good, now let me just get the magic elves and unicorns to take care of that for you. It will cost you one soul. Doesn’t have to be yours.

Or… you could use the Adobe Air SDK. Yeah, Adobe Air can do all that. Check out this video from Christian Cantrell’s blog where he shows how a single AS3 code base can be used to create an app for the iPad, iPhone, iPod Touch, Droid, multiple desktops, and the web. Pretty incredible stuff for indie developers:

For those wondering how you get past the Steve Jobs stranglehold on the Apple app store with an Adobe Air app, check out the Adobe Labs project “Packager for iPhone,” which also works for the iPad and iPod Touch. He also got it running on the Blackberry Playbook emulator. Its also worthy to note that Adobe Air and Flash are in the pipeline for Windows Phone 7, Blackberry phones, and many more mobile devices.

Now if I can do this with one language and one framework rather than 1/2 a dozen, why even bother learning the Java & Android SDK, Objective-C & iOS, or any other combination that may arise? At some point you have to have a better answer than “to learn it.” As with any consideration like this, there’s lots of pros and cons for each side of the argument. Here’s a few things to consider.

on the native side…

People want a uniform user experience

And by “people” I mean “non-technical users.” And by “uniform” I mean “native.” People want all their interface components to have the same look and feel. Its gives apps a more intuitive nature. While Adobe’s Flex Hero interface components are uniform to Adobe Air apps, they don’t represent the components found on each individual mobile device.

You can, however, use AS3 libraries like as3iphonecomponents or android-components to preserve that native experience. As you might be able to guess by their names, they are collections of UI components for the iPhone and Android respectively that mimic those of the native system. While this solves the uniformity problem, it adds additional complexity to your multiscreen projects thereby undoing some of the efficiency added by the Adobe Air & AS3 workflow.

Or you could just forgo the whole uniformity thing and have a designer make all your components.

Native code will perform better

This is kind of a no-brainer. In my experience, and in talking with mobile users, responsiveness and performance is consistently better in native mobile applications. And not just that it is consistently better, but also that it is consistent across devices. I’ve heard many complaints about packaged Flash apps running crazy slow on Apple devices but fine elsewhere. This is especially true of resource intensive apps like games. Granted this isn’t shocking news, but it is a concern for those trying to preserve the user experience.

But this doesn’t necessarily apply to everyone. If you are building a simple data and UI component driven app, Adobe Air should be more than enough to handle that with smooth performance. And those resource intensive apps that may not run as well as native apps now are going to be catching up soon. Adobe is constantly increasing performance on mobile devices. Recently they have had a strong focus on GPU processing for graphics and will even be releasing a full, low level 3D API called “Molehill” mid 2011. As long as they keep this pace with performance enhancements, there’s no reason to believe that Flash and Air games won’t be as prevalent on mobile devices as they are on the web.

Steve Jobs can shut you down

Until just a few months ago, deploying AS3 written apps to Apple devices was impossible. This was because Apple had a restriction that no 3rd party development tools could be used to create Apple apps. You used the Apple sanctioned workflow or you were SOL.

Luckily Steve came to his senses and lifted the ban and Adobe re-released the iPhone packager. But it shines light on a dangerous precedent. There’s nothing to stop him from doing it again at some point in the future. Hell, MacBook Airs are not even preinstalled with Flash anymore. If Apple drops the hammer, BOOM, there goes a significant portion of your mobile audience.

Native functionality

Without native coding, you are at the mercy of what Adobe has currently implemented and abstracted. Things like Android Intents hit the cutting room floor for the sake of creating a single framework. While Adobe does a good job of either capturing all available functionality (like Geolocation, microphones, and cameras) or creating similar functionality, it will be by nature, a step behind the advances in mobile development. This could be offset if Adobe maintains a close relationship with the major mobile players.

on the adobe air side…

Spend more time creating, less time battling compatibility

This is why we’re here, isn’t it? With a single language, framework, and workflow you can create a code base that can be applied to any device that can support Adobe Air or Flash. That should be mighty intriguing to any indie developer. You can cut your development time down to a fraction of what it would be if you had to learn every mobile device’s framework. You are instantly building to multiple devices and broadening your target audience with almost no additional effort.

Flash, Air, and AS3 resources are abundant

The mobile APIs out there are well documented and have strong, growing communities. Adobe’s communities, though, are even more so. They have been around a much longer time than these relatively new APIs and are chock full of expert developers, designers, examples, and code. The sheer volume of resources available to AS3 and Flash based projects is incredible, just look at this list of available game engines for example. Need inspiration? Check out one of the many open Flash sites out there, like wonderfl.net.

Now lets move on to the tools invovled. Love them or hate them, Adobe knows how to make design and development software. Expensive, yes, but worth every penny. They have the design to development workflow that helps apps stand out down to a science. Let’s say you don’t believe me, or you don’t want to pay the money. That’s fine, because there’s plenty of free tools for creating Flash and Air content out there too. Check out FlashDevelop or FDT for great alternatives to the Adobe suite.

Reuse existing AS3 code

I know what you’re thinking: Can’t I also reuse existing Java in Android or Objective-C on the iPhone? Well yes, but not to the level that you can with AS3. Let’s say you have a game that logs top scores, uses a physics engine, and has some built in menus. Chances are that most of these things, with some serious effort, can be translated into the mobile API of your choice. But even if that is the case, you still need to integrate that all into the mobile API’s framework, which can be a daunting task.

With Flash or Air, though, you can literally compile or package the application AS IT IS to any mobile format that Adobe supports. Wanna make your old flash game a mobile app? Run it through the appropriate compiler or packager and you are good to go, no changes necessary. Now don’t get too excited. Chances are you will need to do some scaling and appearance tweaking in descriptor files to accommodate your target devices, but the transition is much simpler than with mobile APIs and native code.

Flex “Hero” and flash builder “Burrito” makes things a lot easier

Before the MobileApplication framework added to the Flex SDK, mobile development was very possible, but still felt like a flash app instead of a mobile app. With Flex “Hero” Adobe focused on creating a framework for multiscreen development, but also to be able to create apps that behaved like mobile apps.

What do I mean by “behaved like mobile apps?” Well, mobile apps typically operate as a stack of full screen views. Gestures or menu options are used to navigate between the views. Things like “Back”, “Menu”, and “Search” buttons need to be handled in a way the user expects. The app also needs to be able to close itself when no longer in use. These are just a few of the things that give that mobile feel that are not typical of flash apps. These are now present in Hero.

And how do we simply and quickly leverage this new functionality in the Flex SDK? With Flash Builder “Burrito” of course! Burrito is currently a preview release of Flash Builder that supports the creation, development, debugging, and deployment of Air for Android apps (And you can bet other devices are just around the corner). Complete with design view and dimension emulation for the various target Android devices it supports. I highly suggest trying it out since its now available free for a 60 day trial.

The Summary

Condensing the majority of your mobile development down to one framework can cause one indie developer to match the work of a team of native mobile developers. But there are drawbacks. The factors listed above point out the potential shortcomings of an abstracted Adobe Air solution. If you are not willing to deviate from native workflows or only need to develop for one platform, perhaps the Adobe Air path is not for you.

If you are a mobile developer, you owe it to yourself to spend some time with Adobe Air’s workflow for deploying mobile applications. If you are an INDIE mobile developer, especially with an AS3 background, you are shooting yourself in the foot productivity-wise if you are not pursuing this further. Here’s some links to help you on your way to multiscreen development bliss:

Flex SDKAir SDKFlex “Hero” SDKFlash Builder “Burrito”Packager for iPhone

If you do go down this path, let me know, I’d love to hear your experience. If not, why not?