浏览代码

Require Android 8+

Given that the next stable version of Chrome (120) will require Android 8+, it's
inevitable that the WebView functionality will gradually break. As always, newer
OS versions are recommended for better support with evolving Internet technologies.

According to https://apilevels.com/, Android 8+ still covers 93.7% of Android users.
arkon 1 年之前
父节点
当前提交
64c50c1283

+ 1 - 5
app/src/main/java/eu/kanade/domain/ui/UiPreferences.kt

@@ -1,6 +1,5 @@
 package eu.kanade.domain.ui
 
-import android.os.Build
 import eu.kanade.domain.ui.model.AppTheme
 import eu.kanade.domain.ui.model.TabletUiMode
 import eu.kanade.domain.ui.model.ThemeMode
@@ -16,10 +15,7 @@ class UiPreferences(
     private val preferenceStore: PreferenceStore,
 ) {
 
-    fun themeMode() = preferenceStore.getEnum(
-        "pref_theme_mode_key",
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { ThemeMode.SYSTEM } else { ThemeMode.LIGHT },
-    )
+    fun themeMode() = preferenceStore.getEnum("pref_theme_mode_key", ThemeMode.SYSTEM)
 
     fun appTheme() = preferenceStore.getEnum(
         "pref_app_theme",

+ 1 - 7
app/src/main/java/eu/kanade/presentation/manga/components/MangaCoverDialog.kt

@@ -2,7 +2,6 @@ package eu.kanade.presentation.manga.components
 
 import android.graphics.Bitmap
 import android.graphics.drawable.BitmapDrawable
-import android.os.Build
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Row
@@ -176,14 +175,9 @@ fun MangaCoverDialog(
                                 // Copy bitmap in case it came from memory cache
                                 // Because SSIV needs to thoroughly read the image
                                 val copy = (drawable as? BitmapDrawable)?.let {
-                                    val config = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-                                        Bitmap.Config.HARDWARE
-                                    } else {
-                                        Bitmap.Config.ARGB_8888
-                                    }
                                     BitmapDrawable(
                                         view.context.resources,
-                                        it.bitmap.copy(config, false),
+                                        it.bitmap.copy(Bitmap.Config.HARDWARE, false),
                                     )
                                 } ?: drawable
                                 view.setImage(copy, ReaderPageImageView.Config(zoomDuration = 500))

+ 44 - 57
app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt

@@ -3,7 +3,6 @@ package eu.kanade.presentation.more.settings.screen
 import android.annotation.SuppressLint
 import android.content.ActivityNotFoundException
 import android.content.Intent
-import android.os.Build
 import android.provider.Settings
 import android.webkit.WebStorage
 import android.webkit.WebView
@@ -81,62 +80,50 @@ object SettingsAdvancedScreen : SearchableSettings {
         val basePreferences = remember { Injekt.get<BasePreferences>() }
         val networkPreferences = remember { Injekt.get<NetworkPreferences>() }
 
-        return buildList {
-            addAll(
-                listOf(
-                    Preference.PreferenceItem.SwitchPreference(
-                        pref = basePreferences.acraEnabled(),
-                        title = stringResource(R.string.pref_enable_acra),
-                        subtitle = stringResource(R.string.pref_acra_summary),
-                        enabled = isPreviewBuildType || isReleaseBuildType,
-                    ),
-                    Preference.PreferenceItem.TextPreference(
-                        title = stringResource(R.string.pref_dump_crash_logs),
-                        subtitle = stringResource(R.string.pref_dump_crash_logs_summary),
-                        onClick = {
-                            scope.launch {
-                                CrashLogUtil(context).dumpLogs()
-                            }
-                        },
-                    ),
-                    Preference.PreferenceItem.SwitchPreference(
-                        pref = networkPreferences.verboseLogging(),
-                        title = stringResource(R.string.pref_verbose_logging),
-                        subtitle = stringResource(R.string.pref_verbose_logging_summary),
-                        onValueChanged = {
-                            context.toast(R.string.requires_app_restart)
-                            true
-                        },
-                    ),
-                    Preference.PreferenceItem.TextPreference(
-                        title = stringResource(R.string.pref_debug_info),
-                        onClick = { navigator.push(DebugInfoScreen()) },
-                    ),
-                ),
-            )
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-                add(
-                    Preference.PreferenceItem.TextPreference(
-                        title = stringResource(R.string.pref_manage_notifications),
-                        onClick = {
-                            val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {
-                                putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
-                            }
-                            context.startActivity(intent)
-                        },
-                    ),
-                )
-            }
-            addAll(
-                listOf(
-                    getBackgroundActivityGroup(),
-                    getDataGroup(),
-                    getNetworkGroup(networkPreferences = networkPreferences),
-                    getLibraryGroup(),
-                    getExtensionsGroup(basePreferences = basePreferences),
-                ),
-            )
-        }
+        return listOf(
+            Preference.PreferenceItem.SwitchPreference(
+                pref = basePreferences.acraEnabled(),
+                title = stringResource(R.string.pref_enable_acra),
+                subtitle = stringResource(R.string.pref_acra_summary),
+                enabled = isPreviewBuildType || isReleaseBuildType,
+            ),
+            Preference.PreferenceItem.TextPreference(
+                title = stringResource(R.string.pref_dump_crash_logs),
+                subtitle = stringResource(R.string.pref_dump_crash_logs_summary),
+                onClick = {
+                    scope.launch {
+                        CrashLogUtil(context).dumpLogs()
+                    }
+                },
+            ),
+            Preference.PreferenceItem.SwitchPreference(
+                pref = networkPreferences.verboseLogging(),
+                title = stringResource(R.string.pref_verbose_logging),
+                subtitle = stringResource(R.string.pref_verbose_logging_summary),
+                onValueChanged = {
+                    context.toast(R.string.requires_app_restart)
+                    true
+                },
+            ),
+            Preference.PreferenceItem.TextPreference(
+                title = stringResource(R.string.pref_debug_info),
+                onClick = { navigator.push(DebugInfoScreen()) },
+            ),
+            Preference.PreferenceItem.TextPreference(
+                title = stringResource(R.string.pref_manage_notifications),
+                onClick = {
+                    val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {
+                        putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
+                    }
+                    context.startActivity(intent)
+                },
+            ),
+            getBackgroundActivityGroup(),
+            getDataGroup(),
+            getNetworkGroup(networkPreferences = networkPreferences),
+            getLibraryGroup(),
+            getExtensionsGroup(basePreferences = basePreferences),
+        )
     }
 
     @Composable

+ 5 - 13
app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAppearanceScreen.kt

@@ -2,7 +2,6 @@ package eu.kanade.presentation.more.settings.screen
 
 import android.app.Activity
 import android.content.Context
-import android.os.Build
 import androidx.annotation.StringRes
 import androidx.appcompat.app.AppCompatDelegate
 import androidx.compose.runtime.Composable
@@ -81,18 +80,11 @@ object SettingsAppearanceScreen : SearchableSettings {
                 Preference.PreferenceItem.ListPreference(
                     pref = themeModePref,
                     title = stringResource(R.string.pref_theme_mode),
-                    entries = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-                        mapOf(
-                            ThemeMode.SYSTEM to stringResource(R.string.theme_system),
-                            ThemeMode.LIGHT to stringResource(R.string.theme_light),
-                            ThemeMode.DARK to stringResource(R.string.theme_dark),
-                        )
-                    } else {
-                        mapOf(
-                            ThemeMode.LIGHT to stringResource(R.string.theme_light),
-                            ThemeMode.DARK to stringResource(R.string.theme_dark),
-                        )
-                    },
+                    entries = mapOf(
+                        ThemeMode.SYSTEM to stringResource(R.string.theme_system),
+                        ThemeMode.LIGHT to stringResource(R.string.theme_light),
+                        ThemeMode.DARK to stringResource(R.string.theme_dark),
+                    ),
                 ),
                 Preference.PreferenceItem.CustomPreference(
                     title = stringResource(R.string.pref_app_theme),

+ 0 - 1
app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt

@@ -58,7 +58,6 @@ object SettingsReaderScreen : SearchableSettings {
                 pref = readerPref.trueColor(),
                 title = stringResource(R.string.pref_true_color),
                 subtitle = stringResource(R.string.pref_true_color_summary),
-                enabled = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O,
             ),
             Preference.PreferenceItem.SwitchPreference(
                 pref = readerPref.pageTransitions(),

+ 1 - 0
app/src/main/java/eu/kanade/presentation/util/Navigator.kt

@@ -79,6 +79,7 @@ fun ScreenTransition(
         targetState = navigator.lastItem,
         transitionSpec = transition,
         modifier = modifier,
+        label = "ScreenTransition",
     ) { screen ->
         navigator.saveableState("transition", screen) {
             content(screen)

+ 12 - 15
app/src/main/java/eu/kanade/tachiyomi/App.kt

@@ -171,22 +171,19 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
     }
 
     override fun getPackageName(): String {
-        // This causes freezes in Android 6/7 for some reason
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-            try {
-                // Override the value passed as X-Requested-With in WebView requests
-                val stackTrace = Looper.getMainLooper().thread.stackTrace
-                val chromiumElement = stackTrace.find {
-                    it.className.equals(
-                        "org.chromium.base.BuildInfo",
-                        ignoreCase = true,
-                    )
-                }
-                if (chromiumElement?.methodName.equals("getAll", ignoreCase = true)) {
-                    return WebViewUtil.SPOOF_PACKAGE_NAME
-                }
-            } catch (e: Exception) {
+        try {
+            // Override the value passed as X-Requested-With in WebView requests
+            val stackTrace = Looper.getMainLooper().thread.stackTrace
+            val chromiumElement = stackTrace.find {
+                it.className.equals(
+                    "org.chromium.base.BuildInfo",
+                    ignoreCase = true,
+                )
             }
+            if (chromiumElement?.methodName.equals("getAll", ignoreCase = true)) {
+                return WebViewUtil.SPOOF_PACKAGE_NAME
+            }
+        } catch (e: Exception) {
         }
         return super.getPackageName()
     }

+ 1 - 3
app/src/main/java/eu/kanade/tachiyomi/data/coil/TachiyomiImageDecoder.kt

@@ -1,6 +1,5 @@
 package eu.kanade.tachiyomi.data.coil
 
-import android.os.Build
 import androidx.core.graphics.drawable.toDrawable
 import coil.ImageLoader
 import coil.decode.DecodeResult
@@ -48,8 +47,7 @@ class TachiyomiImageDecoder(private val resources: ImageSource, private val opti
                 ImageUtil.findImageType(it)
             }
             return when (type) {
-                ImageUtil.ImageType.AVIF, ImageUtil.ImageType.JXL -> true
-                ImageUtil.ImageType.HEIF -> Build.VERSION.SDK_INT < Build.VERSION_CODES.O
+                ImageUtil.ImageType.AVIF, ImageUtil.ImageType.JXL, ImageUtil.ImageType.HEIF -> true
                 else -> false
             }
         }

+ 11 - 14
app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt

@@ -5,7 +5,6 @@ import android.content.BroadcastReceiver
 import android.content.Context
 import android.content.Intent
 import android.net.Uri
-import android.os.Build
 import androidx.core.net.toUri
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.backup.BackupRestoreJob
@@ -368,20 +367,18 @@ class NotificationReceiver : BroadcastReceiver() {
 
             When programmatically dismissing this notification, the group notification is not automatically dismissed.
              */
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-                val groupKey = context.notificationManager.activeNotifications.find {
-                    it.id == notificationId
-                }?.groupKey
-
-                if (groupId != null && groupId != 0 && groupKey != null && groupKey.isNotEmpty()) {
-                    val notifications = context.notificationManager.activeNotifications.filter {
-                        it.groupKey == groupKey
-                    }
+            val groupKey = context.notificationManager.activeNotifications.find {
+                it.id == notificationId
+            }?.groupKey
 
-                    if (notifications.size == 2) {
-                        context.cancelNotification(groupId)
-                        return
-                    }
+            if (groupId != null && groupId != 0 && !groupKey.isNullOrEmpty()) {
+                val notifications = context.notificationManager.activeNotifications.filter {
+                    it.groupKey == groupKey
+                }
+
+                if (notifications.size == 2) {
+                    context.cancelNotification(groupId)
+                    return
                 }
             }
 

+ 1 - 6
app/src/main/java/eu/kanade/tachiyomi/extension/installer/ShizukuInstaller.kt

@@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.extension.installer
 
 import android.app.Service
 import android.content.pm.PackageManager
-import android.os.Build
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.extension.model.InstallStep
 import eu.kanade.tachiyomi.util.system.getUriSize
@@ -50,11 +49,7 @@ class ShizukuInstaller(private val service: Service) : Installer(service) {
             try {
                 val size = service.getUriSize(entry.uri) ?: throw IllegalStateException()
                 service.contentResolver.openInputStream(entry.uri)!!.use {
-                    val createCommand = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-                        "pm install-create --user current -r -i ${service.packageName} -S $size"
-                    } else {
-                        "pm install-create -r -i ${service.packageName} -S $size"
-                    }
+                    val createCommand = "pm install-create --user current -r -i ${service.packageName} -S $size"
                     val createResult = exec(createCommand)
                     sessionId = SESSION_ID_REGEX.find(createResult.out)?.value
                         ?: throw RuntimeException("Failed to create install session")

+ 1 - 7
app/src/main/java/eu/kanade/tachiyomi/util/storage/FileExtensions.kt

@@ -2,9 +2,7 @@ package eu.kanade.tachiyomi.util.storage
 
 import android.content.Context
 import android.net.Uri
-import android.os.Build
 import androidx.core.content.FileProvider
-import androidx.core.net.toUri
 import eu.kanade.tachiyomi.BuildConfig
 import java.io.File
 
@@ -17,11 +15,7 @@ val Context.cacheImageDir: File
  * @param context context of application
  */
 fun File.getUriCompat(context: Context): Uri {
-    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-        FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", this)
-    } else {
-        this.toUri()
-    }
+    return FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", this)
 }
 
 /**

+ 1 - 2
app/src/main/java/eu/kanade/tachiyomi/util/system/NetworkExtensions.kt

@@ -18,8 +18,7 @@ fun Context.isOnline(): Boolean {
     val networkCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork) ?: return false
     val maxTransport = when {
         Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 -> NetworkCapabilities.TRANSPORT_LOWPAN
-        Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> NetworkCapabilities.TRANSPORT_WIFI_AWARE
-        else -> NetworkCapabilities.TRANSPORT_VPN
+        else -> NetworkCapabilities.TRANSPORT_WIFI_AWARE
     }
     return (NetworkCapabilities.TRANSPORT_CELLULAR..maxTransport).any(networkCapabilities::hasTransport)
 }

+ 1 - 1
buildSrc/src/main/kotlin/AndroidConfig.kt

@@ -1,6 +1,6 @@
 object AndroidConfig {
     const val compileSdk = 34
-    const val minSdk = 23
+    const val minSdk = 26
     const val targetSdk = 29
     const val ndk = "22.1.7171670"
 }

+ 0 - 3
core/src/main/java/eu/kanade/tachiyomi/util/system/WebViewClientCompat.kt

@@ -1,7 +1,5 @@
 package eu.kanade.tachiyomi.util.system
 
-import android.annotation.TargetApi
-import android.os.Build
 import android.webkit.WebResourceError
 import android.webkit.WebResourceRequest
 import android.webkit.WebResourceResponse
@@ -28,7 +26,6 @@ abstract class WebViewClientCompat : WebViewClient() {
     ) {
     }
 
-    @TargetApi(Build.VERSION_CODES.N)
     final override fun shouldOverrideUrlLoading(
         view: WebView,
         request: WebResourceRequest,

+ 5 - 10
core/src/main/java/eu/kanade/tachiyomi/util/system/WebViewUtil.kt

@@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.util.system
 import android.annotation.SuppressLint
 import android.content.Context
 import android.content.pm.PackageManager
-import android.os.Build
 import android.webkit.CookieManager
 import android.webkit.WebSettings
 import android.webkit.WebView
@@ -35,15 +34,11 @@ object WebViewUtil {
     }
 
     fun getVersion(context: Context): String {
-        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-            val webView = WebView.getCurrentWebViewPackage() ?: return "how did you get here?"
-            val pm = context.packageManager
-            val label = webView.applicationInfo.loadLabel(pm)
-            val version = webView.versionName
-            "$label $version"
-        } else {
-            "Unknown"
-        }
+        val webView = WebView.getCurrentWebViewPackage() ?: return "how did you get here?"
+        val pm = context.packageManager
+        val label = webView.applicationInfo.loadLabel(pm)
+        val version = webView.versionName
+        return "$label $version"
     }
 
     fun supportsWebView(context: Context): Boolean {