Share on Twitter
Share on Facebook
Share on HackerNews
Share on LinkedIn

Converting Your iOS Application to Android: Part 2

In my previous article, we looked at reasons for converting your iOS application to Android, and things you’ll want to consider when porting your application across. In this article we’ll take a deeper dive into developing in Android compared to iOS.

Before you consider converting your iOS application to Android, you of course will need to convert your own skillset from iOS development to Android development. Though this can be an intimidating prospect at first, you will soon realize that there are many similarities between developing for iOS and developing for Android, and your experience developing for iOS will go far in preparing you for development in Android.

In native iOS development you most likely work in Xcode. In native Android development you will probably find yourself working in Android Studio. (Of course, there are a number of other alternatives to building applications for iOS and Android, such as cross-platform tools like Xamarin, React Native or Flutter, but in these articles I’m going to be focusing on mobile application development using these native tools.)

Let’s take a closer look at the differences - and similarities - between developing for Android and iOS.

Migrating your skills to Android

Just as when you first opened Xcode, when you first open Android Studio you will probably be taken aback by the complexity of the interface. This development tool is massive. However, after you take some time to familiarize yourself you will find that much of it has similarities to Xcode. You’ll find a project window on the left showing your project files (similar to Xcode, project files may be organized differently to how you would find them on disk), a toolbar along the top containing all of your most common actions, such as running or debugging your application, a tool window along the bottom where you’ll find many common features such as the debugger window or console, and of course the biggest window is the editor window where you can edit your code or layouts.

In Xcode you’ll be used to adjusting the preferences for your application in the Project and Target Settings - you know the ones - up the top you’ll see tabs such as General, Signing & Capabilities, Info, Build Settings etc. It is here you can customize your application with details such as your application’s bundle ID, application version number, deployment target, external frameworks, application icons, supported devices, capabilities, device orientations etc. Xcode’s Build Settings has many similarities to Android’s gradle scripts - scripts that build when you build your application and configure your project. The script you’ll most commonly see is called the ‘build.gradle’ file - it is here you can do things such as define your applicationlication ID, application version number, target SDK version and dependencies. Other customisations are defined in an XML file called the AndroidManifest. Amongst other details, it is here you will find the application icon, supported devices, permissions, and screen orientations.

In Xcode you will be used to including assets such as images, icons, vector graphics or colors in a folder called an asset catalog(Assets.xcassets). In Android you will find a folder called res, short for resources, that contains all resources your application will need. You will find a folder called drawable that contains images and vector graphics, and you will find a folder called mipmap that contains your application icons. Another folder called layout contains the XML files that represent layout files for each of the screens in your application. Another folder called values is a super useful concept in Android, containing XML files with values that can be accessed in your code or layouts, such as colors, strings or styles.

In iOS you will be accustomed to including variations (1x, 2x and 3x) for each image you include. The graphic variation which the system decides to use depends on the resolution of the screen. Instead of working in pixels, you are recommended to think of designs in points, which account for different pixel densities. The situation in Android is actually very similar. You are encouraged to include different variations for each image, just the variations have different names - MDPI (1x), HDPI (1.5x), XHDPI (2x), XXHDPI (3x) and XXXHDPI (4x). Similar to points in iOS, Android also recommends you to think of density independent pixels, which are called dp for short.

While applications in iOS are made up of various screens called View Controllers that control visual elements called Views, applications in Android are made up of various screens called Activities that can contain visual elements, also called Views. A common container within an Activity is called a Fragment, which is a concept I find especially useful - Fragments are reusable visible components that help you to build up your UI in a modular way. In Xcode you probably would have edited your view controllers visually using Interface Builder. As I mentioned earlier, layouts for screens in Android are represented by XML files - you can edit these visually by selecting Design mode.

Laying out your views in Xcode has a lot of similarities with Android. If you’re used to laying out your views with auto-layout in Interface Builder, over in Android you’ll find a lot of familiarity if you lay out your views with constraints, within a Constraint Layout. (Relative Layout may be of interest too.) If horizontal and vertical stack views are more your thing, in Android you’ll want to try laying out your views within a Linear Layout. If you build your applications with SwiftUI, Android’s native toolkit Jetpack Compose might be worth a peek. One last layout, Frame Layout, is often used to display just one view but can also be used for placing views on top of each other, regardless of whether they overlap. It might sound super basic, but I actually found Frame Layout quite a useful addition to my layout arsenal, for example when I wanted a layout to contain multiple child views that filled the available space.

You are of course able to set up layouts in Xcode storyboards that adapt for different ‘size classes’ - which represent different device types (eg tablet vs phone), resolutions, multitasking modes, orientations, etc. Android has a similar approach - when editing a layout in Design Mode, you can create a layout variation that adapts for orientation, device type. Android layout variations however, go much further, and can be generated for a variety of other qualifiers, such as density, country code, OS version number, or even whether the software keyboard is visible or not.

Of course, not every concept in iOS is directly transferable to Android, and you will find some concepts strange and unfamiliar in Android.

iOS developers used to describing the flow of an application using a storyboard might find it strange to work without this concept in Android development. Traditionally in Android, you would just design each screen (i.e. activity) or fragment visually. Any connections between activities are not outlined visually in Android Studio - instead these connections are described in XML in the Android Manifest file. Those who appreciate the visual representation of navigation in an Xcode storyboard will appreciate that you can now also visually represent navigation in your application in what is called a navigation graph. The navigation graph shows actions (you’d know these as segues in Xcode) that connect destinations, or fragments.

One concept that might feel a little more unfamiliar in Android is intents. At its most basic, an intent is an object that is sent to another part of your application, to request something to happlicationen. One common example is to send an intent to an activity, requesting it to start. The intent can contain data to initialize the activity too. This use case has some similarities to a segue in iOS. Intents are used for many other purposes - starting a service, for example, which has similarities to iOS’s Background Tasks, or delivering a broadcast, which has similarities to broadcasting a notification using iOS’s Notification Center. You describe your intent objects with the intent-filter tag in the Android Manifest. For example, one intent-filter I described in Subtitles Viewer triggered the View Subtitle activity to start when the user tapped on a subtitle file.

Migrating your coding skills to Android

In iOS development you probably work in Swift, and you may have had the pleasure of working with the much older and - let’s say unique - Objective-C. Android development has a similar story - Android development for many years was just possible using Java - a language from the 90’s, until support for developing in a fancy newer language called Kotlin was introduced in 2017. You can choose to develop in either, though Google suggests that “Android development will become increasingly Kotlin-first”. Kotlin also has a lot of benefits over Java, such as more modern features and safety. The 2021 Stack Overflow survey presents some interesting insights - Kotlin (61%) is much more well-loved by developers than Java (47%). That said, Java (35%) is still much more commonly used in general, compared to Kotlin (8%).

Though it can be intimidating to learn a new language, you’ll often find that many differences between languages are mere syntax. Comparing Swift with Kotlin or Java, you’ll find it fairly easy to follow along. Here is a section of code written in the three languages, for a taste of the different syntax between the languages:

let dice = [1,2,3,4,5,6]
func rollDice(diceOptions:[Int])->Int {
    return diceOptions.randomElement() ?? 0
}
for _ in 1...2 {
    print(rollDice(diceOptions: dice))
}
val dice : IntArray = intArrayOf(1, 2, 3, 4, 5, 6)
fun rollDice(diceOptions:IntArray):Int {
    return diceOptions.random()
}
for (roll in 1..2) {
    Log.d("test",rollDice(dice).toString())
}

int[] dice = {1, 2, 3, 4, 5, 6};
int rollDice(int[] diceOptions) {
    return (new Random().nextInt(diceOptions.length));
}
for (int roll = 0; roll < 2; roll++) {
    Log.d("test",rollDice(dice));
}

As you can see, there are syntactical differences but with a little time to adjust, you’ll find it quite easy to follow along.

Just like Swift, Java and Kotlin are object oriented, imperative languages, that support classes, functions, protocols (called interfaces in Kotlin and Java), initializers (called constructors in Kotlin and Java), modifiers (such as public, private etc) and optional types (called nullable types in Kotlin, as they are in Objective-C).

Of course you will inevitably find some more significant differences between the languages too. A key feature of Swift is value types, or structs. Neither Kotlin nor Java have support for custom value types. That said, Kotlin has a type specifically for storing data, called the data class. Neither Kotlin nor Java support tuples either, though there are ways of approximating similar functionality to Swift’s tuple type. While for loops in Swift and Kotlin can loop over collections or ranges, Java supports for loops over collections or the more antiquated for loop syntax (as you can see in the example above).

One interesting difference that I found was how a screen was connected to its underlying code. In iOS development in Swift, you’ll be used to specifying the custom ViewController class in the identity inspector for a screen in the storyboard. In Android, it works the other way - instead of the layout specifying its code, the code specifies its layout. This way, instead of setting up IBActions and IBOutlets in your View Controller as you would be used to doing in Xcode, after specifying the layout for an Activity in Android in the Activity’s onCreate method, you immediately have access to its child views. The following shows how to achieve this in Java.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_quiz);
    //get views
	answerButton = findViewById(R.id.answerButton);
}

Which language did I choose to use, I hear you ask? Call me a traditionalist - call me reckless if you like, but I wanted to learn Android development using the more established Java initially, so I migrated Subtitles Viewer to Android using Java. (Full disclosure, I also have some experience developing in Android with Java but from several years ago.) I must say though, I am very curious to try out Kotlin, and will definitely be building my next Android project in Kotlin.

Migrating your Application

I think you’re ready - you’ve familiarized yourself with the similarities and differences in the interface of Android Studio, how to structure the assets of your application, and you’ve spent some time working up your skills in either Java or Kotlin. In short, you’re ready to go ahead and do the work of converting your application from iOS to Android.

In part 3 of this series, I’ll be looking at next steps - preparing your application’s online presence and beta testing your application, installing a third party library, checking your application for errors and performance issues using Sentry, and finally, publishing your application to the Google Play Store.

Your code is broken. Let's Fix it.
Get Started

More from the Sentry blog

ChangelogCodecovDashboardsDiscoverDogfooding ChroniclesEcosystemError MonitoringEventsGuest PostsMobileOpen SourcePerformance MonitoringRelease HealthResourceSDK UpdatesSentry
© 2024 • Sentry is a registered Trademark
of Functional Software, Inc.