Since its inception in 2003, the Android Framework has evolved into an ever-changing open-source beast. Even with recent additions to the cross-platform world, namely, Flutter and React Native, Android-specific platform development has remained the dominant method of development, with over 70% of mobile developers using single-platform Android development tools.
The Android open-source project has welcomed contributions big and small from its thriving developer community with the ultimate aim of improving the user experience of the platform. Originally designed for digital cameras by Android Inc, the framework is a cocktail of Java, Kotlin, XML, C++ and a plethora of third-party libraries. Android has endured a long process of retrofitting by Google over the years to become the ‘mobile-first’ platform we know and love today.
Consequently, with the ever-changing requirements, comes the necessity for Android developers to be versatile and aim for continuous improvement. The platform has undergone rapid transformation and is aging out of older design paradigms, legacy architectures and concurrency methods used in the construction of mobile apps.
Table Of Contents
In recent times, the team at Google has focused heavily on improving the architecture and optimizing performance, and even baked some of this functionality directly into the platform with the lifecycle-aware jetpack libraries. The question of Android architecture is an ongoing dialogue and, consequently, provides a plethora of ways to create these apps, especially when scaling for a larger audience.
In this guide, we’ll cover the fundamental hard and soft skills you should look for in a good Android developer, as well as the libraries and tools they should be aware of, address some of the code quality and testing issues to check for, and provide some interview questions to help find a suitable match for your project.
Evaluating Soft Skills of Android Developers
General Fit and Soft Skills
There’s always been a great deal of emphasis on the technical ability of your Android developers. However, in recent times, there’s been a shift towards less tangible qualities i.e. their soft skills, to help create a well-rounded team. Even the FAANG companies (Facebook, Amazon, Apple, Netflix & Google) have shifted the focus towards soft skills during their multi-staged processes.
In the office, before a developer starts pumping out code, they typically have an ongoing dialogue with the stakeholders and members of the team; whose decisions will ultimately impact how that developer aims to solve the issues presented to them. One component of this dialogue is Consulting and occurs during sprint planning and refinement sessions throughout the entirety of the project.
The best Android developers typically find useful metaphors to communicate their ideas effectively and more importantly, break down complex concepts to non-technical members of the team and use the information to guide them towards an effective solution. The developer should be tested for their ability to compare and contrast different solutions to a familiar problem and then ultimately help the team decide which would be the most appropriate approach for the given scenario.
Android Versions and History
Android is a big ecosystem and no single developer is expected to know every aspect of it. Understanding which version(s) of the Android OS a developer has worked with is insightful. It can provide us with a surface-level understanding of the problems they’ve likely encountered. Typically, you’ll get to assess their exposure to specific versions of the OS and both the problems that plagued the platform and their equivalent solutions at particular eras during the lifetime of the platform.
Similarly, the types of projects the developer has previously worked on can help gauge the developer’s compatibility with a given project (especially greenfield and bespoke apps). There are usually similarities across problem domains depending on the type of app. For example, Games, Utility apps, Social media and Streaming apps may tend to have common problems which an Android developer exposed only to a particular type or group of apps may not have experienced.
Conversely, that may mean a particular developer may be familiar with more deep-routed, domain-specific issues with particular types of apps. A brief walkthrough from the developer about a prior project can be enough to assess if there’s some overlap and transferable skills that can be applied to a new project.
Cultural Fit and Team Dynamics
Mobile development involves many overlapping processes, and understanding this ecosystem is just as important as the technical challenges being solved. Familiarity with particular team sizes, team structures and working styles helps paint a clear picture of a developer’s cultural fit. Some developers prefer Scrum or Kanban to coordinate the tasks with the team. Others even choose to code solo and feel more comfortable with the “one-man band” approach.
Each has its strengths, but they may not always be compatible with the existing project setup. The Android developer should be asked to pick their most successful projects and asked to describe the team setup, as this can help give an accurate depiction of which setup would facilitate optimal performance within the team.
Conflict Resolution and Peer Review
Moreover, for consulting, it’s unrealistic to expect all stakeholders to agree at all times. A developer should have effective methods of communicating their ideas, but also ways to resolve conflict if a given dialogue doesn’t necessarily go their way. The ability to move past disagreements to solutions helps reduce the combativeness and friction among team members that could ultimately slow down a project. Appreciation for peer review and experience in both giving and receiving feedback is the hallmark of a seasoned developer who has spent some time improving their problem solving ability.
Technical Skills to Look For in an Android Developer
Android Architectural Patterns
Generally, an Android developer should be familiar with or at least interested in the discussion about architectural patterns as part of the Android ecosystem or any relevant platform for that matter. A developer should understand the history of the platform and the paradigm shift towards robust architecture to aid testability. This is the foundation upon which most other technical design decisions might be made.
This understanding will also provide insight into how they tailor solutions to the end client and how they balance the pros and cons of speed, maintainability, scalability and feasibility. Android developers could be asked to compare and contrast architectures like Model View Presenter (MVP), Model View ViewModel (MVVM) and Model View Intent (MVI). The developer should know that Google has endorsed the MVVM architecture for Android applications and has even built the pattern directly into the framework through the jetpack libraries: LiveData, ViewModels, and other lifecycle aware components based on the publish subscribe design pattern.
Moreover, Android developers should consider and highlight platform-specific design patterns and principles and acknowledge that Android has its own design language which makes it distinct from iOS and Web, i.e. Material Design. The developer should be able to consult with the stakeholders, product owners and UX designers about end-users’ expectations and not blur the lines between the platforms.
For tasks such as implementing navigation, dark theme, or choosing a color palette, the developer could start with a general approach, but put emphasis on the Android-specific implementation. For example, the developer could describe the use of file image formats (JPEG, PNG) or both programmatic and declarative methods for rendering screen designs (jetpack compose and XML layouts respectively). Android developers should then further elaborate on preferred layouts (Constraint or Relative vs AbsoluteLayout) and file resource management mechanisms such as ‘string’, ‘color’, ‘styles’ and ‘themes’ xml files and how they can be applied to screens.
The Android Lifecycle
Android developers should understand the importance of the Android lifecycle and how it impacts many design decisions when creating solutions even for the most simple of mobile applications.
As the platform has tons of libraries and tools available, it would be unreasonable to check for experience with every single one of them before being deemed a “good developer”. A lot of these tools have overlap, and therefore experience with one type of tool (e.g. a networking or analytics library, or a DevOps CI/CD pipeline) can easily be transferred onto alternate solutions.
For example, the developer should be able to explain how the lifecycle introduces complexity when dealing with configuration changes such as screen rotation and the various elements such as Activities, Fragments that may need to be recreated and reliably managing and persisting any cache or data as a result of this user action.
A general understanding of the development lifecycle outside the coding aspect is a strong bonus. For instance, security awareness (app security and user data security) is vital, especially when trying to prevent app release hiccups. In most cases, security importance is domain-specific i.e. the security considerations of a banking or Blockchain app, would be different from a mobile game.
Nonetheless, Android developers should demonstrate awareness of potential security issues by highlighting best practices in app development. For example, the developer should recall the benefits of code obfuscation via the proguard tool and how that can minimize the number of vulnerabilities in the codebase. An Android developer could also compare and contrast different storage mechanisms i.e. preference data store, room database and how the data might be persisted or cached for later use.
Android Device Fragmentation
A developer should have an appreciation for Android fragmentation (multiple device resolutions, configurations and Android OS versions) and the design considerations necessary to create simple yet effective solutions.
As there are so many devices, knowing when to utilize different file image resources for different screen sizes or having to write conditional statements depending on the Android build OS version are useful experiences to have for any Android developer. Knowledge of support libraries and their features, allows developers to make changes to implementation in an older version of Android.
This enables support for legacy systems that may not be able to easily add newer libraries due to the limitations of the Java language or API level the application has been compiled against. For example, an older application that was compiled against Java 7 may need several changes if the Java version was merely bumped up to Java 8 or even Java 11, but working within the limits of the Java 7 feature set and solving the problem without a version bump can save more rewrites in the immediate future and reduce the maintenance cost.
Concurrency and Background Tasks
One challenging area within the Android ecosystem has always been concurrency and asynchronous tasks. Android applications typically perform their functions on the main thread (UI thread), which is fine for small and simple apps. However, as apps become larger, complex and feature-rich, synchronizing all this activity becomes very tricky.
Over the years, Google has introduced several additions to the platform to tackle these synchronization issues, namely: AsyncTasks, Services, Loaders and recently Kotlin Coroutines and WorkManagers.
Each method has strengths and weaknesses and an ideal use case fit for a particular point in the lifetime of the platform. Although experience with every method is not necessary, the knowledge of their appropriate use is paramount.
As some projects evolve, they can become difficult to maintain and due to cost implications, it’s not always feasible for developers to rewrite an app simply because it’s a legacy system and uses older concurrency methods. Instead, developers typically will join a project and work within the constraints of an application already released and may undergo maintenance. For example, an older project using RxJava or Eventbus may incur a huge development cost if adapted to now support Kotlin coroutines and suspend functions. In the event that retrofitting and refactoring the solution won‘t be feasible, it may be more cost-effective if the developer were to work with Rxjava given the context of the particular change request.
Networking has always been a challenge on Android, especially around the inception of the first generation devices in 2008, back when low memory, low-performance phones were the norm. As applications become more complex and scale to millions of users, it often means the data required by the user is not necessarily always stored physically on the device, but requested by the app from a server through cloud services.
There are many well-documented methods for achieving this such as RESTful APIs, Graph QL etc, but there are also several differences as each organization usually has its own API, data sets and server setup. An Android developer should have a general understanding of networking on mobile and possible challenges and limitations on Android devices. They should be familiar with how to make API calls, receive and parse the JSON responses and determine how to respond to edge cases (e.g. patchy wifi) and errors such as when a network call simply fails or requested data can’t be found and the implications this may have on the user experience.
Libraries such as retrofit, RxJava, and Coroutines, among others, are used abundantly across many popular apps. The developer should know which form to expect the retrieved data, how to process (read and present) the data and display it back to the user via the user interface.
Testability is a key driver in many architectural discussions because it can severely impact the speed, reliability and overall performance of an app if not approached methodically. Testing (both manual and automated) should be at the forefront of developer decisions, as it helps greatly by making code easier to manage, maintain and extend as more features are added.
The developer should demonstrate making design decisions that were made because they facilitated testability. For example, using a service locator pattern to facilitate testing ‘fake’ implementations of a repository, or favoring a ‘clean architecture’ with separations of concerns.
There should be an emphasis on the testing tools and familiarity of the common libraries in the Android testing world such as Espresso for user interface testing, JUnit for testing individual app components, Mockito for creating simpler implementations of application components and the cases where we test concurrency mechanisms like coroutines or Livedata and other jetpack components.
Kotlin Language-Specific Features
Android developers should be familiar with both Java and Kotlin. Additional features of the platform that are Kotlin-specific should be leveraged to fully maximize the potential of the language. Kotlin features such as scope functions, coroutines, properties and extension functions are very useful and provide easier ways to tackle difficult problems with Android when compared to Java.
Understanding Java and Kotlin interoperability and the benefits of using both languages interchangeably and the advantages a developer has in utilizing aspects of both languages within a project is a bonus.
Technical Interview Questions for Android developers
Question: What is the difference between an Activity and a Fragment?
Answer: An Activity can exist without a fragment, but a Fragment can not exist without an Activity.
- Plausible detractor 1: An activity is a lifecycle aware component, whereas a fragment is not lifecycle aware.
- Plausible detractor 2: An activity has UI and can be connected to multiple fragments, but fragments can only be connected to one Activity.
- Plausible detractor 3: An activity does have a lifecycle that enables it to observe ViewModels, whereas a fragment does not have a lifecycle.
Question: What does the ‘suspend’ keyword mean, and what does it do in Kotlin?
Answer: This type of function is for long running operations that are non-blocking and can be paused and resumed for a later time.
- Plausible detractor 1: This type of class is for background tasks that are blocking and can potentially cause the application to freeze.
- Plausible detractor 2: This type of annotation can be used to mark a method as a long running task if it blocks the main user thread for up to 5 seconds.
- Plausible detractor 3:This type of annotation is used to mark libraries that are no longer supporting Java interoperability.
Question: What is the difference between Model, View, View Model (MVVM) and Model View Presenter (MVP) architectural patterns on Android?
Answer: MVVM passively updates the user interface, whereas MVP actively updates the user interface of android applications.
- Plausible detractor 1: MVVM is slower at updating databases and making network calls, whereas MVP is much faster as it has fewer components to connect to.
- Plausible detractor 2: MVVM has the potential to leak views whereas MVP is not able to leak views because the views are not tied to the model.
- Plausible detractor 3: MVVM is more battery intensive due to the use of observers whereas MVP is better with battery life, but likely to cause memory leaks.
Question: Which of the following attributes in the AndroidManifest.xml, would be used to declare the Android OS a particular app is tested against and is able to support?
- Plausible detractor 1: minSdkVersion
- Plausible detractor 2: compileSdkVersion
- Plausible detractor 3: maxSdkVersion
Question: Which of the following is a likely cause for an Application Not Responding Error (ANR)?
Answer: The app is likely performing a long-running task on the main thread, after a short period the system will reclaim control from the application.
- Plausible detractor 1: The main Android system services stop working due to overheating and that can stop the app currently open from responding.
- Plausible detractor 2: The system detects that the app is too large and shuts down the application to preserve system resources.
- Plausible detractor 3: The user has entered too many touch events and the app is unable to process the clicks fast enough and so shuts down the application.
The Android ecosystem is heavily fragmented and therefore requires experienced developers who have encountered different flavors of the platform, an appreciation for the history of the platform and various issues with different versions of the framework. The longer the developer has worked with the platform the more insight they might have into the pain points most likely encountered by most development teams. Furthermore, they’ll likely be able to use consulting and experience from past projects to solve problems and tailor solutions to particular clients’ needs.
An Android developer should be able to reference successful projects and team dynamics to help the client decide whether they would be a good cultural fit (the developer should be doing this assessment for themselves too) as social awareness would be key for an accurate reflection and cultural fit assessment.
Lastly, the developer should be cognizant of the various landmines in the Android ecosystem such as concurrency, networking fragmentation and Material design. A well-tested app with modern Kotlin features may not always be possible so appreciation for older paradigms would be an asset to an organization that is likely going to have such project constraints.