Revert "Require Android 8+"

This reverts commit 64c50c1283.

Forgot we need to manage app update checks manually...
This commit is contained in:
arkon 2023-11-04 19:36:25 -04:00
parent 64c50c1283
commit c5e8c9f01f
15 changed files with 143 additions and 84 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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