Merge branch 'android-14'

Updates target SDK to Android 14 (34) and fixes compatibility issues.
This commit is contained in:
Tobias Brunner
2024-08-06 18:02:18 +02:00
19 changed files with 123 additions and 40 deletions
+6 -6
View File
@@ -7,10 +7,10 @@ android {
applicationId "org.strongswan.android"
compileSdk 34
minSdkVersion 21
targetSdkVersion 33
targetSdkVersion 34
versionCode 82
versionName "2.5.1"
versionCode 84
versionName "2.5.2"
externalNativeBuild {
ndkBuild {
@@ -45,10 +45,10 @@ android {
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.lifecycle:lifecycle-process:2.7.0'
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'androidx.lifecycle:lifecycle-process:2.8.3'
implementation 'androidx.preference:preference:1.2.1'
implementation 'com.google.android.material:material:1.10.0'
implementation 'com.google.android.material:material:1.12.0'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.assertj:assertj-core:3.24.2'
testImplementation 'org.mockito:mockito-core:5.8.0'
@@ -22,9 +22,11 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<!-- necessary to allow users to select ex-/included apps and EAP-TNC -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
@@ -176,10 +178,14 @@
<service
android:name=".logic.CharonVpnService"
android:exported="false"
android:foregroundServiceType="specialUse"
android:permission="android.permission.BIND_VPN_SERVICE">
<intent-filter>
<action android:name="android.net.VpnService" />
</intent-filter>
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="VpnService instance"/>
</service>
<service
android:name=".ui.VpnTileService"
@@ -16,6 +16,7 @@
package org.strongswan.android.logic;
import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -37,6 +38,7 @@ public class Scheduler extends BroadcastReceiver
private final AlarmManager mManager;
private final PriorityQueue<ScheduledJob> mJobs;
@SuppressLint("UnspecifiedRegisterReceiverFlag")
public Scheduler(Context context)
{
mContext = context;
@@ -45,7 +47,14 @@ public class Scheduler extends BroadcastReceiver
IntentFilter filter = new IntentFilter();
filter.addAction(EXECUTE_JOB);
mContext.registerReceiver(this, filter);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
{
mContext.registerReceiver(this, filter, Context.RECEIVER_NOT_EXPORTED);
}
else
{
mContext.registerReceiver(this, filter);
}
}
/**
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2012-2015 Tobias Brunner
* Copyright (C) 2012-2024 Tobias Brunner
* Copyright (C) 2012 Giuliano Grassi
* Copyright (C) 2012 Ralf Sager
*
@@ -20,6 +20,8 @@ package org.strongswan.android.logic;
import android.util.Log;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.Certificate;
@@ -27,10 +29,9 @@ import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Observable;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class TrustedCertificateManager extends Observable
public class TrustedCertificateManager
{
private static final String TAG = TrustedCertificateManager.class.getSimpleName();
private final ReentrantReadWriteLock mLock = new ReentrantReadWriteLock();
@@ -38,6 +39,7 @@ public class TrustedCertificateManager extends Observable
private volatile boolean mReload;
private boolean mLoaded;
private final ArrayList<KeyStore> mKeyStores = new ArrayList<KeyStore>();
private PropertyChangeSupport mObservers = new PropertyChangeSupport(this);
public enum TrustedCertificateSource
{
@@ -98,6 +100,35 @@ public class TrustedCertificateManager extends Observable
return Singleton.mInstance;
}
/**
* Add an observer for changes to the trusted certificate store. There will
* be a "storeChanged" property "change" when anything in the store changed.
*
* @param observer observer to add
*/
public void addObserver(PropertyChangeListener observer)
{
mObservers.addPropertyChangeListener(observer);
}
/**
* Remove an observer for changes to the trusted certificate store.
*
* @param observer observer to remove
*/
public void deleteObserver(PropertyChangeListener observer)
{
mObservers.removePropertyChangeListener(observer);
}
/**
* Use a fake property with a forced change to notify observers.
*/
private void notifyObservers()
{
mObservers.firePropertyChange("storeChanged", false, true);
}
/**
* Invalidates the current load state so that the next call to load()
* will force a reload of the cached CA certificates.
@@ -110,7 +141,6 @@ public class TrustedCertificateManager extends Observable
{
Log.d(TAG, "Force reload of cached CA certificates on next load");
this.mReload = true;
this.setChanged();
this.notifyObservers();
return this;
}
@@ -152,7 +182,6 @@ public class TrustedCertificateManager extends Observable
this.mCACerts = certs;
if (!this.mLoaded)
{
this.setChanged();
this.notifyObservers();
this.mLoaded = true;
}
@@ -33,14 +33,14 @@ import org.strongswan.android.logic.TrustedCertificateManager.TrustedCertificate
import org.strongswan.android.security.TrustedCertificateEntry;
import org.strongswan.android.ui.adapter.TrustedCertificateAdapter;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import java.util.Map.Entry;
import java.util.Observable;
import java.util.Observer;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -249,12 +249,12 @@ public class TrustedCertificateListFragment extends ListFragment implements Load
}
}
private class TrustedCertificateManagerObserver implements Observer
private class TrustedCertificateManagerObserver implements PropertyChangeListener
{
private ForceLoadContentObserver mContentObserver = new ForceLoadContentObserver();
@Override
public void update(Observable observable, Object data)
public void propertyChange(PropertyChangeEvent evt)
{
mContentObserver.onChange(false);
}
@@ -380,7 +380,7 @@ public class VpnProfileDetailActivity extends AppCompatActivity
{
Intent intent = new Intent(VpnProfileDetailActivity.this, SelectedApplicationsActivity.class);
intent.putExtra(VpnProfileDataSource.KEY_SELECTED_APPS_LIST, new ArrayList<>(mSelectedApps));
intent.putExtra(VpnProfileDataSource.KEY_READ_ONLY, mProfile.isReadOnly());
intent.putExtra(VpnProfileDataSource.KEY_READ_ONLY, mProfile != null && mProfile.isReadOnly());
mSelectApplications.launch(intent);
}
});
@@ -16,7 +16,9 @@
package org.strongswan.android.ui;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
@@ -26,6 +28,7 @@ import android.content.SharedPreferences;
import android.graphics.drawable.Icon;
import android.os.Build;
import android.os.IBinder;
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
@@ -127,6 +130,7 @@ public class VpnTileService extends TileService implements VpnStateService.VpnSt
return mDataSource != null ? mDataSource.getVpnProfile(uuid) : null;
}
@SuppressLint("StartActivityAndCollapseDeprecated")
@Override
public void onClick()
{
@@ -177,10 +181,26 @@ public class VpnTileService extends TileService implements VpnStateService.VpnSt
if (profile.getVpnType().has(VpnType.VpnTypeFeature.USER_PASS) &&
profile.getPassword() == null)
{ /* the user will have to enter the password, so collapse the drawer */
startActivityAndCollapse(intent);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
{
startActivityAndCollapse(PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE));
}
else
{
startActivityAndCollapse(intent);
}
}
else
{
/* a bug in Android 14+ requires us to request this permission in
* order to start the activity from this "background" service */
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && !Settings.canDrawOverlays(this))
{
Intent permIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
permIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityAndCollapse(PendingIntent.getActivity(this, 0, permIntent, PendingIntent.FLAG_IMMUTABLE));
return;
}
startActivity(intent);
}
return;
@@ -188,7 +208,14 @@ public class VpnTileService extends TileService implements VpnStateService.VpnSt
}
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityAndCollapse(intent);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
{
startActivityAndCollapse(PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE));
}
else
{
startActivityAndCollapse(intent);
}
}
@Override
@@ -16,6 +16,8 @@
package org.strongswan.android.ui.widget;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.Editable;
@@ -33,8 +35,6 @@ import com.google.android.material.textfield.TextInputLayout;
import org.strongswan.android.R;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import androidx.core.view.ViewPropertyAnimatorListenerAdapter;
/**
* Layout that extends {@link TextInputLayout} with a helper text
@@ -113,8 +113,8 @@ public class TextInputLayoutHelper extends TextInputLayout
showHelper(hasFocus);
}
});
ViewCompat.setPaddingRelative(mHelperContainer, ViewCompat.getPaddingStart(text),
0, ViewCompat.getPaddingEnd(text), text.getPaddingBottom());
mHelperContainer.setPaddingRelative(text.getPaddingStart(), 0,
text.getPaddingEnd(), text.getPaddingBottom());
}
}
}
@@ -158,27 +158,27 @@ public class TextInputLayoutHelper extends TextInputLayout
}
if (show)
{
ViewCompat.animate(mHelperContainer)
mHelperContainer.animate()
.alpha(1f)
.setDuration(200)
.setListener(new ViewPropertyAnimatorListenerAdapter() {
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(View view)
public void onAnimationStart(Animator animation)
{
view.setVisibility(View.VISIBLE);
mHelperContainer.setVisibility(View.VISIBLE);
}
}).start();
}
else
{
ViewCompat.animate(mHelperContainer)
mHelperContainer.animate()
.alpha(0f)
.setDuration(200)
.setListener(new ViewPropertyAnimatorListenerAdapter() {
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(View view)
public void onAnimationEnd(Animator animation)
{
view.setVisibility(View.INVISIBLE);
mHelperContainer.setVisibility(View.INVISIBLE);
}
}).start();
}
@@ -1,3 +1,9 @@
# 2.5.2 #
- Ziel-SDK auf Android 14 erhöht
- Wegen eines Bugs in Android 14 ist eine zusätzliche Permission ist nötig, um von der Status-Kachel eine Verbindung im Hintergrund zu starten
- Fixt einen Crash beim Öffnen der Liste installierter Apps in neuen Profilen
# 2.5.1 #
- Fix für existierende Verknüpfungen und Automatisierung via Intents
@@ -1,3 +1,9 @@
# 2.5.2 #
- Increased target SDK to Android 14
- Due to a bug in Android 14, a new permission is necessary to start a profile in the background from the status tile
- Fix crash when listing installed apps for new profiles
# 2.5.1 #
- Fix for existing shortcuts and automation via Intents
@@ -39,7 +39,7 @@
<!-- Managed configuration, VPN profile -->
<string name="managed_config_uuid_title">Unique identifier</string>
<string name="managed_config_uuid_description">Unique identifier of the VPN profile. Version 4 UUIDs (random-generated) are recommended</string>
<string name="managed_config_name_title">@string/profile_name_label</string>
<string name="managed_config_name_title">@string/profile_name_label_simple</string>
<string name="managed_config_name_description">@string/profile_name_hint</string>
<string name="managed_config_vpn_type_title">@string/profile_vpn_type_label</string>
<string name="managed_config_vpn_type_description">The type of client authentication used by the VPN profile</string>
@@ -39,7 +39,7 @@
<!-- Managed configuration, VPN profile -->
<string name="managed_config_uuid_title">Unique identifier</string>
<string name="managed_config_uuid_description">Unique identifier of the VPN profile. Version 4 UUIDs (random-generated) are recommended</string>
<string name="managed_config_name_title">@string/profile_name_label</string>
<string name="managed_config_name_title">@string/profile_name_label_simple</string>
<string name="managed_config_name_description">@string/profile_name_hint</string>
<string name="managed_config_vpn_type_title">@string/profile_vpn_type_label</string>
<string name="managed_config_vpn_type_description">The type of client authentication used by the VPN profile</string>
@@ -39,7 +39,7 @@
<!-- Managed configuration, VPN profile -->
<string name="managed_config_uuid_title">Unique identifier</string>
<string name="managed_config_uuid_description">Unique identifier of the VPN profile. Version 4 UUIDs (random-generated) are recommended</string>
<string name="managed_config_name_title">@string/profile_name_label</string>
<string name="managed_config_name_title">@string/profile_name_label_simple</string>
<string name="managed_config_name_description">@string/profile_name_hint</string>
<string name="managed_config_vpn_type_title">@string/profile_vpn_type_label</string>
<string name="managed_config_vpn_type_description">The type of client authentication used by the VPN profile</string>
@@ -39,7 +39,7 @@
<!-- Managed configuration, VPN profile -->
<string name="managed_config_uuid_title">Unique identifier</string>
<string name="managed_config_uuid_description">Unique identifier of the VPN profile. Version 4 UUIDs (random-generated) are recommended</string>
<string name="managed_config_name_title">@string/profile_name_label</string>
<string name="managed_config_name_title">@string/profile_name_label_simple</string>
<string name="managed_config_name_description">@string/profile_name_hint</string>
<string name="managed_config_vpn_type_title">@string/profile_vpn_type_label</string>
<string name="managed_config_vpn_type_description">The type of client authentication used by the VPN profile</string>
@@ -39,7 +39,7 @@
<!-- Managed configuration, VPN profile -->
<string name="managed_config_uuid_title">Unique identifier</string>
<string name="managed_config_uuid_description">Unique identifier of the VPN profile. Version 4 UUIDs (random-generated) are recommended</string>
<string name="managed_config_name_title">@string/profile_name_label</string>
<string name="managed_config_name_title">@string/profile_name_label_simple</string>
<string name="managed_config_name_description">@string/profile_name_hint</string>
<string name="managed_config_vpn_type_title">@string/profile_vpn_type_label</string>
<string name="managed_config_vpn_type_description">The type of client authentication used by the VPN profile</string>
@@ -39,7 +39,7 @@
<!-- Managed configuration, VPN profile -->
<string name="managed_config_uuid_title">Unique identifier</string>
<string name="managed_config_uuid_description">Unique identifier of the VPN profile. Version 4 UUIDs (random-generated) are recommended</string>
<string name="managed_config_name_title">@string/profile_name_label</string>
<string name="managed_config_name_title">@string/profile_name_label_simple</string>
<string name="managed_config_name_description">@string/profile_name_hint</string>
<string name="managed_config_vpn_type_title">@string/profile_vpn_type_label</string>
<string name="managed_config_vpn_type_description">The type of client authentication used by the VPN profile</string>
@@ -39,7 +39,7 @@
<!-- Managed configuration, VPN profile -->
<string name="managed_config_uuid_title">Unique identifier</string>
<string name="managed_config_uuid_description">Unique identifier of the VPN profile. Version 4 UUIDs (random-generated) are recommended</string>
<string name="managed_config_name_title">@string/profile_name_label</string>
<string name="managed_config_name_title">@string/profile_name_label_simple</string>
<string name="managed_config_name_description">@string/profile_name_hint</string>
<string name="managed_config_vpn_type_title">@string/profile_vpn_type_label</string>
<string name="managed_config_vpn_type_description">The type of client authentication used by the VPN profile</string>
+1 -1
View File
@@ -4,7 +4,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.2.0'
classpath 'com.android.tools.build:gradle:8.5.1'
}
}
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip