Friday, May 22, 2009
Well, that was easy.
So I created a new Google AppEngine project in Python: a very simple one, which just takes a particular HTTP POST request, stores its values to the datastore, and displays them on-screen. Then I added a "upload" function to my Android's DbHelper class, and connected the latter to the former.
I expected the debugging to be messy and lengthy. But whaddaya know? All I had to do was add the INTERNET permission to my AndroidManifest.xml, and correct the URL that I was pointing to (I'm running the AppEngine app locally; the Android emulator has a special IP address, 10.0.2.2, to connect to its host machine) and poof, amazingly, It Just Worked.
Here's the Android code, in case anyone needs an example:
I'm not even going to bother posting the server code, as it's so simple; 70 lines of Python, and 30 lines of HTML.
You'll note at the moment I just upload a picture URL, rather than actual data, but I'm going to move to doing the latter eventually.
I expected the debugging to be messy and lengthy. But whaddaya know? All I had to do was add the INTERNET permission to my AndroidManifest.xml, and correct the URL that I was pointing to (I'm running the AppEngine app locally; the Android emulator has a special IP address, 10.0.2.2, to connect to its host machine) and poof, amazingly, It Just Worked.
Here's the Android code, in case anyone needs an example:
public boolean uploadNote(long rowId, String location, String title, String comments, String picturePath) {
try {
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter("http.useragent", Util.AppName);
HttpPost httpost = new HttpPost(Util.wtwSite); // temporarily 10.0.2.2:8080/sendUpdate
Log.i(""+this, "Preparing to post to "+Util.wtwSite);
ListparamList = new LinkedList ();
paramList.add(new BasicNameValuePair("email", Util.GetUserEmail()));
paramList.add(new BasicNameValuePair("title", title));
paramList.add(new BasicNameValuePair("location", location));
paramList.add(new BasicNameValuePair("comments", comments));
paramList.add(new BasicNameValuePair("image", picturePath));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,
HTTP.DEFAULT_CONTENT_CHARSET);
httpost.setEntity(entity);
HttpResponse response = httpclient.execute(httpost);
Log.i(""+this, "Sent POST, got " + response.getStatusLine());
entity.consumeContent();
markUploaded(rowId);
return true;
}
catch (IOException ex)
{
Log.e(""+this, "Could not upload note with row "+rowId+ " due to "+ex, ex);
return false;
}
}
I'm not even going to bother posting the server code, as it's so simple; 70 lines of Python, and 30 lines of HTML.
You'll note at the moment I just upload a picture URL, rather than actual data, but I'm going to move to doing the latter eventually.
Labels: Android, AndroidManifest, AppEngine, Java, python, upload
Saturday, May 16, 2009
Things I learned about Android today
Since I'm at the foothill of the learning curve, I figure I should document as I go, as I'm learning more now than I will later. Spent most of the day coding, except for a break to go to yoga, and progress is good. Am about to go for beer, but before I do, a point-form list of what I learned and relearned today:
OK, beer beckons, more next week.
- To use either camera or location data in a package , you have to add a permission entry to its AndroidManifest.xml.
- Also, when you add an Activity, don't forget to add it to the manifest.
- "this" in an anonymous inner class refers, of course, to the inner class. Duh.
- I've stumbled into an interesting problem with cancellation. Because any Android activity can be preempted and/or killed at any time, you have to be ready to save the current state. But in order to provide a cancel button, you also have to save the initial state. Which may mean, if you're using a database for storage, that you have to have two DB rows allocated to the current UI. And bear in mind that more than one copy of your Activity might be running at any given time ... I have some notion how I might deal with this, but am hoping some more elegant solution will arise.
- The XML-file layout structure is a bit clunky, but both powerful and flexible.
- That said, I still haven't worked out how to make a ListView's entries selectable across their entire width, rather than just on their text field. (And woe betide you if that text field is empty ...)
- To create and use a custom View subclass, you have to add a new xml namespace to the layout file, and provide all the necessary constructors. (And, um, it's also important to spell its package name correctly.)
- The camera is remarkably easy to work with. So far.
- Location information is, too, but it doesn't seem to sit well with the emulator; I've tried two different ways to simulate a particular location, but am still getting null back when I ask the emulator where it is.
- Running test cases in the emulator's context works pretty well. Debugger, too.
OK, beer beckons, more next week.
Labels: Android, AndroidManifest, cancellation
Friday, May 15, 2009
Pronoid Android
Hi! Welcome to Pronoid Android.
My name's Jon Evans. I'm a novelist, journalist, comics scriptwriter, and lapsed former software engineer - see my web site rezendi.com for far more than you ever wanted to know. This is a blog about my (mis)adventures in Android development, and related subjects.
I used to be a fairly expert software developer, with an EE degree from Canada's University of Waterloo, and years spent as a coder and project lead at various consulting companies in California, London, New York, and Toronto. Then I took six years off to write books. Now that I'm jumping back in the saddle (currently for fun, eventually for profit) I thought that documenting what I learn en route might be useful to both myself and others.
So, let's begin at
The Beginning
You need to download three things to start working with Android: the latest Java Software Development Kit (SDK) the Eclipse Integrated Development Environment (IDE), and the Android SDK itself. Technically, you could live without the Eclipse IDE, but trust me, it makes your life a lot easier.
The downloads were pretty straightfoward. Unpacking the zip files took forever, as in several hours. I suppose this is what I get for having Windows Vista on my development machine. It has already become apparent that I need a faster computer; my two-year-old cheapest-Dell-that-money-could-buy is still perfectly adequate for word processing and web surfing, but software development is a little more demanding.
Hello, Android!
The Android SDK comes with decent getting-started documentation, including a detailed "Hello world!" howto. A longstanding software tradition dictates that the first thing one does with any new development platform is make it output "Hello, world!" to your screen; and a longstanding truism warns that if this is hard to do, it means your new platform is complex and difficult to work with.
Fortunately, Android was pretty straightforward, at least in Eclipse, though I suspect without the IDE I would have been muttering and cursing in fairly short order. First you have to create the "virtual device" on which your code will run; basically, a software emulator of an Android phone. Then you create an Eclipse project, and four files: HelloWorld.java (five lines of code), AndroidManifest.xml (packaging information), main.xml (UI information) and strings.xml (what it says on the box.) When you run them, a very impressive emulated Android phone pops up on your screen, and when you push its MENU button to unlock it, voila, "Hello, Android."
Two notes. One is an Eclipse bug; it sometimes hangs when launching the emulator, without ever installing your package and/or turning over control of the virtual phone. This seems to be correlated with adding or removing Eclipse projects beforehand. (Note, however, that you can and should re-install packages into a running emulator.)
The other is that I had to go into the filesystem and remove a bunch of source files that began with "._" for the app to work. This was true for the Notepad tutorial files as well.
Oh, yes. The tutorial. "Hello world!" is useful, but doesn't actually teach you all that much, especially in an environment where (so far, at least) you mostly write connective tissue for Android's extensive existing capabilities, rather than creating things from scratch. So the SDK comes with a three-step Notepad tutorial to introduce you to its class hierarchy, application lifecycle, and object library. I was impressed by how much you can do with just a few lines of code.
Testing, Testing
Like all good software engineers, I intend to do Test-Driven Development. (Well, sorta. Full-on TDD means you write the tests first, then the code; I'm going to cheat a little and do "code a little, test a little, code a little, test a little" instead.) In theory, Android comes with built-in out-of-the-box unit-test capabilities that makes this very straightforward.
The practice is a little more challenging. Not least because the "API Demos" part of the SDK failed to install on my machine - the documentation wasn't created, and the classes won't compile, for no obvious reason. The source code remains accessible, but there's still no succinct explanation of how to create Android test cases, much less a full-fledged Android test harness.
So I spent an hour or two today trial-and-erroring my way through that obstacle course, and am pleased to say that I now have Android unit tests working both from within Eclipse and from the command line. I was helped greatly by this blog post and those it links to. Here's my own attempt to summarize:
My name's Jon Evans. I'm a novelist, journalist, comics scriptwriter, and lapsed former software engineer - see my web site rezendi.com for far more than you ever wanted to know. This is a blog about my (mis)adventures in Android development, and related subjects.
I used to be a fairly expert software developer, with an EE degree from Canada's University of Waterloo, and years spent as a coder and project lead at various consulting companies in California, London, New York, and Toronto. Then I took six years off to write books. Now that I'm jumping back in the saddle (currently for fun, eventually for profit) I thought that documenting what I learn en route might be useful to both myself and others.
So, let's begin at
The Beginning
You need to download three things to start working with Android: the latest Java Software Development Kit (SDK) the Eclipse Integrated Development Environment (IDE), and the Android SDK itself. Technically, you could live without the Eclipse IDE, but trust me, it makes your life a lot easier.
The downloads were pretty straightfoward. Unpacking the zip files took forever, as in several hours. I suppose this is what I get for having Windows Vista on my development machine. It has already become apparent that I need a faster computer; my two-year-old cheapest-Dell-that-money-could-buy is still perfectly adequate for word processing and web surfing, but software development is a little more demanding.
Hello, Android!
The Android SDK comes with decent getting-started documentation, including a detailed "Hello world!" howto. A longstanding software tradition dictates that the first thing one does with any new development platform is make it output "Hello, world!" to your screen; and a longstanding truism warns that if this is hard to do, it means your new platform is complex and difficult to work with.
Fortunately, Android was pretty straightforward, at least in Eclipse, though I suspect without the IDE I would have been muttering and cursing in fairly short order. First you have to create the "virtual device" on which your code will run; basically, a software emulator of an Android phone. Then you create an Eclipse project, and four files: HelloWorld.java (five lines of code), AndroidManifest.xml (packaging information), main.xml (UI information) and strings.xml (what it says on the box.) When you run them, a very impressive emulated Android phone pops up on your screen, and when you push its MENU button to unlock it, voila, "Hello, Android."
Two notes. One is an Eclipse bug; it sometimes hangs when launching the emulator, without ever installing your package and/or turning over control of the virtual phone. This seems to be correlated with adding or removing Eclipse projects beforehand. (Note, however, that you can and should re-install packages into a running emulator.)
The other is that I had to go into the filesystem and remove a bunch of source files that began with "._" for the app to work. This was true for the Notepad tutorial files as well.
Oh, yes. The tutorial. "Hello world!" is useful, but doesn't actually teach you all that much, especially in an environment where (so far, at least) you mostly write connective tissue for Android's extensive existing capabilities, rather than creating things from scratch. So the SDK comes with a three-step Notepad tutorial to introduce you to its class hierarchy, application lifecycle, and object library. I was impressed by how much you can do with just a few lines of code.
Testing, Testing
Like all good software engineers, I intend to do Test-Driven Development. (Well, sorta. Full-on TDD means you write the tests first, then the code; I'm going to cheat a little and do "code a little, test a little, code a little, test a little" instead.) In theory, Android comes with built-in out-of-the-box unit-test capabilities that makes this very straightforward.
The practice is a little more challenging. Not least because the "API Demos" part of the SDK failed to install on my machine - the documentation wasn't created, and the classes won't compile, for no obvious reason. The source code remains accessible, but there's still no succinct explanation of how to create Android test cases, much less a full-fledged Android test harness.
So I spent an hour or two today trial-and-erroring my way through that obstacle course, and am pleased to say that I now have Android unit tests working both from within Eclipse and from the command line. I was helped greatly by this blog post and those it links to. Here's my own attempt to summarize:
- Create an Eclipse project with your working code. (In my case, the project is WTW, and the java package is "com.rezendi.wtw").
- Create an Eclipse project where test code will go. (In my case, WTWTest, java package "com.rezendi.wtw.test").
- Write a test case that inherits from android.test.AndroidTestCase, and create "testXYZ()" methods in it. (I haven't yet written tests that use the emulated phone's Context; that's the next step. But I presume since basic tests work on the emulated phone, the more complex ones will too.)
- Modify the AndroidManifest.xml in the test project to point to an InstrumentationTestRunner. Something like:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.rezendi.wtw.test"
android:versionCode="1"
android:versionName="1.0">
<application>
<uses-library android:name="android.test.runner">
</uses-library>
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetpackage="com.rezendi.wtw" android:label="Tests for WTW.">
</instrumentation>
</application>
</manifest> - To run it from Eclipse, right-click on (I think) either WTW or WTWTest, and select "Run As -> Android JUnit Test." The emulator will launch. Once it has, select the phone's app list (that upward-arrow button from the home menu), select "Dev Tools", select "Instrumentation", and then select your package (in this case, "WTW".) JUnit output should go to your Eclipse console.
- If you find this ridiculously complex and time-consuming - and you should, because forcing the user to jump through all those UI hoops to run tests that should be automatable is ridiculous - you can do the same thing through the command line. Run your test package normally, ie as an Android Application. Ignore the "no Launcher activity found" warning. The package being tested will also be installed into the emulator.
- Once the emulator is up and running, open a command line, go to the "tools" subdirectory in your Android install directory, and use the "adb" tool to connect to the emulation and run your test cases. In my case, the correct command line is: "adb shell am instrument -w com.rezendi.wtw.test/android.test.InstrumentationTestRunner".
- Profit!
Labels: Android, AndroidManifest, Eclipse, InstrumentationTestRunner, Java, testing
Subscribe to Posts [Atom]