All posts by Adam Jodłowski

How we stopped worrying and learned to use Kotlin in our Androd App

Kotlin is a relatively new programming language, becoming more and more popular among Android developers. It is officially defined as Statically typed programming language for the JVM, Android and the browser by its creators, JetBrains – who are also responsible for the Android Studio (and other great IDEs).

Kotlin at HolidayCheck

After the release of Kotlin in stable version, Android team at HolidayCheck decided to finaly give it a go. We’ve implemented a significant feature of Android app (Booking Module) over the course of three months, learned from our mistakes and enjoyed every single moment of the Kotlin experiment. We can safely say it went well and we’re not looking back.

Here are the top 5 reasons why we recommend everyone to try it in their Android apps.

NullPointerException hell is gone

This might not be the most important reason, but it resonates with every Java developer so strongly, that it needed to be put in the first place. Kotlin is type and null safe. If you use it correctly, NPEs will not happen, it is guaranteed by the language. References that might contain null value, must be explicitly marked as nullable – everything else must have value and the compiler makes sure of it. This is built into type system, no Optional<T> needed.

Lambda expressions & collections

Lambda expressions were one of the most imporant additions to Java 8 – it’s finally available for Android so it’s not such a game changer now, but still – Kotlin adds its own lambda support without the need for Java 8 or external libraries for Android.

Lambdas alone can greatly reduce boilerplate code, but their use with collections shows real power in expressiveness and conciseness. Simple mapping and filtering collections is a touch of functional programming that every modern application needs.

Simplified and more powerful syntax

Operator overloading and extension functions greatly improve expressiveness of the code – no static helper classes needed for simple calculations performed on your custom objects. Setting text on your TextView or hiding it when the text is empty – simple as writing one function shared among all TextViews, instead of polluting view code with logic and if statements.

As a matter of fact, if in Kotlin is an expression, so it can return a value. The same applies to when expression, an improved switch operator.

Default function parameters? Check. No semicolons required? Check. String interpolation? Check, check, check.

You don’t need to go all in

Greenfield projects are rare, most of our day-to-day work is all about maintaining software and building features on top of existing codebase. Some projects (even in the worst tech-debt imaginable), cannot be migrated (even into the most promising programming language ever) for the cost of stopping development. We wouldn’t do that either, but fortunately this is not the case. You can migrate old code or write only new one in Kotlin and everything works fine with Java, because the bytecode is JVM-compatible.

Great way to dive into Kotlin development in your Android app is to separate one single Activity in your project and (re)write it in Kotlin. If anything goes wrong, you can always go to Java, even for single, specific classes.

Java Interoperability

Of course the code of your beloved Android app doesn’t exist in vacuum. What about all those Java libraries, that are not (and probably never will be) ported to Kotlin? Fear not, they don’t need to. You can simply cal Java code from Kotlin and vice versa. Thanks to that, Kotlin can be easily adopted in current code, hopefully phasing out Java in the future.

This list is of course not exhaustive, Kotlin has many other features available. In case this doesn’t convince you, here’s a sneak peek of upcoming changes in version 1.1.

Get started right away

This tutorial shows how you can start with Kotlin, migrating single classes one by one. If anything goes wrong, make sure you have the latest Android Studio and Kotlin plugin installed.

Bonus: Anko library

Anko is a DSL for Android, written in Kotlin. It greatly simplifies development, both in terms of code we must write, as well as its complexity, getting rid of many points of interaction with Android SDK and Java quirks. Be aware though – it’s specific to Android and can potentially introduce yet-another level of complexity if you’re just starting out with migration to Kotlin.

Android Runtime Permissions

Android Runtime Permissions

Permissions are used to restrict access to sensitive resources, data and hardware features. Android 6.0 Marshmallow (SDK level 23) introduced the concept of Runtime Permissions, changing many aspects of managing them in Android. The change is aimed to greatly improve user experience and it seems the Android Team did just that. On the other hand, developers need to incorporate those changes into their apps, which might not look that easy at first glance.

Traditional permission model

  • application install requires all of the permissions to be accepted by the user
  • the only way to revoke them is to uninstall application (all or nothing approach)
  • new permissions prevent apps from auto-updating, they need additional review by the user1
  • required permissions are declared in Android Manifest and application can assume, that if it is installed, it has all of them granted

New runtime permission model

Now, every permission falls into one of three protection levels:

  • normal applications get them by default at the time of installation (for instance Internet connectivity)
  • dangerous must be granted explicitly by the user
  • signature custom permissions based on signing certificates that should match in order to request them, typically used by applications by the same developer in order to exchange some private, proprietary data

In addition to protection levels, new concept of permission groups has been introduced:

  • few separate permissions (like we are used to) might be grouped together into one group
  • user implicitly grants us all permissions from the group, that requested permission belongs to
  • if we ask for more than one permission in a group, they are granted/denied automatically based on users decision regarding the group

Dont assume that if you possess a permission from particular group, you also have all the other permissions from that group always ask for specific ones, because current behavior might change in the future.

What all of that means for your users, is they can just install any given app from the Play Store and start using it right away (no questions during installation asked). Permissions falling into normal protection level are granted by default, and those should be enough for typical app to function, at least at the beginning. The process of asking for permissions is pushed back to the last possible moment the moment that user wants to perform an action requiring dangerous permission, for example action of taking a photo would be briefly interrupted by a system dialog with permission request. Finally, user can grant or revoke2 any permission at any time from system settings, without uninstalling app.

App permissions can be fine-tuned separately app by app

When user revokes permissions, our applications process gets killed.

All is fine for the user, but life of an ordinary Android developer has just got slightly more complicated. Were now required to take extra care and prepare for few scenarios, making sure that we:

  • declare required permissions in Android Manifest as usual
  • check on-the-fly, that we are actually granted permissions required to perform given actions
  • disable certain UI controls or indicate in other ways that application could perform those actions, if it had those permissions
  • are prepared for permission revocation at any given time
  • make a clear distinction between permissions vital to your application and optional ones
  • show disclaimers and reasoning behind requests up-front or in context as they are needed

Asking for Runtime Permissions

All features are backported to both Support Library v4 and v13.

1. Opt-in for Runtime Permissions

In order to opt-in for Runtime Permissions, you need to build your application with Target SDK 23 or higher. If youre using Gradle (which you should be doing), make sure its set in build.gradle:

compileSdkVersion 23
targetSdkVersion 23

2. Declare permissions in AndroidManifest

No changes here, declare needed permissions in AndroidManifest.xml as usual:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="io.github.adamjodlowski.playground">

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

    <application>...</application>

</manifest>

3. Make sure to check if permissions have been granted and ask for them if necessary

System window pops up to get user's approval

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.ACCESS_FINE_LOCATION }, 123);
        } else {
            Log.d("PLAYGROUND", "Permission was already granted");
        }
    }

    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == 123) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Log.d("PLAYGROUND", "Permission has been just granted");
            } else {
                Log.d("PLAYGROUND", "Permission has been denied or request cancelled");
            }
        }
    }
}

As you can see, we use few new methods from Runtime Permissions API. Those are fairly straightforward, but there are few things to note:

  • you can request many permissions, passing an array to ActivityCompat#requestPermissions() method
  • you need to make sure the code is prepared for brief interruption introduced by the request, as well as correctly receive result in onRequestPermissionsResult(), the mechanism is the same as onActivityResult() that you should be already familiar with
  • you can check approval/denial on single permission level notice that response contains requested permissions and separate results for them

You are required to check permissions status every time you might need them, dont assume that you got permission once and its available forever.

Additional considerations

I suppose youve noticed that after first denial user is given the option not to bug them anymore with our request. This is virtually our last chance to explain them reasoning behind the request. In order to do that gracefully, API contains method that returns true, if we previously requested particular permission, but user denied the request:

if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
	// the request has been denied previously, show explanation why you need this, then request permission again!
} else {
	// ask without explanations
}

Please note, this method returns false if user already checked Never ask again checkbox.

Asking second time, user can permanently dismiss this dialog for our app

Theres another feature introduced in SDK 23. You can ask for permissions only if the platform supports runtime permissions, so you can optionally provide new features, but dont request new permissions from users on older platforms upon auto-update of existing installed app. All we need is declaration in Android Manifest:

<uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION"/>

This permission would behave as runtime permission and request for it would appear only on Android 6.0 and newer. For users on older platforms, nothing changes.

Few points to keep in mind

  • apps compiled with Target SDK < 23 are treated as usual
  • many basic permissions are granted by default
  • you still need to declare them in the Manifest
  • you must check every time you need them (Activity#onCreate() is sufficient)

Protip: Android Studio parses annotations and warns you if you try to make an API call but dont request needed permissions.


  1. That leads to developers requesting more permissions that they really need, in order to prevent already installed applications from bugging user again when new app features arrive. This is bad practice. ©
  2. This doesnt mean legacy apps are going to crash like crazy after you revoke permissions, throwing Exceptions all over the place. What really happens is, on Android 23+, API calls that had been restricted would return empty data sets or default values, as if there were no data available. ©