Merge branch 'android-updates'

This fixes GUI-related compatibility issues with Android 16 and allows
(pre-)selecting on-device certificates/keys with managed profiles.  Also
fixes a typo in the managed config description that prevented
split-tunneling settings from working.
diff --git a/src/frontends/android/app/build.gradle b/src/frontends/android/app/build.gradle
index 9b59f44..f684b10 100644
--- a/src/frontends/android/app/build.gradle
+++ b/src/frontends/android/app/build.gradle
@@ -1,16 +1,16 @@
 apply plugin: 'com.android.application'
 
 android {
-    namespace 'org.strongswan.android'
+    namespace = 'org.strongswan.android'
 
     defaultConfig {
         applicationId "org.strongswan.android"
-        compileSdk 34
+        compileSdk = 36
         minSdkVersion 21
-        targetSdkVersion 34
+        targetSdkVersion 36
 
-        versionCode 91
-        versionName "2.5.6"
+        versionCode 94
+        versionName "2.6.0"
 
         externalNativeBuild {
             ndkBuild {
@@ -19,7 +19,7 @@
         }
     }
 
-    ndkVersion "27.2.12479018"
+    ndkVersion = "27.3.13750724"
 
     externalNativeBuild {
         ndkBuild {
@@ -46,10 +46,12 @@
 
 dependencies {
     implementation 'androidx.appcompat:appcompat:1.7.1'
-    implementation 'androidx.lifecycle:lifecycle-process:2.9.1'
+    implementation 'androidx.core:core:1.17.0'
+    implementation 'androidx.lifecycle:lifecycle-process:2.9.4'
     implementation 'androidx.preference:preference:1.2.1'
-    implementation 'com.google.android.material:material:1.12.0'
+    implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0'
+    implementation 'com.google.android.material:material:1.13.0'
     testImplementation 'junit:junit:4.13.2'
-    testImplementation 'org.assertj:assertj-core:3.24.2'
-    testImplementation 'org.mockito:mockito-core:5.8.0'
+    testImplementation 'org.assertj:assertj-core:3.27.6'
+    testImplementation 'org.mockito:mockito-core:5.20.0'
 }
diff --git a/src/frontends/android/app/src/main/AndroidManifest.xml b/src/frontends/android/app/src/main/AndroidManifest.xml
index 51c6ff8..c0a8ed4 100644
--- a/src/frontends/android/app/src/main/AndroidManifest.xml
+++ b/src/frontends/android/app/src/main/AndroidManifest.xml
@@ -36,6 +36,7 @@
         android:icon="@mipmap/ic_launcher"
         android:label="@string/app_name"
         android:theme="@style/ApplicationTheme"
+        android:windowSoftInputMode="adjustResize"
         android:networkSecurityConfig="@xml/network_security_config"
         android:enableOnBackInvokedCallback="true"
         android:allowBackup="false" >
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/data/ManagedVpnProfile.java b/src/frontends/android/app/src/main/java/org/strongswan/android/data/ManagedVpnProfile.java
index 47e85a5..dfe519a 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/data/ManagedVpnProfile.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/data/ManagedVpnProfile.java
@@ -38,6 +38,7 @@
 	private static final String KEY_REMOTE_REVOCATION_CRL_FLAG = "remote_revocation_crl";
 	private static final String KEY_REMOTE_REVOCATION_OCSP_FLAG = "remote_revocation_ocsp";
 	private static final String KEY_REMOTE_REVOCATION_STRICT_FLAG = "remote_revocation_strict";
+	private static final String KEY_LOCAL_USER_CERTIFICATE_ALIAS = "user_certificate_alias";
 	private static final String KEY_LOCAL_RSA_PSS_FLAG = "local_rsa_pss";
 
 	private static final String KEY_SPLIT_TUNNELLING_BLOCK_IPV4_FLAG = "split_tunnelling_block_ipv4";
@@ -152,6 +153,10 @@
 			userCertificate = new ManagedUserCertificate(uuid.toString(), userCertificateData, userCertificatePassword);
 			setUserCertificateAlias(userCertificate.getAlias());
 		}
+		else
+		{
+			setUserCertificateAlias(getString(local, KEY_LOCAL_USER_CERTIFICATE_ALIAS));
+		}
 
 		flags = addPositiveFlag(flags, local, KEY_LOCAL_RSA_PSS_FLAG, VpnProfile.FLAGS_RSA_PSS);
 		return flags;
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/data/VpnProfileManagedDataSource.java b/src/frontends/android/app/src/main/java/org/strongswan/android/data/VpnProfileManagedDataSource.java
index 0f6ec62..eaf0cfa 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/data/VpnProfileManagedDataSource.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/data/VpnProfileManagedDataSource.java
@@ -33,6 +33,7 @@
 public class VpnProfileManagedDataSource implements VpnProfileDataSource
 {
 	private static final String NAME_MANAGED_VPN_PROFILES = "org.strongswan.android.data.VpnProfileManagedDataSource.preferences";
+	private static final String PREFIX_USER_CERT = "usercert:";
 
 	private final ManagedConfigurationService mManagedConfigurationService;
 	private final SharedPreferences mSharedPreferences;
@@ -52,11 +53,14 @@
 	@Override
 	public void close()
 	{
-		/* remove passwords that are no longer referenced by a VPN profile */
-		final Set<String> actualKeys = mManagedConfigurationService.getManagedProfiles().keySet();
-
+		/* remove settings not referenced by a VPN profile */
 		final Set<String> storedKeys = new HashSet<>(mSharedPreferences.getAll().keySet());
-		storedKeys.removeAll(actualKeys);
+
+		for (String uuid : mManagedConfigurationService.getManagedProfiles().keySet())
+		{
+			storedKeys.remove(uuid);
+			storedKeys.remove(PREFIX_USER_CERT + uuid);
+		}
 
 		final SharedPreferences.Editor editor = mSharedPreferences.edit();
 		for (String key : storedKeys)
@@ -84,6 +88,7 @@
 
 		final SharedPreferences.Editor editor = mSharedPreferences.edit();
 		editor.putString(profile.getUUID().toString(), profile.getPassword());
+		editor.putString(PREFIX_USER_CERT + profile.getUUID().toString(), profile.getUserCertificateAlias());
 		return editor.commit();
 	}
 
@@ -100,8 +105,10 @@
 	private VpnProfile prepareVpnProfile(VpnProfile managedProfile)
 	{
 		final String password = mSharedPreferences.getString(managedProfile.getUUID().toString(), managedProfile.getPassword());
+		final String alias = mSharedPreferences.getString(PREFIX_USER_CERT + managedProfile.getUUID().toString(), managedProfile.getUserCertificateAlias());
 		final VpnProfile vpnProfile = managedProfile.clone();
 		vpnProfile.setPassword(password);
+		vpnProfile.setUserCertificateAlias(alias);
 		vpnProfile.setDataSource(this);
 		return vpnProfile;
 	}
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/logic/CharonVpnService.java b/src/frontends/android/app/src/main/java/org/strongswan/android/logic/CharonVpnService.java
index 69b217a..97e93e8 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/logic/CharonVpnService.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/logic/CharonVpnService.java
@@ -966,7 +966,6 @@
 			return fd != null ? fd.detachFd() : -1;
 		}
 
-		@TargetApi(Build.VERSION_CODES.LOLLIPOP)
 		public synchronized void establishBlocking()
 		{
 			/* just choose some arbitrary values to block all traffic (except for what's configured in the profile) */
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogActivity.java
index 40738fe..c7d052e 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogActivity.java
@@ -26,10 +26,12 @@
 import org.strongswan.android.R;
 import org.strongswan.android.data.LogContentProvider;
 import org.strongswan.android.logic.CharonVpnService;
+import org.strongswan.android.utils.Utils;
 
 import java.io.File;
 
 import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.view.WindowCompat;
 
 public class LogActivity extends AppCompatActivity
 {
@@ -38,6 +40,8 @@
 	{
 		super.onCreate(savedInstanceState);
 		setContentView(R.layout.log_activity);
+		WindowCompat.enableEdgeToEdge(getWindow());
+		Utils.applyWindowInsetsAsMarginsForLists(findViewById(R.id.layout));
 
 		getSupportActionBar().setDisplayHomeAsUpEnabled(true);
 	}
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogFragment.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogFragment.java
index ca873a7..d83e1ec 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogFragment.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogFragment.java
@@ -30,6 +30,7 @@
 
 import org.strongswan.android.R;
 import org.strongswan.android.logic.CharonVpnService;
+import org.strongswan.android.utils.Utils;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -81,6 +82,8 @@
 		mLog = view.findViewById(R.id.log);
 		mLog.setAdapter(mLogAdapter);
 
+		Utils.applyWindowInsetsAsPaddingForLists(mLog);
+
 		mScrollPosition = -1;
 		if (savedInstanceState != null)
 		{
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/MainActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/MainActivity.java
index 603dede..a1e6472 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/MainActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/MainActivity.java
@@ -34,6 +34,7 @@
 import org.strongswan.android.logic.StrongSwanApplication;
 import org.strongswan.android.logic.TrustedCertificateManager;
 import org.strongswan.android.ui.VpnProfileListFragment.OnVpnProfileSelectedListener;
+import org.strongswan.android.utils.Utils;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -43,6 +44,7 @@
 import androidx.appcompat.app.AlertDialog;
 import androidx.appcompat.app.AppCompatActivity;
 import androidx.appcompat.app.AppCompatDialogFragment;
+import androidx.core.view.WindowCompat;
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentManager;
 import androidx.fragment.app.FragmentTransaction;
@@ -66,6 +68,8 @@
 	{
 		super.onCreate(savedInstanceState);
 		setContentView(R.layout.main);
+		WindowCompat.enableEdgeToEdge(getWindow());
+		Utils.applyWindowInsetsAsMarginsForLists(findViewById(R.id.layout));
 
 		ActionBar bar = getSupportActionBar();
 		bar.setDisplayShowHomeEnabled(true);
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/RemediationInstructionsActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/RemediationInstructionsActivity.java
index d1de552..3e8bd03 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/RemediationInstructionsActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/RemediationInstructionsActivity.java
@@ -18,6 +18,8 @@
 
 import android.os.Bundle;
 import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.view.WindowCompat;
+
 import android.view.MenuItem;
 
 import org.strongswan.android.R;
@@ -33,6 +35,7 @@
 	{
 		super.onCreate(savedInstanceState);
 		setContentView(R.layout.remediation_instructions);
+		WindowCompat.enableEdgeToEdge(getWindow());
 		getSupportActionBar().setDisplayHomeAsUpEnabled(true);
 
 		if (savedInstanceState != null)
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/SelectedApplicationsActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/SelectedApplicationsActivity.java
index d1b66e4..b3c23ff 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/SelectedApplicationsActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/SelectedApplicationsActivity.java
@@ -26,6 +26,7 @@
 import androidx.annotation.Nullable;
 import androidx.appcompat.app.ActionBar;
 import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.view.WindowCompat;
 import androidx.fragment.app.FragmentManager;
 
 public class SelectedApplicationsActivity extends AppCompatActivity
@@ -37,6 +38,8 @@
 	protected void onCreate(@Nullable Bundle savedInstanceState)
 	{
 		super.onCreate(savedInstanceState);
+		WindowCompat.enableEdgeToEdge(getWindow());
+		WindowCompat.setDecorFitsSystemWindows(getWindow(), true);
 
 		ActionBar actionBar = getSupportActionBar();
 		actionBar.setDisplayHomeAsUpEnabled(true);
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/SettingsActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/SettingsActivity.java
index d1b5190..eec782f 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/SettingsActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/SettingsActivity.java
@@ -20,6 +20,7 @@
 import android.view.MenuItem;
 
 import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.view.WindowCompat;
 
 public class SettingsActivity extends AppCompatActivity
 {
@@ -28,6 +29,8 @@
 	protected void onCreate(Bundle savedInstanceState)
 	{
 		super.onCreate(savedInstanceState);
+		WindowCompat.enableEdgeToEdge(getWindow());
+		WindowCompat.setDecorFitsSystemWindows(getWindow(), true);
 
 		getSupportActionBar().setDisplayHomeAsUpEnabled(true);
 
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificateImportActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificateImportActivity.java
index 322e21e..a794e93 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificateImportActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificateImportActivity.java
@@ -41,6 +41,7 @@
 import androidx.appcompat.app.AlertDialog;
 import androidx.appcompat.app.AppCompatActivity;
 import androidx.appcompat.app.AppCompatDialogFragment;
+import androidx.core.view.WindowCompat;
 import androidx.fragment.app.FragmentTransaction;
 
 public class TrustedCertificateImportActivity extends AppCompatActivity
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificatesActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificatesActivity.java
index 0a0b26a..c9e2428 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificatesActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/TrustedCertificatesActivity.java
@@ -33,6 +33,7 @@
 import org.strongswan.android.logic.TrustedCertificateManager.TrustedCertificateSource;
 import org.strongswan.android.security.TrustedCertificateEntry;
 import org.strongswan.android.ui.CertificateDeleteConfirmationDialog.OnCertificateDeleteListener;
+import org.strongswan.android.utils.Utils;
 
 import java.security.KeyStore;
 
@@ -41,6 +42,7 @@
 import androidx.annotation.NonNull;
 import androidx.appcompat.app.ActionBar;
 import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.view.WindowCompat;
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentActivity;
 import androidx.viewpager2.adapter.FragmentStateAdapter;
@@ -71,6 +73,7 @@
 	{
 		super.onCreate(savedInstanceState);
 		setContentView(R.layout.trusted_certificates_activity);
+		WindowCompat.enableEdgeToEdge(getWindow());
 
 		ActionBar actionBar = getSupportActionBar();
 		actionBar.setDisplayHomeAsUpEnabled(true);
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileControlActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileControlActivity.java
index a7b39b6..9ff0717 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileControlActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileControlActivity.java
@@ -70,6 +70,7 @@
 	private static final String WAITING_FOR_RESULT = "WAITING_FOR_RESULT";
 	private static final String PROFILE_NAME = "PROFILE_NAME";
 	private static final String PROFILE_REQUIRES_PASSWORD = "REQUIRES_PASSWORD";
+	private static final String PROFILE_CERTIFICATE_MISSING = "CERTIFICATE_MISSING";
 	private static final String PROFILE_RECONNECT = "RECONNECT";
 	private static final String PROFILE_DISCONNECT = "DISCONNECT";
 	private static final String DIALOG_TAG = "Dialog";
@@ -332,6 +333,8 @@
 		profileInfo.putString(VpnProfileDataSource.KEY_USERNAME, profile.getUsername());
 		profileInfo.putString(VpnProfileDataSource.KEY_PASSWORD, profile.getPassword());
 		profileInfo.putBoolean(PROFILE_REQUIRES_PASSWORD, profile.getVpnType().has(VpnTypeFeature.USER_PASS));
+		profileInfo.putBoolean(PROFILE_CERTIFICATE_MISSING, profile.getVpnType().has(VpnTypeFeature.CERTIFICATE) &&
+							   profile.getUserCertificateAlias() == null);
 		profileInfo.putString(PROFILE_NAME, profile.getName());
 
 		removeFragmentByTag(DIALOG_TAG);
@@ -355,6 +358,13 @@
 	 */
 	private void startVpnProfile(Bundle profileInfo)
 	{
+		if (profileInfo.getBoolean(PROFILE_CERTIFICATE_MISSING))
+		{
+			CertificateRequiredDialog dialog = new CertificateRequiredDialog();
+			dialog.setArguments(profileInfo);
+			dialog.show(getSupportFragmentManager(), DIALOG_TAG);
+			return;
+		}
 		if (profileInfo.getBoolean(PROFILE_REQUIRES_PASSWORD) &&
 			profileInfo.getString(VpnProfileDataSource.KEY_PASSWORD) == null)
 		{
@@ -622,6 +632,36 @@
 	}
 
 	/**
+	 * Class that displays a dialog warning about a missing certificate.
+	 */
+	public static class CertificateRequiredDialog extends AppCompatDialogFragment
+	{
+		@Override
+		public Dialog onCreateDialog(Bundle savedInstanceState)
+		{
+			final Bundle profileInfo = getArguments();
+
+			AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
+				.setTitle(R.string.certificate_required_title)
+				.setMessage(R.string.certificate_required_text)
+				.setNegativeButton(android.R.string.cancel, (dialog, which) -> getActivity().finish())
+				.setPositiveButton(R.string.edit_profile, (dialog, which) -> {
+					Intent editIntent = new Intent(getActivity(), VpnProfileDetailActivity.class);
+					editIntent.putExtra(VpnProfileDataSource.KEY_UUID, profileInfo.getString(VpnProfileDataSource.KEY_UUID));
+					startActivity(editIntent);
+					getActivity().finish();
+				});
+			return builder.create();
+		}
+
+		@Override
+		public void onCancel(DialogInterface dialog)
+		{
+			getActivity().finish();
+		}
+	}
+
+	/**
 	 * Class that displays a warning before asking the user to add the app to the
 	 * device's power whitelist.
 	 */
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java
index cf1789d..aeef179 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileDetailActivity.java
@@ -54,6 +54,7 @@
 import android.widget.TextView;
 
 import org.strongswan.android.R;
+import org.strongswan.android.data.ManagedVpnProfile;
 import org.strongswan.android.data.VpnProfile;
 import org.strongswan.android.data.VpnProfile.SelectedAppsHandling;
 import org.strongswan.android.data.VpnProfileDataSource;
@@ -84,6 +85,7 @@
 import androidx.appcompat.app.AppCompatDialogFragment;
 import androidx.appcompat.widget.SwitchCompat;
 import androidx.core.text.HtmlCompat;
+import androidx.core.view.WindowCompat;
 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
 
 public class VpnProfileDetailActivity extends AppCompatActivity
@@ -199,6 +201,7 @@
 		mDataSource.open();
 
 		setContentView(R.layout.profile_detail_view);
+		WindowCompat.enableEdgeToEdge(getWindow());
 
 		mManagedProfile = findViewById(R.id.managed_profile);
 
@@ -815,7 +818,7 @@
 				alias = mProfile.getCertificateAlias();
 				getSupportActionBar().setTitle(mProfile.getName());
 
-				setReadOnly(mProfile.isReadOnly());
+				setReadOnly(mProfile);
 			}
 			else
 			{
@@ -880,8 +883,10 @@
 		}
 	}
 
-	private void setReadOnly(final boolean readOnly)
+	private void setReadOnly(final VpnProfile profile)
 	{
+		final boolean readOnly = profile.isReadOnly();
+
 		mManagedProfile.setVisibility(readOnly ? View.VISIBLE : View.GONE);
 
 		mName.setEnabled(!readOnly);
@@ -918,8 +923,12 @@
 
 		if (readOnly)
 		{
+			ManagedVpnProfile managedProfile = (ManagedVpnProfile)profile;
 			mSelectCert.setOnClickListener(null);
-			mSelectUserCert.setOnClickListener(null);
+			if (managedProfile.getUserCertificate() != null)
+			{
+				mSelectUserCert.setOnClickListener(null);
+			}
 		}
 	}
 
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileImportActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileImportActivity.java
index ee56c1e..f10ce0e 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileImportActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileImportActivity.java
@@ -78,6 +78,7 @@
 import androidx.activity.result.ActivityResultLauncher;
 import androidx.activity.result.contract.ActivityResultContracts;
 import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.view.WindowCompat;
 import androidx.loader.app.LoaderManager;
 import androidx.loader.content.AsyncTaskLoader;
 import androidx.loader.content.Loader;
@@ -204,6 +205,7 @@
 		mDataSource.open();
 
 		setContentView(R.layout.profile_import_view);
+		WindowCompat.enableEdgeToEdge(getWindow());
 
 		mProgressBar = findViewById(R.id.progress_bar);
 		mExistsWarning = findViewById(R.id.exists_warning);
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileListFragment.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileListFragment.java
index 9b25785..e845cc6 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileListFragment.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileListFragment.java
@@ -48,6 +48,7 @@
 import org.strongswan.android.logic.StrongSwanApplication;
 import org.strongswan.android.ui.adapter.VpnProfileAdapter;
 import org.strongswan.android.utils.Constants;
+import org.strongswan.android.utils.Utils;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -60,7 +61,6 @@
 import androidx.annotation.NonNull;
 import androidx.core.view.MenuProvider;
 import androidx.fragment.app.Fragment;
-import androidx.lifecycle.Lifecycle;
 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
 
 public class VpnProfileListFragment extends Fragment implements MenuProvider
@@ -149,6 +149,8 @@
 		mListView.setEmptyView(view.findViewById(R.id.profile_list_empty));
 		mListView.setOnItemClickListener(mVpnProfileClicked);
 
+		Utils.applyWindowInsetsAsPaddingForLists(mListView);
+
 		if (!mReadOnly)
 		{
 			requireActivity().addMenuProvider(this, getViewLifecycleOwner());
@@ -197,7 +199,10 @@
 	public void onSaveInstanceState(Bundle outState)
 	{
 		super.onSaveInstanceState(outState);
-		outState.putIntegerArrayList(SELECTED_KEY, new ArrayList<>(mSelected));
+		if (!mReadOnly)
+		{
+			outState.putIntegerArrayList(SELECTED_KEY, new ArrayList<>(mSelected));
+		}
 	}
 
 	@Override
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileSelectActivity.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileSelectActivity.java
index dd64d0c..56aefbe 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileSelectActivity.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/VpnProfileSelectActivity.java
@@ -22,11 +22,13 @@
 import org.strongswan.android.R;
 import org.strongswan.android.data.VpnProfile;
 import org.strongswan.android.ui.VpnProfileListFragment.OnVpnProfileSelectedListener;
+import org.strongswan.android.utils.Utils;
 
 import androidx.appcompat.app.AppCompatActivity;
 import androidx.core.content.pm.ShortcutInfoCompat;
 import androidx.core.content.pm.ShortcutManagerCompat;
 import androidx.core.graphics.drawable.IconCompat;
+import androidx.core.view.WindowCompat;
 
 public class VpnProfileSelectActivity extends AppCompatActivity implements OnVpnProfileSelectedListener
 {
@@ -35,6 +37,8 @@
 	{
 		super.onCreate(savedInstanceState);
 		setContentView(R.layout.vpn_profile_select);
+		WindowCompat.enableEdgeToEdge(getWindow());
+		Utils.applyWindowInsetsAsMarginsForLists(findViewById(R.id.layout));
 
 		/* we should probably return a result also if the user clicks the back
 		 * button before selecting a profile */
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/adapter/VpnProfileAdapter.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/adapter/VpnProfileAdapter.java
index c2942b8..097c422 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/adapter/VpnProfileAdapter.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/adapter/VpnProfileAdapter.java
@@ -86,7 +86,8 @@
 		tv = vpnProfileView.findViewById(R.id.profile_item_certificate);
 		if (profile.getVpnType().has(VpnTypeFeature.CERTIFICATE))
 		{
-			tv.setText(getContext().getString(R.string.profile_user_certificate_label) + ": " + profile.getUserCertificateAlias());
+			String alias = profile.getUserCertificateAlias();
+			tv.setText(getContext().getString(R.string.profile_user_certificate_label) + ": " + (alias != null ? alias : ""));
 			tv.setVisibility(View.VISIBLE);
 		}
 		else
diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/utils/Utils.java b/src/frontends/android/app/src/main/java/org/strongswan/android/utils/Utils.java
index 5142ee1..ac1a315 100644
--- a/src/frontends/android/app/src/main/java/org/strongswan/android/utils/Utils.java
+++ b/src/frontends/android/app/src/main/java/org/strongswan/android/utils/Utils.java
@@ -17,9 +17,16 @@
 package org.strongswan.android.utils;
 
 
+import android.view.View;
+import android.view.ViewGroup;
+
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 
+import androidx.core.graphics.Insets;
+import androidx.core.view.ViewCompat;
+import androidx.core.view.WindowInsetsCompat;
+
 public class Utils
 {
 	static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
@@ -75,4 +82,39 @@
 		}
 		return InetAddress.getByAddress(bytes);
 	}
+
+	/**
+	 * Apply window insets for the system UI as margins except for the bottom,
+	 * which is useful if the view ends with a list. WindowInsetsCompat.CONSUMED
+	 * is not returned so padding can be applied to the list.
+	 *
+	 * @param view view to apply margins to
+	 */
+	public static void applyWindowInsetsAsMarginsForLists(View view)
+	{
+		ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> {
+			Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
+			ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams)v.getLayoutParams();
+			mlp.topMargin = insets.top;
+			mlp.leftMargin = insets.left;
+			mlp.rightMargin = insets.right;
+			v.setLayoutParams(mlp);
+			return windowInsets;
+		});
+	}
+
+	/**
+	 * Apply bottom inset for the system UI as padding on the given (list) view
+	 * so the last item can be scrolled fully into view.
+	 *
+	 * @param view view to apply padding to
+	 */
+	public static void applyWindowInsetsAsPaddingForLists(View view)
+	{
+		ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> {
+			Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
+			v.setPaddingRelative(0, 0, 0, insets.bottom);
+			return WindowInsetsCompat.CONSUMED;
+		});
+	}
 }
diff --git a/src/frontends/android/app/src/main/play/release-notes/de-DE/default.txt b/src/frontends/android/app/src/main/play/release-notes/de-DE/default.txt
index 9409e3a..8650f20 100644
--- a/src/frontends/android/app/src/main/play/release-notes/de-DE/default.txt
+++ b/src/frontends/android/app/src/main/play/release-notes/de-DE/default.txt
@@ -1,18 +1,11 @@
+# 2.6.0 #
+
+- Erlaubt die Vorauswahl eines Benutzer-Zertifikats via Alias in verwalteten Profilen
+- Erlaubt die Auswahl von Benutzer-Zertifikaten in verwalteten Profilen, die kein eigenes Zertifikat installieren
+- Fixt das Lesen von Split-Tunneling Settings in verwalteten Profilen
+- Anpassungen für die randlose Anzeige, welche erzwungen wird, wenn Android 16 als Ziel-SDK verwendet wird
+- Ziel-SDK auf Android 16 erhöht
+
 # 2.5.6 #
 
 - Unterstützt benutzerdefinierte HTTP Proxy-Server (Android 10+)
-
-# 2.5.5 #
-
-- Fixt den Start von verwalteten Profilen als Always-on VPN
-
-# 2.5.4 #
-
-- Fixt Probleme beim Wiederherstellen der Verbindung
-
-# 2.5.3 #
-
-- Unterstützt die Verteilung von Passwörtern in verwalteten Profilen
-- Unterstützt den Import von Profil-Dateien mit Passwörtern
-- Fixt einen Crash beim Ändern des Passworts von verwalteten Profilen
-- Fixt einen Crash beim Importieren eines bereit existierenden Profils
diff --git a/src/frontends/android/app/src/main/play/release-notes/en-US/default.txt b/src/frontends/android/app/src/main/play/release-notes/en-US/default.txt
index 2ae7780..c9d90c1 100644
--- a/src/frontends/android/app/src/main/play/release-notes/en-US/default.txt
+++ b/src/frontends/android/app/src/main/play/release-notes/en-US/default.txt
@@ -1,18 +1,11 @@
+# 2.6.0 #
+
+- Allow pre-selecting a user certificate via alias in managed profiles
+- Allow selecting a user certificate for managed profiles that don't install their own certificate
+- Fix reading split-tunneling settings in managed profiles
+- Adapt to edge-to-edge display, which becomes mandatory when targeting Android 16
+- Increase target SDK to Android 16
+
 # 2.5.6 #
 
 - Add support for custom HTTP proxy server (Android 10+)
-
-# 2.5.5 #
-
-- Fix initiating managed profiles as Always-on VPN
-
-# 2.5.4 #
-
-- Fix issues when reestablishing the connection
-
-# 2.5.3 #
-
-- Add support for distributing passwords in managed profiles
-- Add support for importing profile files with passwords
-- Fix crash when editing password of managed profiles
-- Fix crash when re-importing an already existing profile
diff --git a/src/frontends/android/app/src/main/res/layout-large/remediation_instructions.xml b/src/frontends/android/app/src/main/res/layout-large/remediation_instructions.xml
index 1c6494f..a2db351 100644
--- a/src/frontends/android/app/src/main/res/layout-large/remediation_instructions.xml
+++ b/src/frontends/android/app/src/main/res/layout-large/remediation_instructions.xml
@@ -18,7 +18,8 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="horizontal"
-    android:baselineAligned="false" >
+    android:baselineAligned="false"
+    android:fitsSystemWindows="true" >
 
     <fragment
         class="org.strongswan.android.ui.RemediationInstructionsFragment"
diff --git a/src/frontends/android/app/src/main/res/layout/log_activity.xml b/src/frontends/android/app/src/main/res/layout/log_activity.xml
index 7f85456..7a1fe3b 100644
--- a/src/frontends/android/app/src/main/res/layout/log_activity.xml
+++ b/src/frontends/android/app/src/main/res/layout/log_activity.xml
@@ -16,7 +16,8 @@
 -->
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent" >
+    android:layout_height="match_parent"
+    android:id="@+id/layout" >
 
     <fragment
             class="org.strongswan.android.ui.LogFragment"
diff --git a/src/frontends/android/app/src/main/res/layout/log_fragment.xml b/src/frontends/android/app/src/main/res/layout/log_fragment.xml
index b305b4d..a707054 100644
--- a/src/frontends/android/app/src/main/res/layout/log_fragment.xml
+++ b/src/frontends/android/app/src/main/res/layout/log_fragment.xml
@@ -14,23 +14,24 @@
     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     for more details.
 -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical" >
+    android:paddingBottom="0dp"
+    android:paddingTop="5dp"
+    android:paddingStart="5dp"
+    android:paddingEnd="5dp" >
 
     <ListView
         android:id="@+id/log"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:layout_margin="10dp"
         android:dividerHeight="0dp"
         android:divider="@null"
         android:fadeScrollbars="false"
         android:scrollbarFadeDuration="0"
         android:scrollbarAlwaysDrawVerticalTrack="true"
-        android:transcriptMode="normal">
+        android:transcriptMode="normal"
+        android:clipToPadding="false" />
 
-    </ListView>
-
-</LinearLayout>
+</FrameLayout>
diff --git a/src/frontends/android/app/src/main/res/layout/main.xml b/src/frontends/android/app/src/main/res/layout/main.xml
index 2aaf181..0693286 100644
--- a/src/frontends/android/app/src/main/res/layout/main.xml
+++ b/src/frontends/android/app/src/main/res/layout/main.xml
@@ -17,7 +17,8 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical" >
+    android:orientation="vertical"
+    android:id="@+id/layout" >
 
     <fragment
             class="org.strongswan.android.ui.VpnStateFragment"
diff --git a/src/frontends/android/app/src/main/res/layout/profile_detail_view.xml b/src/frontends/android/app/src/main/res/layout/profile_detail_view.xml
index 0469605..878514e 100644
--- a/src/frontends/android/app/src/main/res/layout/profile_detail_view.xml
+++ b/src/frontends/android/app/src/main/res/layout/profile_detail_view.xml
@@ -20,7 +20,8 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:fitsSystemWindows="true">
 
     <TextView
         android:id="@+id/managed_profile"
diff --git a/src/frontends/android/app/src/main/res/layout/profile_import_view.xml b/src/frontends/android/app/src/main/res/layout/profile_import_view.xml
index 231b552..f6cbf2c 100644
--- a/src/frontends/android/app/src/main/res/layout/profile_import_view.xml
+++ b/src/frontends/android/app/src/main/res/layout/profile_import_view.xml
@@ -15,9 +15,10 @@
     for more details.
 -->
 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
-            xmlns:app="http://schemas.android.com/apk/res-auto"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent" >
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fitsSystemWindows="true" >
 
     <LinearLayout
         android:layout_width="match_parent"
diff --git a/src/frontends/android/app/src/main/res/layout/profile_list_fragment.xml b/src/frontends/android/app/src/main/res/layout/profile_list_fragment.xml
index 6cc9d5b..9878147 100644
--- a/src/frontends/android/app/src/main/res/layout/profile_list_fragment.xml
+++ b/src/frontends/android/app/src/main/res/layout/profile_list_fragment.xml
@@ -17,7 +17,7 @@
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:paddingBottom="10dp"
+    android:paddingBottom="0dp"
     android:paddingTop="10dp"
     android:paddingStart="5dp"
     android:paddingEnd="5dp" >
@@ -28,9 +28,11 @@
         android:layout_height="match_parent"
         android:dividerHeight="1dp"
         android:divider="?android:attr/listDivider"
-        android:scrollbarAlwaysDrawVerticalTrack="true" />
+        android:overScrollFooter="@android:color/transparent"
+        android:scrollbarAlwaysDrawVerticalTrack="true"
+        android:clipToPadding="false" />
 
-     <TextView android:id="@+id/profile_list_empty"
+    <TextView android:id="@+id/profile_list_empty"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_marginStart="15dp"
diff --git a/src/frontends/android/app/src/main/res/layout/remediation_instructions.xml b/src/frontends/android/app/src/main/res/layout/remediation_instructions.xml
index c23f982..5b3f644 100644
--- a/src/frontends/android/app/src/main/res/layout/remediation_instructions.xml
+++ b/src/frontends/android/app/src/main/res/layout/remediation_instructions.xml
@@ -17,6 +17,7 @@
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:fitsSystemWindows="true"
     android:id="@+id/fragment_container">
 
-</FrameLayout>
\ No newline at end of file
+</FrameLayout>
diff --git a/src/frontends/android/app/src/main/res/layout/trusted_certificates_activity.xml b/src/frontends/android/app/src/main/res/layout/trusted_certificates_activity.xml
index 1eee059..ee7ec19 100644
--- a/src/frontends/android/app/src/main/res/layout/trusted_certificates_activity.xml
+++ b/src/frontends/android/app/src/main/res/layout/trusted_certificates_activity.xml
@@ -15,10 +15,11 @@
     for more details.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              xmlns:app="http://schemas.android.com/apk/res-auto"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent"
-              android:orientation="vertical">
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:fitsSystemWindows="true">
 
     <com.google.android.material.tabs.TabLayout
         android:id="@+id/tabs"
diff --git a/src/frontends/android/app/src/main/res/layout/vpn_profile_select.xml b/src/frontends/android/app/src/main/res/layout/vpn_profile_select.xml
index b7fbb66..6db6041 100644
--- a/src/frontends/android/app/src/main/res/layout/vpn_profile_select.xml
+++ b/src/frontends/android/app/src/main/res/layout/vpn_profile_select.xml
@@ -18,7 +18,8 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical" >
+    android:orientation="vertical"
+    android:id="@+id/layout" >
 
     <fragment
             class="org.strongswan.android.ui.VpnProfileListFragment"
@@ -28,4 +29,4 @@
             android:layout_weight="1"
             app:read_only="true" />
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/src/frontends/android/app/src/main/res/layout/vpn_state_fragment.xml b/src/frontends/android/app/src/main/res/layout/vpn_state_fragment.xml
index 9227007..b3d8cfd 100644
--- a/src/frontends/android/app/src/main/res/layout/vpn_state_fragment.xml
+++ b/src/frontends/android/app/src/main/res/layout/vpn_state_fragment.xml
@@ -74,11 +74,11 @@
         </LinearLayout>
     </LinearLayout>
 
-    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                  android:layout_width="match_parent"
-                  android:layout_height="match_parent"
-                  android:background="@drawable/state_background"
-                  android:orientation="vertical" >
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@drawable/state_background"
+        android:orientation="vertical" >
 
         <GridLayout
             android:layout_width="match_parent"
diff --git a/src/frontends/android/app/src/main/res/values-de/strings.xml b/src/frontends/android/app/src/main/res/values-de/strings.xml
index 6047ed6..c282004 100644
--- a/src/frontends/android/app/src/main/res/values-de/strings.xml
+++ b/src/frontends/android/app/src/main/res/values-de/strings.xml
@@ -158,7 +158,7 @@
     <string name="alert_text_no_subnets">Bitte geben Sie mit Leerzeichen getrennte, gültige Subnetzte und/oder IP-Adressen ein</string>
     <string name="alert_text_no_ips">Bitte geben Sie mit Leerzeichen getrennte, gültige IP-Adressen ein</string>
     <string name="alert_text_no_proposal">Bitte geben Sie eine mit Bindestrichen getrennte, gültige Liste von Algorithmen ein</string>
-    <string name="alert_text_vpn_profile_read_only">Dieses Profil wird von Ihrem Administrator verwaltet und kann nicht bearbeitet werden. Nur das Passwort kann geändert werden</string>
+    <string name="alert_text_vpn_profile_read_only">Dieses Profil wird von Ihrem Administrator verwaltet und kann nicht bearbeitet werden. Nur das Passwort bzw. Benutzer-Zertifikat kann geändert werden</string>
     <string name="tnc_notice_title">EAP-TNC kann Ihre Privatsphäre beeinträchtigen</string>
     <string name="tnc_notice_subtitle">Gerätedaten werden an den Server-Betreiber gesendet</string>
     <string name="tnc_notice_details"><![CDATA[<p>Trusted Network Connect (TNC) erlaubt Server-Betreibern den Gesundheitszustand von Endgeräten zu prüfen.</p><p>Dazu kann der Betreiber Daten verlangen, wie etwa eine eindeutige Identifikationsnummer, eine Liste der installierten Pakete, Systemeinstellungen oder kryptografische Prüfsummen von Dateien.</p><b>Solche Daten werden nur übermittelt nachdem die Identität des Servers geprüft wurde.</b>]]></string>
@@ -234,6 +234,8 @@
     <string name="cancel_retry">Wiederholen abbrechen</string>
     <string name="power_whitelist_title">Akku-Optimierung deaktivieren</string>
     <string name="power_whitelist_text">Bitte den nächsten Dialog bestätigen, um die App auf die weisse Liste für Akku-Optimierung zu setzen, so dass sie NAT keepalives und Rekeyings zeitlich korrekt planen kann, um konstant erreichbar zu bleiben während die VPN-Verbindung besteht.</string>
+    <string name="certificate_required_title">Benutzer-Zertifikat benötigt</string>
+    <string name="certificate_required_text">Bitte bearbeiten Sie das VPN Profil, um eines auszuwählen.</string>
 
     <!-- Quick Settings tile -->
     <string name="tile_default">VPN umschalten</string>
diff --git a/src/frontends/android/app/src/main/res/values-de/strings_managed_configuration.xml b/src/frontends/android/app/src/main/res/values-de/strings_managed_configuration.xml
index c7d5160..c0bdd7f 100644
--- a/src/frontends/android/app/src/main/res/values-de/strings_managed_configuration.xml
+++ b/src/frontends/android/app/src/main/res/values-de/strings_managed_configuration.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
+    Copyright (C) 2025 Tobias Brunner
     Copyright (C) 2023 Relution GmbH
 
     Copyright (C) secunet Security Networks AG
@@ -93,6 +94,8 @@
     <string name="managed_config_local_p12_description">Base64-encoded PKCS#12-container with the client certificate and private key and optional certificate chain (the latter might cause warnings on older Android releases, see Android VPN client configuration for details). Not necessary for username/password-based EAP authentication or if the user already has the certificate/key installed as it may be selected while importing the profile</string>
     <string name="managed_config_local_p12_password_title">User certificate password (Optional)</string>
     <string name="managed_config_local_p12_password_description">Password required to extract the private key of the PKCS#12-container for installation</string>
+    <string name="managed_config_local_user_certificate_alias_title">User certificate alias (Optional)</string>
+    <string name="managed_config_local_user_certificate_alias_description">Alias of a user certificate/key already installed on the device. The app must be granted access to it by the MDM. Only used if no certificate is distributed with the config. If a certificate is required and this is not set, the user may select a local certificate manually</string>
     <string name="managed_config_local_rsa_pss_title">@string/profile_rsa_pss_label</string>
     <string name="managed_config_local_rsa_pss_description">@string/profile_rsa_pss_hint</string>
 
diff --git a/src/frontends/android/app/src/main/res/values-pl/strings.xml b/src/frontends/android/app/src/main/res/values-pl/strings.xml
index 8d98fe3..82d9655 100644
--- a/src/frontends/android/app/src/main/res/values-pl/strings.xml
+++ b/src/frontends/android/app/src/main/res/values-pl/strings.xml
@@ -160,7 +160,7 @@
     <string name="alert_text_no_subnets">Please enter valid subnets and/or IP addresses, separated by spaces</string>
     <string name="alert_text_no_ips">Please enter valid IP addresses, separated by spaces</string>
     <string name="alert_text_no_proposal">Please enter a valid list of algorithms, separated by hyphens</string>
-    <string name="alert_text_vpn_profile_read_only">This VPN profile is managed by your administrator and can\'t be modified. You can only change the password</string>
+    <string name="alert_text_vpn_profile_read_only">This VPN profile is managed by your administrator and can\'t be modified. You can only change the password or user certificate</string>
     <string name="tnc_notice_title">EAP-TNC may affect your privacy</string>
     <string name="tnc_notice_subtitle">Device data is sent to the server operator</string>
     <string name="tnc_notice_details"><![CDATA[<p>Trusted Network Connect (TNC) allows server operators to assess the health of a client device.</p><p>For that purpose the server operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.</p><b>Any data will be sent only after verifying the server\'s identity.</b>]]></string>
@@ -236,6 +236,8 @@
     <string name="cancel_retry">Cancel retry</string>
     <string name="power_whitelist_title">Disable battery optimizations</string>
     <string name="power_whitelist_text">Please confirm the next dialog to add the app to the device\'s power whitelist so it can ignore battery optimizations and schedule NAT keep-alives and rekeyings accurately in order to constantly keep reachable while the VPN is established.</string>
+    <string name="certificate_required_title">User certificate required</string>
+    <string name="certificate_required_text">Please edit the VPN profile to select one.</string>
 
     <!-- Quick Settings tile -->
     <string name="tile_default">Toggle VPN</string>
diff --git a/src/frontends/android/app/src/main/res/values-pl/strings_managed_configuration.xml b/src/frontends/android/app/src/main/res/values-pl/strings_managed_configuration.xml
index c7d5160..c0bdd7f 100644
--- a/src/frontends/android/app/src/main/res/values-pl/strings_managed_configuration.xml
+++ b/src/frontends/android/app/src/main/res/values-pl/strings_managed_configuration.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
+    Copyright (C) 2025 Tobias Brunner
     Copyright (C) 2023 Relution GmbH
 
     Copyright (C) secunet Security Networks AG
@@ -93,6 +94,8 @@
     <string name="managed_config_local_p12_description">Base64-encoded PKCS#12-container with the client certificate and private key and optional certificate chain (the latter might cause warnings on older Android releases, see Android VPN client configuration for details). Not necessary for username/password-based EAP authentication or if the user already has the certificate/key installed as it may be selected while importing the profile</string>
     <string name="managed_config_local_p12_password_title">User certificate password (Optional)</string>
     <string name="managed_config_local_p12_password_description">Password required to extract the private key of the PKCS#12-container for installation</string>
+    <string name="managed_config_local_user_certificate_alias_title">User certificate alias (Optional)</string>
+    <string name="managed_config_local_user_certificate_alias_description">Alias of a user certificate/key already installed on the device. The app must be granted access to it by the MDM. Only used if no certificate is distributed with the config. If a certificate is required and this is not set, the user may select a local certificate manually</string>
     <string name="managed_config_local_rsa_pss_title">@string/profile_rsa_pss_label</string>
     <string name="managed_config_local_rsa_pss_description">@string/profile_rsa_pss_hint</string>
 
diff --git a/src/frontends/android/app/src/main/res/values-ru/strings.xml b/src/frontends/android/app/src/main/res/values-ru/strings.xml
index 0f8c724..ac09e3e 100644
--- a/src/frontends/android/app/src/main/res/values-ru/strings.xml
+++ b/src/frontends/android/app/src/main/res/values-ru/strings.xml
@@ -154,7 +154,7 @@
     <string name="alert_text_no_subnets">Please enter valid subnets and/or IP addresses, separated by spaces</string>
     <string name="alert_text_no_ips">Please enter valid IP addresses, separated by spaces</string>
     <string name="alert_text_no_proposal">Please enter a valid list of algorithms, separated by hyphens</string>
-    <string name="alert_text_vpn_profile_read_only">This VPN profile is managed by your administrator and can\'t be modified. You can only change the password</string>
+    <string name="alert_text_vpn_profile_read_only">This VPN profile is managed by your administrator and can\'t be modified. You can only change the password or user certificate</string>
     <string name="tnc_notice_title">EAP-TNC may affect your privacy</string>
     <string name="tnc_notice_subtitle">Device data is sent to the server operator</string>
     <string name="tnc_notice_details"><![CDATA[<p>Trusted Network Connect (TNC) allows server operators to assess the health of a client device.</p><p>For that purpose the server operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.</p><b>Any data will be sent only after verifying the server\'s identity.</b>]]></string>
@@ -230,6 +230,8 @@
     <string name="cancel_retry">Cancel retry</string>
     <string name="power_whitelist_title">Disable battery optimizations</string>
     <string name="power_whitelist_text">Please confirm the next dialog to add the app to the device\'s power whitelist so it can ignore battery optimizations and schedule NAT keep-alives and rekeyings accurately in order to constantly keep reachable while the VPN is established.</string>
+    <string name="certificate_required_title">User certificate required</string>
+    <string name="certificate_required_text">Please edit the VPN profile to select one.</string>
 
     <!-- Quick Settings tile -->
     <string name="tile_default">Toggle VPN</string>
diff --git a/src/frontends/android/app/src/main/res/values-ru/strings_managed_configuration.xml b/src/frontends/android/app/src/main/res/values-ru/strings_managed_configuration.xml
index c7d5160..c0bdd7f 100644
--- a/src/frontends/android/app/src/main/res/values-ru/strings_managed_configuration.xml
+++ b/src/frontends/android/app/src/main/res/values-ru/strings_managed_configuration.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
+    Copyright (C) 2025 Tobias Brunner
     Copyright (C) 2023 Relution GmbH
 
     Copyright (C) secunet Security Networks AG
@@ -93,6 +94,8 @@
     <string name="managed_config_local_p12_description">Base64-encoded PKCS#12-container with the client certificate and private key and optional certificate chain (the latter might cause warnings on older Android releases, see Android VPN client configuration for details). Not necessary for username/password-based EAP authentication or if the user already has the certificate/key installed as it may be selected while importing the profile</string>
     <string name="managed_config_local_p12_password_title">User certificate password (Optional)</string>
     <string name="managed_config_local_p12_password_description">Password required to extract the private key of the PKCS#12-container for installation</string>
+    <string name="managed_config_local_user_certificate_alias_title">User certificate alias (Optional)</string>
+    <string name="managed_config_local_user_certificate_alias_description">Alias of a user certificate/key already installed on the device. The app must be granted access to it by the MDM. Only used if no certificate is distributed with the config. If a certificate is required and this is not set, the user may select a local certificate manually</string>
     <string name="managed_config_local_rsa_pss_title">@string/profile_rsa_pss_label</string>
     <string name="managed_config_local_rsa_pss_description">@string/profile_rsa_pss_hint</string>
 
diff --git a/src/frontends/android/app/src/main/res/values-uk/strings.xml b/src/frontends/android/app/src/main/res/values-uk/strings.xml
index 2b552b6..a819bc8 100644
--- a/src/frontends/android/app/src/main/res/values-uk/strings.xml
+++ b/src/frontends/android/app/src/main/res/values-uk/strings.xml
@@ -155,7 +155,7 @@
     <string name="alert_text_no_subnets">Please enter valid subnets and/or IP addresses, separated by spaces</string>
     <string name="alert_text_no_ips">Please enter valid IP addresses, separated by spaces</string>
     <string name="alert_text_no_proposal">Please enter a valid list of algorithms, separated by hyphens</string>
-    <string name="alert_text_vpn_profile_read_only">This VPN profile is managed by your administrator and can\'t be modified. You can only change the password</string>
+    <string name="alert_text_vpn_profile_read_only">This VPN profile is managed by your administrator and can\'t be modified. You can only change the password or user certificate</string>
     <string name="tnc_notice_title">EAP-TNC may affect your privacy</string>
     <string name="tnc_notice_subtitle">Device data is sent to the server operator</string>
     <string name="tnc_notice_details"><![CDATA[<p>Trusted Network Connect (TNC) allows server operators to assess the health of a client device.</p><p>For that purpose the server operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.</p><b>Any data will be sent only after verifying the server\'s identity.</b>]]></string>
@@ -231,6 +231,8 @@
     <string name="cancel_retry">Cancel retry</string>
     <string name="power_whitelist_title">Disable battery optimizations</string>
     <string name="power_whitelist_text">Please confirm the next dialog to add the app to the device\'s power whitelist so it can ignore battery optimizations and schedule NAT keep-alives and rekeyings accurately in order to constantly keep reachable while the VPN is established.</string>
+    <string name="certificate_required_title">User certificate required</string>
+    <string name="certificate_required_text">Please edit the VPN profile to select one.</string>
 
     <!-- Quick Settings tile -->
     <string name="tile_default">Toggle VPN</string>
diff --git a/src/frontends/android/app/src/main/res/values-uk/strings_managed_configuration.xml b/src/frontends/android/app/src/main/res/values-uk/strings_managed_configuration.xml
index c7d5160..c0bdd7f 100644
--- a/src/frontends/android/app/src/main/res/values-uk/strings_managed_configuration.xml
+++ b/src/frontends/android/app/src/main/res/values-uk/strings_managed_configuration.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
+    Copyright (C) 2025 Tobias Brunner
     Copyright (C) 2023 Relution GmbH
 
     Copyright (C) secunet Security Networks AG
@@ -93,6 +94,8 @@
     <string name="managed_config_local_p12_description">Base64-encoded PKCS#12-container with the client certificate and private key and optional certificate chain (the latter might cause warnings on older Android releases, see Android VPN client configuration for details). Not necessary for username/password-based EAP authentication or if the user already has the certificate/key installed as it may be selected while importing the profile</string>
     <string name="managed_config_local_p12_password_title">User certificate password (Optional)</string>
     <string name="managed_config_local_p12_password_description">Password required to extract the private key of the PKCS#12-container for installation</string>
+    <string name="managed_config_local_user_certificate_alias_title">User certificate alias (Optional)</string>
+    <string name="managed_config_local_user_certificate_alias_description">Alias of a user certificate/key already installed on the device. The app must be granted access to it by the MDM. Only used if no certificate is distributed with the config. If a certificate is required and this is not set, the user may select a local certificate manually</string>
     <string name="managed_config_local_rsa_pss_title">@string/profile_rsa_pss_label</string>
     <string name="managed_config_local_rsa_pss_description">@string/profile_rsa_pss_hint</string>
 
diff --git a/src/frontends/android/app/src/main/res/values-v15/styles.xml b/src/frontends/android/app/src/main/res/values-v15/styles.xml
deleted file mode 100644
index 2b152c4..0000000
--- a/src/frontends/android/app/src/main/res/values-v15/styles.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2016 Tobias Brunner
-
-    Copyright (C) secunet Security Networks AG
-
-    This program is free software; you can redistribute it and/or modify it
-    under the terms of the GNU General Public License as published by the
-    Free Software Foundation; either version 2 of the License, or (at your
-    option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
-
-    This program is distributed in the hope that it will be useful, but
-    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-    for more details.
--->
-<resources>
-
-    <style name="ApplicationTheme" parent="ApplicationTheme.Base">
-        <item name="android:activatedBackgroundIndicator">@drawable/activated_background</item>
-        <item name="android:selectableItemBackground">@drawable/activated_background</item>
-    </style>
-
-    <style name="AlertDialogTheme" parent="AlertDialogTheme.Base">
-        <item name="android:windowBackground">@android:color/transparent</item>
-    </style>
-
-</resources>
\ No newline at end of file
diff --git a/src/frontends/android/app/src/main/res/values-v21/styles.xml b/src/frontends/android/app/src/main/res/values-v21/styles.xml
deleted file mode 100644
index 050c319..0000000
--- a/src/frontends/android/app/src/main/res/values-v21/styles.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2016 Tobias Brunner
-
-    Copyright (C) secunet Security Networks AG
-
-    This program is free software; you can redistribute it and/or modify it
-    under the terms of the GNU General Public License as published by the
-    Free Software Foundation; either version 2 of the License, or (at your
-    option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
-
-    This program is distributed in the hope that it will be useful, but
-    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-    for more details.
--->
-<resources>
-
-    <style name="ApplicationTheme" parent="ApplicationTheme.Base">
-    </style>
-
-    <style name="AlertDialogTheme" parent="AlertDialogTheme.Base">
-    </style>
-
-</resources>
\ No newline at end of file
diff --git a/src/frontends/android/app/src/main/res/values-zh-rCN/strings.xml b/src/frontends/android/app/src/main/res/values-zh-rCN/strings.xml
index fe96028..a7ad193 100644
--- a/src/frontends/android/app/src/main/res/values-zh-rCN/strings.xml
+++ b/src/frontends/android/app/src/main/res/values-zh-rCN/strings.xml
@@ -154,7 +154,7 @@
     <string name="alert_text_no_subnets">请输入有效的子网和/或IP地址,用空格分隔</string>
     <string name="alert_text_no_ips">请输入有效的IP地址,以空格分隔</string>
     <string name="alert_text_no_proposal">请输入用连字符分隔的有效算法列表</string>
-    <string name="alert_text_vpn_profile_read_only">This VPN profile is managed by your administrator and can\'t be modified. You can only change the password</string>
+    <string name="alert_text_vpn_profile_read_only">This VPN profile is managed by your administrator and can\'t be modified. You can only change the password or user certificate</string>
     <string name="tnc_notice_title">EAP-TNC可能会影响您的隐私</string>
     <string name="tnc_notice_subtitle">设备数据已被发送至服务器管理员</string>
     <string name="tnc_notice_details"><![CDATA[<p>可信网络连接t (TNC) 允许服务器管理员评定一个用户设备的状况。</p><p>出于此目的,服务器管理员可能要求以下数据如独立ID、已安装软件列表、系统设置、或加密过的文件校验值。</p><b>任何数据都仅将在验证过服务器的身份ID之后被发出。</b>]]></string>
@@ -230,6 +230,8 @@
     <string name="cancel_retry">取消重试</string>
     <string name="power_whitelist_title">禁用电池优化</string>
     <string name="power_whitelist_text">请确认下一个对话框,将应用程序添加到设备的电源白名单中,这样它就可以忽略电池优化,并准确地安排NAT保持有效和重新键入,以便在建立VPN时始终保持可访问性。</string>
+    <string name="certificate_required_title">User certificate required</string>
+    <string name="certificate_required_text">Please edit the VPN profile to select one.</string>
 
     <!-- Quick Settings tile -->
     <string name="tile_default">切换VPN</string>
diff --git a/src/frontends/android/app/src/main/res/values-zh-rCN/strings_managed_configuration.xml b/src/frontends/android/app/src/main/res/values-zh-rCN/strings_managed_configuration.xml
index c7d5160..c0bdd7f 100644
--- a/src/frontends/android/app/src/main/res/values-zh-rCN/strings_managed_configuration.xml
+++ b/src/frontends/android/app/src/main/res/values-zh-rCN/strings_managed_configuration.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
+    Copyright (C) 2025 Tobias Brunner
     Copyright (C) 2023 Relution GmbH
 
     Copyright (C) secunet Security Networks AG
@@ -93,6 +94,8 @@
     <string name="managed_config_local_p12_description">Base64-encoded PKCS#12-container with the client certificate and private key and optional certificate chain (the latter might cause warnings on older Android releases, see Android VPN client configuration for details). Not necessary for username/password-based EAP authentication or if the user already has the certificate/key installed as it may be selected while importing the profile</string>
     <string name="managed_config_local_p12_password_title">User certificate password (Optional)</string>
     <string name="managed_config_local_p12_password_description">Password required to extract the private key of the PKCS#12-container for installation</string>
+    <string name="managed_config_local_user_certificate_alias_title">User certificate alias (Optional)</string>
+    <string name="managed_config_local_user_certificate_alias_description">Alias of a user certificate/key already installed on the device. The app must be granted access to it by the MDM. Only used if no certificate is distributed with the config. If a certificate is required and this is not set, the user may select a local certificate manually</string>
     <string name="managed_config_local_rsa_pss_title">@string/profile_rsa_pss_label</string>
     <string name="managed_config_local_rsa_pss_description">@string/profile_rsa_pss_hint</string>
 
diff --git a/src/frontends/android/app/src/main/res/values-zh-rTW/strings.xml b/src/frontends/android/app/src/main/res/values-zh-rTW/strings.xml
index 26f3e80..5331675 100644
--- a/src/frontends/android/app/src/main/res/values-zh-rTW/strings.xml
+++ b/src/frontends/android/app/src/main/res/values-zh-rTW/strings.xml
@@ -154,7 +154,7 @@
     <string name="alert_text_no_subnets">Please enter valid subnets and/or IP addresses, separated by spaces</string>
     <string name="alert_text_no_ips">Please enter valid IP addresses, separated by spaces</string>
     <string name="alert_text_no_proposal">Please enter a valid list of algorithms, separated by hyphens</string>
-    <string name="alert_text_vpn_profile_read_only">This VPN profile is managed by your administrator and can\'t be modified. You can only change the password</string>
+    <string name="alert_text_vpn_profile_read_only">This VPN profile is managed by your administrator and can\'t be modified. You can only change the password or user certificate</string>
     <string name="tnc_notice_title">EAP-TNC可能會影響您的隱私安全</string>
     <string name="tnc_notice_subtitle">裝置資料已經發送給伺服器管理者</string>
     <string name="tnc_notice_details"><![CDATA[<p>Trusted Network Connect (TNC) 可以讓伺服器管理者評估用戶裝置的狀況。</p><p>在這個目的下,伺服器管理者可能會要求以下資料,例如ID、已安裝的App項目、系統設定、或加密檔案驗證值。</p><b>任何資料都只有在驗證伺服器的身分ID之後才會被送出。</b>]]></string>
@@ -230,6 +230,8 @@
     <string name="cancel_retry">Cancel retry</string>
     <string name="power_whitelist_title">Disable battery optimizations</string>
     <string name="power_whitelist_text">Please confirm the next dialog to add the app to the device\'s power whitelist so it can ignore battery optimizations and schedule NAT keep-alives and rekeyings accurately in order to constantly keep reachable while the VPN is established.</string>
+    <string name="certificate_required_title">User certificate required</string>
+    <string name="certificate_required_text">Please edit the VPN profile to select one.</string>
 
     <!-- Quick Settings tile -->
     <string name="tile_default">Toggle VPN</string>
diff --git a/src/frontends/android/app/src/main/res/values-zh-rTW/strings_managed_configuration.xml b/src/frontends/android/app/src/main/res/values-zh-rTW/strings_managed_configuration.xml
index c7d5160..c0bdd7f 100644
--- a/src/frontends/android/app/src/main/res/values-zh-rTW/strings_managed_configuration.xml
+++ b/src/frontends/android/app/src/main/res/values-zh-rTW/strings_managed_configuration.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
+    Copyright (C) 2025 Tobias Brunner
     Copyright (C) 2023 Relution GmbH
 
     Copyright (C) secunet Security Networks AG
@@ -93,6 +94,8 @@
     <string name="managed_config_local_p12_description">Base64-encoded PKCS#12-container with the client certificate and private key and optional certificate chain (the latter might cause warnings on older Android releases, see Android VPN client configuration for details). Not necessary for username/password-based EAP authentication or if the user already has the certificate/key installed as it may be selected while importing the profile</string>
     <string name="managed_config_local_p12_password_title">User certificate password (Optional)</string>
     <string name="managed_config_local_p12_password_description">Password required to extract the private key of the PKCS#12-container for installation</string>
+    <string name="managed_config_local_user_certificate_alias_title">User certificate alias (Optional)</string>
+    <string name="managed_config_local_user_certificate_alias_description">Alias of a user certificate/key already installed on the device. The app must be granted access to it by the MDM. Only used if no certificate is distributed with the config. If a certificate is required and this is not set, the user may select a local certificate manually</string>
     <string name="managed_config_local_rsa_pss_title">@string/profile_rsa_pss_label</string>
     <string name="managed_config_local_rsa_pss_description">@string/profile_rsa_pss_hint</string>
 
diff --git a/src/frontends/android/app/src/main/res/values/strings.xml b/src/frontends/android/app/src/main/res/values/strings.xml
index 7f031be..4174636 100644
--- a/src/frontends/android/app/src/main/res/values/strings.xml
+++ b/src/frontends/android/app/src/main/res/values/strings.xml
@@ -158,7 +158,7 @@
     <string name="alert_text_no_subnets">Please enter valid subnets and/or IP addresses, separated by spaces</string>
     <string name="alert_text_no_ips">Please enter valid IP addresses, separated by spaces</string>
     <string name="alert_text_no_proposal">Please enter a valid list of algorithms, separated by hyphens</string>
-    <string name="alert_text_vpn_profile_read_only">This VPN profile is managed by your administrator and can\'t be modified. You can only change the password</string>
+    <string name="alert_text_vpn_profile_read_only">This VPN profile is managed by your administrator and can\'t be modified. You can only change the password or user certificate</string>
     <string name="tnc_notice_title">EAP-TNC may affect your privacy</string>
     <string name="tnc_notice_subtitle">Device data is sent to the server operator</string>
     <string name="tnc_notice_details"><![CDATA[<p>Trusted Network Connect (TNC) allows server operators to assess the health of a client device.</p><p>For that purpose the server operator may request data such as a unique identifier, a list of installed packages, system settings, or cryptographic checksums of files.</p><b>Any data will be sent only after verifying the server\'s identity.</b>]]></string>
@@ -234,6 +234,8 @@
     <string name="cancel_retry">Cancel retry</string>
     <string name="power_whitelist_title">Disable battery optimizations</string>
     <string name="power_whitelist_text">Please confirm the next dialog to add the app to the device\'s power whitelist so it can ignore battery optimizations and schedule NAT keep-alives and rekeyings accurately in order to constantly keep reachable while the VPN is established.</string>
+    <string name="certificate_required_title">User certificate required</string>
+    <string name="certificate_required_text">Please edit the VPN profile to select one.</string>
 
     <!-- Quick Settings tile -->
     <string name="tile_default">Toggle VPN</string>
diff --git a/src/frontends/android/app/src/main/res/values/strings_managed_configuration.xml b/src/frontends/android/app/src/main/res/values/strings_managed_configuration.xml
index 0492203..c0bdd7f 100644
--- a/src/frontends/android/app/src/main/res/values/strings_managed_configuration.xml
+++ b/src/frontends/android/app/src/main/res/values/strings_managed_configuration.xml
@@ -94,6 +94,8 @@
     <string name="managed_config_local_p12_description">Base64-encoded PKCS#12-container with the client certificate and private key and optional certificate chain (the latter might cause warnings on older Android releases, see Android VPN client configuration for details). Not necessary for username/password-based EAP authentication or if the user already has the certificate/key installed as it may be selected while importing the profile</string>
     <string name="managed_config_local_p12_password_title">User certificate password (Optional)</string>
     <string name="managed_config_local_p12_password_description">Password required to extract the private key of the PKCS#12-container for installation</string>
+    <string name="managed_config_local_user_certificate_alias_title">User certificate alias (Optional)</string>
+    <string name="managed_config_local_user_certificate_alias_description">Alias of a user certificate/key already installed on the device. The app must be granted access to it by the MDM. Only used if no certificate is distributed with the config. If a certificate is required and this is not set, the user may select a local certificate manually</string>
     <string name="managed_config_local_rsa_pss_title">@string/profile_rsa_pss_label</string>
     <string name="managed_config_local_rsa_pss_description">@string/profile_rsa_pss_hint</string>
 
diff --git a/src/frontends/android/app/src/main/res/values/styles.xml b/src/frontends/android/app/src/main/res/values/styles.xml
index 0ce04b1..8dc8e44 100644
--- a/src/frontends/android/app/src/main/res/values/styles.xml
+++ b/src/frontends/android/app/src/main/res/values/styles.xml
@@ -16,7 +16,7 @@
 -->
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <style name="ApplicationTheme.Base" parent="Theme.AppCompat">
+    <style name="ApplicationTheme" parent="Theme.AppCompat">
         <item name="colorAccent">@color/accent</item>
         <item name="colorPrimary">@color/primary</item>
         <item name="colorPrimaryDark">@color/primary_dark</item>
@@ -24,7 +24,7 @@
         <item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
     </style>
 
-    <style name="AlertDialogTheme.Base" parent="Theme.AppCompat.Dialog.Alert">
+    <style name="AlertDialogTheme" parent="Theme.AppCompat.Dialog.Alert">
         <item name="colorAccent">@color/accent</item>
     </style>
 
diff --git a/src/frontends/android/app/src/main/res/xml/managed_configuration.xml b/src/frontends/android/app/src/main/res/xml/managed_configuration.xml
index 8c2a70e..aae843f 100644
--- a/src/frontends/android/app/src/main/res/xml/managed_configuration.xml
+++ b/src/frontends/android/app/src/main/res/xml/managed_configuration.xml
@@ -206,6 +206,13 @@
                     android:title="@string/managed_config_local_p12_password_title" />
 
                 <restriction
+                    android:defaultValue=""
+                    android:description="@string/managed_config_local_user_certificate_alias_description"
+                    android:key="user_certificate_alias"
+                    android:restrictionType="string"
+                    android:title="@string/managed_config_local_user_certificate_alias_title" />
+
+                <restriction
                     android:defaultValue="false"
                     android:description="@string/managed_config_local_rsa_pss_description"
                     android:key="local_rsa_pss"
@@ -272,7 +279,7 @@
 
             <restriction
                 android:description="@string/managed_config_split_tunneling_bundle_description"
-                android:key="split_tunnelling"
+                android:key="split_tunneling"
                 android:restrictionType="bundle"
                 android:title="@string/managed_config_split_tunneling_bundle_title">
 
@@ -324,7 +331,7 @@
                     android:description="@string/managed_config_proxy_port_description"
                     android:key="proxy_port"
                     android:restrictionType="integer"
-                    android:title="@string/managed_config_proxy_port_description" />
+                    android:title="@string/managed_config_proxy_port_title" />
 
                 <restriction
                     android:defaultValue=""
diff --git a/src/frontends/android/build.gradle b/src/frontends/android/build.gradle
index 3fa6c71..a35c5ff 100644
--- a/src/frontends/android/build.gradle
+++ b/src/frontends/android/build.gradle
@@ -4,7 +4,7 @@
         google()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:8.5.1'
+        classpath 'com.android.tools.build:gradle:8.13.0'
     }
 }
 
diff --git a/src/frontends/android/gradle/wrapper/gradle-wrapper.properties b/src/frontends/android/gradle/wrapper/gradle-wrapper.properties
index 8c8c77e..917b2e6 100644
--- a/src/frontends/android/gradle/wrapper/gradle-wrapper.properties
+++ b/src/frontends/android/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip