Tuesday, October 18, 2011

Parallels config - CentOS Server 5.0 (guest) on Mac OS X (host)

Not much documentation on getting CentOS Server 5.0 to work as a guest OS on Mac OS X so here's some gouge:

Installing Parallels Tools:
  • To enable networking, be in "Shared Network" and run "/sbin/dhclient eth0".
  • Mount the CDROM: "mount /dev/cdrom /mnt/cdrom". You might need to create /mnt/cdrom directory.
  • Install the prereqs: "yum install gcc kernel-devel".
  • The kernel and kernel-devel package must be exactly the same. To check this, run "uname -a ; rpm -qa kernel\* | sort". For me, this returns 2.6.18-274.3.1.e15 for kernel, kernel-devel, and kernel-headers (don't think headers are required but not sure). If you need to update the kernel, "yum install kernel" and reboot.
  • /mnt/cdrom/install should work
  • Once installed, my Mac OS X home directory was available at /media/psf/Home.

Friday, June 24, 2011

Remote backup of SimpleDB domains

So Amazon Web Services is pretty good but they're still lacking some of the small stuff. I'd like to see automated usage reports, warnings about suspicious traffic surges, and better backup options. I really don't understand why they don't assign a few dudes to build these things out because I know people have been begging for them for years.

Anyway, I coded a really simple Python script that will back up my domains. In no way is this a scalable solution - if you have a couple million items in your database, this is likely not a cost effective option. I've got less than a thousand entries today and I'm adding only a few hundred per week. It's hosted on WebFaction, which is a great hosting company - for only a few bucks per month you get access to your own very capable virtual server (no more mooching off friends or using inferior free services). It also uses boto, which is a very mature Python library for all things AWS. I've added it to my crontab to run a few days per week and it sends me an email when it's done. Of course, all usernames, passwords, email addresses removed. So here it is:

#! /usr/bin/env python2.7

from boto.sdb.connection import SDBConnection
from datetime import date
from smtplib import SMTP
from email.mime.text import MIMEText
import os
import settings

conn = SDBConnection('access_key','secret_key')

# backup account domain
account_filename = 'backup/account-' + date.today().isoformat() + '.xml'
f = open(account_filename, 'w')
domain = conn.get_domain("account")
domain.to_xml(f)
f.close()
account_size = os.stat(account_filename)

# backup timelog domain
timelog_filename = 'backup/timelog-' + date.today().isoformat() + '.xml'
f = open(timelog_filename, 'w')
domain = conn.get_domain("timelog")
domain.to_xml(f)
f.close()
timelog_size = os.stat(timelog_filename)

msg = MIMEText("wrote " + account_filename + " (" + str(account_size.st_size) + " bytes)\nwrote " + timelog_filename + " (" + str(timelog_size.st_size) + " bytpes)")
msg['Subject'] = 'Payroll Nanny backup report for ' + date.today().isoformat()
msg['From'] = 'my_app_address'
msg['To'] = 'my_email_address'

s = SMTP()
s.connect('smtp.webfaction.com')
s.login('my_webfaction_username', 'my_webfaction_password')
s.sendmail('my_app_address', 'my_email_address', msg.as_string())
s.quit()

Wednesday, June 22, 2011

Android Market observations

It's been a few weeks since my last post - I've been super busy launching my first app on Android Market. The prototype was built a couple months ago and it's mature enough to be released into the wild. Homepage here and Android Market entry here.

Anyway, the work necessary to get my app on Android Market was suprisingly minimal. Here are some general observations:

  • Google does a great job tying into Eclipse: You can code with any IDE you want but for my money, I have to use Eclipse because it works so seemlessly with Google stuff. Even signing the app is simple.


  • Be very distrustful about network connections: I've been using my app for a couple months and never got presented with a "Force Close" (a crash). However, some of the errors being logged are the result of devices dropping network connection and my code was not catching these conditions sufficiently. I'm pushing an update this week which catches these exceptions, presents an alert dialog that states the network isn't working, and takes the user to a safe activity.


  • Be careful about security: There as a good article this week warning users of Amazon Web Services (which I am one) to get better with protecting credentials. I spent a good amount of time developing authentication middleware and don't use the VMs this article focuses on but it scared me enough to take a closer look at how I use IAM. I'm rolling credentials more, beefing up my personal password security, and paying more attention to my server logs.


  • Testing is hard: I got caught not checking for some basic weird user behavior, like putting spaces in usernames then putting that string in a GET request. Now that I have a bunch of users, I'm fixing these shortcomings.


  • Android Market exhibits some weird behavior for publishers: When trying to push my update, I was presented with "An unexpected error occurred. Please try again later." after clicking the "Upload" button. It seems like this is a catch-all error message that the Market displays whenever there's a problem. Back in April 2011, some servers were down and this was getting displayed all the time. I finally resolved it by logging out of Android Market and back in.

Sunday, May 22, 2011

A solution in search of a problem

I don't believe in algorithmic trading methods though I am aware that most stocks bought and sold every day are done so because a computer decided to pull the trigger.

Be that as it may, the real reason for my foray into this world was to write a program with server-side Python which utilizes a CouchDB storage solution and an Android app which visualizes the data on a canvas. Oh yeah, and lots and lots of JSON.

I don't really have a name for these programs - I call the collection of Python scripts ZapDome. The Android app is called WebFrenzy. I've open sourced the Python stuff but like I told a startup guy this week, please don't judge me by the excellence of this code - I'm a Python noob. I'll post the WebFrenzy code after I clean it up a bit. It's a real mess right now. Perhaps most importantly, it's yielded a pretty clever (in my opinion) lightweight Java CouchDB library for Android devices specifically built for interacting with Cloudant servers called BarcaJolt. I'll blog about that later.

Anyway, my algorithm is to look for significant volume trends throughout the day and compare those intraday prices with the closing price. So I collect data at the top of the hour 10AM - 3PM EST then sweep up the closing price at 5PM EST. If the volume is >= 125% or <= 75% what SHOULD be according to it's moving volume average at that time, I flag it.

For example, if a stock is averaging 1,000,000 shares of volume a day and at noon EST it's already racked up 900,000 shares traded, that obviously meets my definition of significant volume. Let's say at noon EST, this stock's price is $2.00 and at the end of the day, it closes at $3.00. What if this happens often? That is, hours when the volume is "high", it almost always posts a profit according to it's closing price?

Honestly, I don't really care what the algorithm is. I'm never going to use this data - I'm a value investor!. But it's a fun hack and gets me experience in things I want to learn more about (Python, CouchDB, JSON, Android apps).

So here's a couple screen caps of my Android app showing the behavior of 2 stocks I've been tracking over the last week (I've only pulled a week's worth of data). Obviously you can't pull any trends out of such a small data sample. The data is on an X/Y graph (Vollume/Price). So the top right quadrant shows instances where the stock's volume was high and the stock price rose before the close. More to follow.



Sunday, May 15, 2011

A CouchDB library for Android

So I really liked this article that was featured on Hacker News a week ago and it got me to thinking that maybe I'm using too many 3rd party libraries to help with areas I don't have much experience in (couchdbkit, for example, is awesome). So instead of using Ektorp to help me with Java/CouchDB/JSON stuff, I think I'm going to write my own library to help me with the Android portion of an algorithmic trading system I'm playing around with.

There already is a well-known CouchDB API build specifically for Android called droidcouch but I think this space can use more than 1 option and I have some ideas.

The most striking change between 2003, when I typed my last professional line of code, and now is the influx of 3rd party libraries. The infrastructure necessary to get a lot of adopters is already built out with github/Google Code/sourceforge.

Sunday, May 8, 2011

Some basic couchdbkit 'views' (get it?)

We had to go to LA this weekend and I made my wife drive so I could learn up on CouchDB views. I had to re-read the Design Document and View sections of my O'Reilly book a couple times before it really clicked. Thankfully, the book is detailed enough that I didn't need to be looking at a database through Futon to get the point.

So today I hacked together a simple view in a Python script. This returns all my documents with a .symbol of 'C'. I'm not good at JavaScript (yet) so this is about as advanced as I want to get as I focus on Python and CouchDB:

design_doc = {
    '_id': '_design/test',
    'language': 'javascript',
    'views': {
        'allcitis': {
            "map": """function(doc) { if (doc.symbol == "C") { emit(doc._id, doc); }}"""
            }
        }
    }
frenzydb.save_doc(design_doc)


No problem - worked the first time and I saw it my Cloudant database. Parsing the view results through couchdbkit to a little longer to figure out. The Getting Started page ends with:

greets = Greeting.view('greeting/all’)


It took me a little while to figure out 'greets' wasn't a list, it's a couchdbkit.client.ViewResults. As it says in the comments for couchdbkit/client.py, "It return an ViewResults object on which you could iterate, list, ...". Okay great, throw it in a list. Here's a trivial function to get the average of 'price' using the aforementioned view:

citis = list(frenzydb.view('/test/allcitis'))

sum = 0
for citi in citis:
    sum += float(dict(citi['value'])['price'])
print round(sum / len(citis), 2)

Friday, May 6, 2011

Google App Engine is pretty great (if you go all the way)

So I'm starting to bang around another project. As I describe it on my Careers 2.0 profile:
Project is still in its infancy but it will have server (GAE-hosted Python program evaluating JSON feeds of stock data with Cloundant [CouchDB] backend) and mobile (Android app to visualize/manipulate the data from Cloundant) components. There really isn't a point behind this program and I don't necessarily condone algorithmic trading - it's just a fun hack.

Or so I thought. Doesn't look like I'll be using Google App Engine because I don't want to do it the "GAE way" (not that there's anything wrong with that). Deploying an app to GAE is super simple but I ran into problems when starting to incorporate 3rd-party libraries (couchdbkit and restkit to be exact). These libs are too small to be part of the standard runtime environment. It's interesting to note that even Django is implemented in a slightly different way on GAE.

I'll spare the details (though they are available in my stackoverflow question) but I was having importing couchdbkit into my script. It was choking on things likes sockets and resources, which made me think I was running afoul of the sandbox rules:
An App Engine application cannot:
  • write to the filesystem. Applications must use the App Engine datastore for storing persistent data. Reading from the filesystem is allowed, and all application files uploaded with the application are available.
  • open a socket or access another host directly. An application can use the App Engine URL fetch service to make HTTP and HTTPS requests to other hosts on ports 80 and 443, respectively.
  • spawn a sub-process or thread. A web request to an application must be handled in a single process within a few seconds. Processes that take a very long time to respond are terminated to avoid overloading the web server.
  • make other kinds of system calls.

I put a question on the Cloudant discussion board and got not 1 but 2 answers from Cloudant techs within an hour (these dudes are good - I don't even have a paying account and they are very responsive). Anyway, they tipped me off to this telling Quora answer. It looks like the Django/Python hosting space is about to blow up with Heroku-like solutions.

Both the Cloudant tech and Django responder (a Django co-inventor) had good things to say about WebFaction. It is not a free hosting service ($9.50 per month and goes down with longer term contracts). After a quick Q&A session with a sales rep, I took the plunge. 1 hour later, my program was working perfectly on my WebFaction account. Success! The only thing that makes me nervous is having to do any sys admin stuff at all - getting my script and installations to reference the right Python version (WebFaction comes everything from 2.4 [default] up through 3.2) is about all I care to handle.

Sunday, May 1, 2011

Python + Couchdbkit = nice

So I'm working on a CouchDB project and you can read more about what I'm doing on the mobile side here.. There will be a server-side component and I want to get my feet wet with Python. I'm currently working through the tutorial but like most people I learn more by doing.

There are several CouchDB libraries for Python but I went with Couchdbkit. This decision was influenced by a post on the Cloudant discussion board stating Couchdbkit and Cloudant should work well together. So far, I have to agree.

The installation instructions for Couchdbkit are pretty straight forward. For the record, I'm using Python 2.6.6. I did find I needed to use restkit for HTTP resources. I set my sights low - I just wanted to get the program of Couchdbkit's Getting Started page to work. Username/password redacted to protect the innocent:

#! /usr/bin/env python

import datetime
from couchdbkit import *
from restkit import BasicAuth

class Greeting(Document):
    author = StringProperty()
    content = StringProperty()
    date = DateTimeProperty()

server = Server('https://[username].cloudant.com/', filters=[BasicAuth('[usename]', '[password]')])
db = server.get_or_create_db("greeting")

Greeting.set_db(db)
greet = Greeting(
    author="Benoit",
    content="Welcome to couchdbkit world",
    date=datetime.datetime.utcnow()
)
greet.save()

There are more exercises on the Getting Started page including an introduction to views. This worked as advertised with no need to change the supplied code.

Saturday, April 23, 2011

Rocking and rolling with Ektorp and Cloudant

My first Android app was developed using AWS' SimpleDB. While I like the Android SDK, I'm not terribly satisfied with the performance I'm getting. As far as NoSQL databases go, CouchDB is getting really great press. Cloudant is a well-respected YC-aligned startup which hosts CouchDB databases. I decided to give it a try, as I'd like to get deeper into JSON as well (generally, SimpleDB uses XML while CouchDB uses JSON).

Ektorp is one of several Java APIs for CouchDB but it doesn't look like many people (anyone as far as I can tell) are using it with Cloudant. So I decided to give it a try just for fun.

First off, Ektorp requires a lot of external JARs (9 or 10 from what I see). Importing the 1 org.ektorp JAR and 8-9 other JARs into an Eclipse project quickly proved tiresome. Ektorp recommends using Maven, which manages all dependencies. Better yet, m2eclipse offers a way to integrate Maven with Eclipse. The setup instructions and videos are very self-explanatory. Dropping the supplied Ektorp entry into my pom.xml was simple. All required dependencies were quickly and correctly imported. Piece of cake.

Okay, now to connect to Cloudant. Getting a free Cloudant account is easy. The database UI is clean and simple. I want to be a good coder and use SSL, which Cloudant can certainly support. Ektorp supplies a good API tutorial which accomplishes what I want to start off with:

HttpClient httpClient = new StdHttpClient.Builder()
.host("localhost")
.port(5984)
.build();

CouchDbInstance dbInstance = new StdCouchDbInstance(httpClient);
CouchDbConnector db = new StdCouchDbConnector("mydatabase", dbInstance);

db.createDatabaseIfNotExists();


Initial attempts proved unsuccessful as I couldn't figure out what .host() to use. The supplied documentation wasn't clicking - on to StackOverflow where I'm sure someone's dealt with something similar before. Not being able to add an "ektorp" tag to my question leads me to believe the library isn't as prevalent as I thought. No worries, someone was able to kindly point out I shouldn't be including "http://" or "https://" in my host variable. Oh yeah. Read my StackOverflow question for the details. So I was able to get it working using http as follows:

HttpClient httpClient = new StdHttpClient.Builder()
.host("[username].cloudant.com")
.port(5984)
.username("[username]")
.password("[password]")
.build();


Getting SSL to play nice proved difficult. Using port 443 didn't readily work until someone from Cloudant wisely told me to RTFM. Okay, adding .enableSSL(true) and .relaxedSSLSettings(true) is a good point but I was still getting an IllegalStateException and the stack trace indicated it was trying to use http after initializing my object with https. Huh? Finally, after scouring the Ektorp discussion board, I found this post which indicated Ektorp 1.1.1 included SSL-related bug fixes. So I updated my pom.xml to look for 1.1.1 vice 1.1.0. Recompile Maven, run Java application, success! Database added to my cloudant account via https.

I was getting an annoying but non-fatal exception relating to SLF4J:

Failed to load class "org.slf4j.impl.StaticLoggerBinder"

This is fairly common. Manually adding slf4j-simple-X.jar (slf4j-simple-1.6.1.jar to be exact) to the project resolved the issue.

So this is my super-complex program:

HttpClient httpClient = new StdHttpClient.Builder()
.host("[username].cloudant.com")
.port(443)
.username("[username]")
.password("[password]")
.enableSSL(true)
.relaxedSSLSettings(true)
.build();

CouchDbInstance dbInstance = new StdCouchDbInstance(httpClient);
CouchDbConnector db = new StdCouchDbConnector("httpsdatabase", dbInstance);

db.createDatabaseIfNotExists();


and remember to make ektorp's dependency look for version "1.1.1" in your pom.xml.

Friday, April 22, 2011

Ext4 delayed allocation data loss

My Ubuntu (Maverick Meerkat) netbook crashed this week and completely wiped an open .odt document. The behavior was very similiar to what happened here. I'm not a file system guru so I wasn't aware until now of the long standing issue with Ext4 file system delayed allocation. From LinuxInsight:
In Ext4 file system, Delayed Allocation causes some extra risks of the data loss if your system gets crashed before all the data is written to hard drive.

This was also covered on slashdot over 2 years ago.

It appears that the transition to Ext4 requires applications properly use fsync() to prevent data loss. Theodore T'so, who played a major role in developing Ext4, includes a good summary here. In fact, Android devices which run on Ext4 are rolling out and preventing data loss has been a major concern.

I can't imagine the Open Office that ships with Ubuntu 10.10 doesn't adhere to the Ext4 spec and use fsync() properly but I've never had this problem in other apps. Very aggravating and perhaps another reason to use Google Docs or give Libre Office a try!

Monday, March 7, 2011

Stop powering through code

Much like a sleep pattern, most people work in a fairly predictable cycle in which they need a little warm-up time, get into a groove in which productivity steadily rises then falls, and finally they burn out. This is usually over the period of a few hours or much more.

Not me. All night hackathons for school or work were fun in my twenties but I've found I'm now most effective in shorter "bursts" of coding. I think I've always been this way but it's definitely manifesting itself more that I'm in my thirties.

Back in my startup days, someone set up a web cam over the foosball table. People could log in from their desks. If someone was practicing (yes, some people were really serious about learning the angles and working on 'footwork'), others would inevitably meander over and start a game. These kinds of environments really helped me hit a sweet spot between creativity and burn out.

I can't sit in front of a monitor for 4 hours like some people and write a Java library or bang out some shell scripts. I need breaks or else the quality of my code really dips. Currently, my day job doesn't entail programming so I'm doing it at night and weekends. I also have a toddler at home so any opportunity to lock myself away for 3 hours straight and code is out the window. That's fine and here's why:


  1. I write better code by coding less. It seems the longer someone sits at their computer trying to solve a problem, the more likely they are to write shitty code. This can be because they don't see the big picture or just want to get through their current objective. Great article today in Hacker News detailing this hazard. During frequent breaks, I find myself debating my next move or talking myself into/out of a course of action.

  2. I get bored. 2 hours is about all I can take before I need to stand up and do something else.

  3. I don't need that long to ramp back up. Since I've probably already thought of what I need to do, I'm usually able to get into "the zone" and reach high productivity within a few minutes.

Thursday, February 24, 2011

Review of AWS SDK for Android (SimpleDB)

So development of my Android app, PayNanny, continues and I'm at the point where I can make some observations about the AWS SDK for Android (Beta release). Note that of the 4 AWS services (S3, SimpleDB, SNS, and SQS), I'm only using the SimpleDB API. I won't bore you with how easy it is to make a free AWS account but believe me, it's easy.

First off, I'm so happy I don't have to write an HTTP library or any of the framework necessary for code on a mobile device to interact with a cloud database Isn't is awesome that this is all that's required to add an entry to a SimpleDB domain (similar to a table) is:


List attributes = new ArrayList(5);
attributes.add(new ReplaceableAttribute().withName("date").withValue(date));
// more lines of attributes.add

PutAttributesRequest request = new PutAttributesRequest("timelog", UUID.randomUUID().toString(), attributes);

AmazonSimpleDB mDB = new AmazonSimpleDBClient(credentials);
mDB.putAttributes(request);


Everything's taken care of (well, except transaction handling as SimpleDB is NoSQL) and it keeps your code compact and easy to read. Most of my utilization of the AWS SDK follows in the same vein and I heavily reference the AmazonSimpleDBClient class. I kept the database structure very flat to use SimpleDB the way it's supposed to be used. For instance, I've combined some things which would usually be different fields in an RDBMS into 1 attribute. Once I get this value from the database, I parse it according to the schema I designed.

Like any database-centric app, you're going to loop around your search results often so you'll take your List, pull out each Item, and look at the Attributes like:


// itemList is a List
for(Item item : itemList) {
    List attributeList = item.getAttributes();
    String itemName = item.getName();

    // parse attribute list and sort the data
    for(Attribute a : attributeList) {


It can get a little monotonous and having a bunch of nested loops always makes me nervous but what are you going to do.

SimpleDB is typeless - everything gets stored as a string. I find this to be good and bad. I liked not being so limited in what I had to send to the database but it makes writing optimized queries more difficult. Instead of writing an RDBMS SQL statement saying "get me all data between the dates of 1/2/11 and 1/8/11", I had to code a SimpleDB statement saying "get me all data with the date 1/2/11 or 1/3/11 or 1/4/11 or 1/5/11 or 1/6/11 or 1/7/11 or 1/8/11". So in effect, SimpleDB is pushing a bunch of logic that would usually be handled by the database server into the application code. Mobile devices are pretty fast but I'd rather some server farm in Oregon or wherever do this work than my Droid. Zero padding and offsetting numbers allows for some of this RDBMS functionality but I didn't utilize that in my code.

One major feature lacking in the API is access to the AWS Identify and Access Management (IAM), which is a vital requirement for those who wish to deploy Android apps without giving away your keys. In the meantime, check out the awskeyserver project, which does a good job providing this funtionality via Google App Engine.

I haven't made up my mind about the NoSQL concept. While I won't have to deal with the data consistency issues inherent in this design, I appreciate that the strong consistency option is built into SelectRequests. I don't think NoSQL databases wouldn work for, say, financial applications that need to keep track of a transaction but I don't see why it wouldn't be fine for a social app that needs to scale. Whenever I write stuff like that, I'm reminded of Ted Dziuba's great anti-NoSQL piece which includes the words "You Are Not Google".

Overall, I'm satisfied with this API and the performance I'm getting (for free, mind you). Once my app goes Beta, I hope to have more insights.

Saturday, February 19, 2011

Native Client - where web apps and native apps meet

I was motivated by a web apps presentation by Seth Ladd, a Google Chrome developer advocate, to write a short white paper why my organization should be moving in this direction. But it's hard to get around the fact that native apps still beat the pants off of web apps in many functional areas. Until this week, I wasn't aware Google was working on Native Client, a way to run native compiled code directly in the browser. This certainly makes sense if Chrome is to become a major OS.

I don't think I'm brave enough to fool around with the developer release SDK right now - I'm busy working on my Android app - but once it goes beta it'll be worth a look.

Tuesday, February 8, 2011

PayNanny

PayNanny is a household employer payroll app I'm working on for Android devices. So far, the only functionality I've built consists of a way for the user to "log in" (identification only - no authentication yet), create/delete/edit employee names, and link or delink their account with another.

I've open sourced it on github.

Saturday, January 29, 2011

NoSQL databases - now with SQL!

So I'm writing an app and wanted to take the opportunity to see what the NoSQL buzz was all about. By no means would I need to scale to the level most programmers expect when they employ NoSQL (like Netflix) but I think I've worked with RDBMS enough (though it's been awhile). Ted Dziuba has a pretty funny critique of the NoSQL craze here.

Amazon Web Services (AWS) SimpleDB was a perfect fit - not only is it free for small fish like me but the new AWS Android SDK includes SimpleDB support. I'm not interested in writing a bunch of HTTP libraries - the AWS Android API does everything for me.

The big knock against NoSQL is its data consistency. You're not always guaranteed to get the data you're expecting. SimpleDB counters with a Consistent Read option which I'm employing. You give up a little speed but for a small app like mine it's a no-brainer. But there are no transactions to track so there's still some risk.

Another surprise was SimpleDB's support of SQl through SelectRequest. You can't do stuff like JOINs (these kinds of "advanced" operations are handled in application code) but it's convenient when you need to pull a targeted set of data.

Special shout out to the folk(s) who made sdbtool, a Firefox plug in that let's you interact with your SimpleDB account.

Here are a couple snippets from my class which handles SimpleDB interaction. Connecting is as easy as:

BasicAWSCredentials credentials;
Properties properties = new Properties();
try {
properties.load(getClass().getResourceAsStream(AWS_PROPERTIES));

String accessKeyId = properties.getProperty("accessKey");
String secretKey = properties.getProperty("secretKey");

// some boring error checking

credentials = new BasicAWSCredentials( properties.getProperty( "accessKey" ), properties.getProperty( "secretKey" ) );
// note mDB is an AmazonSimpleDBClient
mDB = new AmazonSimpleDBClient(credentials);
}

Executing queries and putting results in a List is fairly easy:

SelectRequest selectRequest = new SelectRequest("select * from accounts where m_username = '" + username + "'").withConsistentRead(true);
SelectResult selectResult = mDB.select(selectRequest);
List resultList = selectResult.getItems();

I'm able to really take advantage of the API simplicity when adding stuff to the database. NoSQL architectures seem to be pretty great for these types of actions (as long as the data gets there!).

List attributes = new ArrayList(1);
attributes.add(new ReplaceableAttribute().withName("m_username").withValue( username));
PutAttributesRequest request = new PutAttributesRequest("accounts", username, attributes);
mDB.putAttributes(request);

You know, if data consistency is critical, you could keep querying the database until your data is positively there...

Sunday, January 23, 2011

Super simple identification code

So I'm working on an Android app and I really don't care about authentication (yet) but need a way to identify a user. I can assume the user will have at least 1 google (or gmail) account and I'm also going to leverage off the Google App Engine for many services. I'll probably add in the AuthToken functionality eventually - hopefully the Authentication features of Android and Google App Engine will continue to improve in the meantime.

So here's a class that extends ListActivity:


Account[] mAccts;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main);

// get google/gmail accounts
AccountManager acctMan = AccountManager.get(this);
mAccts = acctMan.getAccountsByType("com.google");

// put the account names into a String[]
String[] acctnames = new String[mAccts.length];
for (int i=0; i< mAccts.length; i++) {
acctnames[i] = mAccts[i].name;
}

this.setListAdapter(new ArrayAdapter(this, R.layout.accts_row, acctnames));
}


That will show the user a list of their Google accounts. Here's the onListItemClick:


super.onListItemClick(l, v, position, id);

// find the account clicked and send the intent on its way
Account acct = mAccts[position];
Intent i = new Intent(this, PayMain.class);
i.putExtra(PayMain.KEY_ACCT, acct);
startActivity(i);


In your target activity class (PayMain in this case), the account will be bundled into the Intent.

The XML files are basic for ListActivity programs. Make sure you ask for GET_ACCOUNTS permission in AndroidManifest.xml (plus USE_CREDENTIALS and INTERNET if you're going to get an AuthToken).

I ran this on my Droid X with 2 gmail accounts and it works fine. Works with no Google accounts also (says the user needs to get a Google account and try again). Having problems adding an account to the emulator. I believe I'm supposed to do it through Dev Tools but can't seem to get it to work. I'm able to add a gmail account to the email app but it's not added to the system as a real account. Plus I can't locate any good documentation of Dev Tools. Strange...

Monday, January 17, 2011

Dropbox - the way cloud apps should be

Very impressed with the functionality and ease of use of Dropbox, a revolutionary step forward in how data can be shared across multiple devices. In 4 minutes, I installed the app on my Ubuntu (Maverick Meerkat) netbook and Droid X (Froyo) phone and was passing files back and forth. I feel so stupid emailing myself just to get files from one place to another - this should resolve that problem for good. The web UI is perfect and feels a lot like a Google app. Much respect.

Sunday, January 16, 2011

And finally, Notepad Example #3

The final example changes the manner in which data is passed between the Add/Edit activity and the main activity. Instead of packing them in the extras Bundle, the data is pulled from the database. So, note my first note from the Exercise 2 entry. I failed to consider what would happen when pausing the activity for whatever reason. Here are some random thoughts:
  • Not loving the ContextMenu: Doesn't seem to be an intuitive way to access operations but I'll keep an open mind. I would prefer to offer the "Delete Note" option as a button in the NodeEdit activity.
  • Moving the SQLiteDatabase object to the NoteEdit activity makes perfect sense. I just wonder if all those reads/writes introduces risk of lag, particularly when a remote/cloud data storage solution is used.

Friday, January 14, 2011

Thoughts about Google's Notepad Example 2

So I'm not going to rewrite the Example 2 app like I did for Example 1 but here are some thoughts after going through the exercise.
  • Firing intents via startActivityForResult(): It's a little tedious packing items into the extra Bundle, especially if you have a lot of data but I'm sure it's much faster than hitting the database again.
  • Local variables versus accessing the Dalvik VM: It's included as a note in the example text, but it bears repeating, especially for mobile developers: "Accessing a local variable is much more efficient than accessing a field in the Dalvik VM, so by doing this we make only one access to the field, and five accesses to the local variable, making the routine much more efficient."
  • XML layouts are hard to debug: While the schema is pretty straightforward, it's not like there's a debugger for your XML files so any dumb mistake can make for very tedious troubleshooting.
  • Once you get a Virtual Device going in Eclipse, don't turn it off!: Upon starting up Eclipse, the AVD fires up very quickly when executing a program. But if I shut it down, do some coding or whatnot, and try to run it again, it often sits on the "Waiting for HOME ('android.process.acore') to be launched..." step. Out of habit, I sometimes kill the AVD mistakenly.

Thursday, January 13, 2011

Getting into SQLite

I grew bored drawing things on a Canvas so I moved on to the very helpful Notepad example. I like it because it's centered around the SQLite database package. Understand the importance of a good UI but the database interaction is much more my thing.

So I went through Exercise 1 then put it away and tried to code it myself. I'll spare the boring screenshots because my program doest exactly what Example 1 does - add dummy rows to a database and display them.

Couple things:
  • Got some compile errors related to Cursor stuff (specifically setListAdapter) in my main class. I was extending Activity not ListActivity. Whoops - there is a difference.
  • I like the idea of startManagingCursor and wonder why it's not default. Maybe only noobs like me use it but are people really managing their Cursor's lifecycles so thoroughly?
  • When I tried to account for SQLExceptions, Eclipse never recognized its reference even though I imported android.database.SQLException. So I just removed it. I'll come back to that one. I'm sure I'm overlooking something obvious.
  • Loving Eclipse's Ctrl-Shift-O shortcut to auto-import.
  • Took me awhile to figure out the Context data type so I could access the SQLiteOpenHelper constructor. One difference between my code and Google's example was they kept the Context around as a private variable while I just discarded it. I wonder if keeping Contexts around is useful.

Tuesday, January 4, 2011

Oh, activities need to be defined within the application?

Continue to play around with the Android SDK. I'm working on a program that makes whatever kind of shape the user requests via a menu. Yes, very advanced which is why I named it Simple App. Anyway, the app was crashing when the shape was selected so I got some hands on experience with the Eclipse debugger.

I was getting ActivityNotFoundException and it was bombing on the startActivity() call. But how can that be? The class was properly included and I declared it in AndroidManifest.xml. Well, for some reason, I added this activity outside the application tag. Rookie mistake but it wasn't self evident in the debugger.

Monday, January 3, 2011

Amazon AWS and Database.com

Much of my application development has been "data structure centric". Future projects might be in the same vein so while tinkering with Android coding, I'm looking into 2 major database products with hooks into Android (among others devices, languages, and platforms, of course).

Amazon's AWS has been a major web services provider for awhile. Their data storage product is Amazon S3 but the interesting part is the AWS SDK for Android which provides S3 storage, database creation and messaging. In fact, Amazon might have made it TOO easy to deploy mobile enterprise ("cloud") apps has this PCWorld article suggests! Once I've secured a moderate amount of Android development knowledge, I'm definitely going to open an AWS account and play around with this API (the AWS Free Usage Tier is free for a year).

Salesforce has moved into the database-as-a-service market with database.com, which as this InfoWorld article states aims to be the "back end for the entire Internet". While other companies are playing catch up, Salesforce appears heavily leveraged into the cloud computing and ASP worlds so they might be well positioned to be a database of choice for mobile developers. Unfortunately, database.com is not really live yet (their FAQ page states the full developer preview is coming out in 2011) so I guess this is the end for now.

Sunday, January 2, 2011

CNNMoney - Apple vs. Android: The view from Google

Interesting take from senior Google engineers about what the future holds for Android and iOS. The press is trying to play up an angle that these views aren't exact carbon copies of each other but they seem pretty close to me. I agree with Don Dodge that both Google and Apple can achieve their goals (Apple to continue owning the high-end market and Google to grow their software distribution by being the OS of choice for smartphone hardware makers). Perhaps a better question is "Will a third player be able to make significant inroads to the mobile OS market?". Tim Bray (in probably the best article I've read in several weeks) thinks Windows Phone 7 might make inroads and it's hard to envision Microsoft ceding such a huge market without a fight.