diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index ced0de8aba4c885ef2a603be567aeb27512e6a9d..079b23acad3b26e46063e85c03ce33666faf950f 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -35,9 +35,6 @@
       <option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
       <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
     </JetCodeStyleSettings>
-    <XML>
-      <option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
-    </XML>
     <codeStyleSettings language="Groovy">
       <indentOptions>
         <option name="USE_TAB_CHARACTER" value="true" />
diff --git a/bramble-android/build.gradle b/bramble-android/build.gradle
index f23cb213b765ce48d878c00a8d192737023ca01c..e6761ac2f1d77c38c53ab005655f7122308bd6fa 100644
--- a/bramble-android/build.gradle
+++ b/bramble-android/build.gradle
@@ -5,8 +5,8 @@ apply plugin: 'witness'
 apply from: 'witness.gradle'
 
 android {
-	compileSdkVersion 30
-	buildToolsVersion '30.0.3'
+	compileSdkVersion 33
+	buildToolsVersion '33.0.0'
 
 	packagingOptions {
 		doNotStrip '**/*.so'
@@ -14,12 +14,13 @@ android {
 
 	defaultConfig {
 		minSdkVersion 16
-		targetSdkVersion 30
+		targetSdkVersion 31
 		versionCode 10415
 		versionName "1.4.15"
 		consumerProguardFiles 'proguard-rules.txt'
 
 		testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+		testInstrumentationRunnerArguments disableAnalytics: 'true'
 	}
 
 	compileOptions {
diff --git a/bramble-android/src/main/AndroidManifest.xml b/bramble-android/src/main/AndroidManifest.xml
index 9a4bd9810c28b97b47a029d928d2590c669e904e..d1aebe349908420397b42fffec1f1c2f1d836887 100644
--- a/bramble-android/src/main/AndroidManifest.xml
+++ b/bramble-android/src/main/AndroidManifest.xml
@@ -1,15 +1,25 @@
-<manifest
-	package="org.briarproject.bramble"
-	xmlns:android="http://schemas.android.com/apk/res/android">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+	package="org.briarproject.bramble">
 
-	<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
+	<uses-feature
+		android:name="android.hardware.bluetooth"
+		android:required="false" />
 
-	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
-	<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
-	<uses-permission android:name="android.permission.BLUETOOTH"/>
-	<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
-	<uses-permission android:name="android.permission.INTERNET"/>
-	<uses-permission android:name="android.permission.WAKE_LOCK"/>
+	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+	<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+	<uses-permission
+		android:name="android.permission.BLUETOOTH"
+		android:maxSdkVersion="30" />
+	<uses-permission
+		android:name="android.permission.BLUETOOTH_ADMIN"
+		android:maxSdkVersion="30" />
+	<uses-permission
+		android:name="android.permission.BLUETOOTH_SCAN"
+		android:usesPermissionFlags="neverForLocation" />
+	<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
+	<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
+	<uses-permission android:name="android.permission.INTERNET" />
+	<uses-permission android:name="android.permission.WAKE_LOCK" />
 
 	<application
 		android:allowBackup="false"
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPlugin.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPlugin.java
index 70f0229cf9a26371629d3417feb8b242d06f8896..f2d8c02ad1bad892405961bac37628521d66a06e 100644
--- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPlugin.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPlugin.java
@@ -55,6 +55,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 import static java.util.logging.Logger.getLogger;
+import static org.briarproject.bramble.util.AndroidUtils.hasBtConnectPermission;
 import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
 
 @MethodsNotNullByDefault
@@ -97,6 +98,11 @@ class AndroidBluetoothPlugin extends
 		this.clock = clock;
 	}
 
+	@Override
+	protected boolean isBluetoothAccessible() {
+		return hasBtConnectPermission(app);
+	}
+
 	@Override
 	public void start() throws PluginException {
 		super.start();
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSecureRandomProvider.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSecureRandomProvider.java
index 0f7ad28351cc93754d569553bdcfbbe1b8cf12ff..b6c0c87da12c11a55d11d6edb735012e38495e14 100644
--- a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSecureRandomProvider.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSecureRandomProvider.java
@@ -6,7 +6,6 @@ import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.os.Build;
 import android.os.Parcel;
 import android.os.StrictMode;
 import android.provider.Settings;
@@ -15,12 +14,19 @@ import org.briarproject.nullsafety.NotNullByDefault;
 
 import java.io.DataOutputStream;
 import java.io.IOException;
+import java.util.Set;
 
 import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
 
+import static android.os.Build.FINGERPRINT;
+import static android.os.Build.SERIAL;
 import static android.os.Build.VERSION.SDK_INT;
+import static android.os.Process.myPid;
+import static android.os.Process.myTid;
+import static android.os.Process.myUid;
 import static android.provider.Settings.Secure.ANDROID_ID;
+import static org.briarproject.bramble.util.AndroidUtils.hasBtConnectPermission;
 
 @Immutable
 @NotNullByDefault
@@ -39,22 +45,27 @@ class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
 	@Override
 	protected void writeToEntropyPool(DataOutputStream out) throws IOException {
 		super.writeToEntropyPool(out);
-		out.writeInt(android.os.Process.myPid());
-		out.writeInt(android.os.Process.myTid());
-		out.writeInt(android.os.Process.myUid());
-		if (Build.FINGERPRINT != null) out.writeUTF(Build.FINGERPRINT);
-		if (Build.SERIAL != null) out.writeUTF(Build.SERIAL);
+		out.writeInt(myPid());
+		out.writeInt(myTid());
+		out.writeInt(myUid());
+		if (FINGERPRINT != null) out.writeUTF(FINGERPRINT);
+		if (SERIAL != null) out.writeUTF(SERIAL);
 		ContentResolver contentResolver = appContext.getContentResolver();
 		String id = Settings.Secure.getString(contentResolver, ANDROID_ID);
 		if (id != null) out.writeUTF(id);
-		Parcel parcel = Parcel.obtain();
-		BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
-		if (bt != null) {
-			for (BluetoothDevice device : bt.getBondedDevices())
-				parcel.writeParcelable(device, 0);
+		// use bluetooth paired devices as well, if allowed
+		if (hasBtConnectPermission(appContext)) {
+			Parcel parcel = Parcel.obtain();
+			BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
+			if (bt != null) {
+				@SuppressLint("MissingPermission")
+				Set<BluetoothDevice> deviceSet = bt.getBondedDevices();
+				for (BluetoothDevice device : deviceSet)
+					parcel.writeParcelable(device, 0);
+			}
+			out.write(parcel.marshall());
+			parcel.recycle();
 		}
-		out.write(parcel.marshall());
-		parcel.recycle();
 	}
 
 	@Override
@@ -77,7 +88,7 @@ class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
 					.invoke(null, (Object) seed);
 			// Mix the output of the Linux PRNG into the OpenSSL PRNG
 			int bytesRead = (Integer) Class.forName(
-					"org.apache.harmony.xnet.provider.jsse.NativeCrypto")
+							"org.apache.harmony.xnet.provider.jsse.NativeCrypto")
 					.getMethod("RAND_load_file", String.class, long.class)
 					.invoke(null, "/dev/urandom", 1024);
 			if (bytesRead != 1024) throw new IOException();
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidTaskScheduler.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidTaskScheduler.java
index b57a91d1f5b0853bebda29f3cd67956ce58ba10c..92fb8c4d594195fb20a0fd2b0172801e719a1541 100644
--- a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidTaskScheduler.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidTaskScheduler.java
@@ -41,6 +41,7 @@ import static java.util.logging.Level.INFO;
 import static java.util.logging.Logger.getLogger;
 import static org.briarproject.bramble.system.AlarmConstants.EXTRA_PID;
 import static org.briarproject.bramble.system.AlarmConstants.REQUEST_ALARM;
+import static org.briarproject.bramble.util.AndroidUtils.getImmutableFlags;
 
 @ThreadSafe
 @NotNullByDefault
@@ -199,7 +200,7 @@ class AndroidTaskScheduler implements TaskScheduler, Service, AlarmListener {
 		Intent i = new Intent(app, AlarmReceiver.class);
 		i.putExtra(EXTRA_PID, android.os.Process.myPid());
 		return PendingIntent.getBroadcast(app, REQUEST_ALARM, i,
-				FLAG_CANCEL_CURRENT);
+				getImmutableFlags(FLAG_CANCEL_CURRENT));
 	}
 
 	private class ScheduledTask
diff --git a/bramble-android/src/main/java/org/briarproject/bramble/util/AndroidUtils.java b/bramble-android/src/main/java/org/briarproject/bramble/util/AndroidUtils.java
index 7e3adef92572d267b17409ad3ae533ad63f49e30..a3a64fa9d3d0f35d58bc5e09e126f5c5c5f5fce8 100644
--- a/bramble-android/src/main/java/org/briarproject/bramble/util/AndroidUtils.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/util/AndroidUtils.java
@@ -22,8 +22,13 @@ import java.util.Scanner;
 
 import javax.annotation.Nullable;
 
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.app.PendingIntent.FLAG_IMMUTABLE;
 import static android.content.Context.MODE_PRIVATE;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.Build.VERSION.SDK_INT;
+import static android.os.Process.myPid;
+import static android.os.Process.myUid;
 import static java.lang.Runtime.getRuntime;
 import static java.util.Arrays.asList;
 import static org.briarproject.nullsafety.NullSafety.requireNonNull;
@@ -48,6 +53,11 @@ public class AndroidUtils {
 		return abis;
 	}
 
+	public static boolean hasBtConnectPermission(Context ctx) {
+		return SDK_INT < 31 || ctx.checkPermission(BLUETOOTH_CONNECT, myPid(),
+				myUid()) == PERMISSION_GRANTED;
+	}
+
 	public static String getBluetoothAddress(Context ctx,
 			BluetoothAdapter adapter) {
 		return getBluetoothAddressAndMethod(ctx, adapter).getFirst();
@@ -139,4 +149,11 @@ public class AndroidUtils {
 	public static boolean isUiThread() {
 		return Looper.myLooper() == Looper.getMainLooper();
 	}
+
+	public static int getImmutableFlags(int flags) {
+		if (SDK_INT >= 23) {
+			return FLAG_IMMUTABLE | flags;
+		}
+		return flags;
+	}
 }
diff --git a/bramble-android/witness.gradle b/bramble-android/witness.gradle
index 180fa06d80a212ab93de7e5d081561d628d2898f..788a6185bfc5109af7596b6c10c1b9b1887e8e56 100644
--- a/bramble-android/witness.gradle
+++ b/bramble-android/witness.gradle
@@ -2,164 +2,58 @@ dependencyVerification {
     verify = [
         'androidx.annotation:annotation:1.5.0:annotation-1.5.0.jar:261fb7c0210858500bab66d34354972a75166ab4182add283780b05513d6ec4a',
         'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
-        'com.android.tools.analytics-library:protos:30.0.3:protos-30.0.3.jar:f62b89dcd9de719c6a7b7e15fb1dd20e45b57222e675cf633607bd0ed6bca7e7',
-        'com.android.tools.analytics-library:shared:30.0.3:shared-30.0.3.jar:05aa9ba3cc890354108521fdf99802565aae5dd6ca44a6ac8bb8d594d1c1cd15',
-        'com.android.tools.analytics-library:tracker:30.0.3:tracker-30.0.3.jar:5d0ef35bf6733e96210b5085a2a202152921bf834d345959dce1ca3369b528df',
-        'com.android.tools.build:aapt2-proto:4.1.0-alpha01-6193524:aapt2-proto-4.1.0-alpha01-6193524.jar:17e75523e1e92dd4f222c7368ee41df9e964a508232f591e265d0c499baf9dca',
-        'com.android.tools.build:apksig:7.0.3:apksig-7.0.3.jar:012337a2803c9a30dfc41dcbc6450686ee9e5f582549f7f126479f743a343ec9',
-        'com.android.tools.build:apkzlib:7.0.3:apkzlib-7.0.3.jar:b31e53174c92db83c5cc6e7dac6734ea4e907a72e452c2bf1818dfd082c59397',
-        'com.android.tools.build:builder-model:7.0.3:builder-model-7.0.3.jar:483f99d7494a5bed027e1e8d29111384cf535d4842f0be5a79805bd44bb68d4e',
-        'com.android.tools.build:builder-test-api:7.0.3:builder-test-api-7.0.3.jar:f6de4bc2cef545e8367bf82d7c733829c7be3b0b3b8b09fd8c58f2150e59ab46',
-        'com.android.tools.build:builder:7.0.3:builder-7.0.3.jar:c6952da0094b094c2ba0fe84c675622097c5d9b9f9beb53485b860320540cf1d',
-        'com.android.tools.build:manifest-merger:30.0.3:manifest-merger-30.0.3.jar:72b346ba6318b4b6260e6e49df4bea5da2e12329ab6c2beb2269c49a9f51f178',
-        'com.android.tools.ddms:ddmlib:30.0.3:ddmlib-30.0.3.jar:7a914a68ab93393657297234e2f37b22410ae9a433cba692ce8c727c9607e3bb',
-        'com.android.tools.external.com-intellij:intellij-core:30.0.3:intellij-core-30.0.3.jar:1ebe858d3f58eeaa8c06507f8ac0f1c7051e6c61f35a70f3c3967d5734d3abc5',
-        'com.android.tools.external.com-intellij:kotlin-compiler:30.0.3:kotlin-compiler-30.0.3.jar:ed00e441f427cb4e0d418287b9da30b12b7f735f9af32e6b5d3dc960b6a742fc',
-        'com.android.tools.external.org-jetbrains:uast:30.0.3:uast-30.0.3.jar:a77801bee6ff509910e459525c9c34d7f04b066ade123547f16f1917548eadea',
-        'com.android.tools.layoutlib:layoutlib-api:30.0.3:layoutlib-api-30.0.3.jar:4caa87e9ca2e11315f650d576cd59fec1793373bc3fca3f6d53c029e7534e7c4',
-        'com.android.tools.lint:lint-api:30.0.3:lint-api-30.0.3.jar:bcecbd2f752a6560096a9029a47d1de6bd788a51bab505c5ebfba6a18524b983',
-        'com.android.tools.lint:lint-checks:30.0.3:lint-checks-30.0.3.jar:25a7cd42dc3ad502337f131fb8b7e873c53301db0a67b1c64dd4ae7a8eb66cec',
-        'com.android.tools.lint:lint-gradle:30.0.3:lint-gradle-30.0.3.jar:94544d6147a809bf2fd3440e51f28a4e42e547d74aab53eefd74938cdad42c26',
-        'com.android.tools.lint:lint-model:30.0.3:lint-model-30.0.3.jar:0b940a7f575c2ff5cbd038260f41dde686a93c672213881ead3ce8af3513b396',
-        'com.android.tools.lint:lint:30.0.3:lint-30.0.3.jar:ee4f11001e0c7e3b776e0d67399ad354b19b0f168822ec2b7db47c0910ed227d',
-        'com.android.tools:annotations:30.0.3:annotations-30.0.3.jar:5c1944982fda8555855c4f5422fabf0dc8e2306e1f5460e9ad82dae71316bc31',
-        'com.android.tools:common:30.0.3:common-30.0.3.jar:8751efaaf2c2ddd1f0a37526c794347def6a3057ca9fc510307c13a6cf0d036f',
-        'com.android.tools:dvlib:30.0.3:dvlib-30.0.3.jar:5affafcec390041e5afd64cb924153f5e474db47ee8ccc2f555b495083141233',
-        'com.android.tools:repository:30.0.3:repository-30.0.3.jar:0a40c6f16c506903ce2c609affd8228aceda73a69d93dfa42d4f02b8491449f6',
-        'com.android.tools:sdk-common:30.0.3:sdk-common-30.0.3.jar:b45570a380360236ffee0f6bb593d66b673bad3834dfe0d6c9871fa7188ee0eb',
-        'com.android.tools:sdklib:30.0.3:sdklib-30.0.3.jar:7088f20a414fab170a21e457825e14ebe099f753558e02c8acc12c67eb412162',
-        'com.android:signflinger:7.0.3:signflinger-7.0.3.jar:903a4536db3e96b4e1e1dc1e400eb0b91bf7866d9b39cd7ec94d75dde158f152',
-        'com.android:zipflinger:7.0.3:zipflinger-7.0.3.jar:fd209c960a3eff7a339e6fcba07d5e9ef4604d1633c69ab2df987460d9804140',
-        'com.beust:jcommander:1.78:jcommander-1.78.jar:7891debb84b5f83e9bd57593ebece3399abbe0fd938cf306b3534c57913b9615',
-        'com.github.javaparser:javaparser-core:3.17.0:javaparser-core-3.17.0.jar:23f5c982e1c7771423d37d52c774e8d2e80fd7ea7305ebe448797a96f67e6fca',
         'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
         'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
-        'com.google.code.gson:gson:2.8.6:gson-2.8.6.jar:c8fb4839054d280b3033f800d1f5a97de2f028eb8ba2eb458ad287e536f3f25f',
-        'com.google.dagger:dagger-compiler:2.33:dagger-compiler-2.33.jar:aa8a0d8370c578fd6999802d0d90b9829377a46d2c1141e11b8f737970e7155e',
-        'com.google.dagger:dagger-producers:2.33:dagger-producers-2.33.jar:5897f0b6eef799c2adfe3ccacc58c0fb374d58acb063c3ebe5366c38a8bce5c8',
-        'com.google.dagger:dagger-spi:2.33:dagger-spi-2.33.jar:e2dcab2221b8afb9556ef0a1c83b0bd5f42552e254322a257330f754cdbbb9d4',
-        'com.google.dagger:dagger:2.33:dagger-2.33.jar:d8798c5b8cf6b125234e33af5c6293bb9f2208ce29b57924c35b8c0be7b6bdcb',
-        'com.google.errorprone:error_prone_annotations:2.2.0:error_prone_annotations-2.2.0.jar:6ebd22ca1b9d8ec06d41de8d64e0596981d9607b42035f9ed374f9de271a481a',
-        'com.google.errorprone:error_prone_annotations:2.3.4:error_prone_annotations-2.3.4.jar:baf7d6ea97ce606c53e11b6854ba5f2ce7ef5c24dddf0afa18d1260bd25b002c',
+        'com.google.dagger:dagger-compiler:2.43.2:dagger-compiler-2.43.2.jar:298c020ee6ed2f4cc651ebbfdb7f8de329b07c44b618d65be117846a850e2a03',
+        'com.google.dagger:dagger-producers:2.43.2:dagger-producers-2.43.2.jar:e7f5d9ffc85d48a49c8e22e02833d418f7ccad5d7512f529964db5127ab915ff',
+        'com.google.dagger:dagger-spi:2.43.2:dagger-spi-2.43.2.jar:3bae8d9dadeaaa5927da6f094389a560c12c05fec3d2711d2fa79292c7a7d7ad',
+        'com.google.dagger:dagger:2.43.2:dagger-2.43.2.jar:c89681f7cbbf8c527bf4ac2748515d617fdb54a1d425c08d914fdc28192b5fe4',
+        'com.google.devtools.ksp:symbol-processing-api:1.7.0-1.0.6:symbol-processing-api-1.7.0-1.0.6.jar:adc29417be5ca9ff42118105fea4e36d9ef44987abfc41432309371a60198941',
+        'com.google.errorprone:error_prone_annotations:2.7.1:error_prone_annotations-2.7.1.jar:cd5257c08a246cf8628817ae71cb822be192ef91f6881ca4a3fcff4f1de1cff3',
         'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30',
         'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e',
         'com.google.guava:failureaccess:1.0.1:failureaccess-1.0.1.jar:a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26',
-        'com.google.guava:guava:27.1-jre:guava-27.1-jre.jar:4a5aa70cc968a4d137e599ad37553e5cfeed2265e8c193476d7119036c536fe7',
-        'com.google.guava:guava:30.1-jre:guava-30.1-jre.jar:e6dd072f9d3fe02a4600688380bd422bdac184caf6fe2418cfdd0934f09432aa',
+        'com.google.guava:guava:31.0.1-jre:guava-31.0.1-jre.jar:d5be94d65e87bd219fb3193ad1517baa55a3b88fc91d21cf735826ab5af087b9',
         'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
-        'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6',
         'com.google.j2objc:j2objc-annotations:1.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b',
-        'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
-        'com.google.protobuf:protobuf-java:3.10.0:protobuf-java-3.10.0.jar:161d7d61a8cb3970891c299578702fd079646e032329d6c2cabf998d191437c9',
-        'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
         'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
-        'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
-        'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
-        'com.sun.istack:istack-commons-runtime:3.0.8:istack-commons-runtime-3.0.8.jar:4ffabb06be454a05e4398e20c77fa2b6308d4b88dfbef7ca30a76b5b7d5505ef',
-        'com.sun.xml.fastinfoset:FastInfoset:1.2.16:FastInfoset-1.2.16.jar:056f3a1e144409f21ed16afc26805f58e9a21f3fce1543c42d400719d250c511',
-        'com.thoughtworks.qdox:qdox:1.12.1:qdox-1.12.1.jar:21fba22f830e9268f07cf4ab2d99e8181abbdcb0cb91ee0228eb3cb918dcdd1d',
-        'commons-codec:commons-codec:1.10:commons-codec-1.10.jar:4241dfa94e711d435f29a4604a3e2de5c4aa3c165e23bd066be6fc1fc4309569',
-        'commons-io:commons-io:2.4:commons-io-2.4.jar:cc6a41dc3eaacc9e440a6bd0d2890b20d36b4ee408fe2d67122f328bb6e01581',
-        'commons-logging:commons-logging:1.2:commons-logging-1.2.jar:daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636',
-        'info.picocli:picocli:4.5.2:picocli-4.5.2.jar:b4395e9a67932616efd2245d984bf5fcd453c2c5049558c3ce959ac2af4d3fac',
-        'it.unimi.dsi:fastutil:8.4.0:fastutil-8.4.0.jar:2ad2824a4a0a0eb836b52ee2fc84ba2134f44bce7bfa54015ae3f31c710a3071',
-        'jakarta.activation:jakarta.activation-api:1.2.1:jakarta.activation-api-1.2.1.jar:8b0a0f52fa8b05c5431921a063ed866efaa41dadf2e3a7ee3e1961f2b0d9645b',
-        'jakarta.xml.bind:jakarta.xml.bind-api:2.3.2:jakarta.xml.bind-api-2.3.2.jar:69156304079bdeed9fc0ae3b39389f19b3cc4ba4443bc80508995394ead742ea',
         'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
         'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
-        'jline:jline:2.14.6:jline-2.14.6.jar:97d1acaac82409be42e622d7a54d3ae9d08517e8aefdea3d2ba9791150c2f02d',
-        'junit:junit:4.13.1:junit-4.13.1.jar:c30719db974d6452793fe191b3638a5777005485bae145924044530ffa5f6122',
         'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
         'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
-        'net.java.dev.jna:jna-platform:5.6.0:jna-platform-5.6.0.jar:9ecea8bf2b1b39963939d18b70464eef60c508fed8820f9dcaba0c35518eabf7',
-        'net.java.dev.jna:jna:5.6.0:jna-5.6.0.jar:5557e235a8aa2f9766d5dc609d67948f2a8832c2d796cea9ef1d6cbe0b3b7eaf',
         'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
         'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
-        'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
-        'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2',
         'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
-        'org.apache.ant:ant-antlr:1.10.9:ant-antlr-1.10.9.jar:7623dc9d0f20ea713290c6bf1a23f4c059447aef7ff9f5b2be75960f3f028d2e',
-        'org.apache.ant:ant-junit:1.10.9:ant-junit-1.10.9.jar:960bdc8827954d62206ba42d0a68a7ee4476175ba47bb113e17e77cce7394630',
-        'org.apache.ant:ant-launcher:1.10.9:ant-launcher-1.10.9.jar:fcce891f57f3be72149ff96ac2a80574165b3e0839866b95d24528f3027d50c1',
-        'org.apache.ant:ant:1.10.9:ant-1.10.9.jar:0715478af585ea80a18985613ebecdc7922122d45b2c3c970ff9b352cddb75fc',
-        'org.apache.commons:commons-compress:1.20:commons-compress-1.20.jar:0aeb625c948c697ea7b205156e112363b59ed5e2551212cd4e460bdb72c7c06e',
-        'org.apache.httpcomponents:httpclient:4.5.6:httpclient-4.5.6.jar:c03f813195e7a80e3608d0ddd8da80b21696a4c92a6a2298865bf149071551c7',
-        'org.apache.httpcomponents:httpcore:4.4.10:httpcore-4.4.10.jar:78ba1096561957db1b55200a159b648876430342d15d461277e62360da19f6fd',
-        'org.apache.httpcomponents:httpmime:4.5.6:httpmime-4.5.6.jar:0b2b1102c18d3c7e05a77214b9b7501a6f6056174ae5604e0e256776eda7553e',
-        'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
-        'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
         'org.briarproject:obfs4proxy-android:0.0.14-tor1:obfs4proxy-android-0.0.14-tor1.jar:8b08068778b133484b17956d8f7a7710739c33f671a26a68156f4d34e6f28c30',
         'org.briarproject:snowflake-android:2.3.1:snowflake-android-2.3.1.jar:1f83c9a070f87b7074af13627709a8b5aced5460104be7166af736b1bb73c293',
         'org.briarproject:tor-android:0.4.5.14:tor-android-0.4.5.14.jar:7cf1beaa6c1db51fc8fac263aba9624ef289c3db29772509efcbc59f7057330a',
-        'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
-        'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
-        'org.checkerframework:checker-qual:3.5.0:checker-qual-3.5.0.jar:729990b3f18a95606fc2573836b6958bcdb44cb52bfbd1b7aa9c339cff35a5a4',
-        'org.codehaus.groovy:groovy-ant:3.0.7:groovy-ant-3.0.7.jar:6ed2ba82813d128f7050c24142e87b3dc2ad8b504786280eb03e81f0cf6a5793',
-        'org.codehaus.groovy:groovy-astbuilder:3.0.7:groovy-astbuilder-3.0.7.jar:b290451eb1583666e906c41f7d14747b4cc96363c99c478b244634fd5dfc9013',
-        'org.codehaus.groovy:groovy-cli-picocli:3.0.7:groovy-cli-picocli-3.0.7.jar:71b4bd11fb30a9c7b5618e22122c9c5141958fb27f4dcf0068b6f715088f6916',
-        'org.codehaus.groovy:groovy-console:3.0.7:groovy-console-3.0.7.jar:0541b358b6b8e5363215026736168fccfec1d91bac678d066fa77349eeeaa5dd',
-        'org.codehaus.groovy:groovy-datetime:3.0.7:groovy-datetime-3.0.7.jar:b9823d14b1a4f94236ae2f8a471701aab17e093e1b33402b91550b5c8dd88f04',
-        'org.codehaus.groovy:groovy-docgenerator:3.0.7:groovy-docgenerator-3.0.7.jar:bf53f7a11c9eb1e278e1b8ed2714c741bcf781235c803ad3ba1555f2614573f3',
-        'org.codehaus.groovy:groovy-groovydoc:3.0.7:groovy-groovydoc-3.0.7.jar:86b24dfc23c005066ab83927cdb54177f06c9531773f2e2d2ecc9a131f7c2677',
-        'org.codehaus.groovy:groovy-groovysh:3.0.7:groovy-groovysh-3.0.7.jar:5c40e78cbc09726aedd1c75fab112d245d665d6294870f9119e6cd3013ed14ab',
-        'org.codehaus.groovy:groovy-jmx:3.0.7:groovy-jmx-3.0.7.jar:0a89f3007884eb156751937d93382038b83d39c7c2f0ab156ebf251a7251f2ab',
-        'org.codehaus.groovy:groovy-json:3.0.7:groovy-json-3.0.7.jar:df1f0ee475e3fc93a6a0d17548294e160cca5de6d9d36817a7be1fbe650de03b',
-        'org.codehaus.groovy:groovy-jsr223:3.0.7:groovy-jsr223-3.0.7.jar:1dbd969595332416193baa660fbb45743d19696eaa25fe98e591a2739e13517e',
-        'org.codehaus.groovy:groovy-macro:3.0.7:groovy-macro-3.0.7.jar:c6cc06df526b39e2c359e2435f0071594c5a1c7babafaa6c184fdd8fa931531f',
-        'org.codehaus.groovy:groovy-nio:3.0.7:groovy-nio-3.0.7.jar:db54c577882b294cd8c975ec5451596441baf54781319c61627dca0e0c2361ef',
-        'org.codehaus.groovy:groovy-servlet:3.0.7:groovy-servlet-3.0.7.jar:5b6a909bf501c209adfb6205b9e740649609074455fd979bf9da4853e6ff9a39',
-        'org.codehaus.groovy:groovy-sql:3.0.7:groovy-sql-3.0.7.jar:252bb6c74e1a9f41756ad4fbd3b0d2eddc93bb61109961dd1952a37bf2d57a64',
-        'org.codehaus.groovy:groovy-swing:3.0.7:groovy-swing-3.0.7.jar:bd942032d9328d54c6679c49a41f6caa0d4a0039ebe598493b8a647730d98cff',
-        'org.codehaus.groovy:groovy-templates:3.0.7:groovy-templates-3.0.7.jar:f119e07f650ef186ae5a4b944f9e30915b14311bad47c94a6b32de8d4f69bc80',
-        'org.codehaus.groovy:groovy-test-junit5:3.0.7:groovy-test-junit5-3.0.7.jar:c16eeea07b8e396891e266d7ba9388b24ac804237ffdd9a792b0d08969bad014',
-        'org.codehaus.groovy:groovy-test:3.0.7:groovy-test-3.0.7.jar:f71afd7c25d43017f89ea47e6de6daec971d159047dae083c1513a8422d44b90',
-        'org.codehaus.groovy:groovy-testng:3.0.7:groovy-testng-3.0.7.jar:713d5f2231bbb5712aefd362151b9ffd884aeb7ef2e773315cc54259cbdd063d',
-        'org.codehaus.groovy:groovy-xml:3.0.7:groovy-xml-3.0.7.jar:8a62e7c9ddece3e82676c4bef2f2c100f459602cd1fb6a14e94187bf863e97ff',
-        'org.codehaus.groovy:groovy:3.0.7:groovy-3.0.7.jar:51d1777e8dd1f00e60ea56e00d8a354ff5aab1f00fc8464ae8d39d71867e401f',
-        'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
-        'org.glassfish.jaxb:jaxb-runtime:2.3.2:jaxb-runtime-2.3.2.jar:e6e0a1e89fb6ff786279e6a0082d5cef52dc2ebe67053d041800737652b4fd1b',
-        'org.glassfish.jaxb:txw2:2.3.2:txw2-2.3.2.jar:4a6a9f483388d461b81aa9a28c685b8b74c0597993bf1884b04eddbca95f48fe',
-        'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
+        'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a',
+        'org.checkerframework:checker-qual:3.12.0:checker-qual-3.12.0.jar:ff10785ac2a357ec5de9c293cb982a2cbb605c0309ea4cc1cb9b9bc6dbe7f3cb',
         'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
         'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
         'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
-        'org.jacoco:org.jacoco.agent:0.8.3:org.jacoco.agent-0.8.3.jar:522deb254ee16a04cc8341cc8f335f5cb7232982994d961b9cf3a0454709209f',
-        'org.jacoco:org.jacoco.ant:0.8.3:org.jacoco.ant-0.8.3.jar:735844e1ae15f9b875b42a27ac5cb61cc26e106d9e839e5d1c6756709b424ce0',
-        'org.jacoco:org.jacoco.core:0.8.3:org.jacoco.core-0.8.3.jar:0818437bc060a0c7cc798148f22b713702aae2771aba104444407697d578f1ea',
-        'org.jacoco:org.jacoco.report:0.8.3:org.jacoco.report-0.8.3.jar:aae08fa4ff043c807b8876cdb2d8705eb8449a55efce461baa6c09da245088c1',
-        'org.jetbrains.intellij.deps:trove4j:1.0.20181211:trove4j-1.0.20181211.jar:affb7c85a3c87bdcf69ff1dbb84de11f63dc931293934bc08cd7ab18de083601',
-        'org.jetbrains.kotlin:kotlin-reflect:1.4.32:kotlin-reflect-1.4.32.jar:dbf19e9cdaa9c3c170f3f6f6ce3922f38dfc1d7fa1cab5b7c23a19da8b5eec5b',
-        'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20:kotlin-stdlib-common-1.4.20.jar:a7112c9b3cefee418286c9c9372f7af992bd1e6e030691d52f60cb36dbec8320',
-        'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.32:kotlin-stdlib-common-1.4.32.jar:e1ff6f55ee9e7591dcc633f7757bac25a7edb1cc7f738b37ec652f10f66a4145',
+        'org.jacoco:org.jacoco.agent:0.8.7:org.jacoco.agent-0.8.7.jar:9cbcc986e0fbe821a78ff1f8f7d5216f200e5eb124e7f6837d1dc4a77b28b143',
+        'org.jacoco:org.jacoco.ant:0.8.7:org.jacoco.ant-0.8.7.jar:97ca96a382c3f23a44d8eb4c4e6c3742a30cb8005774a76ced0fc4806ce49605',
+        'org.jacoco:org.jacoco.core:0.8.7:org.jacoco.core-0.8.7.jar:ad7739b5fb5969aa1a8aead3d74ed54dc82ed012f1f10f336bd1b96e71c1a13c',
+        'org.jacoco:org.jacoco.report:0.8.7:org.jacoco.report-0.8.7.jar:cc89258623700a6c932592153cb528785876b6da183d5431f97efbba6f020e5b',
+        'org.jetbrains.kotlin:kotlin-stdlib-common:1.7.0:kotlin-stdlib-common-1.7.0.jar:59c6ff64fe9a6604afce03e8aaa75f83586c6030ac71fb0b34ee7cdefed3618f',
         'org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10:kotlin-stdlib-common-1.7.10.jar:19f102efe9629f8eabc63853ad15c533e47c47f91fca09285c5bde86e59f91d4',
-        'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.32:kotlin-stdlib-jdk7-1.4.32.jar:5f801e75ca27d8791c14b07943c608da27620d910a8093022af57f543d5d98b6',
-        'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.32:kotlin-stdlib-jdk8-1.4.32.jar:adc43e54757b106e0cd7b3b7aa257dff471b61efdabe067fc02b2f57e2396262',
-        'org.jetbrains.kotlin:kotlin-stdlib:1.4.20:kotlin-stdlib-1.4.20.jar:b8ab1da5cdc89cb084d41e1f28f20a42bd431538642a5741c52bbfae3fa3e656',
-        'org.jetbrains.kotlin:kotlin-stdlib:1.4.32:kotlin-stdlib-1.4.32.jar:13e9fd3e69dc7230ce0fc873a92a4e5d521d179bcf1bef75a6705baac3bfecba',
+        'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.0:kotlin-stdlib-jdk7-1.7.0.jar:07e91be9b2ca20672d2bdb7e181b766e73453a2da13492b5ddaee8fa47aea239',
+        'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0:kotlin-stdlib-jdk8-1.7.0.jar:cf058e11db1dfc9944680c8c61b95ac689aaaa8a3eb30bced028100f038f030b',
+        'org.jetbrains.kotlin:kotlin-stdlib:1.7.0:kotlin-stdlib-1.7.0.jar:aa88e9625577957f3249a46cb6e166ee09b369e600f7a11d148d16b0a6d87f05',
         'org.jetbrains.kotlin:kotlin-stdlib:1.7.10:kotlin-stdlib-1.7.10.jar:e771fe74250a943e8f6346713201ff1d8cb95c3a5d1a91a22b65a9e04f6a8901',
-        'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0:kotlinx-metadata-jvm-0.1.0.jar:9753bb39efef35957c5c15df9a3cb769aabf2cdfa74b47afcb7760e5146be3b5',
+        'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0:kotlinx-metadata-jvm-0.5.0.jar:ca063a96639b08b9eaa0de4d65e899480740a6efbe28ab9a8681a2ced03055a4',
         'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
         'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
         'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
         'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd',
         'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04',
         'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
-        'org.junit.jupiter:junit-jupiter-api:5.7.0:junit-jupiter-api-5.7.0.jar:b03f78e0daeed2d77a0af9bcd662b4cdb9693f7ee72e01a539b508b84c63d182',
-        'org.junit.jupiter:junit-jupiter-engine:5.7.0:junit-jupiter-engine-5.7.0.jar:dfa26af94644ac2612dde6625852fcb550a0d21caa243257de54cba738ba87af',
-        'org.junit.platform:junit-platform-commons:1.7.0:junit-platform-commons-1.7.0.jar:5330ee87cc7586e6e25175a34e9251624ff12ff525269d3415d0b4ca519b6fea',
-        'org.junit.platform:junit-platform-engine:1.7.0:junit-platform-engine-1.7.0.jar:75f21a20dc594afdc875736725b408cec6d0344874d29f34b2dd3075500236f2',
-        'org.junit.platform:junit-platform-launcher:1.7.0:junit-platform-launcher-1.7.0.jar:fbdc748fde4c4279fe1d3c607447cb3b7ccd45d7338fc574f8a894ddf2d16818',
-        'org.jvnet.staxex:stax-ex:1.8.1:stax-ex-1.8.1.jar:20522549056e9e50aa35ef0b445a2e47a53d06be0b0a9467d704e2483ffb049a',
         'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
-        'org.opentest4j:opentest4j:1.2.0:opentest4j-1.2.0.jar:58812de60898d976fb81ef3b62da05c6604c18fd4a249f5044282479fc286af2',
-        'org.ow2.asm:asm-analysis:7.0:asm-analysis-7.0.jar:e981f8f650c4d900bb033650b18e122fa6b161eadd5f88978d08751f72ee8474',
-        'org.ow2.asm:asm-commons:7.0:asm-commons-7.0.jar:fed348ef05958e3e846a3ac074a12af5f7936ef3d21ce44a62c4fa08a771927d',
-        'org.ow2.asm:asm-tree:7.0:asm-tree-7.0.jar:cfd7a0874f9de36a999c127feeadfbfe6e04d4a71ee954d7af3d853f0be48a6c',
-        'org.ow2.asm:asm-util:7.0:asm-util-7.0.jar:75fbbca440ef463f41c2b0ab1a80abe67e910ac486da60a7863cbcb5bae7e145',
-        'org.ow2.asm:asm:7.0:asm-7.0.jar:b88ef66468b3c978ad0c97fd6e90979e56155b4ac69089ba7a44e9aa7ffe9acf',
+        'org.ow2.asm:asm-analysis:9.1:asm-analysis-9.1.jar:81a88041b1b8beda5a8a99646098046c48709538270c49def68abff25ac3be34',
+        'org.ow2.asm:asm-commons:9.1:asm-commons-9.1.jar:afcb26dc1fc12c0c4a99ada670908dd82e18dfc488caf5ee92546996b470c00c',
+        'org.ow2.asm:asm-tree:9.1:asm-tree-9.1.jar:fd00afa49e9595d7646205b09cecb4a776a8ff0ba06f2d59b8f7bf9c704b4a73',
         'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
-        'org.testng:testng:7.3.0:testng-7.3.0.jar:63727488f9717d57f0d0a0fee5a1fc10a2be9cfcff2ec3a7187656d663c0774e',
-        'xerces:xercesImpl:2.12.0:xercesImpl-2.12.0.jar:b50d3a4ca502faa4d1c838acb8aa9480446953421f7327e338c5dda3da5e76d0',
-        'xml-apis:xml-apis:1.4.01:xml-apis-1.4.01.jar:a840968176645684bb01aed376e067ab39614885f9eee44abe35a5f20ebe7fad',
+        'org.ow2.asm:asm:9.1:asm-9.1.jar:cda4de455fab48ff0bcb7c48b4639447d4de859a7afc30a094a986f0936beba2',
     ]
 }
diff --git a/bramble-api/witness.gradle b/bramble-api/witness.gradle
index 2b05f3a06519855e28e4f153eb8a4aef68d3ce95..a20be4ee77e17ee3e44d21e08a22957f70b7b76b 100644
--- a/bramble-api/witness.gradle
+++ b/bramble-api/witness.gradle
@@ -1,10 +1,10 @@
 dependencyVerification {
     verify = [
         'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
-        'com.fasterxml.jackson.core:jackson-annotations:2.13.0:jackson-annotations-2.13.0.jar:81f9724d8843e8b08f8f6c0609e7a2b030d00c34861c4ac7e2099a7235047d6f',
+        'com.fasterxml.jackson.core:jackson-annotations:2.13.4:jackson-annotations-2.13.4.jar:ac5b27a634942391ca113850ee7db01df1499a240174021263501c05fc653b44',
         'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
         'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
-        'com.google.dagger:dagger:2.33:dagger-2.33.jar:d8798c5b8cf6b125234e33af5c6293bb9f2208ce29b57924c35b8c0be7b6bdcb',
+        'com.google.dagger:dagger:2.43.2:dagger-2.43.2.jar:c89681f7cbbf8c527bf4ac2748515d617fdb54a1d425c08d914fdc28192b5fe4',
         'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
         'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
         'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
diff --git a/bramble-core/build.gradle b/bramble-core/build.gradle
index f8bbfcf5ac1c95979ff8e30efc86f1f5c8a0de8a..67664e880231db7b509d7b51799543a4ed7b83ab 100644
--- a/bramble-core/build.gradle
+++ b/bramble-core/build.gradle
@@ -10,7 +10,7 @@ apply from: '../dagger.gradle'
 
 dependencies {
 	implementation project(path: ':bramble-api', configuration: 'default')
-	implementation 'org.bouncycastle:bcprov-jdk15to18:1.70'
+	implementation 'org.bouncycastle:bcprov-jdk15to18:1.71'
 	//noinspection GradleDependency
 	implementation 'com.h2database:h2:1.4.192' // The last version that supports Java 1.6
 	implementation 'org.bitlet:weupnp:0.1.4'
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/AbstractBluetoothPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/AbstractBluetoothPlugin.java
index 374c10d4f450de7a3f41b337738286a0c7b61d84..b9eb6665d7813de83a62e0581ee99b75ad86504c 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/AbstractBluetoothPlugin.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/AbstractBluetoothPlugin.java
@@ -89,6 +89,17 @@ abstract class AbstractBluetoothPlugin<S, SS> implements BluetoothPlugin,
 
 	private volatile String contactConnectionsUuid = null;
 
+	/**
+	 * Override and return true, if the plugin is now allowed to access the
+	 * Bluetooth hardware.
+	 * If this returns false, the plugin must be
+	 * {@link org.briarproject.bramble.api.plugin.Plugin.State#DISABLED}
+	 * in {@link #start()} and not attempt to access Bluetooth hardware.
+	 */
+	protected boolean isBluetoothAccessible() {
+		return true;
+	}
+
 	abstract void initialiseAdapter() throws IOException;
 
 	abstract boolean isAdapterEnabled();
@@ -176,19 +187,28 @@ abstract class AbstractBluetoothPlugin<S, SS> implements BluetoothPlugin,
 				DEFAULT_PREF_PLUGIN_ENABLE);
 		everConnected.set(settings.getBoolean(PREF_EVER_CONNECTED,
 				DEFAULT_PREF_EVER_CONNECTED));
+		// disable plugin, if conditions for enabling are not met
+		if (enabledByUser && !isBluetoothAccessible()) {
+			enabledByUser = false;
+			settings.putBoolean(PREF_PLUGIN_ENABLE, false);
+			callback.mergeSettings(settings);
+		}
 		state.setStarted(enabledByUser);
 		try {
 			initialiseAdapter();
 		} catch (IOException e) {
 			throw new PluginException(e);
 		}
-		updateProperties();
-		if (enabledByUser && isAdapterEnabled()) bind();
+		if (enabledByUser) {
+			updateProperties();
+			if (isAdapterEnabled()) bind();
+		}
 	}
 
 	private void bind() {
 		ioExecutor.execute(() -> {
 			if (getState() != INACTIVE) return;
+			if (contactConnectionsUuid == null) updateProperties();
 			// Bind a server socket to accept connections from contacts
 			SS ss;
 			try {
@@ -534,7 +554,8 @@ abstract class AbstractBluetoothPlugin<S, SS> implements BluetoothPlugin,
 	private void onSettingsUpdated(Settings settings) {
 		boolean enabledByUser = settings.getBoolean(PREF_PLUGIN_ENABLE,
 				DEFAULT_PREF_PLUGIN_ENABLE);
-		SS ss = state.setEnabledByUser(enabledByUser);
+		boolean shouldEnable = enabledByUser && isBluetoothAccessible();
+		SS ss = state.setEnabledByUser(shouldEnable);
 		State s = getState();
 		if (ss != null) {
 			LOG.info("Disabled by user, closing server socket");
diff --git a/bramble-core/witness.gradle b/bramble-core/witness.gradle
index 99b4a7033052ae3bfe931ee1e5b184caf6f099e5..74cde5a7932301f2609d984f74ae5842f2d4c13c 100644
--- a/bramble-core/witness.gradle
+++ b/bramble-core/witness.gradle
@@ -1,22 +1,23 @@
 dependencyVerification {
     verify = [
         'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
-        'com.fasterxml.jackson.core:jackson-annotations:2.13.0:jackson-annotations-2.13.0.jar:81f9724d8843e8b08f8f6c0609e7a2b030d00c34861c4ac7e2099a7235047d6f',
-        'com.fasterxml.jackson.core:jackson-core:2.13.0:jackson-core-2.13.0.jar:348bc59b348df2e807b356f1d62d2afb41a974073328abc773eb0932b855d2c8',
-        'com.fasterxml.jackson.core:jackson-databind:2.13.0:jackson-databind-2.13.0.jar:9c826d27176268777adcf97e1c6e2051c7e33a7aaa2c370c2e8c6077fd9da3f4',
+        'com.fasterxml.jackson.core:jackson-annotations:2.13.4:jackson-annotations-2.13.4.jar:ac5b27a634942391ca113850ee7db01df1499a240174021263501c05fc653b44',
+        'com.fasterxml.jackson.core:jackson-core:2.13.4:jackson-core-2.13.4.jar:4c2e043200edd9ee7ba6fc378bd5c17784a5bf2388e152d208068b51fd0839cf',
+        'com.fasterxml.jackson.core:jackson-databind:2.13.4:jackson-databind-2.13.4.jar:c9faff420d9e2c7e1e4711dbeebec2506a32c9942027211c5c293d8d87807eb6',
         'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
         'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
-        'com.google.dagger:dagger-compiler:2.33:dagger-compiler-2.33.jar:aa8a0d8370c578fd6999802d0d90b9829377a46d2c1141e11b8f737970e7155e',
-        'com.google.dagger:dagger-producers:2.33:dagger-producers-2.33.jar:5897f0b6eef799c2adfe3ccacc58c0fb374d58acb063c3ebe5366c38a8bce5c8',
-        'com.google.dagger:dagger-spi:2.33:dagger-spi-2.33.jar:e2dcab2221b8afb9556ef0a1c83b0bd5f42552e254322a257330f754cdbbb9d4',
-        'com.google.dagger:dagger:2.33:dagger-2.33.jar:d8798c5b8cf6b125234e33af5c6293bb9f2208ce29b57924c35b8c0be7b6bdcb',
-        'com.google.errorprone:error_prone_annotations:2.2.0:error_prone_annotations-2.2.0.jar:6ebd22ca1b9d8ec06d41de8d64e0596981d9607b42035f9ed374f9de271a481a',
+        'com.google.dagger:dagger-compiler:2.43.2:dagger-compiler-2.43.2.jar:298c020ee6ed2f4cc651ebbfdb7f8de329b07c44b618d65be117846a850e2a03',
+        'com.google.dagger:dagger-producers:2.43.2:dagger-producers-2.43.2.jar:e7f5d9ffc85d48a49c8e22e02833d418f7ccad5d7512f529964db5127ab915ff',
+        'com.google.dagger:dagger-spi:2.43.2:dagger-spi-2.43.2.jar:3bae8d9dadeaaa5927da6f094389a560c12c05fec3d2711d2fa79292c7a7d7ad',
+        'com.google.dagger:dagger:2.43.2:dagger-2.43.2.jar:c89681f7cbbf8c527bf4ac2748515d617fdb54a1d425c08d914fdc28192b5fe4',
+        'com.google.devtools.ksp:symbol-processing-api:1.7.0-1.0.6:symbol-processing-api-1.7.0-1.0.6.jar:adc29417be5ca9ff42118105fea4e36d9ef44987abfc41432309371a60198941',
+        'com.google.errorprone:error_prone_annotations:2.7.1:error_prone_annotations-2.7.1.jar:cd5257c08a246cf8628817ae71cb822be192ef91f6881ca4a3fcff4f1de1cff3',
         'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30',
         'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e',
         'com.google.guava:failureaccess:1.0.1:failureaccess-1.0.1.jar:a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26',
-        'com.google.guava:guava:27.1-jre:guava-27.1-jre.jar:4a5aa70cc968a4d137e599ad37553e5cfeed2265e8c193476d7119036c536fe7',
+        'com.google.guava:guava:31.0.1-jre:guava-31.0.1-jre.jar:d5be94d65e87bd219fb3193ad1517baa55a3b88fc91d21cf735826ab5af087b9',
         'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
-        'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6',
+        'com.google.j2objc:j2objc-annotations:1.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b',
         'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
         'com.squareup.okhttp3:mockwebserver:4.9.3:mockwebserver-4.9.3.jar:9c8c581c29f22f877a35d11380462f75bb24bf1886204fe835ee695594a2784e',
         'com.squareup.okhttp3:okhttp:3.12.13:okhttp-3.12.13.jar:508234e024ef7e270ab1a6d5b356f5b98e786511239ca986d684fd1e2cf7bc82',
@@ -24,7 +25,6 @@ dependencyVerification {
         'com.squareup.okio:okio:1.15.0:okio-1.15.0.jar:693fa319a7e8843300602b204023b7674f106ebcb577f2dd5807212b66118bd2',
         'com.squareup.okio:okio:2.8.0:okio-jvm-2.8.0.jar:4496b06e73982fcdd8a5393f46e5df2ce2fa4465df5895454cac68a32f09bbc8',
         'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
-        'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
         'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
         'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
         'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
@@ -34,14 +34,13 @@ dependencyVerification {
         'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
         'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
         'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
-        'org.bouncycastle:bcprov-jdk15to18:1.70:bcprov-jdk15to18-1.70.jar:7df4c54f29ce2dd616dc3b198ca4db3dfcc79e3cb397c084a0aff97b85c0bf38',
+        'org.bouncycastle:bcprov-jdk15to18:1.71:bcprov-jdk15to18-1.71.jar:143aaa4a40edd5fc2a18db7900059f6c16f4d931b94b94b20f7e2238e6662886',
         'org.briarproject:jtorctl:0.5:jtorctl-0.5.jar:43f8c7d390169772b9a2c82ab806c8414c136a2a8636c555e22754bb7260793b',
         'org.briarproject:null-safety:0.1:null-safety-0.1.jar:161760de5e838cb982bafa973df820675d4397098e9a91637a36a306d43ba011',
         'org.briarproject:socks-socket:0.1:socks-socket-0.1.jar:e5898822d10f5390363c5dddb945891648c92cf93ba50709e07f0d173ec0eb4b',
-        'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
-        'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
+        'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a',
+        'org.checkerframework:checker-qual:3.12.0:checker-qual-3.12.0.jar:ff10785ac2a357ec5de9c293cb982a2cbb605c0309ea4cc1cb9b9bc6dbe7f3cb',
         'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
-        'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
         'org.codehaus.mojo:animal-sniffer-ant-tasks:1.20:animal-sniffer-ant-tasks-1.20.jar:bb7d2498144118311d968bb08ff6fae3fc535fb1cb9cca8b8e9ea65b189422ac',
         'org.codehaus.mojo:animal-sniffer:1.20:animal-sniffer-1.20.jar:80c422523c38db91260c6d78e5ee4b012862ab61cc55020c9e243dd7b5c62249',
         'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
@@ -49,12 +48,14 @@ dependencyVerification {
         'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
         'org.hsqldb:hsqldb:2.3.5:hsqldb-2.3.5.jar:6676a6977ac98997a80f827ddbd3fe8ca1e0853dad1492512135fd1a222ccfad',
         'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.10:kotlin-stdlib-common-1.4.10.jar:4681f2d436a68c7523595d84ed5758e1382f9da0f67c91e6a848690d711274fe',
-        'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20:kotlin-stdlib-common-1.4.20.jar:a7112c9b3cefee418286c9c9372f7af992bd1e6e030691d52f60cb36dbec8320',
+        'org.jetbrains.kotlin:kotlin-stdlib-common:1.7.0:kotlin-stdlib-common-1.7.0.jar:59c6ff64fe9a6604afce03e8aaa75f83586c6030ac71fb0b34ee7cdefed3618f',
         'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.10:kotlin-stdlib-jdk7-1.4.10.jar:f9566380c08722c780ce33ceee23e98ddf765ca98fabd3e2fabae7975c8d232b',
+        'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.0:kotlin-stdlib-jdk7-1.7.0.jar:07e91be9b2ca20672d2bdb7e181b766e73453a2da13492b5ddaee8fa47aea239',
         'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.10:kotlin-stdlib-jdk8-1.4.10.jar:39b7a9442d7a3865e0f4a732c56c1d5da0e11ffb3bb82a461d32deb0c0ca7673',
+        'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0:kotlin-stdlib-jdk8-1.7.0.jar:cf058e11db1dfc9944680c8c61b95ac689aaaa8a3eb30bced028100f038f030b',
         'org.jetbrains.kotlin:kotlin-stdlib:1.4.10:kotlin-stdlib-1.4.10.jar:01ecb09782c042b931c1839acf21a188340b295d05400afd6e3415d4475b8daa',
-        'org.jetbrains.kotlin:kotlin-stdlib:1.4.20:kotlin-stdlib-1.4.20.jar:b8ab1da5cdc89cb084d41e1f28f20a42bd431538642a5741c52bbfae3fa3e656',
-        'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0:kotlinx-metadata-jvm-0.1.0.jar:9753bb39efef35957c5c15df9a3cb769aabf2cdfa74b47afcb7760e5146be3b5',
+        'org.jetbrains.kotlin:kotlin-stdlib:1.7.0:kotlin-stdlib-1.7.0.jar:aa88e9625577957f3249a46cb6e166ee09b369e600f7a11d148d16b0a6d87f05',
+        'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0:kotlinx-metadata-jvm-0.5.0.jar:ca063a96639b08b9eaa0de4d65e899480740a6efbe28ab9a8681a2ced03055a4',
         'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
         'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
         'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
diff --git a/bramble-java/witness.gradle b/bramble-java/witness.gradle
index ad4624462f067b04f8642bf00dabc47ee52ac084..203b6ec34fc96b670d4a686d3662dfa3bc87439f 100644
--- a/bramble-java/witness.gradle
+++ b/bramble-java/witness.gradle
@@ -3,19 +3,19 @@ dependencyVerification {
         'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
         'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
         'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
-        'com.google.dagger:dagger-compiler:2.33:dagger-compiler-2.33.jar:aa8a0d8370c578fd6999802d0d90b9829377a46d2c1141e11b8f737970e7155e',
-        'com.google.dagger:dagger-producers:2.33:dagger-producers-2.33.jar:5897f0b6eef799c2adfe3ccacc58c0fb374d58acb063c3ebe5366c38a8bce5c8',
-        'com.google.dagger:dagger-spi:2.33:dagger-spi-2.33.jar:e2dcab2221b8afb9556ef0a1c83b0bd5f42552e254322a257330f754cdbbb9d4',
-        'com.google.dagger:dagger:2.33:dagger-2.33.jar:d8798c5b8cf6b125234e33af5c6293bb9f2208ce29b57924c35b8c0be7b6bdcb',
-        'com.google.errorprone:error_prone_annotations:2.2.0:error_prone_annotations-2.2.0.jar:6ebd22ca1b9d8ec06d41de8d64e0596981d9607b42035f9ed374f9de271a481a',
+        'com.google.dagger:dagger-compiler:2.43.2:dagger-compiler-2.43.2.jar:298c020ee6ed2f4cc651ebbfdb7f8de329b07c44b618d65be117846a850e2a03',
+        'com.google.dagger:dagger-producers:2.43.2:dagger-producers-2.43.2.jar:e7f5d9ffc85d48a49c8e22e02833d418f7ccad5d7512f529964db5127ab915ff',
+        'com.google.dagger:dagger-spi:2.43.2:dagger-spi-2.43.2.jar:3bae8d9dadeaaa5927da6f094389a560c12c05fec3d2711d2fa79292c7a7d7ad',
+        'com.google.dagger:dagger:2.43.2:dagger-2.43.2.jar:c89681f7cbbf8c527bf4ac2748515d617fdb54a1d425c08d914fdc28192b5fe4',
+        'com.google.devtools.ksp:symbol-processing-api:1.7.0-1.0.6:symbol-processing-api-1.7.0-1.0.6.jar:adc29417be5ca9ff42118105fea4e36d9ef44987abfc41432309371a60198941',
+        'com.google.errorprone:error_prone_annotations:2.7.1:error_prone_annotations-2.7.1.jar:cd5257c08a246cf8628817ae71cb822be192ef91f6881ca4a3fcff4f1de1cff3',
         'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30',
         'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e',
         'com.google.guava:failureaccess:1.0.1:failureaccess-1.0.1.jar:a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26',
-        'com.google.guava:guava:27.1-jre:guava-27.1-jre.jar:4a5aa70cc968a4d137e599ad37553e5cfeed2265e8c193476d7119036c536fe7',
+        'com.google.guava:guava:31.0.1-jre:guava-31.0.1-jre.jar:d5be94d65e87bd219fb3193ad1517baa55a3b88fc91d21cf735826ab5af087b9',
         'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
-        'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6',
+        'com.google.j2objc:j2objc-annotations:1.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b',
         'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
-        'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
         'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
         'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
         'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
@@ -30,15 +30,16 @@ dependencyVerification {
         'org.briarproject:snowflake-windows:2.3.1:snowflake-windows-2.3.1.jar:d011f1a72c00a221f56380c19aad8ff11db8c2bb1adb0784125572d80b4d275a',
         'org.briarproject:tor-linux:0.4.5.14:tor-linux-0.4.5.14.jar:1844e54cf6df0c85cec219381a3364c759ae444a6b63f7558b757becb7d41d08',
         'org.briarproject:tor-windows:0.4.5.14:tor-windows-0.4.5.14.jar:d337afa1043f0cfa7e6e8c2473d682a5663a2c8052bb97a770450893c78c9b4f',
-        'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
-        'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
-        'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
+        'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a',
+        'org.checkerframework:checker-qual:3.12.0:checker-qual-3.12.0.jar:ff10785ac2a357ec5de9c293cb982a2cbb605c0309ea4cc1cb9b9bc6dbe7f3cb',
         'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
         'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
         'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
-        'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20:kotlin-stdlib-common-1.4.20.jar:a7112c9b3cefee418286c9c9372f7af992bd1e6e030691d52f60cb36dbec8320',
-        'org.jetbrains.kotlin:kotlin-stdlib:1.4.20:kotlin-stdlib-1.4.20.jar:b8ab1da5cdc89cb084d41e1f28f20a42bd431538642a5741c52bbfae3fa3e656',
-        'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0:kotlinx-metadata-jvm-0.1.0.jar:9753bb39efef35957c5c15df9a3cb769aabf2cdfa74b47afcb7760e5146be3b5',
+        'org.jetbrains.kotlin:kotlin-stdlib-common:1.7.0:kotlin-stdlib-common-1.7.0.jar:59c6ff64fe9a6604afce03e8aaa75f83586c6030ac71fb0b34ee7cdefed3618f',
+        'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.0:kotlin-stdlib-jdk7-1.7.0.jar:07e91be9b2ca20672d2bdb7e181b766e73453a2da13492b5ddaee8fa47aea239',
+        'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0:kotlin-stdlib-jdk8-1.7.0.jar:cf058e11db1dfc9944680c8c61b95ac689aaaa8a3eb30bced028100f038f030b',
+        'org.jetbrains.kotlin:kotlin-stdlib:1.7.0:kotlin-stdlib-1.7.0.jar:aa88e9625577957f3249a46cb6e166ee09b369e600f7a11d148d16b0a6d87f05',
+        'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0:kotlinx-metadata-jvm-0.5.0.jar:ca063a96639b08b9eaa0de4d65e899480740a6efbe28ab9a8681a2ced03055a4',
         'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
         'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
         'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
diff --git a/briar-android/build.gradle b/briar-android/build.gradle
index 5dd1f297a08bde0ba24d156f30391d7b1cd35210..ef67411453b17e40db2f911018031603ef582bea 100644
--- a/briar-android/build.gradle
+++ b/briar-android/build.gradle
@@ -16,8 +16,8 @@ def getStdout = { command, defaultValue ->
 }
 
 android {
-	compileSdkVersion 30
-	buildToolsVersion '30.0.3'
+	compileSdkVersion 33
+	buildToolsVersion '33.0.0'
 
 	packagingOptions {
 		doNotStrip '**/*.so'
@@ -25,7 +25,7 @@ android {
 
 	defaultConfig {
 		minSdkVersion 16
-		targetSdkVersion 30
+		targetSdkVersion 31
 		versionCode 10415
 		versionName "1.4.15"
 		applicationId "org.briarproject.briar.android"
@@ -105,7 +105,7 @@ dependencies {
 
 	implementation 'androidx.fragment:fragment:1.3.4'
 	implementation 'androidx.preference:preference:1.1.1'
-	implementation 'androidx.exifinterface:exifinterface:1.3.2'
+	implementation 'androidx.exifinterface:exifinterface:1.3.3'
 	implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
 	implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
 	implementation 'com.google.android.material:material:1.3.0'
@@ -119,7 +119,7 @@ dependencies {
 	implementation 'com.vanniktech:emoji-google:0.7.0' // newer versions need minSdk 21
 	implementation 'com.github.kobakei:MaterialFabSpeedDial:1.2.1'
 	implementation 'com.github.chrisbanes:PhotoView:2.3.0'
-	def glideVersion = '4.11.0'
+	def glideVersion = '4.12.0'
 	implementation("com.github.bumptech.glide:glide:$glideVersion") {
 		exclude group: 'com.android.support'
 		exclude module: 'disklrucache' // when there's no disk cache, we can't accidentally use it
@@ -148,7 +148,7 @@ dependencies {
 	testAnnotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
 
 	androidTestImplementation project(path: ':bramble-api', configuration: 'testOutput')
-	androidTestImplementation 'androidx.test.ext:junit:1.1.2'
+	androidTestImplementation 'androidx.test.ext:junit:1.1.3'
 	androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion"
 	androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion"
 	androidTestImplementation "androidx.test.espresso:espresso-intents:$espressoVersion"
@@ -171,7 +171,7 @@ task verifyTranslations {
 		lc.children().each { value -> translations.add(value.text()) }
 
 		def folders = ["default", "en-US"]
-		def exceptions = ["values-night", "values-v21", "values-ldrtl"]
+		def exceptions = ["values-night", "values-v21", "values-v31", "values-ldrtl"]
 		project.file("src/main/res").eachDir { dir ->
 			if (dir.name.startsWith("values-") && !exceptions.contains(dir.name)) {
 				folders.add(dir.name.substring(7).replace("-r", "-"))
diff --git a/briar-android/src/main/AndroidManifest.xml b/briar-android/src/main/AndroidManifest.xml
index 007b82ee4e9983ca905dd7fc91c11fe7e30b1c2e..96e2cb1789523bc85f459d48d1b38fca39b4286c 100644
--- a/briar-android/src/main/AndroidManifest.xml
+++ b/briar-android/src/main/AndroidManifest.xml
@@ -19,8 +19,6 @@
 	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 	<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
 	<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
-	<uses-permission android:name="android.permission.BLUETOOTH" />
-	<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
 	<uses-permission android:name="android.permission.CAMERA" />
 	<uses-permission android:name="android.permission.INTERNET" />
 	<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
@@ -42,6 +40,7 @@
 		android:name="org.briarproject.briar.android.BriarApplicationImpl"
 		android:allowBackup="false"
 		android:banner="@mipmap/tv_banner"
+		android:dataExtractionRules="@xml/backup_extraction_rules"
 		android:fullBackupContent="@xml/backup_rules"
 		android:icon="@mipmap/ic_launcher_round"
 		android:label="@string/app_name"
@@ -49,8 +48,7 @@
 		android:networkSecurityConfig="@xml/network_security_config"
 		android:supportsRtl="true"
 		android:theme="@style/BriarTheme"
-		tools:ignore="GoogleAppIndexingWarning,UnusedAttribute"
-		tools:targetApi="16">
+		tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
 
 		<receiver
 			android:name="org.briarproject.briar.android.login.SignInReminderReceiver"
@@ -98,22 +96,27 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.splash.ExpiredActivity"
+			android:exported="false"
 			android:label="@string/app_name" />
 
 		<activity
 			android:name="org.briarproject.briar.android.splash.ExpiredOldAndroidActivity"
+			android:exported="false"
 			android:label="@string/app_name" />
 
 		<activity
 			android:name="org.briarproject.briar.android.login.StartupActivity"
+			android:exported="false"
 			android:label="@string/app_name" />
 
 		<activity
 			android:name="org.briarproject.briar.android.account.SetupActivity"
+			android:exported="false"
 			android:label="@string/setup_title" />
 
 		<activity
 			android:name="org.briarproject.briar.android.splash.SplashScreenActivity"
+			android:exported="true"
 			android:label="@string/app_name"
 			android:theme="@style/BriarTheme.NoActionBar">
 			<intent-filter>
@@ -126,6 +129,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
+			android:exported="true"
 			android:launchMode="singleTask"
 			android:theme="@style/BriarTheme.NoActionBar">
 			<intent-filter android:label="@string/add_contact_remotely_title_case">
@@ -145,6 +149,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.conversation.ConversationActivity"
+			android:exported="false"
 			android:label="@string/app_name"
 			android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
 			android:theme="@style/BriarTheme.NoActionBar"
@@ -156,6 +161,7 @@
 
 		<activity
 			android:name=".android.conversation.ImageActivity"
+			android:exported="false"
 			android:parentActivityName="org.briarproject.briar.android.conversation.ConversationActivity"
 			android:theme="@style/BriarTheme.ActionBarOverlay">
 			<meta-data
@@ -165,6 +171,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.privategroup.creation.CreateGroupActivity"
+			android:exported="false"
 			android:label="@string/groups_create_group_title"
 			android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
 			android:windowSoftInputMode="adjustResize|stateAlwaysVisible">
@@ -175,6 +182,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.privategroup.conversation.GroupActivity"
+			android:exported="false"
 			android:label="@string/app_name"
 			android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
 			android:theme="@style/BriarTheme.NoActionBar"
@@ -186,6 +194,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.privategroup.invitation.GroupInvitationActivity"
+			android:exported="false"
 			android:label="@string/groups_invitations_title"
 			android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity">
 			<meta-data
@@ -195,6 +204,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.privategroup.memberlist.GroupMemberListActivity"
+			android:exported="false"
 			android:label="@string/groups_member_list"
 			android:parentActivityName="org.briarproject.briar.android.privategroup.conversation.GroupActivity">
 			<meta-data
@@ -204,6 +214,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.privategroup.reveal.RevealContactsActivity"
+			android:exported="false"
 			android:label="@string/groups_reveal_contacts"
 			android:parentActivityName="org.briarproject.briar.android.privategroup.conversation.GroupActivity">
 			<meta-data
@@ -213,6 +224,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.privategroup.creation.GroupInviteActivity"
+			android:exported="false"
 			android:label="@string/groups_invite_members"
 			android:parentActivityName="org.briarproject.briar.android.privategroup.conversation.GroupActivity"
 			android:windowSoftInputMode="adjustResize|stateHidden">
@@ -223,6 +235,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.sharing.ForumInvitationActivity"
+			android:exported="false"
 			android:label="@string/forum_invitations_title"
 			android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity">
 			<meta-data
@@ -232,6 +245,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.sharing.BlogInvitationActivity"
+			android:exported="false"
 			android:label="@string/blogs_sharing_invitations_title"
 			android:parentActivityName="org.briarproject.briar.android.conversation.ConversationActivity">
 			<meta-data
@@ -241,6 +255,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.forum.CreateForumActivity"
+			android:exported="false"
 			android:label="@string/create_forum_title"
 			android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
 			android:windowSoftInputMode="adjustResize|stateAlwaysVisible">
@@ -251,6 +266,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.forum.ForumActivity"
+			android:exported="false"
 			android:label="@string/app_name"
 			android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
 			android:theme="@style/BriarTheme.NoActionBar"
@@ -262,6 +278,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.sharing.ShareForumActivity"
+			android:exported="false"
 			android:label="@string/activity_share_toolbar_header"
 			android:parentActivityName="org.briarproject.briar.android.forum.ForumActivity"
 			android:windowSoftInputMode="adjustResize|stateHidden">
@@ -272,6 +289,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.sharing.ShareBlogActivity"
+			android:exported="false"
 			android:label="@string/activity_share_toolbar_header"
 			android:parentActivityName="org.briarproject.briar.android.blog.BlogActivity"
 			android:windowSoftInputMode="adjustResize|stateHidden">
@@ -282,6 +300,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.sharing.ForumSharingStatusActivity"
+			android:exported="false"
 			android:label="@string/sharing_status"
 			android:parentActivityName="org.briarproject.briar.android.forum.ForumActivity">
 			<meta-data
@@ -291,6 +310,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.sharing.BlogSharingStatusActivity"
+			android:exported="false"
 			android:label="@string/sharing_status"
 			android:parentActivityName="org.briarproject.briar.android.blog.BlogActivity">
 			<meta-data
@@ -300,6 +320,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.blog.BlogActivity"
+			android:exported="false"
 			android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
 			android:theme="@style/BriarTheme.NoActionBar">
 			<meta-data
@@ -309,6 +330,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.blog.WriteBlogPostActivity"
+			android:exported="false"
 			android:label="@string/blogs_write_blog_post"
 			android:parentActivityName="org.briarproject.briar.android.blog.BlogActivity"
 			android:windowSoftInputMode="adjustResize|stateAlwaysVisible">
@@ -319,6 +341,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.blog.ReblogActivity"
+			android:exported="false"
 			android:label="@string/blogs_reblog_button"
 			android:parentActivityName="org.briarproject.briar.android.blog.BlogActivity"
 			android:windowSoftInputMode="adjustResize|stateHidden">
@@ -329,6 +352,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.contact.add.nearby.AddNearbyContactActivity"
+			android:exported="false"
 			android:label="@string/add_contact_title"
 			android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
 			android:theme="@style/BriarTheme.NoActionBar">
@@ -339,6 +363,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.introduction.IntroductionActivity"
+			android:exported="false"
 			android:label="@string/introduction_activity_title"
 			android:parentActivityName="org.briarproject.briar.android.conversation.ConversationActivity"
 			android:windowSoftInputMode="adjustResize|stateHidden">
@@ -359,6 +384,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.settings.SettingsActivity"
+			android:exported="false"
 			android:label="@string/settings_button"
 			android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
 			android:permission="android.permission.READ_NETWORK_USAGE_HISTORY">
@@ -373,6 +399,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.navdrawer.TransportsActivity"
+			android:exported="false"
 			android:label="@string/network_settings_title"
 			android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity">
 			<meta-data
@@ -382,6 +409,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.login.ChangePasswordActivity"
+			android:exported="false"
 			android:label="@string/change_password"
 			android:parentActivityName="org.briarproject.briar.android.settings.SettingsActivity"
 			android:windowSoftInputMode="adjustResize|stateAlwaysVisible">
@@ -392,6 +420,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.test.TestDataActivity"
+			android:exported="false"
 			android:label="Create test data"
 			android:parentActivityName="org.briarproject.briar.android.settings.SettingsActivity">
 			<meta-data
@@ -401,6 +430,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.panic.PanicPreferencesActivity"
+			android:exported="false"
 			android:label="@string/panic_setting"
 			android:parentActivityName="org.briarproject.briar.android.settings.SettingsActivity">
 			<meta-data
@@ -410,6 +440,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.panic.PanicResponderActivity"
+			android:exported="true"
 			android:noHistory="true"
 			android:theme="@style/TranslucentTheme">
 			<!-- this can never have launchMode singleTask or singleInstance! -->
@@ -421,26 +452,31 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.logout.ExitActivity"
+			android:exported="false"
 			android:theme="@android:style/Theme.NoDisplay" />
 
 		<activity
 			android:name=".android.logout.HideUiActivity"
+			android:exported="false"
 			android:theme="@android:style/Theme.NoDisplay" />
 
 		<activity
 			android:name=".android.account.UnlockActivity"
+			android:exported="false"
 			android:label="@string/lock_unlock"
 			android:launchMode="singleTask"
 			android:theme="@style/BriarTheme.NoActionBar" />
 
 		<activity
 			android:name=".android.contact.add.remote.AddContactActivity"
+			android:exported="false"
 			android:label="@string/add_contact_remotely_title_case"
 			android:theme="@style/BriarTheme"
 			android:windowSoftInputMode="adjustResize|stateHidden" />
 
 		<activity
 			android:name="org.briarproject.briar.android.blog.RssFeedActivity"
+			android:exported="false"
 			android:label="@string/blogs_rss_feeds"
 			android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity">
 			<meta-data
@@ -450,6 +486,7 @@
 
 		<activity
 			android:name="org.briarproject.briar.android.removabledrive.RemovableDriveActivity"
+			android:exported="false"
 			android:label="@string/removable_drive_menu_title"
 			android:parentActivityName="org.briarproject.briar.android.conversation.ConversationActivity">
 			<meta-data
@@ -459,11 +496,13 @@
 
 		<activity
 			android:name=".android.contact.add.remote.PendingContactListActivity"
+			android:exported="false"
 			android:label="@string/pending_contact_requests"
 			android:theme="@style/BriarTheme" />
 
 		<activity
 			android:name=".android.hotspot.HotspotActivity"
+			android:exported="false"
 			android:label="@string/hotspot_title"
 			android:theme="@style/BriarTheme" />
 
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AndroidNotificationManagerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/AndroidNotificationManagerImpl.java
index 64b53bc93eb82ccda155987de8cfe08b10f26376..08fe7067b9f0598a110205abe1647a0ed806dddc 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/AndroidNotificationManagerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/AndroidNotificationManagerImpl.java
@@ -69,6 +69,7 @@ import static android.app.Notification.DEFAULT_VIBRATE;
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.PendingIntent.getActivity;
+import static android.app.PendingIntent.getBroadcast;
 import static android.content.Context.NOTIFICATION_SERVICE;
 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -83,6 +84,7 @@ import static androidx.core.app.NotificationCompat.PRIORITY_LOW;
 import static androidx.core.app.NotificationCompat.PRIORITY_MIN;
 import static androidx.core.app.NotificationCompat.VISIBILITY_SECRET;
 import static androidx.core.content.ContextCompat.getColor;
+import static org.briarproject.bramble.util.AndroidUtils.getImmutableFlags;
 import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
 import static org.briarproject.briar.android.conversation.ConversationActivity.CONTACT_ID;
 import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.BLOG_URI;
@@ -291,7 +293,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 		b.setWhen(0); // Don't show the time
 		b.setOngoing(true);
 		Intent i = new Intent(appContext, SplashScreenActivity.class);
-		b.setContentIntent(getActivity(appContext, 0, i, 0));
+		b.setContentIntent(getActivity(appContext, 0, i, getImmutableFlags(0)));
 		if (SDK_INT >= 21) {
 			b.setCategory(CATEGORY_SERVICE);
 			b.setVisibility(VISIBILITY_SECRET);
@@ -351,7 +353,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 				TaskStackBuilder t = TaskStackBuilder.create(appContext);
 				t.addParentStack(ConversationActivity.class);
 				t.addNextIntent(i);
-				b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
+				b.setContentIntent(t.getPendingIntent(nextRequestId++,
+						getImmutableFlags(0)));
 			} else {
 				// Touching the notification shows the contact list
 				Intent i = new Intent(appContext, NavDrawerActivity.class);
@@ -360,7 +363,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 				TaskStackBuilder t = TaskStackBuilder.create(appContext);
 				t.addParentStack(NavDrawerActivity.class);
 				t.addNextIntent(i);
-				b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
+				b.setContentIntent(t.getPendingIntent(nextRequestId++,
+						getImmutableFlags(0)));
 			}
 			notificationManager.notify(PRIVATE_MESSAGE_NOTIFICATION_ID,
 					b.build());
@@ -399,7 +403,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 		Intent i = new Intent(appContext, NotificationCleanupService.class);
 		i.setData(uri);
 		b.setDeleteIntent(PendingIntent.getService(appContext, nextRequestId++,
-				i, 0));
+				i, getImmutableFlags(0)));
 	}
 
 	@Override
@@ -454,7 +458,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 				TaskStackBuilder t = TaskStackBuilder.create(appContext);
 				t.addParentStack(GroupActivity.class);
 				t.addNextIntent(i);
-				b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
+				b.setContentIntent(t.getPendingIntent(nextRequestId++,
+						getImmutableFlags(0)));
 			} else {
 				// Touching the notification shows the group list
 				Intent i = new Intent(appContext, NavDrawerActivity.class);
@@ -463,7 +468,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 				TaskStackBuilder t = TaskStackBuilder.create(appContext);
 				t.addParentStack(NavDrawerActivity.class);
 				t.addNextIntent(i);
-				b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
+				b.setContentIntent(t.getPendingIntent(nextRequestId++,
+						getImmutableFlags(0)));
 			}
 			notificationManager.notify(GROUP_MESSAGE_NOTIFICATION_ID,
 					b.build());
@@ -522,7 +528,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 				TaskStackBuilder t = TaskStackBuilder.create(appContext);
 				t.addParentStack(ForumActivity.class);
 				t.addNextIntent(i);
-				b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
+				b.setContentIntent(t.getPendingIntent(nextRequestId++,
+						getImmutableFlags(0)));
 			} else {
 				// Touching the notification shows the forum list
 				Intent i = new Intent(appContext, NavDrawerActivity.class);
@@ -531,7 +538,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 				TaskStackBuilder t = TaskStackBuilder.create(appContext);
 				t.addParentStack(NavDrawerActivity.class);
 				t.addNextIntent(i);
-				b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
+				b.setContentIntent(t.getPendingIntent(nextRequestId++,
+						getImmutableFlags(0)));
 			}
 			notificationManager.notify(FORUM_POST_NOTIFICATION_ID, b.build());
 		}
@@ -583,7 +591,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 			TaskStackBuilder t = TaskStackBuilder.create(appContext);
 			t.addParentStack(NavDrawerActivity.class);
 			t.addNextIntent(i);
-			b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
+			b.setContentIntent(
+					t.getPendingIntent(nextRequestId++, getImmutableFlags(0)));
 
 			notificationManager.notify(BLOG_POST_NOTIFICATION_ID, b.build());
 		}
@@ -621,7 +630,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 		TaskStackBuilder t = TaskStackBuilder.create(appContext);
 		t.addParentStack(NavDrawerActivity.class);
 		t.addNextIntent(i);
-		b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
+		b.setContentIntent(
+				t.getPendingIntent(nextRequestId++, getImmutableFlags(0)));
 
 		notificationManager.notify(CONTACT_ADDED_NOTIFICATION_ID,
 				b.build());
@@ -662,12 +672,12 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 		Intent i1 = new Intent(appContext, SignInReminderReceiver.class);
 		i1.setAction(ACTION_DISMISS_REMINDER);
 		PendingIntent actionIntent =
-				PendingIntent.getBroadcast(appContext, 0, i1, 0);
+				getBroadcast(appContext, 0, i1, getImmutableFlags(0));
 		b.addAction(0, actionTitle, actionIntent);
 
 		Intent i = new Intent(appContext, SplashScreenActivity.class);
 		i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP);
-		b.setContentIntent(getActivity(appContext, 0, i, 0));
+		b.setContentIntent(getActivity(appContext, 0, i, getImmutableFlags(0)));
 
 		notificationManager.notify(REMINDER_NOTIFICATION_ID, b.build());
 	}
@@ -761,7 +771,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 		Intent i = new Intent(appContext, HotspotActivity.class);
 		i.addFlags(FLAG_ACTIVITY_SINGLE_TOP);
 		i.setAction(ACTION_STOP_HOTSPOT);
-		PendingIntent actionIntent = getActivity(appContext, 0, i, 0);
+		PendingIntent actionIntent =
+				getActivity(appContext, 0, i, getImmutableFlags(0));
 		int icon = SDK_INT >= 21 ? R.drawable.ic_portable_wifi_off : 0;
 		b.addAction(icon, actionTitle, actionIntent);
 		notificationManager.notify(HOTSPOT_NOTIFICATION_ID, b.build());
@@ -803,7 +814,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 		TaskStackBuilder t = TaskStackBuilder.create(appContext);
 		t.addParentStack(MailboxActivity.class);
 		t.addNextIntent(i);
-		b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
+		b.setContentIntent(
+				t.getPendingIntent(nextRequestId++, getImmutableFlags(0)));
 
 		notificationManager.notify(MAILBOX_PROBLEM_NOTIFICATION_ID, b.build());
 	}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/account/LockManagerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/account/LockManagerImpl.java
index 5ace463a3a3d6de73e0f26a84669a1e88815617f..d48500290e922392627c3453577cace7b3a65442 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/account/LockManagerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/account/LockManagerImpl.java
@@ -39,6 +39,7 @@ import static android.os.Process.myPid;
 import static android.os.SystemClock.elapsedRealtime;
 import static java.util.concurrent.TimeUnit.MINUTES;
 import static java.util.logging.Level.WARNING;
+import static org.briarproject.bramble.util.AndroidUtils.getImmutableFlags;
 import static org.briarproject.bramble.util.LogUtils.logException;
 import static org.briarproject.briar.android.settings.SecurityFragment.PREF_SCREEN_LOCK;
 import static org.briarproject.briar.android.settings.SecurityFragment.PREF_SCREEN_LOCK_TIMEOUT;
@@ -87,7 +88,8 @@ public class LockManagerImpl implements LockManager, Service, EventListener {
 				new Intent(ACTION_LOCK, null, appContext, BriarService.class);
 		i.putExtra(EXTRA_PID, myPid());
 		// When not using FLAG_UPDATE_CURRENT, the intent might have no extras
-		lockIntent = getService(appContext, 0, i, FLAG_UPDATE_CURRENT);
+		lockIntent = getService(appContext, 0, i,
+				getImmutableFlags(FLAG_UPDATE_CURRENT));
 		timeoutNever = Integer.parseInt(
 				appContext.getString(R.string.pref_lock_timeout_value_never));
 		timeoutDefault = Integer.parseInt(
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/nearby/AddNearbyContactPermissionManager.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/nearby/AddNearbyContactPermissionManager.java
index f40dbe094890a35cc5cd0cea9c9c5abb2d9bd494..316c787119c99b8634f7c6b82974ce124a5e586c 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/nearby/AddNearbyContactPermissionManager.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/nearby/AddNearbyContactPermissionManager.java
@@ -11,20 +11,31 @@ import androidx.core.util.Consumer;
 import androidx.fragment.app.FragmentActivity;
 
 import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.Manifest.permission.BLUETOOTH_ADVERTISE;
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_SCAN;
 import static android.Manifest.permission.CAMERA;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.Build.VERSION.SDK_INT;
 import static androidx.core.app.ActivityCompat.shouldShowRequestPermissionRationale;
 import static androidx.core.content.ContextCompat.checkSelfPermission;
-import static org.briarproject.briar.android.util.UiUtils.isLocationEnabled;
-import static org.briarproject.briar.android.util.UiUtils.showDenialDialog;
-import static org.briarproject.briar.android.util.UiUtils.showLocationDialog;
-import static org.briarproject.briar.android.util.UiUtils.showRationale;
+import static org.briarproject.briar.android.util.Permission.GRANTED;
+import static org.briarproject.briar.android.util.Permission.PERMANENTLY_DENIED;
+import static org.briarproject.briar.android.util.Permission.SHOW_RATIONALE;
+import static org.briarproject.briar.android.util.Permission.UNKNOWN;
+import static org.briarproject.briar.android.util.PermissionUtils.areBluetoothPermissionsGranted;
+import static org.briarproject.briar.android.util.PermissionUtils.gotPermission;
+import static org.briarproject.briar.android.util.PermissionUtils.isLocationEnabledForBt;
+import static org.briarproject.briar.android.util.PermissionUtils.showDenialDialog;
+import static org.briarproject.briar.android.util.PermissionUtils.showLocationDialog;
+import static org.briarproject.briar.android.util.PermissionUtils.showRationale;
+import static org.briarproject.briar.android.util.PermissionUtils.wasGrantedBluetoothPermissions;
 
 class AddNearbyContactPermissionManager {
 
-	private Permission cameraPermission = Permission.UNKNOWN;
-	private Permission locationPermission = Permission.UNKNOWN;
+	private Permission cameraPermission = UNKNOWN;
+	private Permission locationPermission = SDK_INT < 31 ? UNKNOWN : GRANTED;
+	private Permission bluetoothPermissions = SDK_INT < 31 ? GRANTED : UNKNOWN;
 
 	private final FragmentActivity ctx;
 	private final Consumer<String[]> requestPermissions;
@@ -39,55 +50,76 @@ class AddNearbyContactPermissionManager {
 	}
 
 	void resetPermissions() {
-		cameraPermission = Permission.UNKNOWN;
-		locationPermission = Permission.UNKNOWN;
+		cameraPermission = UNKNOWN;
+		locationPermission = SDK_INT < 31 ? UNKNOWN : GRANTED;
+		bluetoothPermissions = SDK_INT < 31 ? GRANTED : UNKNOWN;
 	}
 
 	static boolean areEssentialPermissionsGranted(Context ctx,
 			boolean isBluetoothSupported) {
 		int ok = PERMISSION_GRANTED;
-		return checkSelfPermission(ctx, CAMERA) == ok &&
-				(SDK_INT < 23 ||
-						checkSelfPermission(ctx, ACCESS_FINE_LOCATION) == ok ||
-						!isBluetoothSupported);
+		boolean bluetoothOk;
+		if (!isBluetoothSupported || SDK_INT < 23) {
+			bluetoothOk = true;
+		} else if (SDK_INT < 31) {
+			bluetoothOk = checkSelfPermission(ctx, ACCESS_FINE_LOCATION) == ok;
+		} else {
+			bluetoothOk = areBluetoothPermissionsGranted(ctx);
+		}
+		return bluetoothOk && checkSelfPermission(ctx, CAMERA) == ok;
 	}
 
 	private boolean areEssentialPermissionsGranted() {
-		return cameraPermission == Permission.GRANTED &&
-				(SDK_INT < 23 || locationPermission == Permission.GRANTED ||
-						!isBluetoothSupported);
+		boolean bluetoothGranted = locationPermission == GRANTED &&
+				bluetoothPermissions == GRANTED;
+		return cameraPermission == GRANTED &&
+				(SDK_INT < 23 || !isBluetoothSupported || bluetoothGranted);
 	}
 
 	boolean checkPermissions() {
-		boolean locationEnabled = isLocationEnabled(ctx);
+		boolean locationEnabled = isLocationEnabledForBt(ctx);
 		if (locationEnabled && areEssentialPermissionsGranted()) return true;
 		// If an essential permission has been permanently denied, ask the
 		// user to change the setting
-		if (cameraPermission == Permission.PERMANENTLY_DENIED) {
+		if (cameraPermission == PERMANENTLY_DENIED) {
 			showDenialDialog(ctx, R.string.permission_camera_title,
 					R.string.permission_camera_denied_body);
 			return false;
 		}
-		if (isBluetoothSupported &&
-				locationPermission == Permission.PERMANENTLY_DENIED) {
+		if (isBluetoothSupported && locationPermission == PERMANENTLY_DENIED) {
 			showDenialDialog(ctx, R.string.permission_location_title,
 					R.string.permission_location_denied_body);
 			return false;
 		}
+		if (isBluetoothSupported &&
+				bluetoothPermissions == PERMANENTLY_DENIED) {
+			showDenialDialog(ctx, R.string.permission_bluetooth_title,
+					R.string.permission_bluetooth_denied_body);
+			return false;
+		}
 		// Should we show the rationale for one or both permissions?
-		if (cameraPermission == Permission.SHOW_RATIONALE &&
-				locationPermission == Permission.SHOW_RATIONALE) {
+		if (cameraPermission == SHOW_RATIONALE &&
+				locationPermission == SHOW_RATIONALE) {
 			showRationale(ctx, R.string.permission_camera_location_title,
 					R.string.permission_camera_location_request_body,
 					this::requestPermissions);
-		} else if (cameraPermission == Permission.SHOW_RATIONALE) {
+		} else if (cameraPermission == SHOW_RATIONALE &&
+				bluetoothPermissions == SHOW_RATIONALE) {
+			showRationale(ctx, R.string.permission_camera_bluetooth_title,
+					R.string.permission_camera_bluetooth_request_body,
+					this::requestPermissions);
+		} else if (cameraPermission == SHOW_RATIONALE) {
 			showRationale(ctx, R.string.permission_camera_title,
 					R.string.permission_camera_request_body,
 					this::requestPermissions);
-		} else if (locationPermission == Permission.SHOW_RATIONALE) {
+		} else if (locationPermission == SHOW_RATIONALE) {
 			showRationale(ctx, R.string.permission_location_title,
 					R.string.permission_location_request_body,
 					this::requestPermissions);
+		} else if (bluetoothPermissions == SHOW_RATIONALE) {
+			showRationale(ctx, R.string.permission_bluetooth_title,
+					R.string.permission_bluetooth_body,
+					this::requestPermissions);
 		} else if (locationEnabled) {
 			requestPermissions();
 		} else {
@@ -99,7 +131,12 @@ class AddNearbyContactPermissionManager {
 	private void requestPermissions() {
 		String[] permissions;
 		if (isBluetoothSupported) {
-			permissions = new String[] {CAMERA, ACCESS_FINE_LOCATION};
+			if (SDK_INT < 31) {
+				permissions = new String[] {CAMERA, ACCESS_FINE_LOCATION};
+			} else {
+				permissions = new String[] {CAMERA, BLUETOOTH_ADVERTISE,
+						BLUETOOTH_CONNECT, BLUETOOTH_SCAN};
+			}
 		} else {
 			permissions = new String[] {CAMERA};
 		}
@@ -107,35 +144,34 @@ class AddNearbyContactPermissionManager {
 	}
 
 	void onRequestPermissionResult(Map<String, Boolean> result) {
-		if (gotPermission(CAMERA, result)) {
-			cameraPermission = Permission.GRANTED;
+		if (gotPermission(ctx, result, CAMERA)) {
+			cameraPermission = GRANTED;
 		} else if (shouldShowRationale(CAMERA)) {
-			cameraPermission = Permission.SHOW_RATIONALE;
+			cameraPermission = SHOW_RATIONALE;
 		} else {
-			cameraPermission = Permission.PERMANENTLY_DENIED;
+			cameraPermission = PERMANENTLY_DENIED;
 		}
 		if (isBluetoothSupported) {
-			if (gotPermission(ACCESS_FINE_LOCATION, result)) {
-				locationPermission = Permission.GRANTED;
-			} else if (shouldShowRationale(ACCESS_FINE_LOCATION)) {
-				locationPermission = Permission.SHOW_RATIONALE;
+			if (SDK_INT < 31) {
+				if (gotPermission(ctx, result, ACCESS_FINE_LOCATION)) {
+					locationPermission = GRANTED;
+				} else if (shouldShowRationale(ACCESS_FINE_LOCATION)) {
+					locationPermission = SHOW_RATIONALE;
+				} else {
+					locationPermission = PERMANENTLY_DENIED;
+				}
 			} else {
-				locationPermission = Permission.PERMANENTLY_DENIED;
+				if (wasGrantedBluetoothPermissions(ctx, result)) {
+					bluetoothPermissions = GRANTED;
+				} else if (shouldShowRationale(BLUETOOTH_CONNECT)) {
+					bluetoothPermissions = SHOW_RATIONALE;
+				} else {
+					bluetoothPermissions = PERMANENTLY_DENIED;
+				}
 			}
 		}
 	}
 
-	private boolean gotPermission(String permission,
-			Map<String, Boolean> result) {
-		Boolean permissionResult = result.get(permission);
-		return permissionResult == null ?
-				isGranted(permission) : permissionResult;
-	}
-
-	private boolean isGranted(String permission) {
-		return checkSelfPermission(ctx, permission) == PERMISSION_GRANTED;
-	}
-
 	private boolean shouldShowRationale(String permission) {
 		return shouldShowRequestPermissionRationale(ctx, permission);
 	}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/nearby/AddNearbyContactViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/nearby/AddNearbyContactViewModel.java
index f5c543145c03034c0c38328dd6a479974ae48b68..18351c64c4ff9ec354a9b4f258b3708a91b316ce 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/contact/add/nearby/AddNearbyContactViewModel.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/add/nearby/AddNearbyContactViewModel.java
@@ -1,5 +1,6 @@
 package org.briarproject.briar.android.contact.add.nearby;
 
+import android.annotation.SuppressLint;
 import android.app.Application;
 import android.bluetooth.BluetoothAdapter;
 import android.content.BroadcastReceiver;
@@ -88,8 +89,8 @@ import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContact
 import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision.NO_ADAPTER;
 import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision.REFUSED;
 import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision.UNKNOWN;
+import static org.briarproject.briar.android.util.PermissionUtils.isLocationEnabledForBt;
 import static org.briarproject.briar.android.util.UiUtils.handleException;
-import static org.briarproject.briar.android.util.UiUtils.isLocationEnabled;
 
 @NotNullByDefault
 class AddNearbyContactViewModel extends AndroidViewModel
@@ -250,6 +251,7 @@ class AddNearbyContactViewModel extends AndroidViewModel
 	}
 
 	@UiThread
+	@SuppressLint("MissingPermission") // we check permissions before
 	private boolean isBluetoothReady() {
 		if (bt == null || bluetoothPlugin == null) {
 			// Continue without Bluetooth
@@ -394,7 +396,7 @@ class AddNearbyContactViewModel extends AndroidViewModel
 	void showQrCodeFragmentIfAllowed() {
 		boolean permissionsGranted = areEssentialPermissionsGranted(
 				getApplication(), isBluetoothSupported());
-		boolean locationEnabled = isLocationEnabled(getApplication());
+		boolean locationEnabled = isLocationEnabledForBt(getApplication());
 		if (wasContinueClicked && permissionsGranted && locationEnabled) {
 			if (isWifiReady() && isBluetoothReady()) {
 				LOG.info("Wifi and Bluetooth are ready");
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/connect/BluetoothConditionManager.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/connect/BluetoothConditionManager.java
index 7a8ac1d9ae0bb15099ad1b180d5fd077317f4d02..b5e369c2402f832c11d90dcce2dfcf9d0e0f4d16 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/contact/connect/BluetoothConditionManager.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/connect/BluetoothConditionManager.java
@@ -1,84 +1,120 @@
 package org.briarproject.briar.android.contact.connect;
 
 import android.app.Activity;
-import android.content.Context;
+import android.widget.Toast;
 
 import org.briarproject.briar.R;
 import org.briarproject.briar.android.util.Permission;
 
+import java.util.Map;
+
 import androidx.activity.result.ActivityResultLauncher;
 import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
-import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentActivity;
 
 import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
 import static android.os.Build.VERSION.SDK_INT;
+import static android.widget.Toast.LENGTH_LONG;
 import static androidx.core.app.ActivityCompat.shouldShowRequestPermissionRationale;
-import static org.briarproject.briar.android.util.UiUtils.getGoToSettingsListener;
-import static org.briarproject.briar.android.util.UiUtils.isLocationEnabled;
-import static org.briarproject.briar.android.util.UiUtils.showLocationDialog;
+import static org.briarproject.briar.android.util.Permission.GRANTED;
+import static org.briarproject.briar.android.util.Permission.PERMANENTLY_DENIED;
+import static org.briarproject.briar.android.util.Permission.SHOW_RATIONALE;
+import static org.briarproject.briar.android.util.Permission.UNKNOWN;
+import static org.briarproject.briar.android.util.PermissionUtils.gotPermission;
+import static org.briarproject.briar.android.util.PermissionUtils.isLocationEnabledForBt;
+import static org.briarproject.briar.android.util.PermissionUtils.requestBluetoothPermissions;
+import static org.briarproject.briar.android.util.PermissionUtils.showDenialDialog;
+import static org.briarproject.briar.android.util.PermissionUtils.showLocationDialog;
+import static org.briarproject.briar.android.util.PermissionUtils.showRationale;
+import static org.briarproject.briar.android.util.PermissionUtils.wasGrantedBluetoothPermissions;
 
 class BluetoothConditionManager {
 
-	private Permission locationPermission = Permission.UNKNOWN;
+	private Permission locationPermission = SDK_INT < 31 ? UNKNOWN : GRANTED;
+	private Permission bluetoothPermissions = SDK_INT < 31 ? GRANTED : UNKNOWN;
 
 	/**
 	 * Call this when the using activity or fragment starts,
 	 * because permissions might have changed while it was stopped.
 	 */
 	void reset() {
-		locationPermission = Permission.UNKNOWN;
+		locationPermission = SDK_INT < 31 ? UNKNOWN : GRANTED;
+		bluetoothPermissions = SDK_INT < 31 ? GRANTED : UNKNOWN;
+	}
+
+	@UiThread
+	void requestPermissions(ActivityResultLauncher<String[]> launcher) {
+		if (SDK_INT < 31) {
+			requestLocationPermission(launcher);
+		} else {
+			requestBluetoothPermissions(launcher);
+		}
 	}
 
 	@UiThread
 	void onLocationPermissionResult(Activity activity,
-			@Nullable Boolean result) {
-		if (result != null && result) {
-			locationPermission = Permission.GRANTED;
-		} else if (shouldShowRequestPermissionRationale(activity,
-				ACCESS_FINE_LOCATION)) {
-			locationPermission = Permission.SHOW_RATIONALE;
+			@Nullable Map<String, Boolean> result) {
+		if (SDK_INT < 31) {
+			if (gotPermission(activity, result, ACCESS_FINE_LOCATION)) {
+				locationPermission = GRANTED;
+			} else if (shouldShowRequestPermissionRationale(activity,
+					ACCESS_FINE_LOCATION)) {
+				locationPermission = SHOW_RATIONALE;
+			} else {
+				locationPermission = PERMANENTLY_DENIED;
+			}
 		} else {
-			locationPermission = Permission.PERMANENTLY_DENIED;
+			if (wasGrantedBluetoothPermissions(activity, result)) {
+				bluetoothPermissions = GRANTED;
+			} else if (shouldShowRequestPermissionRationale(activity,
+					BLUETOOTH_CONNECT)) {
+				bluetoothPermissions = SHOW_RATIONALE;
+			} else {
+				bluetoothPermissions = PERMANENTLY_DENIED;
+			}
 		}
 	}
 
-	boolean areRequirementsFulfilled(Context ctx,
-			ActivityResultLauncher<String> permissionRequest,
+	boolean areRequirementsFulfilled(FragmentActivity ctx,
+			ActivityResultLauncher<String[]> permissionRequest,
 			Runnable onLocationDenied) {
 		boolean permissionGranted =
-				SDK_INT < 23 || locationPermission == Permission.GRANTED;
-		boolean locationEnabled = isLocationEnabled(ctx);
+				(SDK_INT < 23 || locationPermission == GRANTED) &&
+						bluetoothPermissions == GRANTED;
+		boolean locationEnabled = isLocationEnabledForBt(ctx);
 		if (permissionGranted && locationEnabled) return true;
 
-		if (locationPermission == Permission.PERMANENTLY_DENIED) {
-			showDenialDialog(ctx, onLocationDenied);
-		} else if (locationPermission == Permission.SHOW_RATIONALE) {
-			showRationale(ctx, permissionRequest);
+		if (locationPermission == PERMANENTLY_DENIED) {
+			showDenialDialog(ctx, R.string.permission_location_title,
+					R.string.permission_location_denied_body, onLocationDenied);
+		} else if (locationPermission == SHOW_RATIONALE) {
+			showRationale(ctx, R.string.permission_location_title,
+					R.string.permission_location_request_body,
+					() -> requestLocationPermission(permissionRequest));
 		} else if (!locationEnabled) {
 			showLocationDialog(ctx);
+		} else if (bluetoothPermissions == PERMANENTLY_DENIED) {
+			Runnable onDenied = () -> Toast.makeText(ctx,
+					R.string.connect_via_bluetooth_no_bluetooth_permission,
+					LENGTH_LONG).show();
+			showDenialDialog(ctx, R.string.permission_bluetooth_title,
+					R.string.permission_bluetooth_denied_body, onDenied);
+		} else if (bluetoothPermissions == SHOW_RATIONALE && SDK_INT >= 31) {
+			// SDK_INT is checked to make linter happy, because
+			// requestBluetoothPermissions() requires SDK_INT 31
+			showRationale(ctx,
+					R.string.permission_bluetooth_title,
+					R.string.permission_bluetooth_body, () ->
+							requestBluetoothPermissions(permissionRequest));
 		}
 		return false;
 	}
 
-	private void showDenialDialog(Context ctx, Runnable onLocationDenied) {
-		new AlertDialog.Builder(ctx, R.style.BriarDialogTheme)
-				.setTitle(R.string.permission_location_title)
-				.setMessage(R.string.permission_location_denied_body)
-				.setPositiveButton(R.string.ok, getGoToSettingsListener(ctx))
-				.setNegativeButton(R.string.cancel, (v, d) ->
-						onLocationDenied.run())
-				.show();
-	}
-
-	private void showRationale(Context ctx,
-			ActivityResultLauncher<String> permissionRequest) {
-		new AlertDialog.Builder(ctx, R.style.BriarDialogTheme)
-				.setTitle(R.string.permission_location_title)
-				.setMessage(R.string.permission_location_request_body)
-				.setPositiveButton(R.string.ok, (dialog, which) ->
-						permissionRequest.launch(ACCESS_FINE_LOCATION))
-				.show();
+	private void requestLocationPermission(
+			ActivityResultLauncher<String[]> launcher) {
+		launcher.launch(new String[] {ACCESS_FINE_LOCATION});
 	}
 
 }
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/connect/BluetoothIntroFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/connect/BluetoothIntroFragment.java
index ed774bcd2d1d2be3a9b4b6aa60b52b098f91ef5c..2e2413f5182a68466fc4df76b5992c3e9db2a25c 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/contact/connect/BluetoothIntroFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/connect/BluetoothIntroFragment.java
@@ -1,6 +1,5 @@
 package org.briarproject.briar.android.contact.connect;
 
-import android.app.Activity;
 import android.content.Context;
 import android.os.Bundle;
 import android.view.LayoutInflater;
@@ -14,15 +13,17 @@ import org.briarproject.briar.android.util.ActivityLaunchers.RequestBluetoothDis
 import org.briarproject.nullsafety.MethodsNotNullByDefault;
 import org.briarproject.nullsafety.ParametersNotNullByDefault;
 
+import java.util.Map;
+
 import javax.inject.Inject;
 
 import androidx.activity.result.ActivityResultLauncher;
-import androidx.activity.result.contract.ActivityResultContracts.RequestPermission;
+import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions;
 import androidx.annotation.Nullable;
 import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
 import androidx.lifecycle.ViewModelProvider;
 
-import static android.Manifest.permission.ACCESS_FINE_LOCATION;
 import static android.widget.Toast.LENGTH_LONG;
 import static org.briarproject.briar.android.AppModule.getAndroidComponent;
 
@@ -42,8 +43,8 @@ public class BluetoothIntroFragment extends Fragment {
 	private final ActivityResultLauncher<Integer> bluetoothDiscoverableRequest =
 			registerForActivityResult(new RequestBluetoothDiscoverable(),
 					this::onBluetoothDiscoverable);
-	private final ActivityResultLauncher<String> permissionRequest =
-			registerForActivityResult(new RequestPermission(),
+	private final ActivityResultLauncher<String[]> permissionRequest =
+			registerForActivityResult(new RequestMultiplePermissions(),
 					this::onPermissionRequestResult);
 
 	@Override
@@ -80,12 +81,13 @@ public class BluetoothIntroFragment extends Fragment {
 			// if the permission is already granted.
 			// So we can use the request as a generic entry point
 			// to the whole flow.
-			permissionRequest.launch(ACCESS_FINE_LOCATION);
+			conditionManager.requestPermissions(permissionRequest);
 		}
 	}
 
-	private void onPermissionRequestResult(@Nullable Boolean result) {
-		Activity a = requireActivity();
+	private void onPermissionRequestResult(
+			@Nullable Map<String, Boolean> result) {
+		FragmentActivity a = requireActivity();
 		// update permission result in BluetoothConnecter
 		conditionManager.onLocationPermissionResult(a, result);
 		// what to do when the user denies granting the location permission
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/connect/ConnectViaBluetoothViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/connect/ConnectViaBluetoothViewModel.java
index 3a1cf0f754e2e5aa3a9406317116398118c81996..3f6a6c066d78d7ee836cbc307c12e34029703ccc 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/contact/connect/ConnectViaBluetoothViewModel.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/connect/ConnectViaBluetoothViewModel.java
@@ -46,6 +46,7 @@ import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_UUID;
 import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
 import static org.briarproject.bramble.util.LogUtils.logException;
 import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
+import static org.briarproject.briar.android.util.PermissionUtils.areBluetoothPermissionsGranted;
 
 @UiThread
 @NotNullByDefault
@@ -260,7 +261,8 @@ class ConnectViaBluetoothViewModel extends DbViewModel implements
 
 	private void stopConnecting() {
 		BluetoothPlugin bluetoothPlugin = this.bluetoothPlugin;
-		if (bluetoothPlugin != null) {
+		if (bluetoothPlugin != null &&
+				areBluetoothPermissionsGranted(getApplication())) {
 			bluetoothPlugin.stopDiscoverAndConnect();
 		}
 	}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/hotspot/AbstractConditionManager.java b/briar-android/src/main/java/org/briarproject/briar/android/hotspot/AbstractConditionManager.java
index d0e65a93f6b6a705ca220f95c69a4f790ba92c4a..edfef730342426784d2cc0fbbe9fa9c0da7c02bf 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/hotspot/AbstractConditionManager.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/hotspot/AbstractConditionManager.java
@@ -1,7 +1,6 @@
 package org.briarproject.briar.android.hotspot;
 
 import android.content.Context;
-import android.content.DialogInterface;
 import android.net.wifi.WifiManager;
 
 import org.briarproject.briar.R;
@@ -20,6 +19,12 @@ import static android.content.Context.WIFI_SERVICE;
  */
 abstract class AbstractConditionManager {
 
+	/**
+	 * Consumes false, if permissions have been denied. Then we don't call
+	 * {@link HotspotIntroFragment#startHotspotIfConditionsFulfilled()},
+	 * which would result in the same permission being requested again
+	 * immediately.
+	 */
 	final Consumer<Boolean> permissionUpdateCallback;
 	protected FragmentActivity ctx;
 	WifiManager wifiManager;
@@ -52,19 +57,6 @@ abstract class AbstractConditionManager {
 	 */
 	abstract boolean checkAndRequestConditions();
 
-	void showDenialDialog(FragmentActivity ctx,
-			@StringRes int title, @StringRes int body,
-			DialogInterface.OnClickListener onOkClicked, Runnable onDismiss) {
-		AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
-		builder.setTitle(title);
-		builder.setMessage(body);
-		builder.setPositiveButton(R.string.ok, onOkClicked);
-		builder.setNegativeButton(R.string.cancel,
-				(dialog, which) -> ctx.supportFinishAfterTransition());
-		builder.setOnDismissListener(dialog -> onDismiss.run());
-		builder.show();
-	}
-
 	void showRationale(Context ctx, @StringRes int title,
 			@StringRes int body, Runnable onContinueClicked,
 			Runnable onDismiss) {
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/hotspot/ConditionManager29.java b/briar-android/src/main/java/org/briarproject/briar/android/hotspot/ConditionManager29.java
index 071fbeeb6539c4cbe4fe4d9b1ca582bf13fb8d3e..64e39960573b45915671c23f0b2c8bb5396282f5 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/hotspot/ConditionManager29.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/hotspot/ConditionManager29.java
@@ -5,6 +5,7 @@ import android.provider.Settings;
 
 import org.briarproject.briar.R;
 import org.briarproject.briar.android.util.Permission;
+import org.briarproject.briar.android.util.PermissionUtils;
 
 import java.util.logging.Logger;
 
@@ -17,11 +18,13 @@ import androidx.annotation.RequiresApi;
 import androidx.core.util.Consumer;
 
 import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.os.Build.VERSION.SDK_INT;
 import static androidx.core.app.ActivityCompat.shouldShowRequestPermissionRationale;
 import static java.lang.Boolean.TRUE;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Logger.getLogger;
-import static org.briarproject.briar.android.util.UiUtils.getGoToSettingsListener;
+import static org.briarproject.briar.android.util.PermissionUtils.isLocationEnabledForWiFi;
+import static org.briarproject.briar.android.util.PermissionUtils.showLocationDialog;
 
 /**
  * This class ensures that the conditions to open a hotspot are fulfilled on
@@ -44,6 +47,7 @@ class ConditionManager29 extends AbstractConditionManager {
 	ConditionManager29(ActivityResultCaller arc,
 			Consumer<Boolean> permissionUpdateCallback) {
 		super(permissionUpdateCallback);
+		// permissionUpdateCallback receives false if permissions were denied
 		locationRequest = arc.registerForActivityResult(
 				new RequestPermission(), granted -> {
 					onRequestPermissionResult(granted);
@@ -63,13 +67,16 @@ class ConditionManager29 extends AbstractConditionManager {
 
 	private boolean areEssentialPermissionsGranted() {
 		boolean isWifiEnabled = wifiManager.isWifiEnabled();
+		boolean isLocationEnabled = isLocationEnabledForWiFi(ctx);
 		if (LOG.isLoggable(INFO)) {
 			LOG.info(String.format("areEssentialPermissionsGranted(): " +
 							"locationPermission? %s, " +
-							"wifiManager.isWifiEnabled()? %b",
-					locationPermission, isWifiEnabled));
+							"wifiManager.isWifiEnabled()? %b" +
+							"isLocationEnabled? %b",
+					locationPermission, isWifiEnabled, isLocationEnabled));
 		}
-		return locationPermission == Permission.GRANTED && isWifiEnabled;
+		return locationPermission == Permission.GRANTED && isWifiEnabled &&
+				isLocationEnabled;
 	}
 
 	@Override
@@ -77,24 +84,33 @@ class ConditionManager29 extends AbstractConditionManager {
 		if (areEssentialPermissionsGranted()) return true;
 
 		if (locationPermission == Permission.UNKNOWN) {
-			locationRequest.launch(ACCESS_FINE_LOCATION);
+			requestPermissions();
+			return false;
+		}
+		// ensure location is enabled (if needed on this device)
+		if (!isLocationEnabledForWiFi(ctx)) {
+			showLocationDialog(ctx, false);
 			return false;
 		}
 
 		// If the location permission has been permanently denied, ask the
 		// user to change the setting
 		if (locationPermission == Permission.PERMANENTLY_DENIED) {
-			showDenialDialog(ctx, R.string.permission_location_title,
-					R.string.permission_hotspot_location_denied_body,
-					getGoToSettingsListener(ctx),
+			int res = SDK_INT >= 31 ?
+					R.string.permission_hotspot_location_denied_precise_body :
+					R.string.permission_hotspot_location_denied_body;
+			PermissionUtils.showDenialDialog(ctx,
+					R.string.permission_location_title, res,
 					() -> permissionUpdateCallback.accept(false));
 			return false;
 		}
 
 		// Should we show the rationale for location permission?
 		if (locationPermission == Permission.SHOW_RATIONALE) {
-			showRationale(ctx, R.string.permission_location_title,
-					R.string.permission_hotspot_location_request_body,
+			int res = SDK_INT >= 31 ?
+					R.string.permission_hotspot_location_request_precise_body :
+					R.string.permission_hotspot_location_request_body;
+			showRationale(ctx, R.string.permission_location_title, res,
 					this::requestPermissions,
 					() -> permissionUpdateCallback.accept(false));
 			return false;
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/CameraPermissionManager.java b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/CameraPermissionManager.java
index 34e8191852949581b93f677a0bc8d4a0feb99826..331833c5c265f9229e7dabfcc0eaddb9f250b22a 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/CameraPermissionManager.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/CameraPermissionManager.java
@@ -14,8 +14,8 @@ import static android.Manifest.permission.CAMERA;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static androidx.core.app.ActivityCompat.shouldShowRequestPermissionRationale;
 import static androidx.core.content.ContextCompat.checkSelfPermission;
-import static org.briarproject.briar.android.util.UiUtils.showDenialDialog;
-import static org.briarproject.briar.android.util.UiUtils.showRationale;
+import static org.briarproject.briar.android.util.PermissionUtils.showDenialDialog;
+import static org.briarproject.briar.android.util.PermissionUtils.showRationale;
 
 class CameraPermissionManager {
 
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/TransportsActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/TransportsActivity.java
index 81de79aa4d9ca9f4eb245c833f17206424c7d3f4..65ebccb0755e5499da498bcd09c726e7059781f6 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/TransportsActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/TransportsActivity.java
@@ -26,18 +26,24 @@ import org.briarproject.nullsafety.ParametersNotNullByDefault;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 import javax.inject.Inject;
 
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions;
 import androidx.annotation.ColorRes;
 import androidx.annotation.DrawableRes;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 import androidx.annotation.StringRes;
 import androidx.appcompat.app.ActionBar;
 import androidx.appcompat.widget.SwitchCompat;
 import androidx.core.content.ContextCompat;
 import androidx.lifecycle.ViewModelProvider;
 
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.os.Build.VERSION.SDK_INT;
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
 import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
@@ -47,6 +53,11 @@ import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING
 import static org.briarproject.bramble.api.plugin.TorConstants.REASON_BATTERY;
 import static org.briarproject.bramble.api.plugin.TorConstants.REASON_COUNTRY_BLOCKED;
 import static org.briarproject.bramble.api.plugin.TorConstants.REASON_MOBILE_DATA;
+import static org.briarproject.briar.android.util.PermissionUtils.areBluetoothPermissionsGranted;
+import static org.briarproject.briar.android.util.PermissionUtils.requestBluetoothPermissions;
+import static org.briarproject.briar.android.util.PermissionUtils.showDenialDialog;
+import static org.briarproject.briar.android.util.PermissionUtils.showRationale;
+import static org.briarproject.briar.android.util.PermissionUtils.wasGrantedBluetoothPermissions;
 import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
 
 @MethodsNotNullByDefault
@@ -61,6 +72,11 @@ public class TransportsActivity extends BriarActivity {
 	private PluginViewModel viewModel;
 	private BaseAdapter transportsAdapter;
 
+	@RequiresApi(31)
+	private final ActivityResultLauncher<String[]> requestPermissionLauncher =
+			registerForActivityResult(new RequestMultiplePermissions(),
+					this::handleBtPermissionResult);
+
 	@Override
 	public void injectActivity(ActivityComponent component) {
 		component.inject(this);
@@ -149,8 +165,7 @@ public class TransportsActivity extends BriarActivity {
 						view.findViewById(R.id.switchCompat);
 				switchCompat.setText(getString(t.switchLabel));
 				switchCompat.setOnClickListener(v ->
-						viewModel.enableTransport(t.id,
-								switchCompat.isChecked()));
+						onClicked(t.id, switchCompat.isChecked()));
 				switchCompat.setChecked(t.isSwitchChecked);
 
 				TextView summary = view.findViewById(R.id.summary);
@@ -203,6 +218,20 @@ public class TransportsActivity extends BriarActivity {
 		});
 	}
 
+	private void onClicked(TransportId transportId, boolean enable) {
+		if (enable && SDK_INT >= 31 && !areBluetoothPermissionsGranted(this)) {
+			if (shouldShowRequestPermissionRationale(BLUETOOTH_CONNECT)) {
+				showRationale(this, R.string.permission_bluetooth_title,
+						R.string.permission_bluetooth_body,
+						this::requestBtPermissions);
+			} else {
+				requestBtPermissions();
+			}
+		} else {
+			viewModel.enableTransport(transportId, enable);
+		}
+	}
+
 	private String getBulletString(@StringRes int resId) {
 		return "\u2022 " + getString(resId);
 	}
@@ -316,6 +345,24 @@ public class TransportsActivity extends BriarActivity {
 		return transport;
 	}
 
+	@RequiresApi(31)
+	private void requestBtPermissions() {
+		requestBluetoothPermissions(requestPermissionLauncher);
+	}
+
+	@RequiresApi(31)
+	private void handleBtPermissionResult(Map<String, Boolean> grantedMap) {
+		if (wasGrantedBluetoothPermissions(this, grantedMap)) {
+			viewModel.enableTransport(BluetoothConstants.ID, true);
+		} else {
+			// update adapter to reflect the "off" toggle state after denying
+			transportsAdapter.notifyDataSetChanged();
+			showDenialDialog(this,
+					R.string.permission_bluetooth_title,
+					R.string.permission_bluetooth_denied_body);
+		}
+	}
+
 	private static class Transport {
 
 		private final TransportId id;
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportCollector.java b/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportCollector.java
index ef9e6ad941ff986cf23674936eab315b7209d142..89b12804549df2c53c0da5ae2e83d1223b723428 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportCollector.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportCollector.java
@@ -7,6 +7,7 @@
 package org.briarproject.briar.android.reporting;
 
 import android.annotation.SuppressLint;
+import android.app.usage.UsageStatsManager;
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.content.pm.FeatureInfo;
@@ -48,6 +49,7 @@ import androidx.annotation.Nullable;
 
 import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE;
 import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
+import static android.content.Context.USAGE_STATS_SERVICE;
 import static android.content.Context.WIFI_P2P_SERVICE;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_WIFI;
@@ -58,9 +60,11 @@ import static java.util.Locale.US;
 import static java.util.Objects.requireNonNull;
 import static java.util.TimeZone.getTimeZone;
 import static org.briarproject.bramble.util.AndroidUtils.getBluetoothAddressAndMethod;
+import static org.briarproject.bramble.util.AndroidUtils.hasBtConnectPermission;
 import static org.briarproject.bramble.util.PrivacyUtils.scrubInetAddress;
 import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
 import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
+import static org.briarproject.briar.android.util.PermissionUtils.areBluetoothPermissionsGranted;
 
 @Immutable
 @NotNullByDefault
@@ -120,6 +124,12 @@ class BriarReportCollector {
 				.add("Product", Build.PRODUCT)
 				.add("Model", Build.MODEL)
 				.add("Brand", Build.BRAND);
+		if (SDK_INT >= 28) {
+			UsageStatsManager usageStatsManager = (UsageStatsManager)
+					ctx.getSystemService(USAGE_STATS_SERVICE);
+			deviceInfo.add("AppStandbyBucket",
+					usageStatsManager.getAppStandbyBucket());
+		}
 		return new ReportItem("DeviceInfo", R.string.dev_report_device_info,
 				deviceInfo);
 	}
@@ -273,12 +283,14 @@ class BriarReportCollector {
 
 			// Is Bluetooth enabled?
 			@SuppressLint("HardwareIds")
-			boolean btEnabled = bt.isEnabled()
+			boolean btEnabled = hasBtConnectPermission(ctx) && bt.isEnabled()
 					&& !isNullOrEmpty(bt.getAddress());
 			connectivityInfo.add("BluetoothEnabled", btEnabled);
 
 			// Is Bluetooth connectable?
-			int scanMode = bt.getScanMode();
+			@SuppressLint("MissingPermission")
+			int scanMode = areBluetoothPermissionsGranted(ctx) ?
+					bt.getScanMode() : -1;
 			boolean btConnectable = scanMode == SCAN_MODE_CONNECTABLE ||
 					scanMode == SCAN_MODE_CONNECTABLE_DISCOVERABLE;
 			connectivityInfo.add("BluetoothConnectable", btConnectable);
@@ -298,11 +310,14 @@ class BriarReportCollector {
 						btLeAdvertise);
 			}
 
-			Pair<String, String> p = getBluetoothAddressAndMethod(ctx, bt);
-			String address = p.getFirst();
-			String method = p.getSecond();
-			connectivityInfo.add("BluetoothAddress", scrubMacAddress(address));
-			connectivityInfo.add("BluetoothAddressMethod", method);
+			if (hasBtConnectPermission(ctx)) {
+				Pair<String, String> p = getBluetoothAddressAndMethod(ctx, bt);
+				String address = p.getFirst();
+				String method = p.getSecond();
+				connectivityInfo.add("BluetoothAddress",
+						scrubMacAddress(address));
+				connectivityInfo.add("BluetoothAddressMethod", method);
+			}
 		}
 		return new ReportItem("Connectivity", R.string.dev_report_connectivity,
 				connectivityInfo);
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/settings/ConnectionsFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/settings/ConnectionsFragment.java
index afb594ab59384eb70cca94c5b62127527abcf0dc..3f528d96b04c68c7198c30c37789ff78ee72be90 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/settings/ConnectionsFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/settings/ConnectionsFragment.java
@@ -8,18 +8,31 @@ import org.briarproject.briar.R;
 import org.briarproject.nullsafety.MethodsNotNullByDefault;
 import org.briarproject.nullsafety.ParametersNotNullByDefault;
 
+import java.util.Map;
+
 import javax.inject.Inject;
 
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.fragment.app.FragmentActivity;
 import androidx.lifecycle.LifecycleOwner;
 import androidx.lifecycle.ViewModelProvider;
 import androidx.preference.ListPreference;
 import androidx.preference.PreferenceFragmentCompat;
 import androidx.preference.SwitchPreferenceCompat;
 
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.os.Build.VERSION.SDK_INT;
 import static org.briarproject.briar.android.AppModule.getAndroidComponent;
 import static org.briarproject.briar.android.settings.SettingsActivity.enableAndPersist;
+import static org.briarproject.briar.android.util.PermissionUtils.areBluetoothPermissionsGranted;
+import static org.briarproject.briar.android.util.PermissionUtils.requestBluetoothPermissions;
+import static org.briarproject.briar.android.util.PermissionUtils.showDenialDialog;
+import static org.briarproject.briar.android.util.PermissionUtils.showRationale;
+import static org.briarproject.briar.android.util.PermissionUtils.wasGrantedBluetoothPermissions;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
@@ -47,6 +60,11 @@ public class ConnectionsFragment extends PreferenceFragmentCompat {
 	private SwitchPreferenceCompat torMobile;
 	private SwitchPreferenceCompat torOnlyWhenCharging;
 
+	@RequiresApi(31)
+	private final ActivityResultLauncher<String[]> requestPermissionLauncher =
+			registerForActivityResult(new RequestMultiplePermissions(),
+					this::handleBtPermissionResult);
+
 	@Override
 	public void onAttach(@NonNull Context context) {
 		super.onAttach(context);
@@ -69,6 +87,25 @@ public class ConnectionsFragment extends PreferenceFragmentCompat {
 
 		torNetwork.setSummaryProvider(viewModel.torSummaryProvider);
 
+		if (SDK_INT >= 31) {
+			enableBluetooth.setOnPreferenceChangeListener((p, value) -> {
+				FragmentActivity ctx = requireActivity();
+				if (areBluetoothPermissionsGranted(ctx)) {
+					return true;
+				} else if (shouldShowRequestPermissionRationale(
+						BLUETOOTH_CONNECT)) {
+					showRationale(ctx, R.string.permission_bluetooth_title,
+							R.string.permission_bluetooth_body,
+							this::requestBtPermissions);
+					// we don't update the preference directly,
+					// but do it via the launcher, if we got the permissions
+					return false;
+				} else {
+					requestBtPermissions();
+					return false;
+				}
+			});
+		}
 		enableBluetooth.setPreferenceDataStore(connectionsManager.btStore);
 		enableWifi.setPreferenceDataStore(connectionsManager.wifiStore);
 		enableTor.setPreferenceDataStore(connectionsManager.torStore);
@@ -115,4 +152,19 @@ public class ConnectionsFragment extends PreferenceFragmentCompat {
 		requireActivity().setTitle(R.string.network_settings_title);
 	}
 
+	@RequiresApi(31)
+	private void requestBtPermissions() {
+		requestBluetoothPermissions(requestPermissionLauncher);
+	}
+
+	@RequiresApi(31)
+	private void handleBtPermissionResult(Map<String, Boolean> grantedMap) {
+		if (wasGrantedBluetoothPermissions(requireActivity(), grantedMap)) {
+			enableBluetooth.setChecked(true);
+		} else {
+			showDenialDialog(requireActivity(),
+					R.string.permission_bluetooth_title,
+					R.string.permission_bluetooth_denied_body);
+		}
+	}
 }
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsActivity.java
index 00e4583a24cc117998b3e2dccd58c351219e5f0e..fbc882e07825050cbef7557cdaf66bc3108d545e 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsActivity.java
@@ -1,5 +1,6 @@
 package org.briarproject.briar.android.settings;
 
+import android.content.Intent;
 import android.os.Bundle;
 import android.view.MenuItem;
 
@@ -18,6 +19,8 @@ import androidx.preference.Preference;
 import androidx.preference.PreferenceFragmentCompat;
 import androidx.preference.PreferenceFragmentCompat.OnPreferenceStartFragmentCallback;
 
+import static android.content.Intent.ACTION_MANAGE_NETWORK_USAGE;
+
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
 public class SettingsActivity extends BriarActivity
@@ -40,12 +43,18 @@ public class SettingsActivity extends BriarActivity
 			actionBar.setDisplayHomeAsUpEnabled(true);
 		}
 
-		// show display fragment after theme change
-		Bundle extras = getIntent().getExtras();
+		Intent i = getIntent();
+		Bundle extras = i.getExtras();
 		if (bundle == null && extras != null &&
 				extras.getBoolean(EXTRA_THEME_CHANGE, false)) {
+			// show display fragment after theme change
 			FragmentManager fragmentManager = getSupportFragmentManager();
 			showNextFragment(fragmentManager, new DisplayFragment());
+		} else if (bundle == null &&
+				ACTION_MANAGE_NETWORK_USAGE.equals(i.getAction())) {
+			// show connection if coming from network settings
+			FragmentManager fragmentManager = getSupportFragmentManager();
+			showNextFragment(fragmentManager, new ConnectionsFragment());
 		}
 
 		setContentView(R.layout.activity_settings);
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/util/PermissionUtils.java b/briar-android/src/main/java/org/briarproject/briar/android/util/PermissionUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..fdad47615c00e2dbd83e8895c06618add6fcd367
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/util/PermissionUtils.java
@@ -0,0 +1,176 @@
+package org.briarproject.briar.android.util;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.location.LocationManager;
+import android.net.Uri;
+import android.widget.Toast;
+
+import org.briarproject.briar.R;
+import org.briarproject.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.nullsafety.ParametersNotNullByDefault;
+
+import java.util.Map;
+
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.StringRes;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentActivity;
+
+import static android.Manifest.permission.BLUETOOTH_ADVERTISE;
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_SCAN;
+import static android.content.Intent.CATEGORY_DEFAULT;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.Build.VERSION.SDK_INT;
+import static android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS;
+import static android.widget.Toast.LENGTH_LONG;
+import static androidx.core.content.ContextCompat.checkSelfPermission;
+import static java.lang.Boolean.TRUE;
+import static org.briarproject.briar.BuildConfig.APPLICATION_ID;
+
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
+public class PermissionUtils {
+
+	public static boolean gotPermission(Context ctx,
+			@Nullable Map<String, Boolean> grantedMap, String permission) {
+		if (grantedMap == null || !grantedMap.containsKey(permission)) {
+			return isPermissionGranted(ctx, permission);
+		} else {
+			return TRUE.equals(grantedMap.get(permission));
+		}
+	}
+
+	public static boolean isPermissionGranted(Context ctx, String permission) {
+		return checkSelfPermission(ctx, permission) ==
+				PERMISSION_GRANTED;
+	}
+
+	public static boolean areBluetoothPermissionsGranted(Context ctx) {
+		if (SDK_INT < 31) return true;
+		return isPermissionGranted(ctx, BLUETOOTH_ADVERTISE) &&
+				isPermissionGranted(ctx, BLUETOOTH_CONNECT) &&
+				isPermissionGranted(ctx, BLUETOOTH_SCAN);
+	}
+
+	@RequiresApi(31)
+	public static boolean wasGrantedBluetoothPermissions(Context ctx,
+			@Nullable Map<String, Boolean> grantedMap) {
+		return grantedMap != null &&
+				gotPermission(ctx, grantedMap, BLUETOOTH_ADVERTISE) &&
+				gotPermission(ctx, grantedMap, BLUETOOTH_CONNECT) &&
+				gotPermission(ctx, grantedMap, BLUETOOTH_SCAN);
+	}
+
+	public static DialogInterface.OnClickListener getGoToSettingsListener(
+			Context context) {
+		return (dialog, which) -> {
+			Intent i = new Intent();
+			i.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
+			i.addCategory(CATEGORY_DEFAULT);
+			i.setData(Uri.parse("package:" + APPLICATION_ID));
+			i.addFlags(FLAG_ACTIVITY_NEW_TASK);
+			context.startActivity(i);
+		};
+	}
+
+	/**
+	 * @return true if location is enabled for Bluetooth purposes,
+	 * or it isn't required due to this being a device with SDK < 28 or >= 31.
+	 */
+	public static boolean isLocationEnabledForBt(Context ctx) {
+		if (SDK_INT >= 28 && SDK_INT < 31) {
+			LocationManager lm = ctx.getSystemService(LocationManager.class);
+			return lm.isLocationEnabled();
+		} else {
+			return true;
+		}
+	}
+
+	/**
+	 * @return true if location is enabled for Wi-Fi hotspot purposes,
+	 * or it isn't required due to this being a device with SDK < 31.
+	 */
+	public static boolean isLocationEnabledForWiFi(Context ctx) {
+		if (SDK_INT >= 31) {
+			LocationManager lm = ctx.getSystemService(LocationManager.class);
+			return lm.isLocationEnabled();
+		}
+		return true;
+	}
+
+	public static void showLocationDialog(Context ctx) {
+		showLocationDialog(ctx, true);
+	}
+
+	public static void showLocationDialog(Context ctx, boolean forBluetooth) {
+		AlertDialog.Builder builder =
+				new AlertDialog.Builder(ctx, R.style.BriarDialogTheme);
+		builder.setTitle(R.string.permission_location_setting_title);
+		if (forBluetooth) {
+			builder.setMessage(R.string.permission_location_setting_body);
+		} else {
+			builder.setMessage(
+					R.string.permission_location_setting_hotspot_body);
+		}
+		builder.setNegativeButton(R.string.cancel, null);
+		builder.setPositiveButton(R.string.permission_location_setting_button,
+				(dialog, which) -> {
+					Intent i = new Intent(ACTION_LOCATION_SOURCE_SETTINGS);
+					try {
+						ctx.startActivity(i);
+					} catch (ActivityNotFoundException e) {
+						Toast.makeText(ctx, R.string.error_start_activity,
+								LENGTH_LONG).show();
+					}
+				});
+		builder.show();
+	}
+
+	/**
+	 * This closes the given activity when dialog gets cancelled.
+	 */
+	public static void showDenialDialog(FragmentActivity ctx,
+			@StringRes int title, @StringRes int body) {
+		showDenialDialog(ctx, title, body, ctx::supportFinishAfterTransition);
+	}
+
+	public static void showDenialDialog(FragmentActivity ctx,
+			@StringRes int title, @StringRes int body, Runnable onDenied) {
+		AlertDialog.Builder builder =
+				new AlertDialog.Builder(ctx, R.style.BriarDialogTheme);
+		builder.setTitle(title);
+		builder.setMessage(body);
+		builder.setPositiveButton(R.string.ok, getGoToSettingsListener(ctx));
+		builder.setNegativeButton(R.string.cancel, (dialog, which) ->
+				onDenied.run());
+		builder.show();
+	}
+
+	public static void showRationale(FragmentActivity ctx, @StringRes int title,
+			@StringRes int body, @Nullable Runnable onOk) {
+		AlertDialog.Builder builder =
+				new AlertDialog.Builder(ctx, R.style.BriarDialogTheme);
+		builder.setTitle(title);
+		builder.setMessage(body);
+		builder.setNeutralButton(R.string.continue_button, (dialog, which) -> {
+			if (onOk != null) onOk.run();
+			dialog.dismiss();
+		});
+		builder.show();
+	}
+
+	@RequiresApi(31)
+	public static void requestBluetoothPermissions(
+			ActivityResultLauncher<String[]> launcher) {
+		String[] perms = new String[] {BLUETOOTH_ADVERTISE, BLUETOOTH_CONNECT,
+				BLUETOOTH_SCAN};
+		launcher.launch(perms);
+	}
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java b/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
index baa8939640bce589940c537242d0404ee90fafd5..2a133b6478016ceb16cf454e118ba015beb4b7dd 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
@@ -6,12 +6,9 @@ import android.app.ActivityManager.MemoryInfo;
 import android.app.KeyguardManager;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
-import android.content.DialogInterface.OnClickListener;
 import android.content.Intent;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
-import android.location.LocationManager;
-import android.net.Uri;
 import android.os.Debug;
 import android.text.Spannable;
 import android.text.SpannableString;
@@ -54,7 +51,6 @@ import androidx.annotation.ColorRes;
 import androidx.annotation.DrawableRes;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
-import androidx.annotation.StringRes;
 import androidx.annotation.UiThread;
 import androidx.appcompat.app.AlertDialog;
 import androidx.core.content.ContextCompat;
@@ -71,11 +67,9 @@ import androidx.lifecycle.Observer;
 import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
 
 import static android.content.Context.KEYGUARD_SERVICE;
-import static android.content.Intent.CATEGORY_DEFAULT;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.os.Build.MANUFACTURER;
 import static android.os.Build.VERSION.SDK_INT;
-import static android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static android.text.format.DateUtils.FORMAT_ABBREV_ALL;
 import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
@@ -110,7 +104,6 @@ import static java.util.concurrent.TimeUnit.DAYS;
 import static java.util.logging.Level.WARNING;
 import static java.util.logging.Logger.getLogger;
 import static org.briarproject.bramble.util.LogUtils.logException;
-import static org.briarproject.briar.BuildConfig.APPLICATION_ID;
 import static org.briarproject.briar.android.TestingConstants.EXPIRY_DATE;
 import static org.briarproject.briar.android.TestingConstants.IS_OLD_ANDROID;
 import static org.briarproject.briar.android.TestingConstants.OLD_ANDROID_WARN_DATE;
@@ -325,17 +318,6 @@ public class UiUtils {
 		textView.setMovementMethod(new LinkMovementMethod());
 	}
 
-	public static OnClickListener getGoToSettingsListener(Context context) {
-		return (dialog, which) -> {
-			Intent i = new Intent();
-			i.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
-			i.addCategory(CATEGORY_DEFAULT);
-			i.setData(Uri.parse("package:" + APPLICATION_ID));
-			i.addFlags(FLAG_ACTIVITY_NEW_TASK);
-			context.startActivity(i);
-		};
-	}
-
 	public static void showOnboardingDialog(Context ctx, String text) {
 		new AlertDialog.Builder(ctx, R.style.OnboardingDialogTheme)
 				.setMessage(text)
@@ -344,19 +326,6 @@ public class UiUtils {
 				.show();
 	}
 
-	/**
-	 * @return true if location is enabled,
-	 * or it isn't required due to this being a SDK < 28 device.
-	 */
-	public static boolean isLocationEnabled(Context ctx) {
-		if (SDK_INT >= 28) {
-			LocationManager lm = ctx.getSystemService(LocationManager.class);
-			return lm.isLocationEnabled();
-		} else {
-			return true;
-		}
-	}
-
 	public static boolean isSamsung7() {
 		return (SDK_INT == 24 || SDK_INT == 25) &&
 				MANUFACTURER.equalsIgnoreCase("Samsung");
@@ -523,25 +492,6 @@ public class UiUtils {
 		return isoCode;
 	}
 
-	public static void showLocationDialog(Context ctx) {
-		AlertDialog.Builder builder =
-				new AlertDialog.Builder(ctx, R.style.BriarDialogTheme);
-		builder.setTitle(R.string.permission_location_setting_title);
-		builder.setMessage(R.string.permission_location_setting_body);
-		builder.setNegativeButton(R.string.cancel, null);
-		builder.setPositiveButton(R.string.permission_location_setting_button,
-				(dialog, which) -> {
-					Intent i = new Intent(ACTION_LOCATION_SOURCE_SETTINGS);
-					try {
-						ctx.startActivity(i);
-					} catch (ActivityNotFoundException e) {
-						Toast.makeText(ctx, R.string.error_start_activity,
-								LENGTH_LONG).show();
-					}
-				});
-		builder.show();
-	}
-
 	public static Drawable getDialogIcon(Context ctx, @DrawableRes int resId) {
 		Drawable icon =
 				VectorDrawableCompat.create(ctx.getResources(), resId, null);
@@ -581,29 +531,6 @@ public class UiUtils {
 				SOFT_INPUT_STATE_HIDDEN);
 	}
 
-	public static void showDenialDialog(FragmentActivity ctx,
-			@StringRes int title, @StringRes int body) {
-		AlertDialog.Builder builder =
-				new AlertDialog.Builder(ctx, R.style.BriarDialogTheme);
-		builder.setTitle(title);
-		builder.setMessage(body);
-		builder.setPositiveButton(R.string.ok, getGoToSettingsListener(ctx));
-		builder.setNegativeButton(R.string.cancel,
-				(dialog, which) -> ctx.supportFinishAfterTransition());
-		builder.show();
-	}
-
-	public static void showRationale(FragmentActivity ctx, @StringRes int title,
-			@StringRes int body, Runnable requestPermissions) {
-		AlertDialog.Builder builder =
-				new AlertDialog.Builder(ctx, R.style.BriarDialogTheme);
-		builder.setTitle(title);
-		builder.setMessage(body);
-		builder.setNeutralButton(R.string.continue_button,
-				(dialog, which) -> requestPermissions.run());
-		builder.show();
-	}
-
 	public static void launchActivityToOpenFile(Context ctx,
 			@Nullable ActivityResultLauncher<String[]> docLauncher,
 			ActivityResultLauncher<String> contentLauncher,
@@ -625,4 +552,5 @@ public class UiUtils {
 		}
 		Toast.makeText(ctx, R.string.error_start_activity, LENGTH_LONG).show();
 	}
+
 }
diff --git a/briar-android/src/main/res/values-v31/attrs.xml b/briar-android/src/main/res/values-v31/attrs.xml
new file mode 100644
index 0000000000000000000000000000000000000000..becc65199eae71892beda5ff1f477f4b85b9f415
--- /dev/null
+++ b/briar-android/src/main/res/values-v31/attrs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+	<integer name="splashScreenDuration">0</integer>
+
+</resources>
diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml
index 3bf3edf4952666a947b2a507b0be3b0b249052a1..8887fcd7b11bcd241a1d22501d3586f1fc624994 100644
--- a/briar-android/src/main/res/values/strings.xml
+++ b/briar-android/src/main/res/values/strings.xml
@@ -314,7 +314,7 @@
 	<string name="different_person_button">Different Person</string>
 	<string name="duplicate_link_dialog_text_3">%1$s and %2$s sent you the same link.\n\nOne of them may be trying to discover who your contacts are.\n\nDon\'t tell them you received the same link from someone else.</string>
 	<string name="pending_contact_updated_toast">Pending contact updated</string>
-	
+
 	<!-- Peer trust levels -->
 
 	<string name="peer_trust_level_unverified">Unverified contact</string>
@@ -353,6 +353,7 @@
 	<string name="connect_via_bluetooth_intro">In case Bluetooth connections do not work automatically, you can use this screen to connect manually.\n\nYour contact needs to be nearby for this to work.\n\nYou and your contact should both press \"Start\" at the same time.</string>
 	<string name="connect_via_bluetooth_already_discovering">Already trying to connect via Bluetooth. Please try again shortly.</string>
 	<string name="connect_via_bluetooth_no_location_permission">Cannot continue without location permission</string>
+	<string name="connect_via_bluetooth_no_bluetooth_permission">Cannot continue without nearby devices permission</string>
 	<string name="connect_via_bluetooth_start">Connecting via Bluetooth…</string>
 	<string name="connect_via_bluetooth_success">Successfully connected via Bluetooth</string>
 	<string name="connect_via_bluetooth_error">Could not connect via Bluetooth.</string>
@@ -777,11 +778,18 @@
 	<string name="permission_location_request_body">To discover Bluetooth devices, Briar needs permission to access your location.\n\nBriar does not store your location or share it with anyone.</string>
 	<string name="permission_camera_location_title">Camera and location</string>
 	<string name="permission_camera_location_request_body">To scan the QR code, Briar needs access to the camera.\n\nTo discover Bluetooth devices, Briar needs permission to access your location.\n\nBriar does not store your location or share it with anyone.</string>
+	<string name="permission_camera_bluetooth_title">Camera and nearby devices</string>
+	<string name="permission_camera_bluetooth_request_body">To scan the QR code, Briar needs access to the camera.\n\nTo discover Bluetooth devices, Briar needs permission to find and connect to nearby devices.</string>
 	<string name="permission_camera_denied_body">You have denied access to the camera, but adding contacts requires using the camera.\n\nPlease consider granting access.</string>
 	<string name="permission_location_denied_body">You have denied access to your location, but Briar needs this permission to discover Bluetooth devices.\n\nPlease consider granting access.</string>
 	<string name="permission_location_setting_title">Location setting</string>
 	<string name="permission_location_setting_body">Your device\'s location setting must be turned on to find other devices via Bluetooth. Please enable location to continue. You can disable it again afterwards.</string>
+	<string name="permission_location_setting_hotspot_body">Your device\'s location setting must be turned on to create a Wi-Fi hotspot. Please enable location to continue. You can disable it again afterwards.</string>
 	<string name="permission_location_setting_button">Enable location</string>
+	<string name="permission_bluetooth_title">Nearby devices permission</string>
+	<string name="permission_bluetooth_body">To use Bluetooth communication, Briar needs permission to find and connect to nearby devices.</string>
+	<string name="permission_bluetooth_denied_body">You have denied access to nearby devices, but Briar needs this permission to use Bluetooth.\n\nPlease consider granting access.</string>
+
 	<string name="qr_code">QR code</string>
 	<string name="show_qr_code_fullscreen">Show QR code fullscreen</string>
 
@@ -808,7 +816,9 @@
 	<string name="hotspot_button_connected">Next</string>
 
 	<string name="permission_hotspot_location_request_body">To create a Wi-Fi hotspot, Briar needs permission to access your location.\n\nBriar does not store your location or share it with anyone.</string>
+	<string name="permission_hotspot_location_request_precise_body">To create a Wi-Fi hotspot, Briar needs permission to access your precise location.\n\nBriar does not store your location or share it with anyone.</string>
 	<string name="permission_hotspot_location_denied_body">You have denied access to your location, but Briar needs this permission to create a Wi-Fi hotspot.\n\nPlease consider granting access.</string>
+	<string name="permission_hotspot_location_denied_precise_body">You have denied access to your precise location, but Briar needs this permission to create a Wi-Fi hotspot.\n\nPlease consider granting access.</string>
 	<string name="wifi_settings_title">Wi-Fi setting</string>
 	<string name="wifi_settings_request_enable_body">To create a Wi-Fi hotspot, Briar needs to use Wi-Fi. Please enable it.</string>
 
diff --git a/briar-android/src/main/res/xml/backup_extraction_rules.xml b/briar-android/src/main/res/xml/backup_extraction_rules.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c03286ff83bf46e25985019afee3b907de163a73
--- /dev/null
+++ b/briar-android/src/main/res/xml/backup_extraction_rules.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<data-extraction-rules>
+	<cloud-backup disableIfNoEncryptionCapabilities="true">
+		<!-- docs: https://developer.android.com/guide/topics/data/autobackup#XMLSyntax -->
+		<exclude
+			domain="root"
+			path="." />
+		<!-- the previous entry should exclude things recursively, but we add more just to be sure -->
+		<exclude
+			domain="root"
+			path="app_db" />
+		<exclude
+			domain="root"
+			path="app_key" />
+		<!-- we don't use domain=file (getFilesDir()), but ApplicationInfo#dataDir -->
+		<exclude
+			domain="sharedpref"
+			path="." />
+	</cloud-backup>
+	<device-transfer>
+		<!-- docs: https://developer.android.com/guide/topics/data/autobackup#XMLSyntax -->
+		<exclude
+			domain="root"
+			path="." />
+		<!-- the previous entry should exclude things recursively, but we add more just to be sure -->
+		<exclude
+			domain="root"
+			path="app_db" />
+		<exclude
+			domain="root"
+			path="app_key" />
+		<!-- we don't use domain=file (getFilesDir()), but ApplicationInfo#dataDir -->
+		<exclude
+			domain="sharedpref"
+			path="." />
+	</device-transfer>
+</data-extraction-rules>
diff --git a/briar-android/witness.gradle b/briar-android/witness.gradle
index d2a4e23194ea45d9fb6c41c350c25a2596157996..dcfee5197cf8656dcfc339f4f572e19e998ea776 100644
--- a/briar-android/witness.gradle
+++ b/briar-android/witness.gradle
@@ -1,283 +1,179 @@
 dependencyVerification {
     verify = [
-        'androidx.activity:activity-ktx:1.2.3:activity-ktx-1.2.3.aar:423c0226e237e08de245cf66f8ccaf103854bc19a584d971a4a075fd15d70df1',
-        'androidx.activity:activity:1.2.2:activity-1.2.2.aar:e165fb20f006b77894d349572cc3acd2760baa8416ae4d33cb8de6a84dd6730c',
-        'androidx.activity:activity:1.2.4:activity-1.2.4.aar:ae8e9c7de57e387d2ad90e73f3a5a5dfd502bd4f034c1dccfdb3506d1d2df81a',
-        'androidx.annotation:annotation-experimental:1.0.0:annotation-experimental-1.0.0.aar:b219d2b568e7e4ba534e09f8c2fd242343df6ccbdfbbe938846f5d740e6b0b11',
-        'androidx.annotation:annotation:1.5.0:annotation-1.5.0.jar:261fb7c0210858500bab66d34354972a75166ab4182add283780b05513d6ec4a',
-        'androidx.appcompat:appcompat-resources:1.2.0:appcompat-resources-1.2.0.aar:c470297c03ff3de1c3d15dacf0be0cae63abc10b52f021dd07ae28daa3100fe5',
-        'androidx.appcompat:appcompat:1.2.0:appcompat-1.2.0.aar:3d2131a55a61a777322e2126e0018011efa6339e53b44153eb651b16020cca70',
-        'androidx.arch.core:core-common:2.1.0:core-common-2.1.0.jar:fe1237bf029d063e7f29fe39aeaf73ef74c8b0a3658486fc29d3c54326653889',
-        'androidx.arch.core:core-runtime:2.1.0:core-runtime-2.1.0.aar:dd77615bd3dd275afb11b62df25bae46b10b4a117cd37943af45bdcbf8755852',
-        'androidx.arch.core:core-testing:2.1.0:core-testing-2.1.0.aar:c57ffade2a9a844bd62b4f4c3916fad5e09e9f24cceba27e932c25bb7a6d1d8f',
-        'androidx.cardview:cardview:1.0.0:cardview-1.0.0.aar:1193c04c22a3d6b5946dae9f4e8c59d6adde6a71b6bd5d87fb99d82dda1afec7',
-        'androidx.collection:collection-ktx:1.1.0:collection-ktx-1.1.0.jar:2bfc54475c047131913361f56d0f7f019c6e5bee53eeb0eb7d94a7c499a05227',
-        'androidx.collection:collection:1.1.0:collection-1.1.0.jar:632a0e5407461de774409352940e292a291037724207a787820c77daf7d33b72',
-        'androidx.constraintlayout:constraintlayout-solver:2.0.4:constraintlayout-solver-2.0.4.jar:9ca19f5448709301c7563488ef941be9dfa55c83538ca7a059b2113e83527b46',
-        'androidx.constraintlayout:constraintlayout:2.0.4:constraintlayout-2.0.4.aar:307a79a4a1ccff44249c72a2bf7f47da09fa1b6b1fab2a25808ca889382b738e',
-        'androidx.coordinatorlayout:coordinatorlayout:1.1.0:coordinatorlayout-1.1.0.aar:44a9e30abf56af1025c52a0af506fee9c4131aa55efda52f9fd9451211c5e8cb',
-        'androidx.core:core-ktx:1.2.0:core-ktx-1.2.0.aar:dcb74d510d552b35eff73b0dd27b829649535f3902e5b5a1f26040383c10a940',
-        'androidx.core:core:1.3.1:core-1.3.1.aar:e92ea65a37d589943d405a6a54d1be9d12a225948f26c4e41e511dd55e81efb6',
-        'androidx.cursoradapter:cursoradapter:1.0.0:cursoradapter-1.0.0.aar:a81c8fe78815fa47df5b749deb52727ad11f9397da58b16017f4eb2c11e28564',
-        'androidx.customview:customview:1.0.0:customview-1.0.0.aar:20e5b8f6526a34595a604f56718da81167c0b40a7a94a57daa355663f2594df2',
-        'androidx.documentfile:documentfile:1.0.0:documentfile-1.0.0.aar:865a061ef2fad16522f8433536b8d47208c46ff7c7745197dfa1eeb481869487',
-        'androidx.drawerlayout:drawerlayout:1.0.0:drawerlayout-1.0.0.aar:9402442cdc5a43cf62fb14f8cf98c63342d4d9d9b805c8033c6cf7e802749ac1',
-        'androidx.dynamicanimation:dynamicanimation:1.0.0:dynamicanimation-1.0.0.aar:ce005162c229bf308d2d5b12fb6cad0874069cbbeaccee63a8193bd08d40de04',
-        'androidx.exifinterface:exifinterface:1.3.2:exifinterface-1.3.2.aar:8770c180103e0b8c04a07eb4c59153af639b09eca25deae9bdcdaf869d1e5b6b',
-        'androidx.fragment:fragment-ktx:1.4.0:fragment-ktx-1.4.0.aar:439873b250461eb2245e393fe6683dceb567e7a18d9d6cf4538de9befa4ed1b0',
-        'androidx.fragment:fragment-testing:1.4.0:fragment-testing-1.4.0.aar:1f874b83919c69f2e0df6de0ba2ad87a0d61cc7840d90b481ee0d4db85c2385b',
-        'androidx.fragment:fragment:1.3.4:fragment-1.3.4.aar:c023c0ab666456885284d8e88519a743bc863c2b2effb92741fc789cbdb10db4',
-        'androidx.fragment:fragment:1.4.0:fragment-1.4.0.aar:ec98a3b2f56f25cd247f928ab717d5527d27aea56ca4c02e67fbcd1ec32e5eed',
-        'androidx.interpolator:interpolator:1.0.0:interpolator-1.0.0.aar:33193135a64fe21fa2c35eec6688f1a76e512606c0fc83dc1b689e37add7732a',
-        'androidx.legacy:legacy-support-core-utils:1.0.0:legacy-support-core-utils-1.0.0.aar:a7edcf01d5b52b3034073027bc4775b78a4764bb6202bb91d61c829add8dd1c7',
-        'androidx.lifecycle:lifecycle-common:2.3.1:lifecycle-common-2.3.1.jar:15848fb56db32f4c7cdc72b324003183d52a4884d6bf09be708ac7f587d139b5',
-        'androidx.lifecycle:lifecycle-extensions:2.2.0:lifecycle-extensions-2.2.0.aar:648c8de1d10b025d524a2e46ac994fc3f6bf186826c09ec1a62d250bf1b877ae',
-        'androidx.lifecycle:lifecycle-livedata-core-ktx:2.3.1:lifecycle-livedata-core-ktx-2.3.1.aar:6dd41c3c33daeb503fd87fbfff7043adb0be6c541a9c9e09bf531ca49520fddb',
-        'androidx.lifecycle:lifecycle-livedata-core:2.3.1:lifecycle-livedata-core-2.3.1.aar:e55d38c372460f0a03997ddc950c67227511340fd74f8634d99d29653cd81ab1',
-        'androidx.lifecycle:lifecycle-livedata:2.2.0:lifecycle-livedata-2.2.0.aar:d83af94860aa9f64cbdc51f40796a7cf55b116f0e6efd752e845c0104c8b16f6',
-        'androidx.lifecycle:lifecycle-process:2.2.0:lifecycle-process-2.2.0.aar:3a977e7778fc8418742d388409daaba7ea8fea8823d21ffb96e4c4236f715070',
-        'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1:lifecycle-runtime-ktx-2.3.1.aar:7ad2987dd7f4075c0871a72cf07e9649d9cd790fc23dfab1972eca4710373873',
-        'androidx.lifecycle:lifecycle-runtime:2.3.1:lifecycle-runtime-2.3.1.aar:dd294f4a689c71ff877fd41f3b67a3a62f7760d44ce420e6130f1fc3569d8f00',
-        'androidx.lifecycle:lifecycle-service:2.2.0:lifecycle-service-2.2.0.aar:ca2801ffc069555afed8eddd2292130f436956452bc8bbad30fb56f8e4e382a0',
-        'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1:lifecycle-viewmodel-ktx-2.3.1.aar:5fb3591b6a54eeb3e204be0125d48eb987b8ea45a5048140036865482ccf9de9',
-        'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.3.1:lifecycle-viewmodel-savedstate-2.3.1.aar:97137a8af6a31776a14e4866ab808c7c0a791b484bdbc788bbd83e66407564c0',
-        'androidx.lifecycle:lifecycle-viewmodel:2.3.1:lifecycle-viewmodel-2.3.1.aar:b6db4c274a12ff85a4747e1e6669c7e98aefa2571ace9d1f1a6fa6be417ce838',
-        'androidx.loader:loader:1.0.0:loader-1.0.0.aar:11f735cb3b55c458d470bed9e25254375b518b4b1bad6926783a7026db0f5025',
-        'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0:localbroadcastmanager-1.0.0.aar:e71c328ceef5c4a7d76f2d86df1b65d65fe2acf868b1a4efd84a3f34336186d8',
-        'androidx.preference:preference:1.1.1:preference-1.1.1.aar:317dcbc38242aea2f6262c06d51b8a22827e98959967edd40f82600a15cb4bff',
-        'androidx.print:print:1.0.0:print-1.0.0.aar:1d5c7f3135a1bba661fc373fd72e11eb0a4adbb3396787826dd8e4190d5d9edd',
-        'androidx.recyclerview:recyclerview-selection:1.1.0:recyclerview-selection-1.1.0.aar:9e2ba1c7d6b0eb5e64c10b1b0eb01b51e8511cee002c9bd56ce9cc138ebc4898',
-        'androidx.recyclerview:recyclerview:1.1.0:recyclerview-1.1.0.aar:f0d2b5a67d0a91ee1b1c73ef2b636a81f3563925ddd15a1d4e1c41ec28de7a4f',
-        'androidx.savedstate:savedstate-ktx:1.1.0:savedstate-ktx-1.1.0.aar:e44d61347463b0fafeeb649cbcc3d7109b2eb5e11d1522e986105170cdebbf68',
-        'androidx.savedstate:savedstate:1.1.0:savedstate-1.1.0.aar:d60bbe44c2c08083a17c5dc678a6d6b4d0a2d664858016ab5c049cbea90a63b7',
-        'androidx.test.espresso:espresso-contrib:3.3.0:espresso-contrib-3.3.0.aar:f400cabdc181356acf6b210e4509dcb9649d9e2b6b6e218c60fcfc15e8a756d1',
-        'androidx.test.espresso:espresso-core:3.3.0:espresso-core-3.3.0.aar:23ebf6014645e0c60aec7d1ed924d4d4c848ae8c3673b7d8d06b2ec6a56cafee',
-        'androidx.test.espresso:espresso-idling-resource:3.3.0:espresso-idling-resource-3.3.0.aar:29519b112731f289cc6e2f9b2eccc5ea72c754b04272bb93370f45d7e170a7c6',
-        'androidx.test.espresso:espresso-intents:3.3.0:espresso-intents-3.3.0.aar:5b6cd6aadce78edc705d93c1e81ace3b59be97128aca0e88fd9c5c176aa9bf10',
-        'androidx.test.ext:junit:1.1.2:junit-1.1.2.aar:6c6ab120c640bf16fcaae69cb83c144d0ed6b6298562be0ac35e37ed969c0409',
-        'androidx.test.ext:junit:1.1.3:junit-1.1.3.aar:a97209d75a9a85815fa8934f5a4a320de1163ffe94e2f0b328c0c98a59660690',
-        'androidx.test.services:storage:1.4.0:storage-1.4.0.aar:35cfbf442abb83e5876cd5deb9de02ae047459f18f831097c5caa76d626bc38a',
-        'androidx.test.services:test-services:1.3.0:test-services-1.3.0.apk:1b88faab6864baf25c5d0b92a610c283c159a566e7a56c03307117fa1b542993',
-        'androidx.test.uiautomator:uiautomator:2.2.0:uiautomator-2.2.0.aar:2838e9d961dbffefbbd229a2bd4f6f82ac4fb2462975862a9e75e9ed325a3197',
-        'androidx.test:core:1.3.0:core-1.3.0.aar:86549cae8c5b848f817e2c716e174c7dab61caf0b4df9848680eeb753089a337',
-        'androidx.test:core:1.4.0:core-1.4.0.aar:671284e62e393f16ceae1a99a3a9a07bf1aacda29f8fe7b6b884355ef34c09cf',
-        'androidx.test:monitor:1.3.0:monitor-1.3.0.aar:f73a31306a783e63150c60c49e140dc38da39a1b7947690f4b73387b5ebad77e',
-        'androidx.test:monitor:1.4.0:monitor-1.4.0.aar:46a912a1e175f27a97521af3f50e5af87c22c49275dd2c57c043740012806325',
-        'androidx.test:orchestrator:1.3.0:orchestrator-1.3.0.apk:676f808d08a3d05050eae30c3b7d92ce5cef1e00a54d68355bb7e7d4b72366fe',
-        'androidx.test:rules:1.3.0:rules-1.3.0.aar:c1753946c498b0d5d7cf341cfed661f66915c4c9deb4ed10462a08ae33b2429a',
-        'androidx.test:runner:1.3.0:runner-1.3.0.aar:61d13f5a9fcbbd73ba18fa84e1d6a0111c6e1c665a89b418126966e61fffd93b',
-        'androidx.test:runner:1.4.0:runner-1.4.0.aar:e3f3d8b8d5d4a3edcacbdaa4a31bda2b0e41d3e704b02b3750466a06367ec5a0',
-        'androidx.tracing:tracing:1.0.0:tracing-1.0.0.aar:07b8b6139665b884a162eccf97891ca50f7f56831233bf25168ae04f7b568612',
-        'androidx.transition:transition:1.2.0:transition-1.2.0.aar:a1e059b3bc0b43a58dec0efecdcaa89c82d2bca552ea5bacf6656c46e853157e',
-        'androidx.vectordrawable:vectordrawable-animated:1.1.0:vectordrawable-animated-1.1.0.aar:76da2c502371d9c38054df5e2b248d00da87809ed058f3363eae87ce5e2403f8',
-        'androidx.vectordrawable:vectordrawable:1.1.0:vectordrawable-1.1.0.aar:46fd633ac01b49b7fcabc263bf098c5a8b9e9a69774d234edcca04fb02df8e26',
-        'androidx.versionedparcelable:versionedparcelable:1.1.0:versionedparcelable-1.1.0.aar:9a1d77140ac222b7866b5054ee7d159bc1800987ed2d46dd6afdd145abb710c1',
-        'androidx.viewpager2:viewpager2:1.0.0:viewpager2-1.0.0.aar:e95c0031d4cc247cd48196c6287e58d2cee54d9c79b85afea7c90920330275af',
-        'androidx.viewpager:viewpager:1.0.0:viewpager-1.0.0.aar:147af4e14a1984010d8f155e5e19d781f03c1d70dfed02a8e0d18428b8fc8682',
-        'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
-        'com.almworks.sqlite4java:sqlite4java:0.282:sqlite4java-0.282.jar:9e1d8dd83ca6003f841e3af878ce2dc7c22497493a7bb6d1b62ec1b0d0a83c05',
-        'com.android.tools.analytics-library:protos:30.0.3:protos-30.0.3.jar:f62b89dcd9de719c6a7b7e15fb1dd20e45b57222e675cf633607bd0ed6bca7e7',
-        'com.android.tools.analytics-library:shared:30.0.3:shared-30.0.3.jar:05aa9ba3cc890354108521fdf99802565aae5dd6ca44a6ac8bb8d594d1c1cd15',
-        'com.android.tools.analytics-library:tracker:30.0.3:tracker-30.0.3.jar:5d0ef35bf6733e96210b5085a2a202152921bf834d345959dce1ca3369b528df',
-        'com.android.tools.build:aapt2-proto:4.1.0-alpha01-6193524:aapt2-proto-4.1.0-alpha01-6193524.jar:17e75523e1e92dd4f222c7368ee41df9e964a508232f591e265d0c499baf9dca',
-        'com.android.tools.build:apksig:7.0.3:apksig-7.0.3.jar:012337a2803c9a30dfc41dcbc6450686ee9e5f582549f7f126479f743a343ec9',
-        'com.android.tools.build:apkzlib:7.0.3:apkzlib-7.0.3.jar:b31e53174c92db83c5cc6e7dac6734ea4e907a72e452c2bf1818dfd082c59397',
-        'com.android.tools.build:builder-model:7.0.3:builder-model-7.0.3.jar:483f99d7494a5bed027e1e8d29111384cf535d4842f0be5a79805bd44bb68d4e',
-        'com.android.tools.build:builder-test-api:7.0.3:builder-test-api-7.0.3.jar:f6de4bc2cef545e8367bf82d7c733829c7be3b0b3b8b09fd8c58f2150e59ab46',
-        'com.android.tools.build:builder:7.0.3:builder-7.0.3.jar:c6952da0094b094c2ba0fe84c675622097c5d9b9f9beb53485b860320540cf1d',
-        'com.android.tools.build:manifest-merger:30.0.3:manifest-merger-30.0.3.jar:72b346ba6318b4b6260e6e49df4bea5da2e12329ab6c2beb2269c49a9f51f178',
-        'com.android.tools.ddms:ddmlib:30.0.3:ddmlib-30.0.3.jar:7a914a68ab93393657297234e2f37b22410ae9a433cba692ce8c727c9607e3bb',
-        'com.android.tools.external.com-intellij:intellij-core:30.0.3:intellij-core-30.0.3.jar:1ebe858d3f58eeaa8c06507f8ac0f1c7051e6c61f35a70f3c3967d5734d3abc5',
-        'com.android.tools.external.com-intellij:kotlin-compiler:30.0.3:kotlin-compiler-30.0.3.jar:ed00e441f427cb4e0d418287b9da30b12b7f735f9af32e6b5d3dc960b6a742fc',
-        'com.android.tools.external.org-jetbrains:uast:30.0.3:uast-30.0.3.jar:a77801bee6ff509910e459525c9c34d7f04b066ade123547f16f1917548eadea',
-        'com.android.tools.layoutlib:layoutlib-api:30.0.3:layoutlib-api-30.0.3.jar:4caa87e9ca2e11315f650d576cd59fec1793373bc3fca3f6d53c029e7534e7c4',
-        'com.android.tools.lint:lint-api:30.0.3:lint-api-30.0.3.jar:bcecbd2f752a6560096a9029a47d1de6bd788a51bab505c5ebfba6a18524b983',
-        'com.android.tools.lint:lint-checks:30.0.3:lint-checks-30.0.3.jar:25a7cd42dc3ad502337f131fb8b7e873c53301db0a67b1c64dd4ae7a8eb66cec',
-        'com.android.tools.lint:lint-gradle:30.0.3:lint-gradle-30.0.3.jar:94544d6147a809bf2fd3440e51f28a4e42e547d74aab53eefd74938cdad42c26',
-        'com.android.tools.lint:lint-model:30.0.3:lint-model-30.0.3.jar:0b940a7f575c2ff5cbd038260f41dde686a93c672213881ead3ce8af3513b396',
-        'com.android.tools.lint:lint:30.0.3:lint-30.0.3.jar:ee4f11001e0c7e3b776e0d67399ad354b19b0f168822ec2b7db47c0910ed227d',
-        'com.android.tools:annotations:30.0.3:annotations-30.0.3.jar:5c1944982fda8555855c4f5422fabf0dc8e2306e1f5460e9ad82dae71316bc31',
-        'com.android.tools:common:30.0.3:common-30.0.3.jar:8751efaaf2c2ddd1f0a37526c794347def6a3057ca9fc510307c13a6cf0d036f',
-        'com.android.tools:dvlib:30.0.3:dvlib-30.0.3.jar:5affafcec390041e5afd64cb924153f5e474db47ee8ccc2f555b495083141233',
-        'com.android.tools:repository:30.0.3:repository-30.0.3.jar:0a40c6f16c506903ce2c609affd8228aceda73a69d93dfa42d4f02b8491449f6',
-        'com.android.tools:sdk-common:30.0.3:sdk-common-30.0.3.jar:b45570a380360236ffee0f6bb593d66b673bad3834dfe0d6c9871fa7188ee0eb',
-        'com.android.tools:sdklib:30.0.3:sdklib-30.0.3.jar:7088f20a414fab170a21e457825e14ebe099f753558e02c8acc12c67eb412162',
-        'com.android:signflinger:7.0.3:signflinger-7.0.3.jar:903a4536db3e96b4e1e1dc1e400eb0b91bf7866d9b39cd7ec94d75dde158f152',
-        'com.android:zipflinger:7.0.3:zipflinger-7.0.3.jar:fd209c960a3eff7a339e6fcba07d5e9ef4604d1633c69ab2df987460d9804140',
-        'com.beust:jcommander:1.78:jcommander-1.78.jar:7891debb84b5f83e9bd57593ebece3399abbe0fd938cf306b3534c57913b9615',
-        'com.github.bumptech.glide:annotations:4.11.0:annotations-4.11.0.jar:d219d238006d824962176229d4708abcdddcfe342c6a18a5d0fa48d6f0479b3e',
-        'com.github.bumptech.glide:compiler:4.11.0:compiler-4.11.0.jar:a98cdf265c36261b1d523448b05c322ec290afa865946425eded6361980e8770',
-        'com.github.bumptech.glide:gifdecoder:4.11.0:gifdecoder-4.11.0.aar:197a1cd5b76855aa02b230c13974e293229b901dc2b96fab4315201e78baa804',
-        'com.github.bumptech.glide:glide:4.11.0:glide-4.11.0.aar:5c294e6a5f0f812cef876b8412954c1822da184af38e082a5b766e3c4f4fcd95',
-        'com.github.chrisbanes:PhotoView:2.3.0:PhotoView-2.3.0.aar:6c8989f2945d50ab38b3e0300064f1f8d2d75bbcae1434fe535d9fb6898e9ad6',
-        'com.github.javaparser:javaparser-core:3.17.0:javaparser-core-3.17.0.jar:23f5c982e1c7771423d37d52c774e8d2e80fd7ea7305ebe448797a96f67e6fca',
-        'com.github.kobakei:MaterialFabSpeedDial:1.2.1:MaterialFabSpeedDial-1.2.1.aar:e86198c3c48cd832fb209a769a9f222c2a3cc045743b110ac2391d9737e3ea02',
-        'com.google.android.apps.common.testing.accessibility.framework:accessibility-test-framework:2.0:accessibility-test-framework-2.0.jar:cdf16ef8f5b8023d003ce3cc1b0d51bda737762e2dab2fedf43d1c4292353f7f',
-        'com.google.android.material:material:1.3.0:material-1.3.0.aar:cbf1e7d69fc236cdadcbd1ec5f6c0a1a41aca6ad1ef7f8481058956270ab1f0a',
-        'com.google.auto.value:auto-value-annotations:1.6.2:auto-value-annotations-1.6.2.jar:b48b04ddba40e8ac33bf036f06fc43995fc5084bd94bdaace807ce27d3bea3fb',
-        'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
-        'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
-        'com.google.code.gson:gson:2.8.6:gson-2.8.6.jar:c8fb4839054d280b3033f800d1f5a97de2f028eb8ba2eb458ad287e536f3f25f',
-        'com.google.dagger:dagger-compiler:2.33:dagger-compiler-2.33.jar:aa8a0d8370c578fd6999802d0d90b9829377a46d2c1141e11b8f737970e7155e',
-        'com.google.dagger:dagger-producers:2.33:dagger-producers-2.33.jar:5897f0b6eef799c2adfe3ccacc58c0fb374d58acb063c3ebe5366c38a8bce5c8',
-        'com.google.dagger:dagger-spi:2.33:dagger-spi-2.33.jar:e2dcab2221b8afb9556ef0a1c83b0bd5f42552e254322a257330f754cdbbb9d4',
-        'com.google.dagger:dagger:2.33:dagger-2.33.jar:d8798c5b8cf6b125234e33af5c6293bb9f2208ce29b57924c35b8c0be7b6bdcb',
-        'com.google.errorprone:error_prone_annotations:2.2.0:error_prone_annotations-2.2.0.jar:6ebd22ca1b9d8ec06d41de8d64e0596981d9607b42035f9ed374f9de271a481a',
-        'com.google.errorprone:error_prone_annotations:2.3.4:error_prone_annotations-2.3.4.jar:baf7d6ea97ce606c53e11b6854ba5f2ce7ef5c24dddf0afa18d1260bd25b002c',
-        'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30',
-        'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e',
-        'com.google.guava:failureaccess:1.0.1:failureaccess-1.0.1.jar:a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26',
-        'com.google.guava:guava:27.0.1-jre:guava-27.0.1-jre.jar:e1c814fd04492a27c38e0317eabeaa1b3e950ec8010239e400fe90ad6c9107b4',
-        'com.google.guava:guava:27.1-jre:guava-27.1-jre.jar:4a5aa70cc968a4d137e599ad37553e5cfeed2265e8c193476d7119036c536fe7',
-        'com.google.guava:guava:30.1-jre:guava-30.1-jre.jar:e6dd072f9d3fe02a4600688380bd422bdac184caf6fe2418cfdd0934f09432aa',
-        'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
-        'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6',
-        'com.google.j2objc:j2objc-annotations:1.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b',
-        'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
-        'com.google.protobuf:protobuf-java:3.10.0:protobuf-java-3.10.0.jar:161d7d61a8cb3970891c299578702fd079646e032329d6c2cabf998d191437c9',
-        'com.google.zxing:core:3.3.3:core-3.3.3.jar:5820f81e943e4bce0329306621e2d6255d2930b0a6ce934c5c23c0d6d3f20599',
-        'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
-        'com.ibm.icu:icu4j:53.1:icu4j-53.1.jar:e37a4467bac5cdeb02c5c4b8e5063d2f4e67b69e3c7df6d6b610f13185572bab',
-        'com.jraska:falcon:2.1.1:falcon-2.1.1.aar:827f06556b7fa599f29a48a5277df39ca3dce5080d4ea6f9ea1f9c7b6b78bb7a',
-        'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
-        'com.squareup:javawriter:2.1.1:javawriter-2.1.1.jar:f699823d0081f69cbb676c1845ea222e0ada79bc88a53e5d22d8bd02d328f57e',
-        'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
-        'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
-        'com.sun.istack:istack-commons-runtime:3.0.8:istack-commons-runtime-3.0.8.jar:4ffabb06be454a05e4398e20c77fa2b6308d4b88dfbef7ca30a76b5b7d5505ef',
-        'com.sun.xml.fastinfoset:FastInfoset:1.2.16:FastInfoset-1.2.16.jar:056f3a1e144409f21ed16afc26805f58e9a21f3fce1543c42d400719d250c511',
-        'com.thoughtworks.qdox:qdox:1.12.1:qdox-1.12.1.jar:21fba22f830e9268f07cf4ab2d99e8181abbdcb0cb91ee0228eb3cb918dcdd1d',
-        'com.vanniktech:emoji-google:0.7.0:emoji-google-0.7.0.aar:b98966812e3f607ee823cde15dd9b3823c6f02e5587572b860b9d95e3f971402',
-        'com.vanniktech:emoji:0.7.0:emoji-0.7.0.aar:66f5981f8b5f93e82d2d4b3fa4c6299904d686ca62a2366e61de723b20253707',
-        'commons-codec:commons-codec:1.10:commons-codec-1.10.jar:4241dfa94e711d435f29a4604a3e2de5c4aa3c165e23bd066be6fc1fc4309569',
-        'commons-io:commons-io:2.4:commons-io-2.4.jar:cc6a41dc3eaacc9e440a6bd0d2890b20d36b4ee408fe2d67122f328bb6e01581',
-        'commons-logging:commons-logging:1.2:commons-logging-1.2.jar:daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636',
-        'de.hdodenhof:circleimageview:3.1.0:circleimageview-3.1.0.aar:8e9965b54072ee159074a55df216e17d5a622c94ce915ef311b1a1f32660c7fb',
-        'info.guardianproject.panic:panic:1.0:panic-1.0.jar:35116ab95212e67f94577faf67b88c11a6b21cbf9178b3f5b51d3dff45203ffd',
-        'info.guardianproject.trustedintents:trustedintents:0.2:trustedintents-0.2.jar:6221456d8821a8d974c2acf86306900237cf6afaaa94a4c9c44e161350f80f3e',
-        'info.picocli:picocli:4.5.2:picocli-4.5.2.jar:b4395e9a67932616efd2245d984bf5fcd453c2c5049558c3ce959ac2af4d3fac',
-        'it.unimi.dsi:fastutil:8.4.0:fastutil-8.4.0.jar:2ad2824a4a0a0eb836b52ee2fc84ba2134f44bce7bfa54015ae3f31c710a3071',
-        'jakarta.activation:jakarta.activation-api:1.2.1:jakarta.activation-api-1.2.1.jar:8b0a0f52fa8b05c5431921a063ed866efaa41dadf2e3a7ee3e1961f2b0d9645b',
-        'jakarta.xml.bind:jakarta.xml.bind-api:2.3.2:jakarta.xml.bind-api-2.3.2.jar:69156304079bdeed9fc0ae3b39389f19b3cc4ba4443bc80508995394ead742ea',
-        'javax.annotation:javax.annotation-api:1.3.2:javax.annotation-api-1.3.2.jar:e04ba5195bcd555dc95650f7cc614d151e4bcd52d29a10b8aa2197f3ab89ab9b',
-        'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
-        'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
-        'jline:jline:2.14.6:jline-2.14.6.jar:97d1acaac82409be42e622d7a54d3ae9d08517e8aefdea3d2ba9791150c2f02d',
-        'junit:junit:4.13.1:junit-4.13.1.jar:c30719db974d6452793fe191b3638a5777005485bae145924044530ffa5f6122',
-        'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
-        'net.bytebuddy:byte-buddy-agent:1.10.20:byte-buddy-agent-1.10.20.jar:b592a6c43e752bf41659717956c57fbb790394d2ee5f8941876659f9c5c0e7e8',
-        'net.bytebuddy:byte-buddy:1.10.20:byte-buddy-1.10.20.jar:5fcad05da791e9a22811c255a4a74b7ea094b7243d9dbf3e6fc578c8c94290ac',
-        'net.java.dev.jna:jna-platform:5.6.0:jna-platform-5.6.0.jar:9ecea8bf2b1b39963939d18b70464eef60c508fed8820f9dcaba0c35518eabf7',
-        'net.java.dev.jna:jna:5.6.0:jna-5.6.0.jar:5557e235a8aa2f9766d5dc609d67948f2a8832c2d796cea9ef1d6cbe0b3b7eaf',
-        'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
-        'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
-        'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
-        'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2',
-        'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
-        'org.apache.ant:ant-antlr:1.10.9:ant-antlr-1.10.9.jar:7623dc9d0f20ea713290c6bf1a23f4c059447aef7ff9f5b2be75960f3f028d2e',
-        'org.apache.ant:ant-junit:1.10.9:ant-junit-1.10.9.jar:960bdc8827954d62206ba42d0a68a7ee4476175ba47bb113e17e77cce7394630',
-        'org.apache.ant:ant-launcher:1.10.9:ant-launcher-1.10.9.jar:fcce891f57f3be72149ff96ac2a80574165b3e0839866b95d24528f3027d50c1',
-        'org.apache.ant:ant:1.10.9:ant-1.10.9.jar:0715478af585ea80a18985613ebecdc7922122d45b2c3c970ff9b352cddb75fc',
-        'org.apache.commons:commons-compress:1.20:commons-compress-1.20.jar:0aeb625c948c697ea7b205156e112363b59ed5e2551212cd4e460bdb72c7c06e',
-        'org.apache.httpcomponents:httpclient:4.5.6:httpclient-4.5.6.jar:c03f813195e7a80e3608d0ddd8da80b21696a4c92a6a2298865bf149071551c7',
-        'org.apache.httpcomponents:httpcore:4.4.10:httpcore-4.4.10.jar:78ba1096561957db1b55200a159b648876430342d15d461277e62360da19f6fd',
-        'org.apache.httpcomponents:httpmime:4.5.6:httpmime-4.5.6.jar:0b2b1102c18d3c7e05a77214b9b7501a6f6056174ae5604e0e256776eda7553e',
-        'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
-        'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
-        'org.bouncycastle:bcprov-jdk15on:1.65:bcprov-jdk15on-1.65.jar:e78f96eb59066c94c94fb2d6b5eb80f52feac6f5f9776898634f8addec6e2137',
-        'org.briarproject:dont-kill-me-lib:0.2.5:dont-kill-me-lib-0.2.5.aar:55cd9d511b7016ab573905d64bc54e222e2633144d36389192b8b34485b31b9d',
-        'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
-        'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
-        'org.checkerframework:checker-qual:3.5.0:checker-qual-3.5.0.jar:729990b3f18a95606fc2573836b6958bcdb44cb52bfbd1b7aa9c339cff35a5a4',
-        'org.codehaus.groovy:groovy-ant:3.0.7:groovy-ant-3.0.7.jar:6ed2ba82813d128f7050c24142e87b3dc2ad8b504786280eb03e81f0cf6a5793',
-        'org.codehaus.groovy:groovy-astbuilder:3.0.7:groovy-astbuilder-3.0.7.jar:b290451eb1583666e906c41f7d14747b4cc96363c99c478b244634fd5dfc9013',
-        'org.codehaus.groovy:groovy-cli-picocli:3.0.7:groovy-cli-picocli-3.0.7.jar:71b4bd11fb30a9c7b5618e22122c9c5141958fb27f4dcf0068b6f715088f6916',
-        'org.codehaus.groovy:groovy-console:3.0.7:groovy-console-3.0.7.jar:0541b358b6b8e5363215026736168fccfec1d91bac678d066fa77349eeeaa5dd',
-        'org.codehaus.groovy:groovy-datetime:3.0.7:groovy-datetime-3.0.7.jar:b9823d14b1a4f94236ae2f8a471701aab17e093e1b33402b91550b5c8dd88f04',
-        'org.codehaus.groovy:groovy-docgenerator:3.0.7:groovy-docgenerator-3.0.7.jar:bf53f7a11c9eb1e278e1b8ed2714c741bcf781235c803ad3ba1555f2614573f3',
-        'org.codehaus.groovy:groovy-groovydoc:3.0.7:groovy-groovydoc-3.0.7.jar:86b24dfc23c005066ab83927cdb54177f06c9531773f2e2d2ecc9a131f7c2677',
-        'org.codehaus.groovy:groovy-groovysh:3.0.7:groovy-groovysh-3.0.7.jar:5c40e78cbc09726aedd1c75fab112d245d665d6294870f9119e6cd3013ed14ab',
-        'org.codehaus.groovy:groovy-jmx:3.0.7:groovy-jmx-3.0.7.jar:0a89f3007884eb156751937d93382038b83d39c7c2f0ab156ebf251a7251f2ab',
-        'org.codehaus.groovy:groovy-json:3.0.7:groovy-json-3.0.7.jar:df1f0ee475e3fc93a6a0d17548294e160cca5de6d9d36817a7be1fbe650de03b',
-        'org.codehaus.groovy:groovy-jsr223:3.0.7:groovy-jsr223-3.0.7.jar:1dbd969595332416193baa660fbb45743d19696eaa25fe98e591a2739e13517e',
-        'org.codehaus.groovy:groovy-macro:3.0.7:groovy-macro-3.0.7.jar:c6cc06df526b39e2c359e2435f0071594c5a1c7babafaa6c184fdd8fa931531f',
-        'org.codehaus.groovy:groovy-nio:3.0.7:groovy-nio-3.0.7.jar:db54c577882b294cd8c975ec5451596441baf54781319c61627dca0e0c2361ef',
-        'org.codehaus.groovy:groovy-servlet:3.0.7:groovy-servlet-3.0.7.jar:5b6a909bf501c209adfb6205b9e740649609074455fd979bf9da4853e6ff9a39',
-        'org.codehaus.groovy:groovy-sql:3.0.7:groovy-sql-3.0.7.jar:252bb6c74e1a9f41756ad4fbd3b0d2eddc93bb61109961dd1952a37bf2d57a64',
-        'org.codehaus.groovy:groovy-swing:3.0.7:groovy-swing-3.0.7.jar:bd942032d9328d54c6679c49a41f6caa0d4a0039ebe598493b8a647730d98cff',
-        'org.codehaus.groovy:groovy-templates:3.0.7:groovy-templates-3.0.7.jar:f119e07f650ef186ae5a4b944f9e30915b14311bad47c94a6b32de8d4f69bc80',
-        'org.codehaus.groovy:groovy-test-junit5:3.0.7:groovy-test-junit5-3.0.7.jar:c16eeea07b8e396891e266d7ba9388b24ac804237ffdd9a792b0d08969bad014',
-        'org.codehaus.groovy:groovy-test:3.0.7:groovy-test-3.0.7.jar:f71afd7c25d43017f89ea47e6de6daec971d159047dae083c1513a8422d44b90',
-        'org.codehaus.groovy:groovy-testng:3.0.7:groovy-testng-3.0.7.jar:713d5f2231bbb5712aefd362151b9ffd884aeb7ef2e773315cc54259cbdd063d',
-        'org.codehaus.groovy:groovy-xml:3.0.7:groovy-xml-3.0.7.jar:8a62e7c9ddece3e82676c4bef2f2c100f459602cd1fb6a14e94187bf863e97ff',
-        'org.codehaus.groovy:groovy:3.0.7:groovy-3.0.7.jar:51d1777e8dd1f00e60ea56e00d8a354ff5aab1f00fc8464ae8d39d71867e401f',
-        'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
-        'org.glassfish.jaxb:jaxb-runtime:2.3.2:jaxb-runtime-2.3.2.jar:e6e0a1e89fb6ff786279e6a0082d5cef52dc2ebe67053d041800737652b4fd1b',
-        'org.glassfish.jaxb:txw2:2.3.2:txw2-2.3.2.jar:4a6a9f483388d461b81aa9a28c685b8b74c0597993bf1884b04eddbca95f48fe',
-        'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
-        'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
-        'org.hamcrest:hamcrest-integration:1.3:hamcrest-integration-1.3.jar:70f418efbb506c5155da5f9a5a33262ea08a9e4d7fea186aa9015c41a7224ac2',
-        'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
-        'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
-        'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
-        'org.jacoco:org.jacoco.agent:0.8.3:org.jacoco.agent-0.8.3.jar:522deb254ee16a04cc8341cc8f335f5cb7232982994d961b9cf3a0454709209f',
-        'org.jacoco:org.jacoco.ant:0.8.3:org.jacoco.ant-0.8.3.jar:735844e1ae15f9b875b42a27ac5cb61cc26e106d9e839e5d1c6756709b424ce0',
-        'org.jacoco:org.jacoco.core:0.8.3:org.jacoco.core-0.8.3.jar:0818437bc060a0c7cc798148f22b713702aae2771aba104444407697d578f1ea',
-        'org.jacoco:org.jacoco.report:0.8.3:org.jacoco.report-0.8.3.jar:aae08fa4ff043c807b8876cdb2d8705eb8449a55efce461baa6c09da245088c1',
-        'org.jetbrains.intellij.deps:trove4j:1.0.20181211:trove4j-1.0.20181211.jar:affb7c85a3c87bdcf69ff1dbb84de11f63dc931293934bc08cd7ab18de083601',
-        'org.jetbrains.kotlin:kotlin-reflect:1.4.32:kotlin-reflect-1.4.32.jar:dbf19e9cdaa9c3c170f3f6f6ce3922f38dfc1d7fa1cab5b7c23a19da8b5eec5b',
-        'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20:kotlin-stdlib-common-1.4.20.jar:a7112c9b3cefee418286c9c9372f7af992bd1e6e030691d52f60cb36dbec8320',
-        'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.32:kotlin-stdlib-common-1.4.32.jar:e1ff6f55ee9e7591dcc633f7757bac25a7edb1cc7f738b37ec652f10f66a4145',
-        'org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10:kotlin-stdlib-common-1.7.10.jar:19f102efe9629f8eabc63853ad15c533e47c47f91fca09285c5bde86e59f91d4',
-        'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.32:kotlin-stdlib-jdk7-1.4.32.jar:5f801e75ca27d8791c14b07943c608da27620d910a8093022af57f543d5d98b6',
-        'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.20:kotlin-stdlib-jdk7-1.6.20.jar:aa2fa2e81355c4d98dd97da2169bf401f842261378f5b1cbea1aa11855d67620',
-        'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.32:kotlin-stdlib-jdk8-1.4.32.jar:adc43e54757b106e0cd7b3b7aa257dff471b61efdabe067fc02b2f57e2396262',
-        'org.jetbrains.kotlin:kotlin-stdlib:1.4.20:kotlin-stdlib-1.4.20.jar:b8ab1da5cdc89cb084d41e1f28f20a42bd431538642a5741c52bbfae3fa3e656',
-        'org.jetbrains.kotlin:kotlin-stdlib:1.4.32:kotlin-stdlib-1.4.32.jar:13e9fd3e69dc7230ce0fc873a92a4e5d521d179bcf1bef75a6705baac3bfecba',
-        'org.jetbrains.kotlin:kotlin-stdlib:1.7.10:kotlin-stdlib-1.7.10.jar:e771fe74250a943e8f6346713201ff1d8cb95c3a5d1a91a22b65a9e04f6a8901',
-        'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1:kotlinx-coroutines-android-1.4.1.jar:d4cadb673b2101f1ee5fbc147956ac78b1cfd9cc255fb53d3aeb88dff11d99ca',
-        'org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.4.1:kotlinx-coroutines-core-jvm-1.4.1.jar:6d2f87764b6638f27aff12ed380db4b63c9d46ba55dc32683a650598fa5a3e22',
-        'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0:kotlinx-metadata-jvm-0.1.0.jar:9753bb39efef35957c5c15df9a3cb769aabf2cdfa74b47afcb7760e5146be3b5',
-        'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
-        'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
-        'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
-        'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd',
-        'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04',
-        'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
-        'org.junit.jupiter:junit-jupiter-api:5.7.0:junit-jupiter-api-5.7.0.jar:b03f78e0daeed2d77a0af9bcd662b4cdb9693f7ee72e01a539b508b84c63d182',
-        'org.junit.jupiter:junit-jupiter-engine:5.7.0:junit-jupiter-engine-5.7.0.jar:dfa26af94644ac2612dde6625852fcb550a0d21caa243257de54cba738ba87af',
-        'org.junit.platform:junit-platform-commons:1.7.0:junit-platform-commons-1.7.0.jar:5330ee87cc7586e6e25175a34e9251624ff12ff525269d3415d0b4ca519b6fea',
-        'org.junit.platform:junit-platform-engine:1.7.0:junit-platform-engine-1.7.0.jar:75f21a20dc594afdc875736725b408cec6d0344874d29f34b2dd3075500236f2',
-        'org.junit.platform:junit-platform-launcher:1.7.0:junit-platform-launcher-1.7.0.jar:fbdc748fde4c4279fe1d3c607447cb3b7ccd45d7338fc574f8a894ddf2d16818',
-        'org.jvnet.staxex:stax-ex:1.8.1:stax-ex-1.8.1.jar:20522549056e9e50aa35ef0b445a2e47a53d06be0b0a9467d704e2483ffb049a',
-        'org.mockito:mockito-core:3.9.0:mockito-core-3.9.0.jar:a1f64211407b8dc4cf80b16e07cc11aa9e5228d53dc4a5357326d66825f6a4ac',
-        'org.nanohttpd:nanohttpd:2.3.1:nanohttpd-2.3.1.jar:de864c47818157141a24c9acb36df0c47d7bf15b7ff48c90610f3eb4e5df0e58',
-        'org.objenesis:objenesis:3.2:objenesis-3.2.jar:03d960bd5aef03c653eb000413ada15eb77cdd2b8e4448886edf5692805e35f3',
-        'org.opentest4j:opentest4j:1.2.0:opentest4j-1.2.0.jar:58812de60898d976fb81ef3b62da05c6604c18fd4a249f5044282479fc286af2',
-        'org.ow2.asm:asm-analysis:7.0:asm-analysis-7.0.jar:e981f8f650c4d900bb033650b18e122fa6b161eadd5f88978d08751f72ee8474',
-        'org.ow2.asm:asm-analysis:7.2:asm-analysis-7.2.jar:be922aae60ff1ff1768e8e6544a38a7f92bd0a6d6b0b9791f94955d1bd453de2',
-        'org.ow2.asm:asm-commons:7.0:asm-commons-7.0.jar:fed348ef05958e3e846a3ac074a12af5f7936ef3d21ce44a62c4fa08a771927d',
-        'org.ow2.asm:asm-commons:7.2:asm-commons-7.2.jar:0e86b8b179c5fb223d1a880a0ff4960b6978223984b94e62e71135f2d8ea3558',
-        'org.ow2.asm:asm-tree:7.0:asm-tree-7.0.jar:cfd7a0874f9de36a999c127feeadfbfe6e04d4a71ee954d7af3d853f0be48a6c',
-        'org.ow2.asm:asm-tree:7.2:asm-tree-7.2.jar:c063f5a67fa03cdc9bd79fd1c2ea6816cc4a19473ecdfbd9e9153b408c6f2656',
-        'org.ow2.asm:asm-util:7.0:asm-util-7.0.jar:75fbbca440ef463f41c2b0ab1a80abe67e910ac486da60a7863cbcb5bae7e145',
-        'org.ow2.asm:asm-util:7.2:asm-util-7.2.jar:6e24913b021ffacfe8e7e053d6e0ccc731941148cfa078d4f1ed3d96904530f8',
-        'org.ow2.asm:asm:7.0:asm-7.0.jar:b88ef66468b3c978ad0c97fd6e90979e56155b4ac69089ba7a44e9aa7ffe9acf',
-        'org.ow2.asm:asm:7.2:asm-7.2.jar:7e6cc9e92eb94d04e39356c6d8144ca058cda961c344a7f62166a405f3206672',
-        'org.robolectric:annotations:4.4:annotations-4.4.jar:d2b2d71a1f902a5a016dde5a2feb3be521d120192f9217adadbfb483d79f89ff',
-        'org.robolectric:junit:4.4:junit-4.4.jar:c5ebcb20cf9d2173a294a6feff68331fff718a368e332df70c7ea7e3bdce846e',
-        'org.robolectric:pluginapi:4.4:pluginapi-4.4.jar:b2f743db060502cb366f67dcd6c3929c7f4656744d91ab81d749b8bf641f5512',
-        'org.robolectric:plugins-maven-dependency-resolver:4.4:plugins-maven-dependency-resolver-4.4.jar:5279024a6bdbb2ee1791b06da13cc890628c583ad48414ae13a4f57d7db749a3',
-        'org.robolectric:resources:4.4:resources-4.4.jar:e39862f71887561dfde65030aeca5148bf0f6279b25fb9e146b75c2933fcabcf',
-        'org.robolectric:robolectric:4.4:robolectric-4.4.jar:38e0368914a48d6d8e543c12670beb1e36e09d037e664280fb604dbbfd10fe5f',
-        'org.robolectric:sandbox:4.4:sandbox-4.4.jar:e52f3f012f893ca8458cbe3e664f1f9f13cb0501e2d730bd089d693c49ccedda',
-        'org.robolectric:shadowapi:4.4:shadowapi-4.4.jar:48ce6ab59137366eb88138be5ec65bd9c0b8c54a512151140a02391fc723b83f',
-        'org.robolectric:shadows-framework:4.4:shadows-framework-4.4.jar:0602f5bbef601036831e0ce8600b6d08d80ce3c9260be5cb7b362b176ce3d9f0',
-        'org.robolectric:utils-reflector:4.4:utils-reflector-4.4.jar:35a77865bb9a451e99b95575cb154a5f08ecb007bd17e390817c0f31ab9db869',
-        'org.robolectric:utils:4.4:utils-4.4.jar:f9756b5c57116ae9ec55a65ca52b64ba1f77d30b5eb7b55fef5d125fdf7d69d9',
-        'org.testng:testng:7.3.0:testng-7.3.0.jar:63727488f9717d57f0d0a0fee5a1fc10a2be9cfcff2ec3a7187656d663c0774e',
-        'tools.fastlane:screengrab:2.0.0:screengrab-2.0.0.aar:15ac15eb7c371db05e721be8d466567c2b7274b767d91478e781b6d89ee5d3d0',
-        'uk.co.samuelwall:material-tap-target-prompt:3.3.0:material-tap-target-prompt-3.3.0.aar:00f16e8d7e55d01e3b41cf66e09eee8588870ca7285ba3c72267ca0482f1606e',
-        'xerces:xercesImpl:2.12.0:xercesImpl-2.12.0.jar:b50d3a4ca502faa4d1c838acb8aa9480446953421f7327e338c5dda3da5e76d0',
-        'xml-apis:xml-apis:1.4.01:xml-apis-1.4.01.jar:a840968176645684bb01aed376e067ab39614885f9eee44abe35a5f20ebe7fad',
+            'androidx.activity:activity-ktx:1.2.3:activity-ktx-1.2.3.aar:423c0226e237e08de245cf66f8ccaf103854bc19a584d971a4a075fd15d70df1',
+            'androidx.activity:activity:1.2.2:activity-1.2.2.aar:e165fb20f006b77894d349572cc3acd2760baa8416ae4d33cb8de6a84dd6730c',
+            'androidx.activity:activity:1.2.4:activity-1.2.4.aar:ae8e9c7de57e387d2ad90e73f3a5a5dfd502bd4f034c1dccfdb3506d1d2df81a',
+            'androidx.annotation:annotation-experimental:1.0.0:annotation-experimental-1.0.0.aar:b219d2b568e7e4ba534e09f8c2fd242343df6ccbdfbbe938846f5d740e6b0b11',
+            'androidx.annotation:annotation:1.5.0:annotation-1.5.0.jar:261fb7c0210858500bab66d34354972a75166ab4182add283780b05513d6ec4a',
+            'androidx.appcompat:appcompat-resources:1.2.0:appcompat-resources-1.2.0.aar:c470297c03ff3de1c3d15dacf0be0cae63abc10b52f021dd07ae28daa3100fe5',
+            'androidx.appcompat:appcompat:1.2.0:appcompat-1.2.0.aar:3d2131a55a61a777322e2126e0018011efa6339e53b44153eb651b16020cca70',
+            'androidx.arch.core:core-common:2.1.0:core-common-2.1.0.jar:fe1237bf029d063e7f29fe39aeaf73ef74c8b0a3658486fc29d3c54326653889',
+            'androidx.arch.core:core-runtime:2.1.0:core-runtime-2.1.0.aar:dd77615bd3dd275afb11b62df25bae46b10b4a117cd37943af45bdcbf8755852',
+            'androidx.arch.core:core-testing:2.1.0:core-testing-2.1.0.aar:c57ffade2a9a844bd62b4f4c3916fad5e09e9f24cceba27e932c25bb7a6d1d8f',
+            'androidx.cardview:cardview:1.0.0:cardview-1.0.0.aar:1193c04c22a3d6b5946dae9f4e8c59d6adde6a71b6bd5d87fb99d82dda1afec7',
+            'androidx.collection:collection-ktx:1.1.0:collection-ktx-1.1.0.jar:2bfc54475c047131913361f56d0f7f019c6e5bee53eeb0eb7d94a7c499a05227',
+            'androidx.collection:collection:1.1.0:collection-1.1.0.jar:632a0e5407461de774409352940e292a291037724207a787820c77daf7d33b72',
+            'androidx.constraintlayout:constraintlayout-solver:2.0.4:constraintlayout-solver-2.0.4.jar:9ca19f5448709301c7563488ef941be9dfa55c83538ca7a059b2113e83527b46',
+            'androidx.constraintlayout:constraintlayout:2.0.4:constraintlayout-2.0.4.aar:307a79a4a1ccff44249c72a2bf7f47da09fa1b6b1fab2a25808ca889382b738e',
+            'androidx.coordinatorlayout:coordinatorlayout:1.1.0:coordinatorlayout-1.1.0.aar:44a9e30abf56af1025c52a0af506fee9c4131aa55efda52f9fd9451211c5e8cb',
+            'androidx.core:core-ktx:1.2.0:core-ktx-1.2.0.aar:dcb74d510d552b35eff73b0dd27b829649535f3902e5b5a1f26040383c10a940',
+            'androidx.core:core:1.3.1:core-1.3.1.aar:e92ea65a37d589943d405a6a54d1be9d12a225948f26c4e41e511dd55e81efb6',
+            'androidx.cursoradapter:cursoradapter:1.0.0:cursoradapter-1.0.0.aar:a81c8fe78815fa47df5b749deb52727ad11f9397da58b16017f4eb2c11e28564',
+            'androidx.customview:customview:1.0.0:customview-1.0.0.aar:20e5b8f6526a34595a604f56718da81167c0b40a7a94a57daa355663f2594df2',
+            'androidx.documentfile:documentfile:1.0.0:documentfile-1.0.0.aar:865a061ef2fad16522f8433536b8d47208c46ff7c7745197dfa1eeb481869487',
+            'androidx.drawerlayout:drawerlayout:1.0.0:drawerlayout-1.0.0.aar:9402442cdc5a43cf62fb14f8cf98c63342d4d9d9b805c8033c6cf7e802749ac1',
+            'androidx.dynamicanimation:dynamicanimation:1.0.0:dynamicanimation-1.0.0.aar:ce005162c229bf308d2d5b12fb6cad0874069cbbeaccee63a8193bd08d40de04',
+            'androidx.exifinterface:exifinterface:1.3.3:exifinterface-1.3.3.aar:996814984cb33d90921064c867d0ac41dffa10a1048ada652881c21326602397',
+            'androidx.fragment:fragment-ktx:1.4.0:fragment-ktx-1.4.0.aar:439873b250461eb2245e393fe6683dceb567e7a18d9d6cf4538de9befa4ed1b0',
+            'androidx.fragment:fragment-testing:1.4.0:fragment-testing-1.4.0.aar:1f874b83919c69f2e0df6de0ba2ad87a0d61cc7840d90b481ee0d4db85c2385b',
+            'androidx.fragment:fragment:1.3.4:fragment-1.3.4.aar:c023c0ab666456885284d8e88519a743bc863c2b2effb92741fc789cbdb10db4',
+            'androidx.fragment:fragment:1.4.0:fragment-1.4.0.aar:ec98a3b2f56f25cd247f928ab717d5527d27aea56ca4c02e67fbcd1ec32e5eed',
+            'androidx.interpolator:interpolator:1.0.0:interpolator-1.0.0.aar:33193135a64fe21fa2c35eec6688f1a76e512606c0fc83dc1b689e37add7732a',
+            'androidx.legacy:legacy-support-core-utils:1.0.0:legacy-support-core-utils-1.0.0.aar:a7edcf01d5b52b3034073027bc4775b78a4764bb6202bb91d61c829add8dd1c7',
+            'androidx.lifecycle:lifecycle-common:2.3.1:lifecycle-common-2.3.1.jar:15848fb56db32f4c7cdc72b324003183d52a4884d6bf09be708ac7f587d139b5',
+            'androidx.lifecycle:lifecycle-extensions:2.2.0:lifecycle-extensions-2.2.0.aar:648c8de1d10b025d524a2e46ac994fc3f6bf186826c09ec1a62d250bf1b877ae',
+            'androidx.lifecycle:lifecycle-livedata-core-ktx:2.3.1:lifecycle-livedata-core-ktx-2.3.1.aar:6dd41c3c33daeb503fd87fbfff7043adb0be6c541a9c9e09bf531ca49520fddb',
+            'androidx.lifecycle:lifecycle-livedata-core:2.3.1:lifecycle-livedata-core-2.3.1.aar:e55d38c372460f0a03997ddc950c67227511340fd74f8634d99d29653cd81ab1',
+            'androidx.lifecycle:lifecycle-livedata:2.2.0:lifecycle-livedata-2.2.0.aar:d83af94860aa9f64cbdc51f40796a7cf55b116f0e6efd752e845c0104c8b16f6',
+            'androidx.lifecycle:lifecycle-process:2.2.0:lifecycle-process-2.2.0.aar:3a977e7778fc8418742d388409daaba7ea8fea8823d21ffb96e4c4236f715070',
+            'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1:lifecycle-runtime-ktx-2.3.1.aar:7ad2987dd7f4075c0871a72cf07e9649d9cd790fc23dfab1972eca4710373873',
+            'androidx.lifecycle:lifecycle-runtime:2.3.1:lifecycle-runtime-2.3.1.aar:dd294f4a689c71ff877fd41f3b67a3a62f7760d44ce420e6130f1fc3569d8f00',
+            'androidx.lifecycle:lifecycle-service:2.2.0:lifecycle-service-2.2.0.aar:ca2801ffc069555afed8eddd2292130f436956452bc8bbad30fb56f8e4e382a0',
+            'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1:lifecycle-viewmodel-ktx-2.3.1.aar:5fb3591b6a54eeb3e204be0125d48eb987b8ea45a5048140036865482ccf9de9',
+            'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.3.1:lifecycle-viewmodel-savedstate-2.3.1.aar:97137a8af6a31776a14e4866ab808c7c0a791b484bdbc788bbd83e66407564c0',
+            'androidx.lifecycle:lifecycle-viewmodel:2.3.1:lifecycle-viewmodel-2.3.1.aar:b6db4c274a12ff85a4747e1e6669c7e98aefa2571ace9d1f1a6fa6be417ce838',
+            'androidx.loader:loader:1.0.0:loader-1.0.0.aar:11f735cb3b55c458d470bed9e25254375b518b4b1bad6926783a7026db0f5025',
+            'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0:localbroadcastmanager-1.0.0.aar:e71c328ceef5c4a7d76f2d86df1b65d65fe2acf868b1a4efd84a3f34336186d8',
+            'androidx.preference:preference:1.1.1:preference-1.1.1.aar:317dcbc38242aea2f6262c06d51b8a22827e98959967edd40f82600a15cb4bff',
+            'androidx.print:print:1.0.0:print-1.0.0.aar:1d5c7f3135a1bba661fc373fd72e11eb0a4adbb3396787826dd8e4190d5d9edd',
+            'androidx.recyclerview:recyclerview-selection:1.1.0:recyclerview-selection-1.1.0.aar:9e2ba1c7d6b0eb5e64c10b1b0eb01b51e8511cee002c9bd56ce9cc138ebc4898',
+            'androidx.recyclerview:recyclerview:1.1.0:recyclerview-1.1.0.aar:f0d2b5a67d0a91ee1b1c73ef2b636a81f3563925ddd15a1d4e1c41ec28de7a4f',
+            'androidx.savedstate:savedstate-ktx:1.1.0:savedstate-ktx-1.1.0.aar:e44d61347463b0fafeeb649cbcc3d7109b2eb5e11d1522e986105170cdebbf68',
+            'androidx.savedstate:savedstate:1.1.0:savedstate-1.1.0.aar:d60bbe44c2c08083a17c5dc678a6d6b4d0a2d664858016ab5c049cbea90a63b7',
+            'androidx.test.espresso:espresso-contrib:3.3.0:espresso-contrib-3.3.0.aar:f400cabdc181356acf6b210e4509dcb9649d9e2b6b6e218c60fcfc15e8a756d1',
+            'androidx.test.espresso:espresso-core:3.3.0:espresso-core-3.3.0.aar:23ebf6014645e0c60aec7d1ed924d4d4c848ae8c3673b7d8d06b2ec6a56cafee',
+            'androidx.test.espresso:espresso-idling-resource:3.3.0:espresso-idling-resource-3.3.0.aar:29519b112731f289cc6e2f9b2eccc5ea72c754b04272bb93370f45d7e170a7c6',
+            'androidx.test.espresso:espresso-intents:3.3.0:espresso-intents-3.3.0.aar:5b6cd6aadce78edc705d93c1e81ace3b59be97128aca0e88fd9c5c176aa9bf10',
+            'androidx.test.ext:junit:1.1.3:junit-1.1.3.aar:a97209d75a9a85815fa8934f5a4a320de1163ffe94e2f0b328c0c98a59660690',
+            'androidx.test.services:storage:1.4.0:storage-1.4.0.aar:35cfbf442abb83e5876cd5deb9de02ae047459f18f831097c5caa76d626bc38a',
+            'androidx.test.services:test-services:1.3.0:test-services-1.3.0.apk:1b88faab6864baf25c5d0b92a610c283c159a566e7a56c03307117fa1b542993',
+            'androidx.test.uiautomator:uiautomator:2.2.0:uiautomator-2.2.0.aar:2838e9d961dbffefbbd229a2bd4f6f82ac4fb2462975862a9e75e9ed325a3197',
+            'androidx.test:core:1.4.0:core-1.4.0.aar:671284e62e393f16ceae1a99a3a9a07bf1aacda29f8fe7b6b884355ef34c09cf',
+            'androidx.test:monitor:1.4.0:monitor-1.4.0.aar:46a912a1e175f27a97521af3f50e5af87c22c49275dd2c57c043740012806325',
+            'androidx.test:orchestrator:1.3.0:orchestrator-1.3.0.apk:676f808d08a3d05050eae30c3b7d92ce5cef1e00a54d68355bb7e7d4b72366fe',
+            'androidx.test:rules:1.3.0:rules-1.3.0.aar:c1753946c498b0d5d7cf341cfed661f66915c4c9deb4ed10462a08ae33b2429a',
+            'androidx.test:runner:1.3.0:runner-1.3.0.aar:61d13f5a9fcbbd73ba18fa84e1d6a0111c6e1c665a89b418126966e61fffd93b',
+            'androidx.test:runner:1.4.0:runner-1.4.0.aar:e3f3d8b8d5d4a3edcacbdaa4a31bda2b0e41d3e704b02b3750466a06367ec5a0',
+            'androidx.tracing:tracing:1.0.0:tracing-1.0.0.aar:07b8b6139665b884a162eccf97891ca50f7f56831233bf25168ae04f7b568612',
+            'androidx.transition:transition:1.2.0:transition-1.2.0.aar:a1e059b3bc0b43a58dec0efecdcaa89c82d2bca552ea5bacf6656c46e853157e',
+            'androidx.vectordrawable:vectordrawable-animated:1.1.0:vectordrawable-animated-1.1.0.aar:76da2c502371d9c38054df5e2b248d00da87809ed058f3363eae87ce5e2403f8',
+            'androidx.vectordrawable:vectordrawable:1.1.0:vectordrawable-1.1.0.aar:46fd633ac01b49b7fcabc263bf098c5a8b9e9a69774d234edcca04fb02df8e26',
+            'androidx.versionedparcelable:versionedparcelable:1.1.0:versionedparcelable-1.1.0.aar:9a1d77140ac222b7866b5054ee7d159bc1800987ed2d46dd6afdd145abb710c1',
+            'androidx.viewpager2:viewpager2:1.0.0:viewpager2-1.0.0.aar:e95c0031d4cc247cd48196c6287e58d2cee54d9c79b85afea7c90920330275af',
+            'androidx.viewpager:viewpager:1.0.0:viewpager-1.0.0.aar:147af4e14a1984010d8f155e5e19d781f03c1d70dfed02a8e0d18428b8fc8682',
+            'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
+            'com.almworks.sqlite4java:sqlite4java:0.282:sqlite4java-0.282.jar:9e1d8dd83ca6003f841e3af878ce2dc7c22497493a7bb6d1b62ec1b0d0a83c05',
+            'com.github.bumptech.glide:annotations:4.12.0:annotations-4.12.0.jar:fa430cbf8f931fcd89c38195ab5544ef4d62c8ac6c2e6f49f8f4ae7860fade8e',
+            'com.github.bumptech.glide:compiler:4.12.0:compiler-4.12.0.jar:030297733aa52dd52ef9d45895e02d7446b537d608fe6972514b9f261c23c99a',
+            'com.github.bumptech.glide:gifdecoder:4.12.0:gifdecoder-4.12.0.aar:197a1cd5b76855aa02b230c13974e293229b901dc2b96fab4315201e78baa804',
+            'com.github.bumptech.glide:glide:4.12.0:glide-4.12.0.aar:6ae2944adb62977fe53f42c4f86a22bd326c1828b693441ccce430e92f148384',
+            'com.github.chrisbanes:PhotoView:2.3.0:PhotoView-2.3.0.aar:6c8989f2945d50ab38b3e0300064f1f8d2d75bbcae1434fe535d9fb6898e9ad6',
+            'com.github.kobakei:MaterialFabSpeedDial:1.2.1:MaterialFabSpeedDial-1.2.1.aar:e86198c3c48cd832fb209a769a9f222c2a3cc045743b110ac2391d9737e3ea02',
+            'com.google.android.apps.common.testing.accessibility.framework:accessibility-test-framework:2.0:accessibility-test-framework-2.0.jar:cdf16ef8f5b8023d003ce3cc1b0d51bda737762e2dab2fedf43d1c4292353f7f',
+            'com.google.android.material:material:1.3.0:material-1.3.0.aar:cbf1e7d69fc236cdadcbd1ec5f6c0a1a41aca6ad1ef7f8481058956270ab1f0a',
+            'com.google.auto.value:auto-value-annotations:1.6.2:auto-value-annotations-1.6.2.jar:b48b04ddba40e8ac33bf036f06fc43995fc5084bd94bdaace807ce27d3bea3fb',
+            'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
+            'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
+            'com.google.dagger:dagger-compiler:2.43.2:dagger-compiler-2.43.2.jar:298c020ee6ed2f4cc651ebbfdb7f8de329b07c44b618d65be117846a850e2a03',
+            'com.google.dagger:dagger-producers:2.43.2:dagger-producers-2.43.2.jar:e7f5d9ffc85d48a49c8e22e02833d418f7ccad5d7512f529964db5127ab915ff',
+            'com.google.dagger:dagger-spi:2.43.2:dagger-spi-2.43.2.jar:3bae8d9dadeaaa5927da6f094389a560c12c05fec3d2711d2fa79292c7a7d7ad',
+            'com.google.dagger:dagger:2.43.2:dagger-2.43.2.jar:c89681f7cbbf8c527bf4ac2748515d617fdb54a1d425c08d914fdc28192b5fe4',
+            'com.google.devtools.ksp:symbol-processing-api:1.7.0-1.0.6:symbol-processing-api-1.7.0-1.0.6.jar:adc29417be5ca9ff42118105fea4e36d9ef44987abfc41432309371a60198941',
+            'com.google.errorprone:error_prone_annotations:2.2.0:error_prone_annotations-2.2.0.jar:6ebd22ca1b9d8ec06d41de8d64e0596981d9607b42035f9ed374f9de271a481a',
+            'com.google.errorprone:error_prone_annotations:2.7.1:error_prone_annotations-2.7.1.jar:cd5257c08a246cf8628817ae71cb822be192ef91f6881ca4a3fcff4f1de1cff3',
+            'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30',
+            'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e',
+            'com.google.guava:failureaccess:1.0.1:failureaccess-1.0.1.jar:a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26',
+            'com.google.guava:guava:27.0.1-jre:guava-27.0.1-jre.jar:e1c814fd04492a27c38e0317eabeaa1b3e950ec8010239e400fe90ad6c9107b4',
+            'com.google.guava:guava:31.0.1-jre:guava-31.0.1-jre.jar:d5be94d65e87bd219fb3193ad1517baa55a3b88fc91d21cf735826ab5af087b9',
+            'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
+            'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6',
+            'com.google.j2objc:j2objc-annotations:1.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b',
+            'com.google.zxing:core:3.3.3:core-3.3.3.jar:5820f81e943e4bce0329306621e2d6255d2930b0a6ce934c5c23c0d6d3f20599',
+            'com.ibm.icu:icu4j:53.1:icu4j-53.1.jar:e37a4467bac5cdeb02c5c4b8e5063d2f4e67b69e3c7df6d6b610f13185572bab',
+            'com.jraska:falcon:2.1.1:falcon-2.1.1.aar:827f06556b7fa599f29a48a5277df39ca3dce5080d4ea6f9ea1f9c7b6b78bb7a',
+            'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
+            'com.squareup:javawriter:2.1.1:javawriter-2.1.1.jar:f699823d0081f69cbb676c1845ea222e0ada79bc88a53e5d22d8bd02d328f57e',
+            'com.vanniktech:emoji-google:0.7.0:emoji-google-0.7.0.aar:b98966812e3f607ee823cde15dd9b3823c6f02e5587572b860b9d95e3f971402',
+            'com.vanniktech:emoji:0.7.0:emoji-0.7.0.aar:66f5981f8b5f93e82d2d4b3fa4c6299904d686ca62a2366e61de723b20253707',
+            'de.hdodenhof:circleimageview:3.1.0:circleimageview-3.1.0.aar:8e9965b54072ee159074a55df216e17d5a622c94ce915ef311b1a1f32660c7fb',
+            'info.guardianproject.panic:panic:1.0:panic-1.0.jar:35116ab95212e67f94577faf67b88c11a6b21cbf9178b3f5b51d3dff45203ffd',
+            'info.guardianproject.trustedintents:trustedintents:0.2:trustedintents-0.2.jar:6221456d8821a8d974c2acf86306900237cf6afaaa94a4c9c44e161350f80f3e',
+            'javax.annotation:javax.annotation-api:1.3.2:javax.annotation-api-1.3.2.jar:e04ba5195bcd555dc95650f7cc614d151e4bcd52d29a10b8aa2197f3ab89ab9b',
+            'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
+            'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
+            'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
+            'net.bytebuddy:byte-buddy-agent:1.10.20:byte-buddy-agent-1.10.20.jar:b592a6c43e752bf41659717956c57fbb790394d2ee5f8941876659f9c5c0e7e8',
+            'net.bytebuddy:byte-buddy:1.10.20:byte-buddy-1.10.20.jar:5fcad05da791e9a22811c255a4a74b7ea094b7243d9dbf3e6fc578c8c94290ac',
+            'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
+            'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
+            'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
+            'org.bouncycastle:bcprov-jdk15on:1.65:bcprov-jdk15on-1.65.jar:e78f96eb59066c94c94fb2d6b5eb80f52feac6f5f9776898634f8addec6e2137',
+            'org.briarproject:dont-kill-me-lib:0.2.5:dont-kill-me-lib-0.2.5.aar:55cd9d511b7016ab573905d64bc54e222e2633144d36389192b8b34485b31b9d',
+            'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a',
+            'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
+            'org.checkerframework:checker-qual:3.12.0:checker-qual-3.12.0.jar:ff10785ac2a357ec5de9c293cb982a2cbb605c0309ea4cc1cb9b9bc6dbe7f3cb',
+            'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
+            'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
+            'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
+            'org.hamcrest:hamcrest-integration:1.3:hamcrest-integration-1.3.jar:70f418efbb506c5155da5f9a5a33262ea08a9e4d7fea186aa9015c41a7224ac2',
+            'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
+            'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
+            'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
+            'org.jacoco:org.jacoco.agent:0.8.7:org.jacoco.agent-0.8.7.jar:9cbcc986e0fbe821a78ff1f8f7d5216f200e5eb124e7f6837d1dc4a77b28b143',
+            'org.jacoco:org.jacoco.ant:0.8.7:org.jacoco.ant-0.8.7.jar:97ca96a382c3f23a44d8eb4c4e6c3742a30cb8005774a76ced0fc4806ce49605',
+            'org.jacoco:org.jacoco.core:0.8.7:org.jacoco.core-0.8.7.jar:ad7739b5fb5969aa1a8aead3d74ed54dc82ed012f1f10f336bd1b96e71c1a13c',
+            'org.jacoco:org.jacoco.report:0.8.7:org.jacoco.report-0.8.7.jar:cc89258623700a6c932592153cb528785876b6da183d5431f97efbba6f020e5b',
+            'org.jetbrains.kotlin:kotlin-stdlib-common:1.7.0:kotlin-stdlib-common-1.7.0.jar:59c6ff64fe9a6604afce03e8aaa75f83586c6030ac71fb0b34ee7cdefed3618f',
+            'org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10:kotlin-stdlib-common-1.7.10.jar:19f102efe9629f8eabc63853ad15c533e47c47f91fca09285c5bde86e59f91d4',
+            'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.20:kotlin-stdlib-jdk7-1.6.20.jar:aa2fa2e81355c4d98dd97da2169bf401f842261378f5b1cbea1aa11855d67620',
+            'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.0:kotlin-stdlib-jdk7-1.7.0.jar:07e91be9b2ca20672d2bdb7e181b766e73453a2da13492b5ddaee8fa47aea239',
+            'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0:kotlin-stdlib-jdk8-1.7.0.jar:cf058e11db1dfc9944680c8c61b95ac689aaaa8a3eb30bced028100f038f030b',
+            'org.jetbrains.kotlin:kotlin-stdlib:1.7.0:kotlin-stdlib-1.7.0.jar:aa88e9625577957f3249a46cb6e166ee09b369e600f7a11d148d16b0a6d87f05',
+            'org.jetbrains.kotlin:kotlin-stdlib:1.7.10:kotlin-stdlib-1.7.10.jar:e771fe74250a943e8f6346713201ff1d8cb95c3a5d1a91a22b65a9e04f6a8901',
+            'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1:kotlinx-coroutines-android-1.4.1.jar:d4cadb673b2101f1ee5fbc147956ac78b1cfd9cc255fb53d3aeb88dff11d99ca',
+            'org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.4.1:kotlinx-coroutines-core-jvm-1.4.1.jar:6d2f87764b6638f27aff12ed380db4b63c9d46ba55dc32683a650598fa5a3e22',
+            'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0:kotlinx-metadata-jvm-0.5.0.jar:ca063a96639b08b9eaa0de4d65e899480740a6efbe28ab9a8681a2ced03055a4',
+            'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
+            'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
+            'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
+            'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd',
+            'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04',
+            'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
+            'org.mockito:mockito-core:3.9.0:mockito-core-3.9.0.jar:a1f64211407b8dc4cf80b16e07cc11aa9e5228d53dc4a5357326d66825f6a4ac',
+            'org.nanohttpd:nanohttpd:2.3.1:nanohttpd-2.3.1.jar:de864c47818157141a24c9acb36df0c47d7bf15b7ff48c90610f3eb4e5df0e58',
+            'org.objenesis:objenesis:3.2:objenesis-3.2.jar:03d960bd5aef03c653eb000413ada15eb77cdd2b8e4448886edf5692805e35f3',
+            'org.ow2.asm:asm-analysis:7.2:asm-analysis-7.2.jar:be922aae60ff1ff1768e8e6544a38a7f92bd0a6d6b0b9791f94955d1bd453de2',
+            'org.ow2.asm:asm-analysis:9.1:asm-analysis-9.1.jar:81a88041b1b8beda5a8a99646098046c48709538270c49def68abff25ac3be34',
+            'org.ow2.asm:asm-commons:7.2:asm-commons-7.2.jar:0e86b8b179c5fb223d1a880a0ff4960b6978223984b94e62e71135f2d8ea3558',
+            'org.ow2.asm:asm-commons:9.1:asm-commons-9.1.jar:afcb26dc1fc12c0c4a99ada670908dd82e18dfc488caf5ee92546996b470c00c',
+            'org.ow2.asm:asm-tree:7.2:asm-tree-7.2.jar:c063f5a67fa03cdc9bd79fd1c2ea6816cc4a19473ecdfbd9e9153b408c6f2656',
+            'org.ow2.asm:asm-tree:9.1:asm-tree-9.1.jar:fd00afa49e9595d7646205b09cecb4a776a8ff0ba06f2d59b8f7bf9c704b4a73',
+            'org.ow2.asm:asm-util:7.2:asm-util-7.2.jar:6e24913b021ffacfe8e7e053d6e0ccc731941148cfa078d4f1ed3d96904530f8',
+            'org.ow2.asm:asm:7.2:asm-7.2.jar:7e6cc9e92eb94d04e39356c6d8144ca058cda961c344a7f62166a405f3206672',
+            'org.ow2.asm:asm:9.1:asm-9.1.jar:cda4de455fab48ff0bcb7c48b4639447d4de859a7afc30a094a986f0936beba2',
+            'org.robolectric:annotations:4.4:annotations-4.4.jar:d2b2d71a1f902a5a016dde5a2feb3be521d120192f9217adadbfb483d79f89ff',
+            'org.robolectric:junit:4.4:junit-4.4.jar:c5ebcb20cf9d2173a294a6feff68331fff718a368e332df70c7ea7e3bdce846e',
+            'org.robolectric:pluginapi:4.4:pluginapi-4.4.jar:b2f743db060502cb366f67dcd6c3929c7f4656744d91ab81d749b8bf641f5512',
+            'org.robolectric:plugins-maven-dependency-resolver:4.4:plugins-maven-dependency-resolver-4.4.jar:5279024a6bdbb2ee1791b06da13cc890628c583ad48414ae13a4f57d7db749a3',
+            'org.robolectric:resources:4.4:resources-4.4.jar:e39862f71887561dfde65030aeca5148bf0f6279b25fb9e146b75c2933fcabcf',
+            'org.robolectric:robolectric:4.4:robolectric-4.4.jar:38e0368914a48d6d8e543c12670beb1e36e09d037e664280fb604dbbfd10fe5f',
+            'org.robolectric:sandbox:4.4:sandbox-4.4.jar:e52f3f012f893ca8458cbe3e664f1f9f13cb0501e2d730bd089d693c49ccedda',
+            'org.robolectric:shadowapi:4.4:shadowapi-4.4.jar:48ce6ab59137366eb88138be5ec65bd9c0b8c54a512151140a02391fc723b83f',
+            'org.robolectric:shadows-framework:4.4:shadows-framework-4.4.jar:0602f5bbef601036831e0ce8600b6d08d80ce3c9260be5cb7b362b176ce3d9f0',
+            'org.robolectric:utils-reflector:4.4:utils-reflector-4.4.jar:35a77865bb9a451e99b95575cb154a5f08ecb007bd17e390817c0f31ab9db869',
+            'org.robolectric:utils:4.4:utils-4.4.jar:f9756b5c57116ae9ec55a65ca52b64ba1f77d30b5eb7b55fef5d125fdf7d69d9',
+            'tools.fastlane:screengrab:2.0.0:screengrab-2.0.0.aar:15ac15eb7c371db05e721be8d466567c2b7274b767d91478e781b6d89ee5d3d0',
+            'uk.co.samuelwall:material-tap-target-prompt:3.3.0:material-tap-target-prompt-3.3.0.aar:00f16e8d7e55d01e3b41cf66e09eee8588870ca7285ba3c72267ca0482f1606e',
     ]
 }
diff --git a/briar-core/witness.gradle b/briar-core/witness.gradle
index da2c3be0bf7c62f360cf74760376e38f167a768a..44f776ce4031bb0253b55e5cc9d492cda4a103e8 100644
--- a/briar-core/witness.gradle
+++ b/briar-core/witness.gradle
@@ -3,23 +3,23 @@ dependencyVerification {
         'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
         'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
         'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
-        'com.google.dagger:dagger-compiler:2.33:dagger-compiler-2.33.jar:aa8a0d8370c578fd6999802d0d90b9829377a46d2c1141e11b8f737970e7155e',
-        'com.google.dagger:dagger-producers:2.33:dagger-producers-2.33.jar:5897f0b6eef799c2adfe3ccacc58c0fb374d58acb063c3ebe5366c38a8bce5c8',
-        'com.google.dagger:dagger-spi:2.33:dagger-spi-2.33.jar:e2dcab2221b8afb9556ef0a1c83b0bd5f42552e254322a257330f754cdbbb9d4',
-        'com.google.dagger:dagger:2.33:dagger-2.33.jar:d8798c5b8cf6b125234e33af5c6293bb9f2208ce29b57924c35b8c0be7b6bdcb',
-        'com.google.errorprone:error_prone_annotations:2.2.0:error_prone_annotations-2.2.0.jar:6ebd22ca1b9d8ec06d41de8d64e0596981d9607b42035f9ed374f9de271a481a',
+        'com.google.dagger:dagger-compiler:2.43.2:dagger-compiler-2.43.2.jar:298c020ee6ed2f4cc651ebbfdb7f8de329b07c44b618d65be117846a850e2a03',
+        'com.google.dagger:dagger-producers:2.43.2:dagger-producers-2.43.2.jar:e7f5d9ffc85d48a49c8e22e02833d418f7ccad5d7512f529964db5127ab915ff',
+        'com.google.dagger:dagger-spi:2.43.2:dagger-spi-2.43.2.jar:3bae8d9dadeaaa5927da6f094389a560c12c05fec3d2711d2fa79292c7a7d7ad',
+        'com.google.dagger:dagger:2.43.2:dagger-2.43.2.jar:c89681f7cbbf8c527bf4ac2748515d617fdb54a1d425c08d914fdc28192b5fe4',
+        'com.google.devtools.ksp:symbol-processing-api:1.7.0-1.0.6:symbol-processing-api-1.7.0-1.0.6.jar:adc29417be5ca9ff42118105fea4e36d9ef44987abfc41432309371a60198941',
+        'com.google.errorprone:error_prone_annotations:2.7.1:error_prone_annotations-2.7.1.jar:cd5257c08a246cf8628817ae71cb822be192ef91f6881ca4a3fcff4f1de1cff3',
         'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30',
         'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e',
         'com.google.guava:failureaccess:1.0.1:failureaccess-1.0.1.jar:a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26',
-        'com.google.guava:guava:27.1-jre:guava-27.1-jre.jar:4a5aa70cc968a4d137e599ad37553e5cfeed2265e8c193476d7119036c536fe7',
+        'com.google.guava:guava:31.0.1-jre:guava-31.0.1-jre.jar:d5be94d65e87bd219fb3193ad1517baa55a3b88fc91d21cf735826ab5af087b9',
         'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
-        'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6',
+        'com.google.j2objc:j2objc-annotations:1.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b',
         'com.rometools:rome-utils:1.15.0:rome-utils-1.15.0.jar:2aaa1e95e0630ba5f4c183201f5ca6af8cecebcbf3494e7d11b903c9d1277cb8',
         'com.rometools:rome:1.15.0:rome-1.15.0.jar:51cbcedae56ee0c32f25f3a367a6a9dadeef0f591d2f23d03486aec272e4d3f9',
         'com.squareup.okhttp3:okhttp:3.12.13:okhttp-3.12.13.jar:508234e024ef7e270ab1a6d5b356f5b98e786511239ca986d684fd1e2cf7bc82',
         'com.squareup.okio:okio:1.15.0:okio-1.15.0.jar:693fa319a7e8843300602b204023b7674f106ebcb577f2dd5807212b66118bd2',
         'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
-        'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
         'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
         'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
         'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
@@ -27,19 +27,20 @@ dependencyVerification {
         'net.jodah:concurrentunit:0.4.2:concurrentunit-0.4.2.jar:5583078e1acf91734939e985bc9e7ee947b0e93a8eef679da6bb07bbeb47ced3',
         'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
         'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
-        'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
-        'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
+        'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a',
+        'org.checkerframework:checker-qual:3.12.0:checker-qual-3.12.0.jar:ff10785ac2a357ec5de9c293cb982a2cbb605c0309ea4cc1cb9b9bc6dbe7f3cb',
         'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
-        'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
         'org.codehaus.mojo:animal-sniffer-ant-tasks:1.20:animal-sniffer-ant-tasks-1.20.jar:bb7d2498144118311d968bb08ff6fae3fc535fb1cb9cca8b8e9ea65b189422ac',
         'org.codehaus.mojo:animal-sniffer:1.20:animal-sniffer-1.20.jar:80c422523c38db91260c6d78e5ee4b012862ab61cc55020c9e243dd7b5c62249',
         'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
         'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
         'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
         'org.jdom:jdom2:2.0.6:jdom2-2.0.6.jar:1345f11ba606d15603d6740551a8c21947c0215640770ec67271fe78bea97cf5',
-        'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20:kotlin-stdlib-common-1.4.20.jar:a7112c9b3cefee418286c9c9372f7af992bd1e6e030691d52f60cb36dbec8320',
-        'org.jetbrains.kotlin:kotlin-stdlib:1.4.20:kotlin-stdlib-1.4.20.jar:b8ab1da5cdc89cb084d41e1f28f20a42bd431538642a5741c52bbfae3fa3e656',
-        'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0:kotlinx-metadata-jvm-0.1.0.jar:9753bb39efef35957c5c15df9a3cb769aabf2cdfa74b47afcb7760e5146be3b5',
+        'org.jetbrains.kotlin:kotlin-stdlib-common:1.7.0:kotlin-stdlib-common-1.7.0.jar:59c6ff64fe9a6604afce03e8aaa75f83586c6030ac71fb0b34ee7cdefed3618f',
+        'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.0:kotlin-stdlib-jdk7-1.7.0.jar:07e91be9b2ca20672d2bdb7e181b766e73453a2da13492b5ddaee8fa47aea239',
+        'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0:kotlin-stdlib-jdk8-1.7.0.jar:cf058e11db1dfc9944680c8c61b95ac689aaaa8a3eb30bced028100f038f030b',
+        'org.jetbrains.kotlin:kotlin-stdlib:1.7.0:kotlin-stdlib-1.7.0.jar:aa88e9625577957f3249a46cb6e166ee09b369e600f7a11d148d16b0a6d87f05',
+        'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0:kotlinx-metadata-jvm-0.5.0.jar:ca063a96639b08b9eaa0de4d65e899480740a6efbe28ab9a8681a2ced03055a4',
         'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
         'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
         'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
diff --git a/briar-headless/witness.gradle b/briar-headless/witness.gradle
index 17f1b91d381e8e4d33ec440613ca39681320a7bd..9c7063f5cd8a9f04d08018cbb8977ff963a19f6d 100644
--- a/briar-headless/witness.gradle
+++ b/briar-headless/witness.gradle
@@ -1,8 +1,8 @@
 dependencyVerification {
     verify = [
-        'com.fasterxml.jackson.core:jackson-annotations:2.13.0:jackson-annotations-2.13.0.jar:81f9724d8843e8b08f8f6c0609e7a2b030d00c34861c4ac7e2099a7235047d6f',
-        'com.fasterxml.jackson.core:jackson-core:2.13.0:jackson-core-2.13.0.jar:348bc59b348df2e807b356f1d62d2afb41a974073328abc773eb0932b855d2c8',
-        'com.fasterxml.jackson.core:jackson-databind:2.13.0:jackson-databind-2.13.0.jar:9c826d27176268777adcf97e1c6e2051c7e33a7aaa2c370c2e8c6077fd9da3f4',
+        'com.fasterxml.jackson.core:jackson-annotations:2.13.4:jackson-annotations-2.13.4.jar:ac5b27a634942391ca113850ee7db01df1499a240174021263501c05fc653b44',
+        'com.fasterxml.jackson.core:jackson-core:2.13.4:jackson-core-2.13.4.jar:4c2e043200edd9ee7ba6fc378bd5c17784a5bf2388e152d208068b51fd0839cf',
+        'com.fasterxml.jackson.core:jackson-databind:2.13.4:jackson-databind-2.13.4.jar:c9faff420d9e2c7e1e4711dbeebec2506a32c9942027211c5c293d8d87807eb6',
         'com.github.ajalt:clikt:2.2.0:clikt-2.2.0.jar:beb3136d06764ec8ce0810a8fd6c8b7b49d04287d1deef3a07c016e43a458d33',
         'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
         'com.google.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f',
diff --git a/build.gradle b/build.gradle
index caa6f0ffd62870e58981b4a2c8d377c3d79005be..934440d3b601aa9ff7f6dc22c4f80d47ec17c0ad 100644
--- a/build.gradle
+++ b/build.gradle
@@ -30,10 +30,10 @@ buildscript {
 
 	ext {
 		kotlin_version = '1.7.10'
-		dagger_version = "2.33"
+		dagger_version = "2.43.2"
 		// okhttp 3.12.x is supported until end of 2021, newer versions need minSdk 21
 		okhttp_version = "3.12.13"
-		jackson_version = "2.13.0"
+		jackson_version = "2.13.4"
 		tor_version = "0.4.5.14"
 		obfs4proxy_version = "0.0.14-tor1"
 		snowflake_version = "2.3.1"
@@ -41,7 +41,7 @@ buildscript {
 		jmock_version = '2.12.0'
 	}
 	dependencies {
-		classpath 'com.android.tools.build:gradle:7.0.3'
+		classpath 'com.android.tools.build:gradle:7.2.2'
 		classpath 'ru.vyarus:gradle-animalsniffer-plugin:1.5.3'
 		classpath files('libs/gradle-witness.jar')
 		classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 422ba3f77c20edf991434777107f96c18e87dc69..3bb947249dd3d32f8da67aa4bd2f89366734a17c 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-all.zip
-distributionSha256Sum=00b273629df4ce46e68df232161d5a7c4e495b9a029ce6e0420f071e21316867
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
+distributionSha256Sum=c9490e938b221daf0094982288e4038deed954a3f12fb54cbf270ddf4e37d879
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists