FontAwesome icons in Android's MapFragment

I spent some time trying to customize MapMarkers in Google Maps Android SDK, I hope this guide is useful if you're trying to integrate FontAwesome's icons in your app's map layout. Android Iconfiy is a great library that provides FontAwesome icons in Android, so we'll use that as our source of icons.

Google Map's custom markers needs a BitmapDescriptor:

// Specify an icon
Iconify.IconValue iv = Iconify.IconValue.fa_car;

// Get the bitmap descriptor, we need to build this yet
BitmapDescriptor customMarker = getCustomMarker(iv);

// Setup the marker
MarkerOptions marker = new MarkerOptions()  
                .position(new LatLng(latitude, longitude))
                .title("My title")
                .snippet("My snippet")
                .icon(customMarker)
                .draggable(false);

// Add it to your map instance
mMap.addMarker(marker);  

We can generate the BitmapDescriptor as follows:

public BitmapDescriptor getCustomMarker(final IconValue iconValue) {  
    IconDrawable id = new IconDrawable(getBaseContext(), iconValue).actionBarSize();
    Drawable d = id.getCurrent();
    Bitmap bm = Bitmap.createBitmap(id.getIntrinsicWidth(), id.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(bm);

    d.draw(c);

    return BitmapDescriptorFactory.fromBitmap(bm);
}

This generate a stroked icon:

I would rather have the shape filled. This is somehow tricky since we need to override the IconDrawable's draw method:

public BitmapDescriptor getCustomMarker(IconValue iconValue) {  
    IconDrawable id = new IconDrawable(getBaseContext(), iconValue) {
         @Override
         public void draw(Canvas canvas) {
             // The TextPaint is defined in the constructor
            // but we override it here
            TextPaint paint = new TextPaint();
            paint.setTypeface(Iconify.getTypeface(getBaseContext()));
            paint.setStyle(Paint.Style.STROKE_AND_FILL);
            paint.setTextAlign(Paint.Align.CENTER);
            paint.setUnderlineText(false);

            // If you need a custom color specify it here
            paint.setColor(Color.BLACK);

            paint.setAntiAlias(true);
            paint.setTextSize(getBounds().height());
            Rect textBounds = new Rect();
            String textValue = String.valueOf(iconValue.character());
            paint.getTextBounds(textValue, 0, 1, textBounds);
            float textBottom = (getBounds().height() - textBounds.height()) / 2f + textBounds.height() - textBounds.bottom;
            canvas.drawText(textValue, getBounds().width() / 2f, textBottom, paint);
        }

    }.actionBarSize();
     Drawable d = id.getCurrent();
    Bitmap bm = Bitmap.createBitmap(id.getIntrinsicWidth(), id.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(bm);

    d.draw(c);

    return BitmapDescriptorFactory.fromBitmap(bm);
}

This gives us a filled icon:

Database backups in S3

While I work on a Go backend for RunHedgie, I'm still hosting the database locally on a Raspberry Pi. That requires me to be at the office to play with the data, which is sub-optimal.

So I'd like to make a database backup each day and upload it to AWS's S3 storage service. That way I can download a copy of the data and use it in my computer whenever I want, not depending from an external CPU or server.

Database backup

To make a DB dump with PostgreSQL we'll need pg_dump:

# Create a temporary file
tmp_file=$(mktemp -t backup.XXXXXX)  
# Dump the db
pg_dump -p 3306 -h $DBHOST -U $DBUSER -p$DBPASS $DBNAME > $tmp_file  
# Zip it
gzip $tmp_file $tmp_file.gz  

mktemp is a great utility to generate random temporary files. Fixed-value temporary files are usually a bad option.

If you're in Linux you should take a look at ionice. It tells the SQL dump program to go easy on OS I/O operations, lowering disk and CPU usage (but making your backups a bit longer). I prefer using the -c2 options, which makes the "best effort" to back it up as quickly and seemlessly as possible.

File upload

To upload the file to S3, we'll need the AWS command line utilities. With those we can easily upload a file to S3:

aws s3 cp $tmp_file.gz s3://my_bucket/any_format  

Running it periodically

Finally, let's put it in a script (I'll call it backup.sh and put it in the $HOME folder):

#!/bin/bash
ionice -c2 pg_dump -p 3306 -h $DBHOST -U $DBUSER $PASS $DBNAME > $tmp_file

gzip $tmp_file

aws s3 cp "$tmp_file.gz" s3://$BUCKET_NAME/$FOLDER_FORMAT/

rm $tmp_file.gz

and configure crontab to run it every day at 1 p.m. UTC:

$ chmod +x bachup.sh
$ crontab -e
$ # Put the following line:
$ # * 13 * * * ~/.backups/backup.sh &> /dev/null

And that's it.

Dialogs and activity lifecycle

Here's a typical situation with Android:

  1. Make an HTTP request specifying a callback.
  2. When the callback is executed, show a dialog requesting user input.
  3. Continue with your app's flow based on that input.

Unfortunately, your activity may have been dismissed between steps 1 and 2. So when you actually try to show the dialog, you'll get a nice exception:

 java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
 FragmentManager.java:1343 in "android.support.v4.app.FragmentManagerImpl.checkStateLoss"
FragmentManager.java:1361 in "android.support.v4.app.FragmentManagerImpl.enqueueAction"  
BackStackRecord.java:595 in "android.support.v4.app.BackStackRecord.commitInternal"  
BackStackRecord.java:574 in "android.support.v4.app.BackStackRecord.commit"  
DialogFragment.java:127 in "android.support.v4.app.DialogFragment.show"  

The context of the request is still valid, so the callback will be executed anyways. We should be using the DialogFragment's utilities to manage the dialog's lifecycle, but unfortunately that's available only for API level >= 11.

Another option is to check if the activity is paused and only show the dialog if it's not. A modular way to do that is to specify a base activity and make all your activities inherit from that one:

public class BaseFragmentActivity extends SherlockFragmentActivity {

    private boolean mIsPaused = false;

    protected boolean isPaused() {
        return mIsPaused;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mIsPaused = false;
    }
    @Override
    protected void onPause() {
        super.onPause();
        mIsPaused = true;
    }
    @Override
    protected void onResume() {
        super.onResume();
        mIsPaused = false;
    }
    @Override
    protected void onStart() {
        super.onStart();
        mIsPaused = false;
    }

}

Then in our activity we can check if it is paused. If not, then show the dialog:

public class MyActivity extends BaseFragmentActivity {

    ...

    protected void someCallback() {
        if (!this.isPaused()) {
            dialog.show();
        }
    }

    ...
}

Trying to crash the activity

Now we would like to test if this is working. An easy way to pause your activity can be done calling a new activity or app with adb. For example, to open the browser you can run the following command from the terminal:

adb shell am start -a android.intent.action.VIEW -d 'http://www.google.com'  

References and inspiration

http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html
http://stackoverflow.com/questions/3512198/need-command-line-to-start-web-browser-using-adb
http://stackoverflow.com/questions/10685460/how-to-determine-in-onpostexecute-that-activity-is-not-paused-now-or-destroyed