diff --git a/build.gradle b/build.gradle
index fec6c39f774927589df15314331bc86bf54e227a..ee659d3de2baeb7542224bc7aac9fb5897b62f39 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,11 +1,5 @@
-allprojects {
-    repositories {
-        mavenCentral()
-        google()
-    }
-}
-
 buildscript {
+    ext.kotlin_version = '1.6.10'
     repositories {
         mavenCentral()
         google()
@@ -14,5 +8,13 @@ buildscript {
     dependencies {
         classpath 'com.android.tools.build:gradle:7.0.4'
         classpath 'com.vanniktech:gradle-maven-publish-plugin:0.18.0'
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+    }
+}
+
+allprojects {
+    repositories {
+        mavenCentral()
+        google()
     }
 }
diff --git a/gradle.properties b/gradle.properties
index 478b92e4b2c635e857c4c6c0c47ea1207ddee641..b6829a7d0e53d8a0734ec5156d31d77516b1b3fa 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -20,5 +20,3 @@ POM_DEVELOPER_NAME=Torsten Grote
 POM_DEVELOPER_URL=https://github.com/grote/
 
 RELEASE_SIGNING_ENABLED=false
-
-android.useAndroidX=true
diff --git a/lib/build.gradle b/lib/build.gradle
index 4f61576c4e8bf9c83f7b6cc17635690d270b4b18..e970b5fa3384a14db760f82783e719d73bfaeb05 100644
--- a/lib/build.gradle
+++ b/lib/build.gradle
@@ -1,5 +1,6 @@
 plugins {
     id 'com.android.library'
+    id 'kotlin-android'
     id 'com.vanniktech.maven.publish'
 }
 
@@ -23,8 +24,15 @@ android {
         sourceCompatibility JavaVersion.VERSION_1_8
         targetCompatibility JavaVersion.VERSION_1_8
     }
+    kotlinOptions {
+        freeCompilerArgs += '-Xexplicit-api=strict'
+    }
 }
 
-dependencies {
-    implementation "androidx.annotation:annotation:1.3.0"
+kotlin {
+    explicitApi = 'strict'
 }
+
+dependencies {
+    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
\ No newline at end of file
diff --git a/lib/src/main/java/org/briarproject/android/dontkillmelib/AbstractDozeWatchdogImpl.java b/lib/src/main/java/org/briarproject/android/dontkillmelib/AbstractDozeWatchdogImpl.java
deleted file mode 100644
index 57240726f8dfd8f7f73a7b8b14bfe5820d905dbd..0000000000000000000000000000000000000000
--- a/lib/src/main/java/org/briarproject/android/dontkillmelib/AbstractDozeWatchdogImpl.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package org.briarproject.android.dontkillmelib;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.PowerManager;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import static android.content.Context.POWER_SERVICE;
-import static android.os.Build.VERSION.SDK_INT;
-import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
-
-public abstract class AbstractDozeWatchdogImpl {
-
-	private final Context appContext;
-	private final AtomicBoolean dozed = new AtomicBoolean(false);
-	private final BroadcastReceiver receiver = new DozeBroadcastReceiver();
-
-	public AbstractDozeWatchdogImpl(Context appContext) {
-		this.appContext = appContext;
-	}
-
-	public boolean getAndResetDozeFlag() {
-		return dozed.getAndSet(false);
-	}
-
-	public void startService() {
-		if (SDK_INT < 23) return;
-		IntentFilter filter = new IntentFilter(ACTION_DEVICE_IDLE_MODE_CHANGED);
-		appContext.registerReceiver(receiver, filter);
-	}
-
-	public void stopService() {
-		if (SDK_INT < 23) return;
-		appContext.unregisterReceiver(receiver);
-	}
-
-	private class DozeBroadcastReceiver extends BroadcastReceiver {
-		@Override
-		public void onReceive(Context context, Intent intent) {
-			if (SDK_INT < 23) return;
-			PowerManager pm =
-					(PowerManager) appContext.getSystemService(POWER_SERVICE);
-			if (pm.isDeviceIdleMode()) dozed.set(true);
-		}
-	}
-}
diff --git a/lib/src/main/java/org/briarproject/android/dontkillmelib/AbstractDozeWatchdogImpl.kt b/lib/src/main/java/org/briarproject/android/dontkillmelib/AbstractDozeWatchdogImpl.kt
new file mode 100644
index 0000000000000000000000000000000000000000..597a8361c8ae097f37779066d84cbf3be7a3f0f5
--- /dev/null
+++ b/lib/src/main/java/org/briarproject/android/dontkillmelib/AbstractDozeWatchdogImpl.kt
@@ -0,0 +1,39 @@
+package org.briarproject.android.dontkillmelib
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Context.POWER_SERVICE
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.Build.VERSION.SDK_INT
+import android.os.PowerManager
+import android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED
+import java.util.concurrent.atomic.AtomicBoolean
+
+public abstract class AbstractDozeWatchdogImpl(private val appContext: Context) {
+
+    private val dozed = AtomicBoolean(false)
+
+    private val receiver = object : BroadcastReceiver() {
+        override fun onReceive(context: Context, intent: Intent) {
+            if (SDK_INT < 23) return
+            val pm = appContext.getSystemService(POWER_SERVICE) as PowerManager
+            if (pm.isDeviceIdleMode) dozed.set(true)
+        }
+    }
+
+    public val andResetDozeFlag: Boolean
+        get() = dozed.getAndSet(false)
+
+    public fun startService() {
+        if (SDK_INT < 23) return
+        val filter = IntentFilter(ACTION_DEVICE_IDLE_MODE_CHANGED)
+        appContext.registerReceiver(receiver, filter)
+    }
+
+    public fun stopService() {
+        if (SDK_INT < 23) return
+        appContext.unregisterReceiver(receiver)
+    }
+
+}
diff --git a/lib/src/main/java/org/briarproject/android/dontkillmelib/DozeHelper.java b/lib/src/main/java/org/briarproject/android/dontkillmelib/DozeHelper.java
deleted file mode 100644
index ea80f78bb26edbce7693bcae9569d34fe6ed17de..0000000000000000000000000000000000000000
--- a/lib/src/main/java/org/briarproject/android/dontkillmelib/DozeHelper.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.briarproject.android.dontkillmelib;
-
-import android.content.Context;
-
-public interface DozeHelper {
-	boolean needToShowDoNotKillMeFragment(Context context);
-}
diff --git a/lib/src/main/java/org/briarproject/android/dontkillmelib/DozeHelper.kt b/lib/src/main/java/org/briarproject/android/dontkillmelib/DozeHelper.kt
new file mode 100644
index 0000000000000000000000000000000000000000..520c0c9f197ecc2cf853e658c3ac88c1b5737a25
--- /dev/null
+++ b/lib/src/main/java/org/briarproject/android/dontkillmelib/DozeHelper.kt
@@ -0,0 +1,7 @@
+package org.briarproject.android.dontkillmelib
+
+import android.content.Context
+
+public interface DozeHelper {
+    public fun needToShowDoNotKillMeFragment(context: Context): Boolean
+}
diff --git a/lib/src/main/java/org/briarproject/android/dontkillmelib/DozeHelperImpl.java b/lib/src/main/java/org/briarproject/android/dontkillmelib/DozeHelperImpl.java
deleted file mode 100644
index d01e9583a7d9818f26d01a4db78b5ec2d628d926..0000000000000000000000000000000000000000
--- a/lib/src/main/java/org/briarproject/android/dontkillmelib/DozeHelperImpl.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.briarproject.android.dontkillmelib;
-
-import android.content.Context;
-
-import static org.briarproject.android.dontkillmelib.PowerUtils.huaweiAppLaunchNeedsToBeShown;
-import static org.briarproject.android.dontkillmelib.PowerUtils.huaweiProtectedAppsNeedsToBeShown;
-import static org.briarproject.android.dontkillmelib.PowerUtils.isXiaomiOrRedmiDevice;
-import static org.briarproject.android.dontkillmelib.PowerUtils.needsDozeWhitelisting;
-
-public class DozeHelperImpl implements DozeHelper {
-	@Override
-	public boolean needToShowDoNotKillMeFragment(Context context) {
-		Context appContext = context.getApplicationContext();
-		return needsDozeWhitelisting(appContext) ||
-				huaweiProtectedAppsNeedsToBeShown(appContext) ||
-				huaweiAppLaunchNeedsToBeShown(appContext) ||
-				isXiaomiOrRedmiDevice();
-	}
-}
diff --git a/lib/src/main/java/org/briarproject/android/dontkillmelib/DozeHelperImpl.kt b/lib/src/main/java/org/briarproject/android/dontkillmelib/DozeHelperImpl.kt
new file mode 100644
index 0000000000000000000000000000000000000000..100c25d7f30d514dea67cbf6dfec635d260d57bf
--- /dev/null
+++ b/lib/src/main/java/org/briarproject/android/dontkillmelib/DozeHelperImpl.kt
@@ -0,0 +1,13 @@
+package org.briarproject.android.dontkillmelib
+
+import android.content.Context
+
+public class DozeHelperImpl : DozeHelper {
+    override fun needToShowDoNotKillMeFragment(context: Context): Boolean {
+        val appContext = context.applicationContext
+        return PowerUtils.needsDozeWhitelisting(appContext) ||
+            PowerUtils.huaweiProtectedAppsNeedsToBeShown(appContext) ||
+            PowerUtils.huaweiAppLaunchNeedsToBeShown(appContext) ||
+            PowerUtils.isXiaomiOrRedmiDevice
+    }
+}
diff --git a/lib/src/main/java/org/briarproject/android/dontkillmelib/PowerUtils.java b/lib/src/main/java/org/briarproject/android/dontkillmelib/PowerUtils.java
deleted file mode 100644
index 639ac03d7c2ee679c7ccf98bbe8a472140cf1bc6..0000000000000000000000000000000000000000
--- a/lib/src/main/java/org/briarproject/android/dontkillmelib/PowerUtils.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.briarproject.android.dontkillmelib;
-
-import static android.content.Context.POWER_SERVICE;
-import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
-import static android.os.Build.BRAND;
-import static android.os.Build.VERSION.SDK_INT;
-import static android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS;
-import static java.lang.Runtime.getRuntime;
-
-import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.net.Uri;
-import android.os.PowerManager;
-
-import androidx.annotation.Nullable;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Scanner;
-
-public class PowerUtils {
-
-	private final static String PACKAGE_NAME_HUAWEI =
-			"com.huawei.systemmanager";
-	private final static String CLASS_NAME_POWER_MANAGER =
-			PACKAGE_NAME_HUAWEI + ".power.ui.HwPowerManagerActivity";
-	private final static String CLASS_NAME_PROTECTED_APPS =
-			PACKAGE_NAME_HUAWEI + ".optimize.process.ProtectActivity";
-
-	public static boolean needsDozeWhitelisting(Context ctx) {
-		if (SDK_INT < 23) return false;
-		PowerManager pm = (PowerManager) ctx.getSystemService(POWER_SERVICE);
-		String packageName = ctx.getPackageName();
-		if (pm == null) throw new AssertionError();
-		return !pm.isIgnoringBatteryOptimizations(packageName);
-	}
-
-	@TargetApi(23)
-	@SuppressLint("BatteryLife")
-	public static Intent getDozeWhitelistingIntent(Context ctx) {
-		Intent i = new Intent();
-		i.setAction(ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
-		i.setData(Uri.parse("package:" + ctx.getPackageName()));
-		return i;
-	}
-
-	/**
-	 * Determine whether a Huawei "Protected apps" feature is available on the
-	 * device.
-	 */
-	public static boolean huaweiAppLaunchNeedsToBeShown(Context context) {
-		// "App launch" was introduced in EMUI 8 (Android 8.0)
-		if (SDK_INT < 26) return false;
-		PackageManager pm = context.getPackageManager();
-		List<ResolveInfo> resolveInfos =
-				pm.queryIntentActivities(getHuaweiProtectedAppsIntent(),
-						MATCH_DEFAULT_ONLY);
-		return !resolveInfos.isEmpty();
-	}
-
-	/**
-	 * Determine whether a Huawei "Protected apps" feature is available on the
-	 * device.
-	 */
-	public static boolean huaweiProtectedAppsNeedsToBeShown(Context context) {
-		// "Protected apps" no longer exists on Huawei EMUI 5.0 (Android 7.0)
-		if (SDK_INT >= 24) return false;
-		PackageManager pm = context.getPackageManager();
-		List<ResolveInfo> resolveInfos = pm.queryIntentActivities(
-				getHuaweiPowerManagerIntent(),
-				MATCH_DEFAULT_ONLY);
-		return !resolveInfos.isEmpty();
-	}
-
-	public static Intent getHuaweiPowerManagerIntent() {
-		Intent intent = new Intent();
-		intent.setClassName(PACKAGE_NAME_HUAWEI, CLASS_NAME_POWER_MANAGER);
-		return intent;
-	}
-
-	public static Intent getHuaweiProtectedAppsIntent() {
-		Intent intent = new Intent();
-		intent.setClassName(PACKAGE_NAME_HUAWEI, CLASS_NAME_PROTECTED_APPS);
-		return intent;
-	}
-
-	public static boolean isXiaomiOrRedmiDevice() {
-		return "Xiaomi".equalsIgnoreCase(BRAND) ||
-				"Redmi".equalsIgnoreCase(BRAND);
-	}
-
-	public static boolean isMiuiTenOrLater() {
-		String version = getSystemProperty("ro.miui.ui.version.name");
-		if (version == null || version.equals("")) return false;
-		version = version.replaceAll("[^\\d]", "");
-		try {
-			return Integer.parseInt(version) >= 10;
-		} catch (NumberFormatException e) {
-			return false;
-		}
-	}
-
-	@Nullable
-	private static String getSystemProperty(String propName) {
-		try {
-			Process p = getRuntime().exec("getprop " + propName);
-			Scanner s = new Scanner(p.getInputStream());
-			String line = s.nextLine();
-			s.close();
-			return line;
-		} catch (SecurityException | IOException e) {
-			return null;
-		}
-	}
-}
diff --git a/lib/src/main/java/org/briarproject/android/dontkillmelib/PowerUtils.kt b/lib/src/main/java/org/briarproject/android/dontkillmelib/PowerUtils.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d97c63367861b3e224f8c1a60d6abdf206205850
--- /dev/null
+++ b/lib/src/main/java/org/briarproject/android/dontkillmelib/PowerUtils.kt
@@ -0,0 +1,107 @@
+package org.briarproject.android.dontkillmelib
+
+import android.annotation.SuppressLint
+import android.annotation.TargetApi
+import android.content.Context
+import android.content.Context.POWER_SERVICE
+import android.content.Intent
+import android.content.pm.PackageManager.MATCH_DEFAULT_ONLY
+import android.net.Uri
+import android.os.Build
+import android.os.Build.VERSION.SDK_INT
+import android.os.PowerManager
+import android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
+import java.io.IOException
+import java.util.Scanner
+
+public object PowerUtils {
+
+    private const val PACKAGE_NAME_HUAWEI = "com.huawei.systemmanager"
+    private const val CLASS_NAME_POWER_MANAGER =
+        "$PACKAGE_NAME_HUAWEI.power.ui.HwPowerManagerActivity"
+    private const val CLASS_NAME_PROTECTED_APPS =
+        "$PACKAGE_NAME_HUAWEI.optimize.process.ProtectActivity"
+
+    @JvmStatic
+    public fun needsDozeWhitelisting(ctx: Context): Boolean {
+        if (SDK_INT < 23) return false
+        val pm = ctx.getSystemService(POWER_SERVICE) as PowerManager
+        return !pm.isIgnoringBatteryOptimizations(ctx.packageName)
+    }
+
+    @JvmStatic
+    @TargetApi(23)
+    @SuppressLint("BatteryLife")
+    public fun getDozeWhitelistingIntent(ctx: Context): Intent = Intent().apply {
+        action = ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
+        data = Uri.parse("package:" + ctx.packageName)
+    }
+
+    /**
+     * Determine whether a Huawei "Protected apps" feature is available on the
+     * device.
+     */
+    @JvmStatic
+    public fun huaweiAppLaunchNeedsToBeShown(context: Context): Boolean {
+        // "App launch" was introduced in EMUI 8 (Android 8.0)
+        if (SDK_INT < 26) return false
+        val pm = context.packageManager
+        val resolveInfos = pm.queryIntentActivities(huaweiProtectedAppsIntent, MATCH_DEFAULT_ONLY)
+        return resolveInfos.isNotEmpty()
+    }
+
+    /**
+     * Determine whether a Huawei "Protected apps" feature is available on the
+     * device.
+     */
+    @JvmStatic
+    public fun huaweiProtectedAppsNeedsToBeShown(context: Context): Boolean {
+        // "Protected apps" no longer exists on Huawei EMUI 5.0 (Android 7.0)
+        if (SDK_INT >= 24) return false
+        val pm = context.packageManager
+        val resolveInfos = pm.queryIntentActivities(huaweiPowerManagerIntent, MATCH_DEFAULT_ONLY)
+        return resolveInfos.isNotEmpty()
+    }
+
+    @JvmStatic
+    public val huaweiPowerManagerIntent: Intent = Intent().apply {
+        setClassName(PACKAGE_NAME_HUAWEI, CLASS_NAME_POWER_MANAGER)
+    }
+
+    @JvmStatic
+    public val huaweiProtectedAppsIntent: Intent = Intent().apply {
+        setClassName(PACKAGE_NAME_HUAWEI, CLASS_NAME_PROTECTED_APPS)
+    }
+
+    @JvmStatic
+    public val isXiaomiOrRedmiDevice: Boolean
+        get() = "Xiaomi".equals(Build.BRAND, ignoreCase = true) ||
+            "Redmi".equals(Build.BRAND, ignoreCase = true)
+
+    @JvmStatic
+    public val isMiuiTenOrLater: Boolean
+        get() {
+            var version = getSystemProperty("ro.miui.ui.version.name")
+            if (version == null || version == "") return false
+            version = version.replace("[^\\d]".toRegex(), "")
+            return try {
+                version.toInt() >= 10
+            } catch (e: NumberFormatException) {
+                false
+            }
+        }
+
+    private fun getSystemProperty(propName: String): String? {
+        return try {
+            val p = Runtime.getRuntime().exec("getprop $propName")
+            val s = Scanner(p.inputStream)
+            val line = s.nextLine()
+            s.close()
+            line
+        } catch (e: SecurityException) {
+            null
+        } catch (e: IOException) {
+            null
+        }
+    }
+}