Recent Posts

Organizing Your Android Code Structure

Posted on 19 Nov 2013

This post was originally published on the SmartLogic Blog.

A code structure for your android development projects

Writing a medium to large Android app requires having code structure. In creating our latest Android development project, I came across a structure that has helped me out.</p>

Java Code

I like to have separate files for each class in my Android projects, the only exception being AsyncTasks. Having this many java files means you have to have more packages than the base package. I ended up with a package for each type of main class. Each class is named ending with its type.

  • com.example
    • activities
      • Contains all the activities. Classes are all named with Activity at the end. That way, you can immediately know what it is when reading Java code that doesn’t have its full package name.
    • adapters
      • Contains all the adapters
    • authenticator
      • Contains any class related to signing a user in. I create a local account and having all related classes together is very handy.
    • data
      • Contains all classes related to data management such as ContentProvider and SQLiteHelper.</p>
    • data.migrations
      • Contains all of my SQLite migrations. I created a class for migrations, read about it here, and put them all in this package.
    • fragments
      • Contains all fragments.
    • helpers
      • Contains helper classes. A helper class is a place to put code that is used in more than one place. I have a DateHelper for instance. Most of the methods are static.
    • interfaces
      • Contains all interfaces.
    • models
      • Contains all local models. When syncing from an HTTP API I parse the JSON into these Java objects using Jackson. I also pull Cursor rows into these models as well.
    • preferences
      • Contains all classes for custom preferences. When creating the preferences I required a custom PreferenceDialog as well as a custom PreferenceCategory. They live here.
    • sync
      • Contains all classes related to syncing. I use a SyncAdapter to pull data from an HTTP API. In addition to the SyncAdapter a SyncService is required, so I created a package.

Layouts

The layouts folder can easily become disorganized since you can’t have any folders in it. This is a known issue and has been ignored for 4 years now. To get around this I name my layout files with a prefix depending on what they are for. This sorts them together in the Eclipse file listing.

  • R.layout
    • activity_
    • adapter_
    • fragment_

IDs

All of my IDs are snake_case. I had a project that was inconsistent with how IDs were named and it was a pain. Many projects seem to do mixedCase notation for IDs, but it seemed weird having the different styles in Java code depending on what type of resource it was, e.g. R.layout.snake_case vs R.id.mixedCase.

Values

For values I have a separate file for each type of resource, e.g. dimens.xml. This works out well for most of the values, except for strings. There are a large amount of strings in this app and having them all in the same file is pretty unusable. In this case I split out some of the strings into groups by their activity. This allows you to easily find a string if you’re looking at the activity already.

How do you structure your code for Android development projects? Comment and let me know.

For more on Android development, plus Rails and iOS, follow @SmartLogic on Twitter.

Image Source

Java Hypermedia Client

Posted on 27 Jul 2013

Recently I’ve been working on an Android app that uses a hypermedia API. This has presented some challenges because the JSON library I’m using turns JSON into java objects. Using a HashMap is out because you get into generic hell land.

Up until now I haven’t had to make a hypermedia client in anything but ruby. In ruby it’s very simple because the JSON you receive from the server gets turned into a hash. I think I have come across a nice way to get around it in java though.

Below are my java objects that Jackson parses into.

public class Link {
    @JsonProperty("href")
    public String href;
}
HalRoot
public class HalRoot {
    @JsonProperty("_links")
    protected RootLinks links;

    public String getSelfLink() {
        return links.self.href;
    }

    public String getOrdersLink() {
        return links.orders.href;
    }

    public class RootLinks {
        @JsonProperty("self")
        Link self;
        @JsonProperty("http://example.com/rels/orders")
        Link orders;
    }
}
HalOrders
public class HalOrders {
    @JsonProperty("_embedded")
    protected Embedded embedded;

    @JsonProperty("_links")
    protected Links links;

    public List<HalOrder> orders() {
        return embedded.orders;
    }

    public class Embedded {
        @JsonProperty("orders")
        List<HalOrder> orders;
    }

    public class Links {
        @JsonProperty("self")
        Link self;
    }
}
HalOrder
public class HalOrder {
    @JsonProperty("_embedded")
    protected Embedded embedded;

    @JsonProperty("_links")
    protected Links links;

    public List<HalItem> getItems() {
        return embedded.items;
    }

    public String getSelfLink() {
        return links.self.href;
    }

    public String getItemsLink() {
        return links.items.href;
    }

    public class Embedded {
        @JsonProperty("items")
        List<HalItem> items;
    }

    public class Links {
        @JsonProperty("self")
        Link self;
        @JsonProperty("http://nerdwordapp.com/rels/items")
        Link items;
    }
}
HalItem
public class HalItem {
    @JsonProperty("name")
    public String name;
}

Booting Your Rails Server in a Script

Posted on 02 May 2013

A recent API Craft Google group post has gotten me playing around with hypermedia APIs again after having an extended stay in Android land. I updated my hypermedia APIs repo, specifically the hypermedia.rb script.

I made it look similar to the nerdword-api script/client.rb which boots a server in the script instead of relying on an external server beeing booted. This was taken from how Cucumber boots capybara.

Below is the code required:

#!/usr/bin/env ruby

require File.expand_path('../config/environment',  __FILE__)
require 'capybara/server'

Capybara.server do |app, port|
  require 'rack/handler/thin'
  Thin::Logging.silent = true
  Rack::Handler::Thin.run(app, :Port => port)
end

server = Capybara::Server.new(Rails.application, 8888)
server.boot

Loading a Cursor Row into a Model

Posted on 28 Apr 2013

When using a Cursor in Android I prefer to pull out a row into a Java object. The Java objects will mostly be getters and setters, but will also include convenience methods as well. In order to make going from a cursor row into a model instance I create a static method on each model class called fromCursor.

This method will pull out columns into the appropriate member variable. It will only pull out a column if it is in the selected columns.

public class MyModel {
    public static MyModel fromCursor(Cursor cursor) {
        MyModel myModel = new MyModel();

        if (cursor.getColumnIndex("_id") != -1) {
            myModel.setId(cursor.getInt(cursor.getColumnIndex("_id")));
        }

        if (cursor.getColumnIndex("description") != -1) {
            myModel.setDescription(cursor.getString(cursor.getColumnIndex("description")));
        }

        /* ... */

        return myModel;
    }
}

Using the LoaderManager

Posted on 05 Apr 2013

The LoaderManager is a nice way of handling Cursors in an Android activity or fragment. It was a little tricky to get started with so I wanted to have an example I could come back to as a reference of how to use it.

public class FirmInfoActivity extends Activity implements
    LoaderManager.LoaderCallbacks<Cursor> {

    private static final int LOADER_ONE = 0;
    private static final int LOADER_TWO = 1;

    private AdapterOne mAdapterOne;
    private AdapterTwo mAdapterTwo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // This is incredibly important to do, I forgot it a few times
        // and had no idea why it wasn't working.
        getLoaderManager().initLoader(LOADER_ONE, null, this);
        getLoaderManager().initLoader(LOADER_TWO, null, this);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        switch(id) {
        case LOADER_ONE:
            return new CursorLoader(this, Uri.parse(""),
                    null, null, null, null);
        case LOADER_TWO:
            return new CursorLoader(this, Uri.parse(""),
                    null, null, null, null);
        }
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        switch(loader.getId()) {
        case LOADER_ONE:
            // Update based on the loaded cursor;
            break;
        case LOADER_TWO:
            // Update based on the loaded cursor;
            break;
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        switch(loader.getId()) {
        case LOADER_ONE:
            mAdapterOne.swapCursor(null);
            break;
        case LOADER_TWO:
            mAdapterTwo.swapCursor(null);
            break:
        }
    }
}
Creative Commons License
This site's content is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License unless otherwise specified. Code on this site is licensed under the MIT License unless otherwise specified.