diff --git a/.editorconfig b/.editorconfig
index 8e25e7b5..17f9425d 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -10,4 +10,5 @@ insert_final_newline = true
 end_of_line = lf
 
 # ktlint
-disabled_rules=no-wildcard-imports,import-ordering,max-line-length
+[*.{kt,kts}]
+ktlint_no-wildcard-imports = disabled
diff --git a/build.gradle b/build.gradle
index b28d0392..52cd9848 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,16 +1,17 @@
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
 // Top-level build file where you can add configuration options common to all sub-projects/modules.
 
 buildscript {
-    ext.kotlin_version = '1.7.10'
-    ext.ktlint_version = '0.44.0'
+    ext.kotlin_version = '1.8.10'
+    ext.ktlint_version = '0.48.2'
     ext.coroutines_version = '1.6.4'
-    ext.ktlint_gradle_version = '11.0.0'
-    // https://github.com/cashapp/sqldelight/issues/1574
-    ext.sqldelight_version = '1.5.2'
+    ext.ktlint_gradle_version = '11.3.1'
+    ext.sqldelight_version = '1.5.5'
     ext.nav_version = "2.5.3"
-    ext.fragment_version = "1.5.4"
-    ext.lifecycle_version = "2.5.1"
-    ext.dokka_version = "0.10.1"
+    ext.fragment_version = "1.5.5"
+    ext.lifecycle_version = "2.6.0"
+    ext.dokka_version = "1.8.10"
     repositories {
         google()
         mavenCentral()
@@ -23,13 +24,17 @@ buildscript {
         classpath "org.jlleitschuh.gradle:ktlint-gradle:$ktlint_gradle_version"
         classpath "com.squareup.sqldelight:gradle-plugin:$sqldelight_version"
         classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
-        classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files
     }
 }
 
+plugins {
+    id("org.jetbrains.dokka") version "$dokka_version"
+}
+
 allprojects {
+
     repositories {
         google()
         mavenCentral()
@@ -37,20 +42,20 @@ allprojects {
     }
 
     // Temp fix for issue https://github.com/mockk/mockk/issues/281
-    configurations.all {
+    configurations.configureEach {
         resolutionStrategy {
             force("org.objenesis:objenesis:2.6")
         }
     }
 }
 
-task clean(type: Delete) {
+tasks.register('clean', Delete) {
     delete rootProject.buildDir
 }
 
-tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
+tasks.withType(KotlinCompile).configureEach {
     kotlinOptions.freeCompilerArgs += [
-        "-opt-in=kotlin.Experimental,kotlin.ExperimentalUnsignedTypes",
-        "-opt-in=kotlin.RequiresOptIn"
+        "-opt-in=kotlin.ExperimentalUnsignedTypes,kotlin.RequiresOptIn",
     ]
+    kotlinOptions.jvmTarget = JavaVersion.VERSION_11.toString()
 }
diff --git a/demo-android/build.gradle b/demo-android/build.gradle
index 0dc5210b..eeb7e2b5 100644
--- a/demo-android/build.gradle
+++ b/demo-android/build.gradle
@@ -1,9 +1,12 @@
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-apply plugin: 'kotlin-android-extensions'
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+plugins {
+    id 'com.android.application'
+    id 'kotlin-android'
+}
 
 android {
-    compileSdkVersion 33
+    compileSdk 33
 
     defaultConfig {
         applicationId "nl.tudelft.ipv8.demo"
@@ -22,16 +25,10 @@ android {
         }
     }
 
-    // To inline the bytecode built with JVM target 1.8 into
-    // bytecode that is being built with JVM target 1.6. (e.g. navArgs)
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_11
         targetCompatibility JavaVersion.VERSION_11
     }
-    kotlinOptions {
-        jvmTarget = JavaVersion.VERSION_11.toString()
-        allWarningsAsErrors = true
-    }
 
     viewBinding {
         enabled = true
@@ -53,24 +50,23 @@ dependencies {
     implementation project(':ipv8-android')
 
     // AndroidX
-    implementation 'androidx.appcompat:appcompat:1.1.0'
-    implementation 'androidx.core:core-ktx:1.2.0'
-    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
-    implementation "androidx.recyclerview:recyclerview:1.1.0"
+    implementation 'androidx.appcompat:appcompat:1.6.1'
+    implementation 'androidx.core:core-ktx:1.9.0'
+    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+    implementation "androidx.recyclerview:recyclerview:1.3.0"
     implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
     implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
     implementation "androidx.fragment:fragment-ktx:$fragment_version"
-    implementation "androidx.preference:preference:1.1.0"
-    implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
+    implementation "androidx.preference:preference-ktx:1.2.0"
+    implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
     implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
     implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
     implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
 
     // Material
-    implementation 'com.google.android.material:material:1.1.0'
+    implementation 'com.google.android.material:material:1.8.0'
 
     // Kotlin
-    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
     implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
     implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
     implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
@@ -79,17 +75,18 @@ dependencies {
     implementation 'io.github.microutils:kotlin-logging:1.7.7'
     implementation 'com.github.tony19:logback-android:2.0.0'
 
-    implementation 'com.github.MattSkala:recyclerview-itemadapter:0.4'
+    implementation 'com.github.MattSkala:recyclerview-itemadapter:0.5'
 
     // Testing
-    testImplementation 'junit:junit:4.12'
+    testImplementation 'junit:junit:4.13.2'
     androidTestImplementation 'androidx.test.ext:junit:1.1.5'
-    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
 }
 
-tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
+tasks.withType(KotlinCompile).configureEach {
     kotlinOptions.freeCompilerArgs += [
-        "-opt-in=kotlin.Experimental,kotlin.ExperimentalUnsignedTypes",
-        "-opt-in=kotlin.RequiresOptIn"
+        "-opt-in=kotlin.ExperimentalUnsignedTypes,kotlin.RequiresOptIn",
     ]
+    kotlinOptions.jvmTarget = JavaVersion.VERSION_11.toString()
+    kotlinOptions.allWarningsAsErrors = true
 }
diff --git a/demo-android/src/main/AndroidManifest.xml b/demo-android/src/main/AndroidManifest.xml
index 4c1f2542..ac557a8f 100644
--- a/demo-android/src/main/AndroidManifest.xml
+++ b/demo-android/src/main/AndroidManifest.xml
@@ -9,6 +9,7 @@
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
+    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
 
     <application
         android:name="nl.tudelft.trustchain.demo.DemoApplication"
diff --git a/demo-android/src/main/java/nl/tudelft/trustchain/demo/ui/DemoActivity.kt b/demo-android/src/main/java/nl/tudelft/trustchain/demo/ui/DemoActivity.kt
index 190dd451..62cb7165 100644
--- a/demo-android/src/main/java/nl/tudelft/trustchain/demo/ui/DemoActivity.kt
+++ b/demo-android/src/main/java/nl/tudelft/trustchain/demo/ui/DemoActivity.kt
@@ -5,16 +5,19 @@ import android.widget.LinearLayout
 import androidx.appcompat.app.AppCompatActivity
 import androidx.core.content.res.ResourcesCompat
 import androidx.core.view.isVisible
+import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
 import androidx.recyclerview.widget.DividerItemDecoration
 import androidx.recyclerview.widget.LinearLayoutManager
 import com.mattskala.itemadapter.ItemAdapter
-import kotlinx.android.synthetic.main.fragment_peers.*
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.isActive
+import kotlinx.coroutines.launch
 import nl.tudelft.ipv8.android.IPv8Android
 import nl.tudelft.trustchain.demo.DemoCommunity
 import nl.tudelft.trustchain.demo.R
+import nl.tudelft.trustchain.demo.databinding.FragmentPeersBinding
 import nl.tudelft.trustchain.demo.ui.peers.AddressItem
 import nl.tudelft.trustchain.demo.ui.peers.AddressItemRenderer
 import nl.tudelft.trustchain.demo.ui.peers.PeerItem
@@ -22,11 +25,15 @@ import nl.tudelft.trustchain.demo.ui.peers.PeerItemRenderer
 
 class DemoActivity : AppCompatActivity() {
     private val adapter = ItemAdapter()
+    private lateinit var binding: FragmentPeersBinding
+
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
 
-        setContentView(R.layout.fragment_peers)
+        binding = FragmentPeersBinding.inflate(layoutInflater)
+        val view = binding.root
+        setContentView(view)
 
         adapter.registerRenderer(PeerItemRenderer {
             // NOOP
@@ -36,60 +43,62 @@ class DemoActivity : AppCompatActivity() {
             // NOOP
         })
 
-        recyclerView.adapter = adapter
-        recyclerView.layoutManager = LinearLayoutManager(this)
-        recyclerView.addItemDecoration(DividerItemDecoration(this, LinearLayout.VERTICAL))
+        binding.recyclerView.adapter = adapter
+        binding.recyclerView.layoutManager = LinearLayoutManager(this)
+        binding.recyclerView.addItemDecoration(DividerItemDecoration(this, LinearLayout.VERTICAL))
 
         loadNetworkInfo()
     }
 
     private fun loadNetworkInfo() {
-        lifecycleScope.launchWhenStarted {
-            while (isActive) {
-                val demoCommunity = IPv8Android.getInstance().getOverlay<DemoCommunity>()!!
-                val peers = demoCommunity.getPeers()
-
-                val discoveredAddresses = demoCommunity.network
-                    .getWalkableAddresses(demoCommunity.serviceId)
-
-                val discoveredBluetoothAddresses = demoCommunity.network
-                    .getNewBluetoothPeerCandidates()
-                    .map { it.address }
-
-                val peerItems = peers.map {
-                    PeerItem(
-                        it
-                    )
-                }
-
-                val addressItems = discoveredAddresses.map { address ->
-                    val contacted = demoCommunity.discoveredAddressesContacted[address]
-                    AddressItem(
-                        address,
-                        null,
-                        contacted
-                    )
-                }
-
-                val bluetoothAddressItems = discoveredBluetoothAddresses.map { address ->
-                    AddressItem(
-                        address,
-                        null,
-                        null
-                    )
+        lifecycleScope.launch {
+            repeatOnLifecycle(Lifecycle.State.STARTED) {
+                while (isActive) {
+                    val demoCommunity = IPv8Android.getInstance().getOverlay<DemoCommunity>()!!
+                    val peers = demoCommunity.getPeers()
+
+                    val discoveredAddresses = demoCommunity.network
+                        .getWalkableAddresses(demoCommunity.serviceId)
+
+                    val discoveredBluetoothAddresses = demoCommunity.network
+                        .getNewBluetoothPeerCandidates()
+                        .map { it.address }
+
+                    val peerItems = peers.map {
+                        PeerItem(
+                            it
+                        )
+                    }
+
+                    val addressItems = discoveredAddresses.map { address ->
+                        val contacted = demoCommunity.discoveredAddressesContacted[address]
+                        AddressItem(
+                            address,
+                            null,
+                            contacted
+                        )
+                    }
+
+                    val bluetoothAddressItems = discoveredBluetoothAddresses.map { address ->
+                        AddressItem(
+                            address,
+                            null,
+                            null
+                        )
+                    }
+
+                    val items = peerItems + bluetoothAddressItems + addressItems
+
+                    adapter.updateItems(items)
+                    binding.txtCommunityName.text = demoCommunity.javaClass.simpleName
+                    binding.txtPeerCount.text = getString(R.string.peers, peers.size)
+                    val textColorResId = if (peers.isNotEmpty()) R.color.green else R.color.red
+                    val textColor = ResourcesCompat.getColor(resources, textColorResId, null)
+                    binding.txtPeerCount.setTextColor(textColor)
+                    binding.imgEmpty.isVisible = items.isEmpty()
+
+                    delay(1000)
                 }
-
-                val items = peerItems + bluetoothAddressItems + addressItems
-
-                adapter.updateItems(items)
-                txtCommunityName.text = demoCommunity.javaClass.simpleName
-                txtPeerCount.text = "${peers.size} peers"
-                val textColorResId = if (peers.isNotEmpty()) R.color.green else R.color.red
-                val textColor = ResourcesCompat.getColor(resources, textColorResId, null)
-                txtPeerCount.setTextColor(textColor)
-                imgEmpty.isVisible = items.isEmpty()
-
-                delay(1000)
             }
         }
     }
diff --git a/demo-android/src/main/java/nl/tudelft/trustchain/demo/ui/peers/AddressItemRenderer.kt b/demo-android/src/main/java/nl/tudelft/trustchain/demo/ui/peers/AddressItemRenderer.kt
index 0a7dc724..d3b77db4 100644
--- a/demo-android/src/main/java/nl/tudelft/trustchain/demo/ui/peers/AddressItemRenderer.kt
+++ b/demo-android/src/main/java/nl/tudelft/trustchain/demo/ui/peers/AddressItemRenderer.kt
@@ -1,40 +1,34 @@
 package nl.tudelft.trustchain.demo.ui.peers
 
-import android.annotation.SuppressLint
-import android.view.View
 import androidx.core.view.isVisible
-import com.mattskala.itemadapter.ItemLayoutRenderer
-import kotlinx.android.synthetic.main.item_peer.view.*
-import nl.tudelft.trustchain.demo.R
+import com.mattskala.itemadapter.BindingItemRenderer
+import nl.tudelft.trustchain.demo.databinding.ItemPeerBinding
 import java.util.*
 import kotlin.math.roundToInt
 
 class AddressItemRenderer(
     private val onItemClick: (AddressItem) -> Unit
-) : ItemLayoutRenderer<AddressItem, View>(
-    AddressItem::class.java) {
-    @SuppressLint("SetTextI18n")
-    override fun bindView(item: AddressItem, view: View) = with(view) {
-        txtPeerId.text = "?"
-        txtAddress.text = item.address.toString()
+) : BindingItemRenderer<AddressItem, ItemPeerBinding>(
+    AddressItem::class.java,
+    ItemPeerBinding::inflate
+) {
+    override fun bindView(item: AddressItem, binding: ItemPeerBinding) {
+        binding.txtPeerId.text = "?"
+        binding.txtAddress.text = item.address.toString()
         val lastRequest = item.contacted
         val lastResponse = item.discovered
-        txtBluetoothAddress.isVisible = false
+        binding.txtBluetoothAddress.isVisible = false
 
-        txtLastSent.text = if (lastRequest != null)
+        binding.txtLastSent.text = if (lastRequest != null)
             "" + ((Date().time - lastRequest.time) / 1000.0).roundToInt() + " s" else "?"
 
-        txtLastReceived.text = if (lastResponse != null)
+        binding.txtLastReceived.text = if (lastResponse != null)
             "" + ((Date().time - lastResponse.time) / 1000.0).roundToInt() + " s" else "?"
 
-        txtAvgPing.text = "? ms"
+        binding.txtAvgPing.text = "? ms"
 
-        setOnClickListener {
+        binding.root.setOnClickListener {
             onItemClick(item)
         }
     }
-
-    override fun getLayoutResourceId(): Int {
-        return R.layout.item_peer
-    }
 }
diff --git a/demo-android/src/main/java/nl/tudelft/trustchain/demo/ui/peers/PeerItemRenderer.kt b/demo-android/src/main/java/nl/tudelft/trustchain/demo/ui/peers/PeerItemRenderer.kt
index d8fa7a57..5a6f60d7 100644
--- a/demo-android/src/main/java/nl/tudelft/trustchain/demo/ui/peers/PeerItemRenderer.kt
+++ b/demo-android/src/main/java/nl/tudelft/trustchain/demo/ui/peers/PeerItemRenderer.kt
@@ -1,43 +1,37 @@
 package nl.tudelft.trustchain.demo.ui.peers
 
-import android.annotation.SuppressLint
-import android.view.View
 import androidx.core.view.isVisible
-import com.mattskala.itemadapter.ItemLayoutRenderer
-import kotlinx.android.synthetic.main.item_peer.view.*
-import nl.tudelft.trustchain.demo.R
+import com.mattskala.itemadapter.BindingItemRenderer
+import nl.tudelft.trustchain.demo.databinding.ItemPeerBinding
 import java.util.*
 import kotlin.math.roundToInt
 
 class PeerItemRenderer(
     private val onItemClick: (PeerItem) -> Unit
-) : ItemLayoutRenderer<PeerItem, View>(
-    PeerItem::class.java) {
-    @SuppressLint("SetTextI18n")
-    override fun bindView(item: PeerItem, view: View) = with(view) {
-        txtPeerId.text = item.peer.mid
-        txtAddress.text = item.peer.address.toString()
-        txtAddress.isVisible = !item.peer.address.isEmpty()
-        txtBluetoothAddress.text = item.peer.bluetoothAddress?.toString()
-        txtBluetoothAddress.isVisible = item.peer.bluetoothAddress != null
+) : BindingItemRenderer<PeerItem, ItemPeerBinding>(
+    PeerItem::class.java,
+    ItemPeerBinding::inflate
+) {
+    override fun bindView(item: PeerItem, binding: ItemPeerBinding) {
+        binding.txtPeerId.text = item.peer.mid
+        binding.txtAddress.text = item.peer.address.toString()
+        binding.txtAddress.isVisible = !item.peer.address.isEmpty()
+        binding.txtBluetoothAddress.text = item.peer.bluetoothAddress?.toString()
+        binding.txtBluetoothAddress.isVisible = item.peer.bluetoothAddress != null
         val avgPing = item.peer.getAveragePing()
         val lastRequest = item.peer.lastRequest
         val lastResponse = item.peer.lastResponse
 
-        txtLastSent.text = if (lastRequest != null)
+        binding.txtLastSent.text = if (lastRequest != null)
             "" + ((Date().time - lastRequest.time) / 1000.0).roundToInt() + " s" else "?"
 
-        txtLastReceived.text = if (lastResponse != null)
+        binding.txtLastReceived.text = if (lastResponse != null)
             "" + ((Date().time - lastResponse.time) / 1000.0).roundToInt() + " s" else "?"
 
-        txtAvgPing.text = if (!avgPing.isNaN()) "" + (avgPing * 1000).roundToInt() + " ms" else "? ms"
+        binding.txtAvgPing.text =  if (!avgPing.isNaN()) "" + (avgPing * 1000).roundToInt() + " ms" else "? ms"
 
-        setOnClickListener {
+        binding.root.setOnClickListener {
             onItemClick(item)
         }
     }
-
-    override fun getLayoutResourceId(): Int {
-        return R.layout.item_peer
-    }
 }
diff --git a/demo-android/src/main/res/values/strings.xml b/demo-android/src/main/res/values/strings.xml
new file mode 100644
index 00000000..1e365a85
--- /dev/null
+++ b/demo-android/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="peers">%1$d peers</string>
+</resources>
diff --git a/demo-jvm/build.gradle b/demo-jvm/build.gradle
index bc3a2b60..4388f4d5 100644
--- a/demo-jvm/build.gradle
+++ b/demo-jvm/build.gradle
@@ -1,3 +1,5 @@
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
 apply plugin: 'application'
 
 apply plugin: 'kotlin'
@@ -9,7 +11,7 @@ dependencies {
 
     // Kotlin
     implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
-    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
+    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
     implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
 
     // Logging
@@ -21,3 +23,15 @@ dependencies {
 run {
     systemProperties System.getProperties()
 }
+
+java {
+    sourceCompatibility = JavaVersion.VERSION_11
+    targetCompatibility = JavaVersion.VERSION_11
+}
+
+tasks.withType(KotlinCompile).configureEach {
+    kotlinOptions.freeCompilerArgs += [
+        "-Werror" // Set Kotlin compiler warnings as errors
+    ]
+    kotlinOptions.jvmTarget = JavaVersion.VERSION_11.toString()
+}
diff --git a/ipv8-android/build.gradle b/ipv8-android/build.gradle
index fe959aeb..54540c0f 100644
--- a/ipv8-android/build.gradle
+++ b/ipv8-android/build.gradle
@@ -1,6 +1,7 @@
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
 apply plugin: 'com.android.library'
 apply plugin: 'kotlin-android'
-apply plugin: 'kotlin-android-extensions'
 apply plugin: 'org.jlleitschuh.gradle.ktlint'
 
 ktlint {
@@ -11,8 +12,7 @@ ktlint {
 }
 
 android {
-    compileSdkVersion 33
-
+    compileSdk 33
 
     defaultConfig {
         minSdkVersion 22
@@ -34,36 +34,35 @@ android {
         sourceCompatibility JavaVersion.VERSION_11
     }
 
-    kotlinOptions {
-        jvmTarget = JavaVersion.VERSION_11.toString()
-        allWarningsAsErrors = true
-        freeCompilerArgs += [
-            "-opt-in=kotlin.RequiresOptIn"
-        ]
-    }
     namespace 'nl.tudelft.ipv8.android'
+}
 
+tasks.withType(KotlinCompile).configureEach {
+    kotlinOptions.freeCompilerArgs += [
+        "-opt-in=kotlin.RequiresOptIn",
+        "-Werror" // Set Kotlin compiler warnings as errors
+    ]
+    kotlinOptions.jvmTarget = JavaVersion.VERSION_11.toString()
 }
 
 dependencies {
-    api (project(':ipv8')) {
+    api(project(':ipv8')) {
         exclude module: 'lazysodium-java'
     }
 
     // Kotlin
-    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
     implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
 
     // AndroidX
-    implementation 'androidx.appcompat:appcompat:1.1.0'
-    implementation 'androidx.core:core-ktx:1.2.0'
-    implementation "androidx.lifecycle:lifecycle-runtime:2.2.0"
+    implementation 'androidx.appcompat:appcompat:1.6.1'
+    implementation 'androidx.core:core-ktx:1.9.0'
+    implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.0"
     implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
-    implementation "androidx.lifecycle:lifecycle-common-java8:2.2.0"
+    implementation "androidx.lifecycle:lifecycle-common-java8:2.6.0"
 
     // Crypto
     implementation "com.goterl:lazysodium-android:5.0.1@aar"
-    implementation 'net.java.dev.jna:jna:5.5.0@aar'
+    implementation 'net.java.dev.jna:jna:5.12.1@aar'
 
     // BLE
     implementation 'no.nordicsemi.android:ble:2.2.0-alpha06'
@@ -73,7 +72,7 @@ dependencies {
     api "com.squareup.sqldelight:android-driver:$sqldelight_version"
     api "com.squareup.sqldelight:coroutines-extensions:$sqldelight_version"
 
-    testImplementation 'junit:junit:4.12'
+    testImplementation 'junit:junit:4.13.2'
     androidTestImplementation 'androidx.test.ext:junit:1.1.5'
-    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
 }
diff --git a/ipv8-android/src/androidTest/java/nl/tudelft/ipv8/android/ExampleInstrumentedTest.kt b/ipv8-android/src/androidTest/java/nl/tudelft/ipv8/android/ExampleInstrumentedTest.kt
index 5e193769..d9e5fdeb 100644
--- a/ipv8-android/src/androidTest/java/nl/tudelft/ipv8/android/ExampleInstrumentedTest.kt
+++ b/ipv8-android/src/androidTest/java/nl/tudelft/ipv8/android/ExampleInstrumentedTest.kt
@@ -1,13 +1,11 @@
 package nl.tudelft.ipv8.android
 
-import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.ext.junit.runners.AndroidJUnit4
-
+import androidx.test.platform.app.InstrumentationRegistry
+import org.junit.Assert.assertEquals
 import org.junit.Test
 import org.junit.runner.RunWith
 
-import org.junit.Assert.*
-
 /**
  * Instrumented test, which will execute on an Android device.
  *
diff --git a/ipv8-android/src/main/java/nl/tudelft/ipv8/android/IPv8Android.kt b/ipv8-android/src/main/java/nl/tudelft/ipv8/android/IPv8Android.kt
index e42357e0..35dd424a 100644
--- a/ipv8-android/src/main/java/nl/tudelft/ipv8/android/IPv8Android.kt
+++ b/ipv8-android/src/main/java/nl/tudelft/ipv8/android/IPv8Android.kt
@@ -7,6 +7,7 @@ import android.content.Intent
 import android.net.ConnectivityManager
 import android.os.Build
 import androidx.core.content.getSystemService
+import java.net.InetAddress
 import nl.tudelft.ipv8.IPv8
 import nl.tudelft.ipv8.IPv8Configuration
 import nl.tudelft.ipv8.Peer
@@ -24,7 +25,6 @@ import nl.tudelft.ipv8.keyvault.defaultCryptoProvider
 import nl.tudelft.ipv8.messaging.EndpointAggregator
 import nl.tudelft.ipv8.peerdiscovery.Network
 import nl.tudelft.ipv8.util.defaultEncodingUtils
-import java.net.InetAddress
 
 object IPv8Android {
     private var ipv8: IPv8? = null
@@ -35,7 +35,7 @@ object IPv8Android {
     }
 
     class Factory(
-        private val application: Application,
+        private val application: Application
     ) {
 
         private var privateKey: PrivateKey? = null
@@ -126,9 +126,19 @@ object IPv8Android {
             val bleScanner = IPv8BluetoothLeScanner(bluetoothManager, network)
             val bluetoothEndpoint = if (
                 bluetoothManager.adapter != null && Build.VERSION.SDK_INT >= 24
-            ) BluetoothLeEndpoint(
-                application, bluetoothManager, gattServer, bleAdvertiser, bleScanner, network, myPeer
-            ) else null
+            ) {
+                BluetoothLeEndpoint(
+                    application,
+                    bluetoothManager,
+                    gattServer,
+                    bleAdvertiser,
+                    bleScanner,
+                    network,
+                    myPeer
+                )
+            } else {
+                null
+            }
 
             val endpointAggregator = EndpointAggregator(
                 udpEndpoint,
diff --git a/ipv8-android/src/main/java/nl/tudelft/ipv8/android/messaging/bluetooth/GattClientManager.kt b/ipv8-android/src/main/java/nl/tudelft/ipv8/android/messaging/bluetooth/GattClientManager.kt
index 5a3f75f3..8bae4c73 100644
--- a/ipv8-android/src/main/java/nl/tudelft/ipv8/android/messaging/bluetooth/GattClientManager.kt
+++ b/ipv8-android/src/main/java/nl/tudelft/ipv8/android/messaging/bluetooth/GattClientManager.kt
@@ -46,8 +46,12 @@ class GattClientManager(context: Context) : BleManager<GattClientCallbacks>(cont
 
             val gattService = gatt.getService(GattServerManager.SERVICE_UUID)
             return if (gattService != null) {
-                writeCharacteristic = gattService.getCharacteristic(GattServerManager.WRITE_CHARACTERISTIC_UUID)
-                identityCharacteristic = gattService.getCharacteristic(GattServerManager.IDENTITY_CHARACTERISTIC_UUID)
+                writeCharacteristic = gattService.getCharacteristic(
+                    GattServerManager.WRITE_CHARACTERISTIC_UUID
+                )
+                identityCharacteristic = gattService.getCharacteristic(
+                    GattServerManager.IDENTITY_CHARACTERISTIC_UUID
+                )
                 true
             } else {
                 false
diff --git a/ipv8-android/src/main/java/nl/tudelft/ipv8/android/messaging/bluetooth/GattServerManager.kt b/ipv8-android/src/main/java/nl/tudelft/ipv8/android/messaging/bluetooth/GattServerManager.kt
index b3593c8d..a68176dc 100644
--- a/ipv8-android/src/main/java/nl/tudelft/ipv8/android/messaging/bluetooth/GattServerManager.kt
+++ b/ipv8-android/src/main/java/nl/tudelft/ipv8/android/messaging/bluetooth/GattServerManager.kt
@@ -4,9 +4,9 @@ import android.bluetooth.BluetoothGattCharacteristic
 import android.bluetooth.BluetoothGattService
 import android.content.Context
 import android.util.Log
+import java.util.*
 import nl.tudelft.ipv8.Peer
 import no.nordicsemi.android.ble.BleServerManager
-import java.util.*
 
 class GattServerManager(
     context: Context,
diff --git a/ipv8-android/src/main/java/nl/tudelft/ipv8/android/messaging/bluetooth/IPv8BluetoothLeScanner.kt b/ipv8-android/src/main/java/nl/tudelft/ipv8/android/messaging/bluetooth/IPv8BluetoothLeScanner.kt
index e2fc0818..1581441b 100644
--- a/ipv8-android/src/main/java/nl/tudelft/ipv8/android/messaging/bluetooth/IPv8BluetoothLeScanner.kt
+++ b/ipv8-android/src/main/java/nl/tudelft/ipv8/android/messaging/bluetooth/IPv8BluetoothLeScanner.kt
@@ -4,13 +4,13 @@ import android.annotation.SuppressLint
 import android.bluetooth.BluetoothManager
 import android.bluetooth.le.*
 import android.os.ParcelUuid
+import java.lang.Exception
 import kotlinx.coroutines.*
 import mu.KotlinLogging
 import nl.tudelft.ipv8.android.messaging.bluetooth.GattServerManager.Companion.SERVICE_UUID
 import nl.tudelft.ipv8.messaging.bluetooth.BluetoothAddress
 import nl.tudelft.ipv8.messaging.bluetooth.BluetoothPeerCandidate
 import nl.tudelft.ipv8.peerdiscovery.Network
-import java.lang.Exception
 
 private val logger = KotlinLogging.logger {}
 
diff --git a/ipv8-android/src/main/java/nl/tudelft/ipv8/android/messaging/udp/UdpEndpoint.kt b/ipv8-android/src/main/java/nl/tudelft/ipv8/android/messaging/udp/UdpEndpoint.kt
index a56e82e3..c3549d37 100644
--- a/ipv8-android/src/main/java/nl/tudelft/ipv8/android/messaging/udp/UdpEndpoint.kt
+++ b/ipv8-android/src/main/java/nl/tudelft/ipv8/android/messaging/udp/UdpEndpoint.kt
@@ -7,7 +7,8 @@ import android.os.Build
 import mu.KotlinLogging
 import nl.tudelft.ipv8.IPv4Address
 import nl.tudelft.ipv8.messaging.udp.UdpEndpoint
-import java.net.*
+import java.net.Inet4Address
+import java.net.InetAddress
 
 private val logger = KotlinLogging.logger {}
 
@@ -23,7 +24,10 @@ class AndroidUdpEndpoint(
             logger.debug("onLinkPropertiesChanged " + linkProperties.linkAddresses)
             for (linkAddress in linkProperties.linkAddresses) {
                 if (linkAddress.address is Inet4Address && !linkAddress.address.isLoopbackAddress) {
-                    val estimatedAddress = IPv4Address(linkAddress.address.hostAddress!!, getSocketPort())
+                    val estimatedAddress = IPv4Address(
+                        linkAddress.address.hostAddress!!,
+                        getSocketPort()
+                    )
                     setEstimatedLan(estimatedAddress)
                 }
             }
diff --git a/ipv8-android/src/main/java/nl/tudelft/ipv8/android/peerdiscovery/NetworkServiceDiscovery.kt b/ipv8-android/src/main/java/nl/tudelft/ipv8/android/peerdiscovery/NetworkServiceDiscovery.kt
index 13d59aad..416a047a 100644
--- a/ipv8-android/src/main/java/nl/tudelft/ipv8/android/peerdiscovery/NetworkServiceDiscovery.kt
+++ b/ipv8-android/src/main/java/nl/tudelft/ipv8/android/peerdiscovery/NetworkServiceDiscovery.kt
@@ -2,12 +2,12 @@ package nl.tudelft.ipv8.android.peerdiscovery
 
 import android.net.nsd.NsdManager
 import android.net.nsd.NsdServiceInfo
+import kotlin.random.Random
 import mu.KotlinLogging
 import nl.tudelft.ipv8.IPv4Address
 import nl.tudelft.ipv8.Overlay
 import nl.tudelft.ipv8.messaging.Packet
 import nl.tudelft.ipv8.peerdiscovery.strategy.DiscoveryStrategy
-import kotlin.random.Random
 
 private val logger = KotlinLogging.logger {}
 
diff --git a/ipv8-android/src/main/java/nl/tudelft/ipv8/android/service/IPv8Service.kt b/ipv8-android/src/main/java/nl/tudelft/ipv8/android/service/IPv8Service.kt
index 231f7dde..9b1de0f8 100644
--- a/ipv8-android/src/main/java/nl/tudelft/ipv8/android/service/IPv8Service.kt
+++ b/ipv8-android/src/main/java/nl/tudelft/ipv8/android/service/IPv8Service.kt
@@ -12,23 +12,20 @@ import android.os.Build.VERSION.SDK_INT
 import android.os.IBinder
 import androidx.core.app.NotificationCompat
 import androidx.core.content.getSystemService
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.LifecycleObserver
-import androidx.lifecycle.OnLifecycleEvent
-import androidx.lifecycle.ProcessLifecycleOwner
+import androidx.lifecycle.*
+import kotlin.system.exitProcess
 import kotlinx.coroutines.*
 import nl.tudelft.ipv8.*
 import nl.tudelft.ipv8.android.IPv8Android
 import nl.tudelft.ipv8.android.R
-import kotlin.system.exitProcess
 
-open class IPv8Service : Service(), LifecycleObserver {
+open class IPv8Service : Service(), DefaultLifecycleObserver {
     private val scope = CoroutineScope(Dispatchers.Default)
 
     private var isForeground = false
 
     override fun onCreate() {
-        super.onCreate()
+        super<Service>.onCreate()
 
         createNotificationChannel()
         showForegroundNotification()
@@ -50,20 +47,28 @@ open class IPv8Service : Service(), LifecycleObserver {
             .lifecycle
             .removeObserver(this)
 
-        super.onDestroy()
+        super<Service>.onDestroy()
 
         // We need to kill the app as IPv8 is started in Application.onCreate
         exitProcess(0)
     }
 
-    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
-    fun onBackground() {
+    override fun onStop(owner: LifecycleOwner) {
+        super.onStop(owner)
+        onBackground()
+    }
+
+    override fun onStart(owner: LifecycleOwner) {
+        super<DefaultLifecycleObserver>.onStart(owner)
+        onForeground()
+    }
+
+    private fun onBackground() {
         isForeground = false
         showForegroundNotification()
     }
 
-    @OnLifecycleEvent(Lifecycle.Event.ON_START)
-    fun onForeground() {
+    private fun onForeground() {
         isForeground = true
         showForegroundNotification()
     }
@@ -94,7 +99,9 @@ open class IPv8Service : Service(), LifecycleObserver {
         }
         val cancelPendingIntent = PendingIntent.getBroadcast(
             applicationContext,
-            0, cancelBroadcastIntent, flags
+            0,
+            cancelBroadcastIntent,
+            flags
         )
 
         val builder = createNotification()
diff --git a/ipv8-android/src/test/java/nl/tudelft/ipv8/android/ExampleUnitTest.kt b/ipv8-android/src/test/java/nl/tudelft/ipv8/android/ExampleUnitTest.kt
index d71cad35..1edf9e21 100644
--- a/ipv8-android/src/test/java/nl/tudelft/ipv8/android/ExampleUnitTest.kt
+++ b/ipv8-android/src/test/java/nl/tudelft/ipv8/android/ExampleUnitTest.kt
@@ -1,9 +1,8 @@
 package nl.tudelft.ipv8.android
 
+import org.junit.Assert.assertEquals
 import org.junit.Test
 
-import org.junit.Assert.*
-
 /**
  * Example local unit test, which will execute on the development machine (host).
  *
diff --git a/ipv8-jvm/build.gradle b/ipv8-jvm/build.gradle
index 2b0dc684..5260f1da 100644
--- a/ipv8-jvm/build.gradle
+++ b/ipv8-jvm/build.gradle
@@ -1,3 +1,5 @@
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
 apply plugin: 'kotlin'
 
 apply plugin: 'java-library'
@@ -5,7 +7,16 @@ apply plugin: 'java-library'
 dependencies {
     api project(':ipv8')
 
-    implementation "net.java.dev.jna:jna:5.5.0"
+    implementation "net.java.dev.jna:jna:5.12.1"
     implementation 'org.slf4j:slf4j-simple:2.0.6'
     implementation "com.squareup.sqldelight:sqlite-driver:$sqldelight_version"
 }
+
+java {
+    sourceCompatibility = JavaVersion.VERSION_11
+    targetCompatibility = JavaVersion.VERSION_11
+}
+
+tasks.withType(KotlinCompile).configureEach {
+    kotlinOptions.jvmTarget = JavaVersion.VERSION_11.toString()
+}
diff --git a/ipv8/build.gradle b/ipv8/build.gradle
index e22116d6..7745a951 100644
--- a/ipv8/build.gradle
+++ b/ipv8/build.gradle
@@ -1,18 +1,16 @@
-apply plugin: 'kotlin'
-
-apply plugin: 'java-library'
-
-apply plugin: 'jacoco'
-
-apply plugin: 'org.jetbrains.dokka'
-
-apply plugin: 'org.jlleitschuh.gradle.ktlint'
-
-apply plugin: 'com.squareup.sqldelight'
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+plugins {
+    id 'kotlin'
+    id 'java-library'
+    id 'jacoco'
+    id 'org.jetbrains.dokka'
+    id 'org.jlleitschuh.gradle.ktlint'
+    id 'com.squareup.sqldelight'
+}
 
-dokka {
-    outputFormat = 'html'
-    outputDirectory = "$buildDir/dokka"
+dokkaHtml {
+    outputDirectory.set(file("$buildDir/dokka"))
 }
 
 sqldelight {
@@ -61,7 +59,7 @@ dependencies {
     implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
 
     // Network utils
-    implementation 'commons-net:commons-net:3.6'
+    implementation 'commons-net:commons-net:3.9.0'
 
     // Crypto
     implementation "com.goterl:lazysodium-java:5.1.4"
@@ -70,24 +68,28 @@ dependencies {
     implementation 'io.github.microutils:kotlin-logging:1.7.7'
 
     // JSON
-    implementation 'org.json:json:20201115'
+    implementation 'org.json:json:20220320'
 
     // Testing
-    testImplementation 'junit:junit:4.12'
-    testImplementation "io.mockk:mockk:1.9.3"
+    testImplementation 'junit:junit:4.13.2'
+    testImplementation "io.mockk:mockk:1.10.4"
     testImplementation "com.squareup.sqldelight:sqlite-driver:$sqldelight_version"
     testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
 
 
     // https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on
-    implementation group: 'org.bouncycastle', name: 'bcprov-jdk15to18', version: '1.63'
-
-
+    implementation group: 'org.bouncycastle', name: 'bcprov-jdk15to18', version: '1.70'
 }
 
-tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
+tasks.withType(KotlinCompile).configureEach {
     kotlinOptions.freeCompilerArgs += [
-        "-opt-in=kotlin.Experimental,kotlin.ExperimentalUnsignedTypes",
+        "-opt-in=kotlin.ExperimentalUnsignedTypes",
         "-Werror" // Set Kotlin compiler warnings as errors
     ]
+    kotlinOptions.jvmTarget = JavaVersion.VERSION_11.toString()
+}
+
+java {
+    sourceCompatibility = JavaVersion.VERSION_11
+    targetCompatibility = JavaVersion.VERSION_11
 }
diff --git a/ipv8/src/main/sqldelight/nl/tudelft/ipv8/sqldelight/DbBlock.sq b/ipv8/src/main/sqldelight/nl/tudelft/ipv8/sqldelight/DbBlock.sq
index 4c7cceac..ef2a49ee 100644
--- a/ipv8/src/main/sqldelight/nl/tudelft/ipv8/sqldelight/DbBlock.sq
+++ b/ipv8/src/main/sqldelight/nl/tudelft/ipv8/sqldelight/DbBlock.sq
@@ -39,10 +39,10 @@ SELECT * FROM blocks WHERE public_key = ? AND sequence_number =
 (SELECT MAX(sequence_number) FROM blocks WHERE public_key = ?) LIMIT 1;
 
 getLatestBlocksWithTypes:
-SELECT * FROM blocks WHERE public_key = ? AND type IN (?) ORDER BY sequence_number DESC LIMIT ?;
+SELECT * FROM blocks WHERE public_key = ? AND type IN (?) ORDER BY sequence_number DESC LIMIT :rowNumbers;
 
 getLatestBlocks:
-SELECT * FROM blocks WHERE public_key = ? ORDER BY sequence_number DESC LIMIT ?;
+SELECT * FROM blocks WHERE public_key = ? ORDER BY sequence_number DESC LIMIT :rowNumbers;
 
 getBlockAfterWithType:
 SELECT * FROM blocks WHERE sequence_number > ? AND public_key = ? AND type = ?
@@ -82,25 +82,25 @@ SELECT * FROM
     (SELECT * FROM blocks WHERE
         sequence_number >= ? AND
         sequence_number <= ? AND
-        public_key = ? LIMIT ?)
+        public_key = ? LIMIT :rowNumbers1)
 UNION
 SELECT * FROM
     (SELECT * FROM blocks WHERE
         link_sequence_number >= ? AND
         link_sequence_number <= ? AND
         link_sequence_number != 0 AND
-        link_public_key = ? LIMIT ?);
+        link_public_key = ? LIMIT :rowNumbers2);
 
 getRecentBlocks:
-SELECT * FROM blocks ORDER BY block_timestamp DESC LIMIT ? OFFSET ?;
+SELECT * FROM blocks ORDER BY block_timestamp DESC LIMIT :rowNumbers OFFSET :offset;
 
 getUsers:
 SELECT DISTINCT public_key, MAX(sequence_number) FROM blocks GROUP BY public_key
-ORDER BY MAX(sequence_number) DESC LIMIT ?;
+ORDER BY MAX(sequence_number) DESC LIMIT :rowNumbers;
 
 getMutualBlocks:
 SELECT * FROM blocks WHERE public_key = ? OR link_public_key = ?
-ORDER BY block_timestamp DESC LIMIT ?;
+ORDER BY block_timestamp DESC LIMIT :rowNumbers;
 
 getBlockCountWithPublicKey:
 SELECT COUNT(*) FROM blocks WHERE public_key = ?;
diff --git a/tracker/build.gradle b/tracker/build.gradle
index 009e1c43..11b9bee7 100644
--- a/tracker/build.gradle
+++ b/tracker/build.gradle
@@ -1,3 +1,5 @@
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
 apply plugin: 'application'
 
 apply plugin: 'kotlin'
@@ -9,19 +11,25 @@ dependencies {
 
     // Kotlin
     implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
-    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
+    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
     implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
 
     // Logging
     implementation 'io.github.microutils:kotlin-logging:1.7.7'
 }
 
-tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
+tasks.withType(KotlinCompile).configureEach {
     kotlinOptions.freeCompilerArgs += [
-        "-opt-in=kotlin.Experimental,kotlin.ExperimentalUnsignedTypes"
+        "-opt-in=kotlin.ExperimentalUnsignedTypes"
     ]
+    kotlinOptions.jvmTarget = JavaVersion.VERSION_11.toString()
 }
 
 run {
     systemProperties System.getProperties()
 }
+
+java {
+    sourceCompatibility = JavaVersion.VERSION_11
+    targetCompatibility = JavaVersion.VERSION_11
+}