STUART HALL

Mobile app development and marketing. Appbot and Bytesize Apps.

Android Development Tips For iOS Devs

March 12, 2014

I've been an iOS dev for 5 years and have always managed to avoid Android, until now. But believe it or not it's actually a lot of fun, and not that big of a jump from iOS development.

Here is a bunch of things I learned building 7 Minute Workout for Android, I hope you find them useful. Note that not everything I compare below is an exact match and it's not a complete overview of Android developent, but it does cover everything I learned building a simple app.

7 Minute Workout For Android

IDE

I chose to use Android Studio, I'm taking a punt that this will become the standard once it comes out of beta. There are a lot of reports of it being unstable, but I only had one crash. Maybe I'm just used to Xcode.

Java

Say what you will about Java, in the end it's just another language. It does the job and if you are an experienced developer you are going to spend a lot more time getting your head around the framework than battling Java. Be thankful there is no J2EE in sight.

Simulator

I used to think the iOS simulator was painful, now I realise it's pretty awesome. Skip the Android simulator all together and deploy to a real device, or be prepared to spend a lot of time waiting.

Storyboards / NIBs

After bagging out Storyboards in my iOS development post and getting a few strongly worded emails disagreeing with me, I'm not going to go there again.

Android uses Layouts which are xml. They are completely independent from each other. Android Studio also has a nice WYSIWYG editor:

Layout

But you can still dig into the raw xml if you like (and I did more often than not).

Layout Text

Instead of Auto Layout you can choose the layout container, such as RelativeLayout, FrameLayout etc. There you can choose width / height / padding / margins / gravity based on either pixels (dp - device pixels) or things such as matchparent, wrapcontent.

Wrap-content is quite nice for text, it automatically sizes to the correct height and pushes the rest down in certain layouts like LinearLayout.

I didn't get to use them, but Fragments also look like a really nice way to re-use custom UI elements.

UIViewController

Android's equivialent to UIViewController is an Activity. Each screen / window is an Activity. Here is where you'll do most of the binding of data to the UI, handle events etc.

Transitioning Controllers / Views

In iOS we use segues, pushViewController, presentController etc to move between screens. In Android you use an Intent.

You can easily move to a new activity, and even pass some data through.

public void onItemClick(...) {
       Intent i = new Intent(getBaseContext(), MyActivity.class);
       i.putExtra("row", position);
       startActivity(i);
}

In your new Activity (MyActivity above) you can then pull out the passed data:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_mine);

    Bundle extras = getIntent().getExtras();
    if (extras != null) {
        int row = extras.getInt("row");
        ....
     }
     ...
 }

You also use an Intent to trigger things such as sharing sheets:

 Intent sendIntent = new Intent();
 sendIntent.setAction(Intent.ACTION_SEND);
 sendIntent.putExtra(Intent.EXTRA_TEXT, "Share This");
 sendIntent.setType("text/plain");
 startActivity(sendIntent);

IBOutlet

If you are anything like me you forget to connect IBOutlets at least 50% of the time every time.

With Android every view/component has a unique ID, something like:

@+id/myButton 

Which is then automagically generated into a class called R (learn more about R here), you can access the button in code then with:

Button button = (Button)findViewById(R.id.myButton);

Tag

A trick often used by iOS devs is to use the tag of a view to hold lookup information, such as offset in arrays. With Android you can shove the entire object into the tag; pretty useful.

row.setTag(data);

UITableViewController / UITableViewDataSource / UITableViewCell

Android's equivialent of a UITableView is a ListView.

The rough equivialent of UITableViewDataSource is an ArrayAdapter:

    MyAdapter adapter = new MyAdapter(this, R.layout.listview_item_row);
    listView.setAdapter(adapter);

Where listviewitemrow is a Layout of a row, roughly equivialent to a UITableVIewCell.

The adapter then creates / reuses rows through getView.

You can also set headers:

    View header = getLayoutInflater().inflate(R.layout.listview_header_row, null);
    listView.addHeaderView(header);

There are a bunch of good tutorials on the web like this one.

Images / Resources

Images have become much nicer to deal with since Asset Catalogues came about on iOS, and usually there is only retina and non-retina to deal with (unless you have iPad specific images as well).

Because of all the different resolutions of Android devices you have to provide 4 images.

Resources

These are : mdpi (medium), hdpi (high), and xhdpi (extra high), xxhdpi (extra extra high). I'm personally looking forward to the xxx version.

When you create the project in Android studio you can provide an icon and it will automatically create the different sizes. To any designers out there now having heart palpitations: it's ok, you can go in later and replace with pixel perfect versions.

So the basic idea is to create a version of each image for each density, name it the same and put it in the correct folder, then Android will pick up the correct one.

Custom Font

Custom fonts are pretty easy to do on Android as well: copy the font into main/assets, then you can load it up with:

        Typeface font = Typeface.createFromAsset(getAssets(), "Lato-Regular.ttf");
        textView.setTypeface(font);

The word is that this is unrelaiable on all devices, so you need a try/catch and fallback font, haven't seen it in my vast collection of two Android devices though.

NSLog

Log seems to be the go to solution here, you can specify debug, verbose etc. System.out.println(..) also seems to do the job.

Backwards Compatibility

We've all heard about how fragmented Android is. Turns out gracefully handling older versions is not very different to the tricks you have to use to use new iOS features while supporting older iOS versions. Although, you probably have to keep these tricks around longer and do them a lot more often.

There is a nice constant to check the current version:

if (Build.VERSION.SDK_INT >= 11.0)  {
...
}

You can suppress the warnings for a function using:

@SuppressLint({"NewApi", "LocalSuppress"})
private void myFunction() {
...
}

Things That Were Just Plain Weird

CountDownTimer

CountDownTimer - I was pretty excited that this functionality was built in, it was exactly what I needed for 7 Minutes. Except it turns out that it doesn't send the last onTick before onFinish (link), totally bizarre bug that still isn't fixed. Weird, very weird.

Orientation

When the user rotates the device your activity is completely reset, meaning you have to store state and resume after it has reloaded. A weird one to get your head around coming from iOS where it continues to function nicely.

Kindle Fire / Amazon Store

Getting into the Amazon Store is pretty simple, I only had to tweak two things:

  • The YouTube SDK wouldn't work because it requires the YouTube app, which isn't available, but it does appear to support flash.
  • You'll need to swap out the in app purchase code for the stores.

You can detect manufacturer and model using android.os.Build.MANUFACTURER and android.os.Build.MODEL.

A list of the Kindle Fire model details are here.

What Next?

Hopefully I'll add to 7 Minutes and get to build some more Android apps in the future, I'm sure I've only just started to scratch the surface. Who knows, there could even be a part 4 to An App Store Experiment.

Join The Mailing List

Keep up to date with all the latest mobile developments.

Want More Mobile Goodness?

Add your email to get more great info like this.

No spam, pinky promise.