Porcupine Programmer

Programming rants, random stuff and some more programming.

Guava on Android

| Comments

In November 2012, the revision 21 of Android SDK Tools was released and one of the items in the release notes made me a very happy panda:

Improved the build time by pre-dexing libraries (both JAR files and library projects).

This change solved the most problematic issue with Guava and other large libraries – build time. Before this change Android tools executed dex for your code and every referenced library every time you wanted to launch the application, which in case of Guava took ages and required increasing heap space for Java VM, because the Eclipse closed with “Unable to execute dex: Java heap space” error.

IntelliJ users could work around this issue by enabling Proguard for debug builds, which could reduce the size of dex input by removing unused code. Eclipse users might try generalizing the Treeshaker plugin, which does pretty much the same inside a custom compilation step added before dexing. But there was no straight way to use Guava and keep the build times on the sane level.

Now the first build still takes ages, and the Eclipse still crashes if you don’t bump its heap space, but for all consecutive builds everything works blazing fast. Goodbye hand rolled stuff, welcome immutable collections, fluent comparators, hashCode helper and tons of other goodness. I keep finding in our code base whole chunks of code which can be replaced with one or two lines utilizing Guava features. I plan to post a summary of those changes.

Final note: if you are using Proguard, remember to add Guava specific entries mentioned in the documentation.

Android: Sync Adapter Lifecycle

| Comments

In Android sticky broadcast perils I hinted that the ContentResolver.isSyncActive() might not yield the results you’d expect. I described this issue in the talk I gave during the KrakDroid 2012 conference, but the chances are you weren’t there, so I decided to write a blog post about it.

ContentResolver contains bunch of static methods with “sync” in their name: there is requestSync to start sync process, isSyncPending and isSyncActive for polling the sync state, addStatusChangeListener for listening for sync status and finally cancelSync for stopping the ongoing synchronization process. The list looks fine, in a sense that theoretically it’s enough to implement the most sync-related functionality on the UI side. Let’s see what is the relation between sync status reported by ContentResolver’s sync methods and onPerformSync method in your SyncAdapter.

After calling requestSync, the sync for a given account and authority is added to the pending list, meaning that the sync will be executed as soon as possible (for example when syncs for other authorities are finished). In this state the isSyncPending returns true, the SyncStatusObservers registered with SYNC_OBSERVER_TYPE_PENDING mask will be triggered, and so on. This happens before your onPerformSync code is executed. Nothing especially surprising yet. The key point here is, you should take into consideration that your sync request might spend a lot of time in this state, especially if many other SyncAdapters are registered in the system. For example, it’s a good idea to indicate this state somehow in the UI, otherwise your app might seem unresponsive.

When there are no other pending or active sync requests, your sync operation will move to active state. The onPerformSync will start executing in the background thread, SyncStatusObservers will trigger for both SYNC_OBSERVER_TYPE_ACTIVE (because the sync request enters this state) and SYNC_OBSERVER_TYPE_PENDING (because the sync request leaves this state) masks, isSyncPending will return false, and isSyncActive will return true. In the happy case, when the onPerformSync method will finish normally, the SyncStatusObservers for SYNC_OBSERVER_TYPE_ACTIVE state will trigger again, and isSyncActive will return false again. Booring.

The things get funny when the cancelSync is called during onPerformSync execution. The sync thread will be interrupted and the onSyncCancelled method in SyncAdapter will be called. The SyncStatusObservers will trigger, isSyncActive will return false and so on, and… at some point the onPerformSync method will finish execution.

Say what? Wasn’t the sync thread interrupted? It was, but not in a “Bang, you’re dead” way, but in a “polite” way as described by Herb Sutter. All the stuff described in the Thread.interrupt happened, but in 99% of cases it means that the thread continues to execute as usual, except the interrupted flag is now set. To really support cancelling the sync thread you’d have to define an interruption points at which you’ll check this flag and return early from onPerformSync.

Things get even funnier here: when I used the isInterrupted method for polling the state of the sync thread, I got the bad case of heisenbug. In 9 cases out of 10 everything worked as expected, but every now and then the thread continued to execute even though earlier the onSyncCancelled was called. I guess somewhere else the InterruptedException was caught and never rethrown or someone else was polling the sync thread with interrupted and cleared the flag. To pinpoint the root cause of this behavior I’d have to read through a lot of code, so instead I implemented my own flag and set it in onSyncCancelled callback. Works like a charm.

Why is this an issue though? Can’t we just let onPerformSync to finish in some undefined future? In most cases that’s exactly the right way to think about this issue, but if the onPerformSync holds a lock on some resource like database handle, you might need to ensure that this lock is released as soon as possible after user cancels the sync.

Recap: show the sync pending state in the UI and if you really have to know when the sync has ended, do not trust the ContentResolver sync methods.

2012 Summary

| Comments

The end of the year is the usual time for looking back and making a new years’ resolutions, so I’m going to gloat a little bit and do some wishful thinking about the next year. Without further ado, let me list what I’ve managed to accomplish:

  1. I have published three apps on two mobile platforms.
  2. I changed my safe corporate job for a position in the startup.
  3. I gave a talk at the conference.
  4. There were over 4k unique visits of my blog and got a couple of +1s.

And what are my plans for the next year? I like to keep things simple, so let’s just double the values from the list above, except maybe for the second point – I hope I won’t have to change the job, I’m very happy with my current employer.

Anyways, thanks for reading my blog and stay tuned for more content next year!

UnknownHostException Gotcha

| Comments

Several days ago I was preparing a simple app for the programming contest organized by Future Simple during KrakDroid conference. It consisted of a public ContentProvider, SyncAdapter and an Activity. The contest participants had to write an app which retrieves the input data from ContentProvider, solve a very simple algorithmic problem and save the output back in the ContentProvider. This would trigger the sync and the SyncAdapter would upload the data to our backend. The Activity showed the contest rules and the list of submissions.

As you can see it’s nothing fancy and I hacked everything together rather quickly, but when I tried to send the first submission I got the UnknownHostException from AbstractHttpClient.execute(). Had I googled the issue first, I’d solve this issue in one minute. The problem is, my internet connection was flaky and the backend I tried to connect to was set up couple hours earlier, so the UnknownHostException seemed like a quite probable error.

If you haven’t click the Google link above, here’s the solution: this exception is a way in which Android tells you that your app is missing the INTERNET permission.

KrakDroid Aftermath

| Comments

I finally got some sleep after a really busy weekend. For the first time I had an opportunity to give a talk at the programming related conference. I was also responsible for a programming contest organized by the company I work at, I tried to push the new release of our product and, on top of that, I had to do some Christmas related stuff, so I didn’t get much sleep.

Let’s get back to the programming. I gave the talk about standard synchronization pattern on Android (SyncAdapter + Authenticator + ContentProvider) during this year’s edition of KrakDroid conference. Here are the slides:

Sync on Android from chalup

The link to recorded video can be found in the slideshare content description. I won’t bother posting it here, because a) I gave the talk in Polish, and I try to keep the content of this blog in English b) I was really tired, at one point of the talk I had to stop and ask myself “What the hell am I trying to say”.

Although my talk was average and there are many things I might have done better, I’m very happy I had an opportunity to give this talk. Public speaking is definitely outside of my comfort zone and I learned a lot. Here’s the “conference speaker checklist” for my future self:

  1. Get some sleep
  2. Do the test run of the talk in front of the mirror

    I finished the slides for my presentation half an hour before giving it, so I didn’t have a chance to rehearse it. There were few points during my talk when adding a slide with a summary would make things much clearer. Which brings me to the next point:

  3. Recap

    I’m not sure how much the listeners who didn’t knew anything about sync will remember from my talk. The recaps could help them remember at least some keywords they would be able to google later.

  4. Do the test run of the talk in front of other people

    But not any other people – you want your audience to be critical and at least a bit familiar with the topic. You want someone who will tell you that this part of the talk is boring or that part is not clear.

  5. Get more sleep

And finally, do not freak out – the hardest part is saying “Hello, my name is…”, the rest will pour out of you.

Android Gets Nested Fragments

| Comments

Most of the items in the Android 4.2 APIs list are kind of “meh” to me, but there is one item that’s make me very happy: nested fragments. Fragments were supposed to be reusable UI components, but for some unfathomable reason the initial release of the fragments API didn’t allow composing a fragment from other fragments. Even during the 2012 Google I/O one of the Google developers said that they have discussed this idea, but they’re not sure if it’s a good one, which is an absolute surprise to me, because I don’t think anyone sane would consider making the ViewGroup which isn’t a subclass of a View.

Fragment nesting was a topic I kept on my topic list for a day when I feel I need to bitch about something, but now I’m happy to remove it and write this ecstatic post. So now launch your SDK managers and download the r11 of support package! (or wait for half a year and hope it will be added to Maven Central)

Android Protip: Remove Debug Logs From Release Builds With Proguard

| Comments

I use the android.util.Log extensively – often it’s faster than starting the debugger and (unlike debugging) it’s always on, which is invaluable when you’re trying to track the root cause of some hard to reproduce bugs. Logging is also nice for release candidate builds you give to the QA team – if they find some bugs you’ll have more information than just a stack trace.

On the other hand you don’t want to keep all those logs for release builds, mostly for performance and privacy reasons. If you google around for a solution to this issue you’ll probably find a dozen ideas like using a wrapper for logging class, using a dedicated logging framework or even some sed/awk scripts to ant build process. Among those ideas is the one I’d like to recommend: customizing Proguard configuration.

Proguard is automatically run in release builds by ant and Export wizards from Eclipse and there is an optimization option, which can be used to disable logs:

-assumenosideeffects

Specifies methods that don’t have any side effects (other than maybe returning a value). In the optimization step, ProGuard will then remove calls to such methods, if it can determine that the return values aren’t used.

I wouldn’t use this tool for the purpose stated in the manual, because even if my code doesn’t have any side effects, the methods called from it might have ones; I’d rather use some static code analysis tool to find the unnecessary calls and manually remove them. It looks perfect for suppressing the logs though and it’s very simple to set up – just add the following lines to the proguard-project.txt file generated by android command line tool:

1
2
3
4
5
6
7
-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** v(...);
    public static *** i(...);
    public static *** w(...);
    public static *** e(...);
}

You can of course keep some of the priority levels by removing lines from this config.

The nice thing about this solution is that you have to set it only once and it will just work for all further release builds.

UPDATE (August 2013): do not assume that Proguard will remove any code other than the methods listed in assumenosideeffects setting. See “Proguard gotcha” post for more details.

Android Font Metrics for Dummies

| Comments

Recently I was working on a custom View with overridden onDraw() method and at some point I needed to center some text vertically. Unfortunately Paint.setTextAlign() supports only horizontal orientation, so I tried calculating the y-coordinate of the origin myself, but I couldn’t get it exactly right. After two failed attempts I decided that I need a program which visualizes the available font metrics, because it seems that I do not understand the FontMetrics documentation, or the aforementioned class and it’s documentation sucks.

You can find the source code on my GitHub, and here’s the screenshot for other typographically challenged programmers:

(BTW: the word “Żyłę” used there is not a complete gibberish, it’s an accusative case of word “vein” in Polish; it’s nice, because it’s short, but it covers all cases of the metrics class).

Let’s get back to vertical alignment. In general you should center text vertically either on x-height or on half the cap height above the baseline (at least that’s the info I found). Neither metric is directly available in FontMetrics class, but you can approximate the cap height as a textSize - descent or calculate x-height yourself using Rect height returned by Paint.getTextBounds for string “x”.

Screensaver Blocking on Symbian

| Comments

In my latest game the players spend significant amount of time just watching the screen and trying to figure the puzzle out. The first few levels are obvious and most players will sole them in a few seconds, but as the difficulty of the puzzles increases the players stare at the screen longer and longer. At some point the screensaver would kick in and piss the player off (fortunately my ragtag QA/betatester team found this issue before launch).

Google search results are (as usual) helpful, but the most promising lead, the QSystemScreenSaver class is not a solution. There are three problems with it:

  1. The API of the class itself is terrible.
  2. The API of the related QML element is even worse.
  3. Last, but not least, it doesn’t work (at least not in the Qt Mobility version shipped with the Qt SDK).

(BTW: these three points sums up pretty much every experience with Qt Mobility package I had. Qt devs should either kill this festering boil with fire or fix it and rename it, because I learned to dread everything remotely related to Qt Mobility, and I suspect I’m not the only one).

Anyways, let’s get back to the core of the problem, i.e. “how to block the screensaver”. Qt Mobility failed, but the task doesn’t seems like a rocket science to me. Slightly different Google search suggested using native Symbian’s User::ResetInactivityTime() method. Few minutes and one QTimer later, everything worked:

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
#ifndef SCREENSAVERBLOCKER_H
#define SCREENSAVERBLOCKER_H

#include <QObject>
#include <QApplication>
#include <QTimer>

class ScreenSaverBlocker : public QObject
{
    Q_OBJECT

public:
    explicit ScreenSaverBlocker(QObject *parent = 0) : QObject(parent) {
        mTimer.setInterval(1000);
        connect(&mTimer, SIGNAL(timeout()), this, SLOT(blockScreenSaver()));
        changeScreenSaverState(QApplication::activeWindow() != 0);
        if (qApp) {
            qApp->installEventFilter(this);
        }
    }

    void changeScreenSaverState(bool blockScreenSaver) {
        if (blockScreenSaver && !mTimer.isActive()) {
            mTimer.start();
        } else {
            mTimer.stop();
        }
    }

protected:
    bool eventFilter(QObject *obj, QEvent *event) {
        Q_UNUSED(obj)
        if (event->type() == QEvent::ApplicationActivate
         || event->type() == QEvent::ApplicationDeactivate) {
            changeScreenSaverState(event->type() == QEvent::ApplicationActivate);
        }
        return false;
    }

private slots:
    void blockScreenSaver() {
#ifdef Q_OS_SYMBIAN
        User::ResetInactivityTime();
#endif
    }

private:
    QTimer mTimer;
};

#endif // SCREENSAVERBLOCKER_H

The important thing in the code above is watching the ApplicationActivate and ApplicationDeactivate events – after all, when your app is in background, you shouldn’t affect the phone behavior. I’m not sure if the app would fail the Nokia’s QA process without this feature, but it seemed prudent to write the code this way.

If you want to use this object in your QML UI just register it with qmlRegisterType and add the registered import and QML element to your root element.

Android Sticky Broadcast Perils

| Comments

I might have called this blog post “Android sticky broadcasts considered harmful”, but “Considered harmful” texts are considered harmful, so I opted for a less linkbaity title.

I was working on a bug in a legacy code which used sticky broadcasts for publishing the sync service state (BTW: if you thought “Hello, ContentResolver.isSyncActive()?” you should subscribe to my blog feed – I’m planning to write about the problems with sync state methods in ContentResolver). The bug manifested as a minor UI issue – sometimes the UI indicated that sync is in progress, even in situations when the sync could not be in progress, for example because the network connection was down. The QA team found an easy reproduction steps for it: start sync and reinstall the app before the sync finishes.

I found much more troubling reproduction steps: start sync, uninstall app while sync is in progress and then install it again. The difference between those steps and the ones found by QA is the fact that I’m performing uninstall, which means that all information about my app should be wiped from the system.

I dug deeper and found out two scary facts:

  • Sticky broadcasts are not connected in any way to app package, which means they are not removed on uninstallation. They are removed on phone restart, but that’s not a scenario you should rely upon.
  • Any application with BROADCAST_STICKY permission may alter your sticky broadcasts.

As long as you don’t use sync status for anything more complicated than showing a spinner in Action Bar, you might get away with only minor UI issues, but if you want to use it for business logic, you’re entering the world of pain.

The sticky broadcasts might be garbage left over by the old version of your app or some other app if you’ve chosen the action string poorly (protip: if you really have to use sticky broadcasts, include your app’s package name in action string). Even if you ignore the latter case (and the very unlikely scenario of other app maliciously tinkering with your app’s intents), I consider the former case to be a deal breaker – each sticky broadcast is an additional state which has to be migrated between app versions and app installations which further increases cognitive load of programming, which is high enough already.

Let’s summarize this blog post: remove BROADCAST_STICKY permission from your app’s AndroidManifest.xml, test the app, fix all crashes from SecurityExceptions and never look back.