First contact with the Droid

July 2019 · 8 minute read

I am building iOS applications most of the time. I am becoming familiar playing with the iOS SDK and the way how things work on the platform.

I have been asked recently, for a project, to build an application for both iOS and Android. I had never built an Android application before so this project was a good opportunity to do so.

Moreover, the application was rather small and simple, so no real big deal on the iOS side, but contained most of the features required to have a good overview of the Android SDK (multiple screens, account management, networking, …).

I’ll try in this blog post to describe the differences and similarities I found while working on both iOS and Android.

Language

As I said in the introduction, I had no prior experience with android development, have only used Java back at University and honestly, never been a big fan of it. Another option would have been to use Kotlin. (Describe Kotlin)

At this point, some could argue about using cross-platform technologies (React Native, Flutter, …) to develop once for both platforms.

The objective of this blog post is not to discuss the pros and cons of native vs cross-platform, so I’ll simply conclude that I chose to use Kotlin since the syntax is quite similar to swift and that I was more interested to see the difference between iOS and Android development with this project.

Talking about the similarities and differences between Swift and Kotlin, we can describe:

(Swift)

// Variable
var myVariable = 3

// Constant
let myConstant = 4

// Optional Safe Unwrapping
var myVariable: Int? 
if let strongMyVariable = myVariable {
    print(strongMyVariable)
}

// Switch
let number = 3
switch number {
case 3: 
    print("3")
case 4: 
    print("4")
default: 
    print("retry")
}

// Enum
enum State {
    case .waiting
    case .inConfirmation
    case .running
}

// Simple User model
import Foundation

struct User: Codable {
    let id: Int
    let name: String
    let phone: String
    let address: String

    // Can be ommited in this case but written to give some
    // context if a reader is not familiar with Swift or Codable
    enum CodingKeys: String, CodingKey {
        case id = "id"
        case name = "name"
        case phone = "phone"
        case address = "address"
    }
}

(Kotlin)

// Variable
var myVariable = 3

// Constant
val myConstant = 4

// Optional Safe Unwrapping
var myVariable: Int? 
myVariable?.let {
    print(it)
}

// Switch
val number = 3
when (number) {
    3 -> {
        print("3")
    }
    4 -> {
        print("4")
    }
    else -> {
        print("retry")
    }
}

// Enum
enum class State {
    WAITING,
    INCONFIRMATION,
    RUNNING
}

// Simple User model
import org.json.JSONObject

class User(jsonObject: JSONObject) {
    val id: Int
    val name: String
    val phone: String
    val address: String

    init {
        this.id = jsonObject.getInt("id")
        this.name = jsonObject.getString("name")
        this.phone = jsonObject.getString("phone")
        this.address = jsonObject.getString("address")
    }

}

Unfortunately, it seems there is no way in Kotlin to handle multiple optional safe unwrapping like it can be done in Swift.

When coding the models of our app, here again, it is pretty similar between both languages, even if conforming our struct to Codable in Swift save us some time.

UI

I have never been a huge fan of storyboard on iOS. I am implementing my UI 100% by code and I like it that way. However, I have to say that have been pleasantly surprised by the way how to handle UI on Android.

In Android Studio, you can drag and drop UI components like in the Interface Builder in Xcode:

but I prefer writing the UI directly in XML.

The great thing is both ways are synchronized. That means you can insert an element via the design interface and tweak it directly in XML after. This was quite useful in the beginning when you don’t how is called this component or attribute, just set it in the design interface and you can after seeing the name of the attribute in the XML.

This approach of using different types of layout (LinearLayout, FrameLayout, …) to build the UI makes me think of how it will be handled with the new SwiftUI framework.

One layout file, for example, home_layout.xml, can be served to the Activity (UIViewController on iOS) using:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.home_layout)
}

The same goes for all UI components added to the XML. As you can see in the previous screenshot, the ImageView, TextView and Button have an android:id property. This id can be directly used to act with the element, changing font, size, etc. Let’s add the code in the onCreate() method to call a print a message when we press the button:

my_button.setOnClickListener {
    print("♪ Ba Ba Bi Bu Bu Ba ♪")
}

Even though this way enables the developer to create the UI fast, handling custom and complex interfaces or components will require to pass by the code, which I found less intuitive than doing for iOS, certainly because I was already doing it on iOS for a long time.

User Experience

I’ll not talk too much about the difference of User Experience there is between iOS and Android since there is a lot to say about it. However, I found something about the UX that is radically different from iOS to Android.

The Android OS makes use of a navigation bar at the bottom of the device.

The buttons present on the bar can perform different actions like going back to the previous screen, quitting an app, going the home screen of the device or showing a list of all the open applications. Despite that this navigation bar can indeed be hidden for your application, it is not advised to remove it since many users are used to this particular UX.

This particular UX is not available on iOS, so when you develop an Android application, you have to be aware of this UX and implement your view as a consequence.

Override the onBackPressed() method with your custom logic to perform any change of behavior when the back button is pressed.

override fun onBackPressed() {
    print("Back button was pressed")
}

Dependency Management

Another nice thing found while implementing the Android application is the use of dependencies.

To set an example, I usually use Firebase for my in-app analytics. Firebase provides an SDK for developers to us. On iOS, multiple dependency managers exist like Cocoapods, Carthage or the Swift Package Manager. While only the last one is the official dependency manager, is it also the less used of those 3 since its recent release and the lack of features compared to Cocoapods and Carthage (this will certainly change now that the Swift Package Manager has been greatly improved).

I am a Coacopods user, so if I want to use Firebase on my new app, I will first have to:

// install Coacopods if it's my first time using it
$ sudo gem install cocoapods
// initialize Coacopods for your project
$ pod init
// add Firebase to your dependencies
$ vi Podfile

target 'MyApp' do
    # Comment the next line if you don't want to use dynamic frameworks
    use_frameworks!

    # Pods for MyApp
    pod 'Firebase/Analytics'

end

// install the pod
$ pod install
// close the .xcodeproject and open the .xcworkspace newly created
$ open MyApp.xcworkspace

For Android? The dependency manager is included with gradle, so all you have to do is select your build.gradle file (the Module: app one), add the dependency in the dependencies dictionary like so:

dependencies {
        ...
    // My Firebase dependency
    implementation 'com.google.firebase:firebase-core:16.0.1'
}

and we are done. The dependency will be installed automatically, pretty cool right?

IDE

Last topic I want to talk about, IDE (Integrated Development Environment). For my part, I am using Xcode for iOS and Android Studio for Android.

Honestly, I was sometimes complaining that Xcode was sometimes slow at indexing a big project, but that was before trying Android Studio.

Each time you open or start a new project on Android Studio, I have to wait a very very long time before to build and run the application.

The project hierarchy is a little more confusing on Android Studio than on Xcode (for me) and I highly recommend to switch your project tree to the Android mode instead of the Project mode.

I found that the auto-completion was usually a little bit faster on Android Studio and always functional where it can appear to be totally off on Xcode sometimes.

A cool feature on Android Studio makes it possible to detect typos automatically in the code. it works for strings but also variables and function names:

I wish we could have this in Xcode, especially for those like me which don’t have English for mother-tongue.

Android Studio enables more manipulations of the emulators to fit developers’ needs than what Xcode proposes.

Let’s see what cool new things Xcode 11 will bring us soon to make us more productive.

Conclusion

To conclude, I will say that developing for Android was a great experience. I would also say that having previous experience in mobile development with Swift helped me a lot to be rapidly productive on Android. The similarities of Swift and Kotlin make it easy to code from a platform to another. Kotlin is Java made for mobile, but sometimes it really looks like Java. Moreover, when seeking help on the internet, you will probably find more solutions (and better one) in Java rather than in Kotlin. I think programming in Kotlin reconciled me a little with Java, which is probably a good thing too.

After this first Android application, even it was a simple one, it made me realized that I would consider using cross-platform technology to develop an application for both iOS and Android if I don’t have the resource(s) or mobile developer(s). If I do, especially with resource(s) familiar with Swift, the native approach appears better to me. I spent only a couple of days more crafting the Android application than for the iOS one, with almost the same quality.