Defining semantic versions via versionName and versionNameSuffix in defaultConfig, buildTypes and productFlavors

Image for post
Image for post
Photo by Al Sam on Unsplash

Versioning in Android is critical to identifying capabilities and age of the application. Like many other software components, Android applications are automatically handled by services (such as the CI) or manually managed by persons (such as the QA or PO). While the Android system uses a simple numerical versionCode to protect against downgrades of applications, services and persons mostly rely on the versionName defined for the application. This versionName can be any string and the Android system doesn’t enforce any constraints on it. For human and machine readability, Semantic Versioning should be considered though.

The versionName is part of the Android manifest, but it’s usually defined for all build variants within the build.gradle script of the application. Here it’s possible to declare a versionCode, a versionName and a versionNameSuffix. …


The only RecyclerView.ViewHolder you’ll ever need

Image for post
Image for post
Photo by Rubén Bagüés on Unsplash

The RecyclerView.ViewHolder describes an item view and metadata about its place within the RecyclerView. Also it is responsible for caching potentially expensive View.findViewById(int) call results. In combination with the same synthetic properties that provide access to layout specific views of activities and fragments, this is basically the purpose of the Kotlin Android Extensions LayoutContainer type.

A base interface for all view holders supporting Android Extensions-style view access.

Combining the ViewHolder and the LayoutContainer in one type, provides a powerful tool for all RecyclerView.Adapter implementations with Kotlin.

@ContainerOptions(SPARSE_ARRAY)
open class SyntheticViewHolder(
override val containerView: View
) : ViewHolder(
containerView
), LayoutContainer

The main advantage here is, that the ViewHolder itself handles the caching of the views and does not know about the structure of the view or the items bound to it. …


Useful documentation for any lambda: (foo: Bar) -> Unit

Image for post
Image for post
Photo by Obi Onyeador on Unsplash

Function declarations contain names for their parameters. That’s as ordinary as it gets in programming.

The definition of anonymous functions and lambdas contain named parameters, though it might be implicitly named and used with lambdas. Depending on the context of the function or lambda declaration, there might not even be any need to declare the parameter type.

When it comes to declaring the type of the function itself, the focus is on the type. Thus a common declaration is just (Int) -> Unit, a function expecting a single parameter of type Int. Knowing the context of this, it should be fairly easy to figure out the meaning of it later. But even with only one more Int parameter, the purpose of each would become arbitrary at once. …


SoftwareComponent support from the Android Gradle Plugin

Image for post
Image for post
Photo by Tim Johnson on Unsplash

Support for the Maven Publish plugin has landed in Android Studio 3.6. Unofficial implementations have been around with android-maven-publish or the abandoned android-maven-gradle-plugin. But these tools rely on internal Gradle APIs and thus have to be updated with every new release of the Android Gradle Plugin or Gradle itself.

The Android Library Plugin now creates an adhoc-component named all and one for every single build variant. These components are the basis for the Gradle publishing publications and provide a simple interface for extending these with other artifacts. The variant components declare a single library artifact publication, while the all component declares all maven dependencies as optional and differs in the definition of Android configuration attributes. In addition to the standard Gradle ones, it also provides attributes for the Android variant, the build type and the product flavors. …


How to properly ask a developer to integrate with an SDK

Image for post
Image for post
Photo by ODD on Unsplash

No, it is not clear how to achieve this task. An SDK might help with what you expect it to, within your product and often many more things. It is not a magic wand, performing any task by itself just by adding a reference and calling an initialisation method. Even though there are SDKs and use-cases for which this might hold true, yours does not necessarily fit into this category. An SDK is merely a tool box which has to be used actively.

As with any other task it’s always good to describe the problem first. Your developers might already know of different, or even better, approaches to a solution. The SDK might not even provide any means to solve the problem at all nor hold the only feasible approach. Now the problem itself is an ideal measurement for acceptance and verification of the task and the actual implementation of it. …


A window into and onto the current state of the app

Image for post
Image for post
Photo by John Moeses Bauan on Unsplash

When developing an application, the two build-types debug and release are defined by default. Additional to these two and possibly some other custom ones, different flavors of the app can be defined with multiple dimensions. To differentiate between these, the version or application name should be annotated with a suffix or replaced completely. Furthermore, the app could change its state dynamically on runtime, like switching between staging and production environments.

In most of these cases though, all these app configurations appear alike when being run on the device. Some relevant information might be accessible within the settings or on info screens. While developing or testing the app, this information being displayed as an overlay to the layout of every single screen, and therefore even more accessible, could increase the efficiency in day-to-day work tasks. …


Configure Android plugins once for all project sub-modules

Image for post
Image for post

The struggle is real. To improve on build speed, Android projects modularize into many small sub-modules. Some of these might be pure Java or Kotlin libraries, not concerning themselves with the version of the Android framework. But every Android application, library or feature module should be configured to target and compile with an identical Android SDK version. The most common way to achieve this with the least effort is to define the versions once in the root project, and then referenced afterward within every other project. The extension container for project.ext helps with it.

buildscript {
ext.versions = [
minSdk: 21,
compileSdk: 28,
]…

Image for post
Image for post
Strictly between Alexander Platz and Rosenthaler Platz… Berlin‽

A tale of humanoid monkey testing

Occasionally our app started crashing for some of our users, while on first sight the code looked just fine. But our analytics suggested otherwise. From Firebase it was hard to figure out, how this all could have happened. We’ve just had enough information to figure out, on which screen the error occurred. But that’s about it. Thanks Rx!

All started after replacing the generic call to notifyDatasetChanged() with an implementation of DiffUtil and therefore calls to all the other members of the notifyItem*() family of callbacks. …


How to wrap and (.git)ignore

Generally you’ll find phrases in the JitPack Android documentation like:

Check that you have the Gradle wrapper in your Git repository. […]

But what exactly is a Gradle wrapper?

Most tools require installation on your computer before you can use them. If the installation is easy, you may think that’s fine. But it can be an unnecessary burden on the users of the build. Equally importantly, will the user install the right version of the tool for the build? What if they’re building an old version of the software?

The Gradle Wrapper […] solves both these problems and is the preferred way of starting a Gradle build. …


Crazy config; happy build.

When I started working on our app, I took over an application which was merely an architectural skeleton. Different layers were defined already, as well as dependencies included to work on this given stack. This comprised a dependency to an extensional utility library with dependencies on other smaller libraries and parts of the Android Support Library with a fixed version. In the end we only needed and used a handful of these utility classes, but got all of the other classes and dependencies for free as well.

Like maybe many other Android developers, I object to bloating my libraries and applications with too many dependencies; even though Proguard gets rid of most of these for production builds anyways. Naturally I tried to replace the given behaviors with other implementations, being able to reduce and remove the out of scale dependencies. Then I started wondering, how to solve this issue. Adding modularity like Google did with the Android Support library is a good start. Depending on the library itself, may be overhead as well. Especially when most of the sub-libraries are pulled in separately at once, it does not make any difference. …

About

Christian Schmitz

as? Android Dev // Freelance

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store