[app] Bump minSdkVersion to 23

This is done, because index v2 is signed with apksigner --min-sdk-version 23 by fdroidserver. So to ensure that the client will always be able to verify a v2 index, we force clients to run SDK 23 at least. If they were running 22 and apksigner ever upgrades to incompatible signing algorithms, those clients would get locked out.
This commit is contained in:
Torsten Grote 2022-09-12 14:04:58 -03:00 committed by Hans-Christoph Steiner
parent 6a805c464e
commit 3368519677
31 changed files with 15 additions and 106 deletions

View File

@ -144,7 +144,7 @@ errorprone:
<<: *test-template
<<: *kvm-connected-template
kvm 22 default x86:
kvm 23 default x86:
<<: *test-template
<<: *kvm-template

View File

@ -25,7 +25,7 @@ android {
versionName getVersionName()
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
minSdkVersion 22
minSdkVersion 23
//noinspection ExpiredTargetSdkVersion
targetSdkVersion 25
/*

View File

@ -130,7 +130,7 @@ final public class WifiApControl {
// the actual class when first called.
public static WifiApControl getInstance(Context context) {
if (instance == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.System.canWrite(context)) {
if (!Settings.System.canWrite(context)) {
Log.e(TAG, "6.0 or later, but haven't been granted WRITE_SETTINGS!");
return null;
}
@ -139,36 +139,8 @@ final public class WifiApControl {
return instance;
}
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
private static String getDeviceName(WifiManager wifiManager) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Log.w(TAG, "6.0 or later, unaccessible MAC - falling back to the default device name: " + FALLBACK_DEVICE);
return FALLBACK_DEVICE;
}
@SuppressLint("HardwareIds")
String macString = wifiManager.getConnectionInfo().getMacAddress();
if (macString == null) {
Log.w(TAG, "MAC Address not found - Wi-Fi disabled? Falling back to the default device name: " + FALLBACK_DEVICE);
return FALLBACK_DEVICE;
}
byte[] macBytes = macAddressToByteArray(macString);
try {
Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
while (ifaces.hasMoreElements()) {
NetworkInterface iface = ifaces.nextElement();
byte[] hardwareAddress = iface.getHardwareAddress();
if (hardwareAddress != null && Arrays.equals(macBytes, hardwareAddress)) {
return iface.getName();
}
}
} catch (IOException e) {
Log.e(TAG, "", e);
}
Log.w(TAG, "None found - falling back to the default device name: " + FALLBACK_DEVICE);
Log.w(TAG, "6.0 or later, unaccessible MAC - falling back to the default device name: " + FALLBACK_DEVICE);
return FALLBACK_DEVICE;
}

View File

@ -306,9 +306,6 @@ public class BonjourManager {
* if the device is too old.
*/
public static boolean isVpnActive(Context context) {
if (Build.VERSION.SDK_INT < 23) {
return false;
}
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
Network activeNetwork = cm.getActiveNetwork();
NetworkCapabilities caps = cm.getNetworkCapabilities(activeNetwork);

View File

@ -46,7 +46,6 @@ public class SelectAppsView extends SwapView {
super(context, attrs, defStyleAttr);
}
@TargetApi(21)
public SelectAppsView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}

View File

@ -53,7 +53,6 @@ public class StartSwapView extends SwapView {
super(context, attrs, defStyleAttr);
}
@TargetApi(21)
public StartSwapView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}

View File

@ -69,7 +69,6 @@ public class SwapSuccessView extends SwapView {
super(context, attrs, defStyleAttr);
}
@TargetApi(21)
public SwapSuccessView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}

View File

@ -50,7 +50,6 @@ public class SwapView extends RelativeLayout {
a.recycle();
}
@TargetApi(21)
public SwapView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
final TypedArray a = context.obtainStyledAttributes(

View File

@ -495,7 +495,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
public void onClick(DialogInterface dialog, int which) {
if (Build.VERSION.SDK_INT >= 26) {
showTetheringSettings();
} else if (Build.VERSION.SDK_INT >= 23 && !Settings.System.canWrite(getBaseContext())) {
} else if (!Settings.System.canWrite(getBaseContext())) {
requestWriteSettingsPermission();
} else {
setupWifiAP();
@ -661,7 +661,6 @@ public class SwapWorkflowActivity extends AppCompatActivity {
startActivity(intent);
}
@TargetApi(23)
public void requestWriteSettingsPermission() {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS,
Uri.parse("package:" + getPackageName()));
@ -670,8 +669,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
}
public void sendFDroid() {
if (bluetoothAdapter == null
|| Build.VERSION.SDK_INT >= 23 // TODO make Bluetooth work with content:// URIs
if (bluetoothAdapter == null // TODO make Bluetooth work with content:// URIs
|| (!bluetoothAdapter.isEnabled() && LocalHTTPDManager.isAlive())) {
inflateSwapView(R.layout.swap_send_fdroid);
} else {
@ -809,7 +807,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
}
}
} else if (requestCode == REQUEST_WRITE_SETTINGS_PERMISSION) {
if (Build.VERSION.SDK_INT >= 23 && Settings.System.canWrite(this)) {
if (Settings.System.canWrite(this)) {
setupWifiAP();
}
} else if (requestCode == REQUEST_BLUETOOTH_ENABLE_FOR_SWAP) {

View File

@ -73,7 +73,6 @@ import androidx.documentfile.provider.DocumentFile;
* @see <a href="https://developer.android.com/training/articles/scoped-directory-access.html">Using Scoped Directory Access</a>
* @see <a href="https://developer.android.com/guide/topics/providers/document-provider.html">Open Files using Storage Access Framework</a>
*/
@TargetApi(21)
public class TreeUriScannerIntentService extends IntentService {
public static final String TAG = "TreeUriScannerIntentSer";

View File

@ -45,7 +45,6 @@ public class UsbDeviceAttachedReceiver extends BroadcastReceiver {
public static final String TAG = "UsbDeviceAttachedReceiv";
@RequiresApi(api = 19)
@Override
public void onReceive(final Context context, Intent intent) {

View File

@ -45,7 +45,6 @@ public class UsbDeviceDetachedReceiver extends BroadcastReceiver {
static final HashMap<Uri, ContentObserver> contentObservers = new HashMap<>();
@RequiresApi(api = 19)
@Override
public void onReceive(Context context, Intent intent) {
if (intent == null || TextUtils.isEmpty(intent.getAction())

View File

@ -85,9 +85,7 @@ public class NearbyViewBinder {
@Override
public void onClick(View v) {
final String coarseLocation = Manifest.permission.ACCESS_COARSE_LOCATION;
if (Build.VERSION.SDK_INT >= 23
&& PackageManager.PERMISSION_GRANTED
!= ContextCompat.checkSelfPermission(activity, coarseLocation)) {
if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(activity, coarseLocation)) {
ActivityCompat.requestPermissions(activity, new String[]{coarseLocation},
MainActivity.REQUEST_LOCATION_PERMISSIONS);
} else {
@ -119,13 +117,9 @@ public class NearbyViewBinder {
Button requestReadExternalStorage = swapView.findViewById(R.id.request_read_external_storage_button);
requestReadExternalStorage.setVisibility(View.VISIBLE);
requestReadExternalStorage.setOnClickListener(new View.OnClickListener() {
@RequiresApi(api = 21)
@Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= 23
&& (externalStorage == null || !externalStorage.canRead())
&& PackageManager.PERMISSION_GRANTED
!= ContextCompat.checkSelfPermission(activity, writeExternalStorage)) {
if ((externalStorage == null || !externalStorage.canRead()) && PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(activity, writeExternalStorage)) {
ActivityCompat.requestPermissions(activity, new String[]{writeExternalStorage},
MainActivity.REQUEST_STORAGE_PERMISSIONS);
} else {

View File

@ -158,7 +158,7 @@ public class FDroidApp extends Application implements androidx.work.Configuratio
default:
// `Set by Battery Saver` for Q above (inclusive), `Use system default` for Q below
// https://medium.com/androiddevelopers/appcompat-v23-2-daynight-d10f90c83e94
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
if (Build.VERSION.SDK_INT <= 28) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);

View File

@ -1,6 +1,5 @@
package org.fdroid.fdroid;
import android.annotation.TargetApi;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.res.Configuration;
@ -79,7 +78,6 @@ public final class Languages {
* or different than the current system-wide locale. The preference is cleared
* if the language matches the system-wide locale or "System Default" is chosen.
*/
@TargetApi(17)
public static void setLanguage(final ContextWrapper contextWrapper) {
if (Build.VERSION.SDK_INT >= 24) {
Utils.debugLog(TAG, "Languages.setLanguage() ignored on >= android-24");

View File

@ -1,6 +1,5 @@
package org.fdroid.fdroid;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@ -31,7 +30,6 @@ public class NfcHelper {
return false;
}
@TargetApi(16)
public static void setAndroidBeam(AppCompatActivity activity, String packageName) {
PackageManager pm = activity.getPackageManager();
NfcAdapter nfcAdapter = getAdapter(activity);
@ -49,7 +47,6 @@ public class NfcHelper {
}
}
@TargetApi(16)
public static void disableAndroidBeam(AppCompatActivity activity) {
NfcAdapter nfcAdapter = getAdapter(activity);
if (nfcAdapter != null) {

View File

@ -1,6 +1,5 @@
package org.fdroid.fdroid;
import android.annotation.TargetApi;
import android.content.Intent;
import android.nfc.NfcAdapter;
import android.os.Bundle;
@ -18,7 +17,6 @@ public class NfcNotEnabledActivity extends AppCompatActivity {
* needed for NDEF. Therefore, we detect the current state of NFC,
* and steer the user accordingly.
*/
@TargetApi(16)
private void doOnJellybean(Intent intent) {
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (nfcAdapter == null) {

View File

@ -1,6 +1,5 @@
package org.fdroid.fdroid;
import android.annotation.TargetApi;
import android.app.job.JobParameters;
import android.app.job.JobService;
@ -10,7 +9,6 @@ import android.app.job.JobService;
*
* @see <a href="https://developer.android.com/about/versions/android-5.0.html#Power">Project Volta: Scheduling jobs</a>
*/
@TargetApi(21)
public class UpdateJobService extends JobService {
@Override
public boolean onStartJob(final JobParameters params) {

View File

@ -1,7 +1,5 @@
package org.fdroid.fdroid.compat;
import android.annotation.TargetApi;
import android.os.Build;
import android.system.ErrnoException;
import android.util.Log;
@ -12,8 +10,6 @@ import org.fdroid.fdroid.data.SanitizedFile;
import java.io.IOException;
import java.lang.reflect.Method;
import androidx.annotation.RequiresApi;
/**
* This class works only with {@link SanitizedFile} instances to enforce
* filtering of the file names from files downloaded from the internet.
@ -34,10 +30,8 @@ public class FileCompat {
* not attempt to load this class at runtime. Otherwise, using the Os.symlink method will cause
* a VerifyError to be thrown at runtime when the FileCompat class is first used.
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
private static class Symlink21 {
@TargetApi(21)
void symlink(SanitizedFile source, SanitizedFile dest) {
try {
android.system.Os.symlink(source.getAbsolutePath(), dest.getAbsolutePath());
@ -48,7 +42,6 @@ public class FileCompat {
}
@TargetApi(21)
static void symlinkOs(SanitizedFile source, SanitizedFile dest) {
new Symlink21().symlink(source, dest);
}

View File

@ -1,7 +1,6 @@
package org.fdroid.fdroid.data;
import android.Manifest;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.os.Build;
@ -294,7 +293,6 @@ public class Apk implements Comparable<Apk>, Parcelable {
}
@Override
@TargetApi(19)
public int compareTo(@NonNull Apk apk) {
return Long.compare(versionCode, apk.versionCode);
}

View File

@ -61,7 +61,7 @@ public class ApkFileProvider extends FileProvider {
public static Uri getSafeUri(Context context, PackageInfo packageInfo) throws IOException {
SanitizedFile tempApkFile = ApkCache.copyInstalledApkToFiles(context, packageInfo);
return getSafeUri(context, tempApkFile, Build.VERSION.SDK_INT >= 23);
return getSafeUri(context, tempApkFile, true);
}
/**

View File

@ -118,11 +118,9 @@ public class ObfInstallerService extends IntentService {
} else {
intent.setDataAndType(FileProvider.getUriForFile(this, Installer.AUTHORITY, file), mimeType);
}
if (Build.VERSION.SDK_INT >= 23) {
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
}
if (intent != null && intent.resolveActivity(getPackageManager()) != null) {
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
sendBroadcastInstall(Installer.ACTION_INSTALL_COMPLETE, canonicalUri, apk, null);
} else {

View File

@ -19,7 +19,6 @@
package org.fdroid.fdroid.privileged.views;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
@ -115,7 +114,6 @@ public class AppSecurityPermissions {
super(info);
}
@TargetApi(22)
public Drawable loadGroupIcon(Context context, PackageManager pm) {
Drawable iconDrawable;
if (icon != 0) {
@ -341,7 +339,6 @@ public class AppSecurityPermissions {
* doesn't currently hold this permission. On older devices that don't support
* this concept, permissions are never "new permissions".
*/
@TargetApi(16)
private static boolean isNewPermission(PackageInfo installedPkgInfo, int existingFlags) {
if (installedPkgInfo == null) {
return false;
@ -423,7 +420,6 @@ public class AppSecurityPermissions {
return permView;
}
@TargetApi(23)
private boolean isDisplayablePermission(PermissionInfo pInfo, int existingReqFlags) {
final int base = pInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
final boolean isNormal = base == PermissionInfo.PROTECTION_NORMAL;

View File

@ -4,14 +4,11 @@ import android.content.Context;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import android.os.Build;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.content.ContextCompat;
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public class CameraCharacteristicsMinApiLevel21 extends CameraCharacteristicsChecker {
private static final String TAG = "CameraCharMinApiLevel21";

View File

@ -22,7 +22,6 @@
package org.fdroid.fdroid.views;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
@ -775,7 +774,6 @@ public class AppDetailsActivity extends AppCompatActivity
NfcHelper.disableAndroidBeam(this);
}
@TargetApi(18)
private BluetoothAdapter getBluetoothAdapter() {
// to use the new, recommended way of getting the adapter
// http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html

View File

@ -1,6 +1,5 @@
package org.fdroid.fdroid.views;
import android.annotation.TargetApi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@ -176,7 +175,6 @@ public class RepoDetailsActivity extends AppCompatActivity {
super.onDestroy();
}
@TargetApi(14)
private void setNfc() {
if (NfcHelper.setPushMessage(this, Utils.getSharingUri(repo))) {
findViewById(android.R.id.content).post(new Runnable() {
@ -284,7 +282,6 @@ public class RepoDetailsActivity extends AppCompatActivity {
return true;
}
@TargetApi(16)
private void prepareNfcMenuItems(Menu menu) {
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
MenuItem menuItem = menu.findItem(R.id.menu_enable_nfc);

View File

@ -1,6 +1,5 @@
package org.fdroid.fdroid.views;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@ -150,7 +149,6 @@ public class ScreenShotsActivity extends AppCompatActivity {
}
}
@TargetApi(11)
public static class DepthPageTransformer implements ViewPager.PageTransformer {
public void transformPage(@NonNull View view, float position) {

View File

@ -1,6 +1,5 @@
package org.fdroid.fdroid.views.apps;
import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
@ -119,7 +118,6 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
@Nullable
private Disposable disposable;
@TargetApi(21)
public AppListItemController(final AppCompatActivity activity, View itemView) {
super(itemView);
this.activity = activity;

View File

@ -1,6 +1,5 @@
package org.fdroid.fdroid.views.apps;
import android.annotation.TargetApi;
import android.content.Context;
import android.text.Editable;
import android.text.Spanned;
@ -124,7 +123,6 @@ public class CategoryTextWatcher implements TextWatcher {
* In addition, also adds a {@link TtsSpan} to indicate to screen readers that the category
* span has semantic meaning representing a category.
*/
@TargetApi(21)
private void prepareSpans(Editable textToSpannify) {
if (textToSpannify == null) {
return;

View File

@ -1,6 +1,5 @@
package org.fdroid.fdroid.views.main;
import android.annotation.TargetApi;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.FrameLayout;
@ -40,7 +39,6 @@ public class SettingsView extends FrameLayout {
setId(R.id.preference_fragment_parent);
}
@TargetApi(21)
public SettingsView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setId(R.id.preference_fragment_parent);

View File

@ -1,7 +1,6 @@
package org.fdroid.fdroid.work;
import android.content.Context;
import android.os.Build;
import android.os.Process;
import android.system.ErrnoException;
import android.system.Os;
@ -18,7 +17,6 @@ import java.util.List;
import java.util.concurrent.TimeUnit;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.work.Constraints;
import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.ExistingWorkPolicy;
@ -63,9 +61,7 @@ public class CleanCacheWorker extends Worker {
final Constraints.Builder constraintsBuilder = new Constraints.Builder()
.setRequiresCharging(true)
.setRequiresBatteryNotLow(true);
if (Build.VERSION.SDK_INT >= 23) {
constraintsBuilder.setRequiresDeviceIdle(true);
}
constraintsBuilder.setRequiresDeviceIdle(true);
final PeriodicWorkRequest cleanCache =
new PeriodicWorkRequest.Builder(CleanCacheWorker.class, interval, TimeUnit.MILLISECONDS)
.setConstraints(constraintsBuilder.build())
@ -217,7 +213,6 @@ public class CleanCacheWorker extends Worker {
Utils.debugLog(TAG, "Deleted file: " + file);
}
@RequiresApi(api = 21)
private static class Impl21 {
/**
* Recursively delete files in {@code f} that were last used