Saturday, June 26, 2010

Dalvik ate my projects

I got too clever and wrote a script to build my Android apps. I added the android\tools directory to my system path to help with this.

The script worked fine but problems started when I opened Eclipse. I was patching a file and the build failed with these details:

Problems occurred building the selected resources.
Errors running builder 'Java Builder' on project 'xyz'.
java.lang.NullPointerException
These errors were in the Problems tab:
  • Conversion to Dalvik format failed with error 1
  • R cannot be resolved to a variable

All I had done was add the android tools directory to the system path Troubleshooting 101- even if you don't understand how your change might have caused a problem, undo the change anyway. I undid my path change.

When I tried to build my projects (yes all had the same errors), I still had the Dalvik error listed.
I deleted the error (yes you can! Errors can get stuck and sometimes have to be deleted) from the Problems tab and rebuilt. Then I got:
Could not find xyz.apk!
I manually exported an unsigned apk from the project. This finally fixed things. I had to do similar steps on all my projects.

Thursday, June 24, 2010

Preparing an Android app for publishing ($$)

Writing apps isn't so hard. Writing apps with high usability is another matter. Making the step from one to the other is critical, since you will have better ratings and hence make more money.

First, Wikipedia has a nice definition of usability and it forms a pretty good basis for my purpose. This is the quality of a product as seen by the end-user. I will address each point of the definition in the context of Android but you should be able to see how this applies to devices like the iPhone as well.
  1. Is the user interface intuitive (self-explanatory/self-documenting)? Keep it simple. Mobile devices are powerful, but are best at a limited range of functions per app. Please don't create 20 menu items and a UI that is some complex and detailed that you can't tell what can be clicked.
  2. Is it easy to perform simple operations? Again, keep it simple. The most used functions should not require going into a menu to make them work. If you followed rule one, you might not even need a menu, except for a help file.
  3. Is it feasible to perform complex operations? No. Never.
  4. Does the software give sensible error messages? Use Dialogs or Toast to give good user feedback (and not just for errors). Keep the users in a box so that many errors are precluded by the design of your app. When they do happen, tell the user what they can do about it (if anything). If they can't do anything about the error, keep the message simple: "Please try again later," is just fine. Don't use error codes- this is not Windows development.
  5. Do widgets behave as expected? Use standard widgets, unless you are really good. There is a reason for them. Don't make things hard to use on a touchscreen. Don't make the user guess how something works.
  6. Is the software well documented? Always create a Help or About file. A demo video on YouTube that your app can play is great. I just use a regular html page and load it into a WebView in a Dialog. This is simple and easy to make look good since you can use css. Just put the html and css in the assets directory of your project.
  7. Is the user interface responsive or too slow? Slow apps are bad. Whenever you are doing IO or complex functions, wrap the code in a separate thread so that you can avoid the Application Not Responding message. Web sites do not always respond quickly, different phones runs at different speeds, so help your user out. Eliminate the chance of an ANR and your users will think your app runs like a dream.

Enough motherhood and apple pie. On to some real lessons learned.

Have a kid test your app. they will try all kinds of things you won't and find bugs.

You are going to need to use try/catch/finally a lot, so just get used to it. And you are going to be catching errors you have never even heard of. You will also need to catch some runtime errors (those not declared as thrown, like NullPointerException) since you can't account for everything.

Pay attention to a new feature in the Android Market- errors. Your app listings now show you weekly error reports with stack traces from some phones. This is great! Thousands of people testing your code for you and google reporting the problems. They are not too hard to fix (you usually end up catching some weird error and saying try again).

You can get errors when the handset is rotated unless you prepare your app for working that way. Here's what I put in the Application Manifest to prevent these errors. Include this in your main activity element in the manifest:

android:configChanges="orientation|keyboardHidden"

Don't forget to stop listening for updates to sensors, location services, etc. when your app is paused (unless you need these things). It is simple to turn these back on in onResume.

You may need to catch this: android.view.WindowManager.BadTokenException
It can occur when launching a new activity that wants to put something on screen but you quickly hit 'back'. Basically, you can pull the rug out from under the new activity and cause this error. I have a video app that catches this.

Avoid the ANR by putting IO (and 'expensive' code) into an inner class that extends Thread and uses a Handler to provide data back to the main UI. Other than the main activity Thread, no thread can write data to the screen. You have to use a mechanism like a Handler.

Watch out for window leaks. The fix is to call dismiss() on any Dialog objects in onDestroy(). You are overriding key life cycle events in your Activity, right?

I'm even going so far as to try an work out a scheme to watch memory usage during onCreate to ensure an app can start successfully. On older phones with less memory this can be a problem when a user is running too many apps (and Android fails to shut them down).

That's all for now. Got any more tips to share?

Android logcat filtering for EVO

I'm developing apps for the EVO handset. It spews out more logs than I've ever seen, and it is driving me crazy. Below is a batch file you can use to filter out most of it so you can actually see the things that matter.

rem filter excess Android 2.1 logcat output
adb logcat HtcWimaxStatusBar:W WimaxReceiver:W WimaxStateTracker:W BluetoothHandsfree:W Wimax:F wimax:F UsbConnectedReceiver:W BatteryService:W WimaxInfo:F BatteryStatsImpl:W OpenSSLSessionImpl:W HtcLockScreen:W

Change it as you will.

Saturday, June 19, 2010

The dreaded Android ANR (force close)

Application Not Responding is a message I don't really like to see, unless it is early in development. It means you are doing something wrong and if you want to sell your app, you better fix it. The basic fix is to move your slow process/code into a Thread, but that is another topic.

I sell apps and my code has lots of extra error handling for strange cases that come up. In fact, the new Android Market feature that provides you error reports for your apps is handy. After you get a few thousand users of your apps you will see all kinds of odd things happen to your beautiful code. Mostly, you just have to catch some runtime errors you never heard of and handle them gracefully.

Today I will tell you how to get the detailed stack trace explaining exactly what caused the ANR. Every ANR puts a trace file on the phone and that is what you need.

How to get the trace
  1. connect the phone to your computer (you need the Android SDK and USB drivers for this)
  2. open a command window and cd to the android sdk tools directory
  3. run this command: adb pull /data/anr/traces.txt .

traces.txt is now in your tools directory. It is human readable so check it out.


Wednesday, June 16, 2010

EVO Video Camera Settings

The EVO has a real nice camera and a dual flash (finally). For video, it comes with Qik. I did some testing to figure out how ot make the best Qik videos. Here are the settings for the app when operating on the Sprint 3G network. For 4G results, see below.

low- front (and rear) camera
328 kbits per second
~30frames per second
320 x 240 (qvga)
MPEG-4 video with AMR NArrowband audio (mono, 8KHz)

normal- rear camera
355 kbits per second
~30frames per second
640 x 480 (vga)
MPEG-4 video with AMR NArrowband audio (mono, 8KHz)

high- rear camera
387 kbits per second
~27frames per second
800 x 480 (wvga)
MPEG-4 video with AMR NArrowband audio (mono, 8KHz)

So which looks best? Well, ironically the so-called low quality settings produce the best looking video by far. This is because these settings use nearly the same data rate but only record at qvga size. Simply put, you get more bytes of data per frame (since the frames are smaller) so the quality is higher. I confirmed that using the 'low' quality settings on the rear camera also produce the same good video. I would expect it to be slightly better looking since it uses a better lens, but the data rates are the same.

To really use the normal and high quality settings to get better quality, a much higher data rate is required for the larger video resolution. This shows a basic misunderstanding by Qik as to what affects video quality.

Luckily, the limits of Qik are not the limits of the phone hardware. I did a separate test using the Camcorder app. It recorded VGA video at 30 fps and at a data rate of 1.6 mbps. Now we are talking! The audio is still weak, though, since it uses AMR Narrowband even though the device can record raw 16-bit audio at 44.1 Khz (CD quality). Oh well. I can't upload this video to Qik since I didn't take it with Qik.

Now to test on 4G
Things are much better when on 4G. Qik has this part right- they sense the network you are on and adjust the quality accordingly.

high- rear camera
1 mega bit per second
24 frames per second
800 x 480 (wvga)
MPEG-4 video with AMR NArrowband audio (mono, 8KHz)

You can see this isn't as good as the Camcorder app can deliver, but is excellent for mobile video and truly game changing.

low- front (and rear) camera
1 mega bits per second
~30frames per second
320 x 240 (qvga)
MPEG-4 video with AMR NArrowband audio (mono, 8KHz)

Oddly enough, the Qik app also uses 1 mbps when on low quality for the front camera. This only captures at 320x240 making 1 mbps an absolute waste. All you get is a file 3 times the size with no discernible quality improvements. This really should be set to no more than 400-425 kbps and the lower rate when on 3G (of 325kbps) looks as just good.

Conclusions
With the EVO's front camera and high quality, video calls are going to be great on this and future 4G devices. This type of device, plus 4G will make video calling a meaningful and fun application. Qik has to work out a couple of things regarding how they manage data rate and indicate video quality settings, but their system and Android app is so much better thanks to devices that can really use it well.

You can see the test videos at http://www.qik.com/ski

The EVO files

I have an EVO and it is awesome. If you don't know, it is a new phone from HTC for the Sprint (and Clear 4G) networks. Since I do Android development, I've got some information to share for this device.

First, you need the HTC Sync update for EVO 4G. Without this, you cannot connect your phone to your computer for things like application installation, debugging, etc. A must for developers.
http://www.htc.com/us/support/evo-sprint/downloads/ When you connect, just choose "HTC Sync". That will let you run the adb tools you need and work with Eclipse (and the Android SDK) and of course, charge your phone.

Second, save your battery. There is already an EVO site and it has good tips: http://www.goodandevo.net/2010/05/20-tips-to-improve-htc-evo-4g-battery-life.html My battery life is now as good as other Android handsets I have. But a great phone needs power so be prepared to charge. You can also view what is using your battery from a screen in the phone: Settings > About Phone > Battery > Battery Use

Third, if you don't like having to unlock your home screen or enter passwords to unlock it, you need this widget: Screen Mode Widget Lite. This saves me from going nuts having to enter a password in every time I pick up my phone. You see, once you configure Exchange email (built in to EVO), the password lock is turned on and I found no way to turn off, except this app.

Fourth, there is a developer guide- sort of. It's incomplete but is being updated every 2-3 weeks so keep an eye on it.

Other tidbits
  • The browser appears to support HTML5 Geolocation as opposed to Google Gears.
  • The front camera only works in low resolution with Qik. Rear camera supports low, medium, and high, but exactly what they are is not known (yet!)
  • The phone is wicked fast, so when developing don't get carried away otherwise your apps won't work on older Android phones
  • You need to test if on a 4G network specially, since the Android code does not know what 4G is. See the Sprint guide.