Make the app Android 8+
@ -3,7 +3,7 @@
|
|||||||
| [![CI](https://github.com/tachiyomiorg/tachiyomi/actions/workflows/build_push.yml/badge.svg)](https://github.com/tachiyomiorg/tachiyomi/actions/workflows/build_push.yml) | [![stable release](https://img.shields.io/github/release/tachiyomiorg/tachiyomi.svg?maxAge=3600&label=download)](https://github.com/tachiyomiorg/tachiyomi/releases) | [![latest preview build](https://img.shields.io/github/v/release/tachiyomiorg/tachiyomi-preview.svg?maxAge=3600&label=download)](https://github.com/tachiyomiorg/tachiyomi-preview/releases) | [![Translation status](https://hosted.weblate.org/widgets/tachiyomi/-/svg-badge.svg)](https://hosted.weblate.org/engage/tachiyomi/?utm_source=widget) | [![Discord](https://img.shields.io/discord/1195734228319617024.svg?label=discord&labelColor=7289da&color=2c2f33&style=flat)](https://discord.gg/mihon) |
|
| [![CI](https://github.com/tachiyomiorg/tachiyomi/actions/workflows/build_push.yml/badge.svg)](https://github.com/tachiyomiorg/tachiyomi/actions/workflows/build_push.yml) | [![stable release](https://img.shields.io/github/release/tachiyomiorg/tachiyomi.svg?maxAge=3600&label=download)](https://github.com/tachiyomiorg/tachiyomi/releases) | [![latest preview build](https://img.shields.io/github/v/release/tachiyomiorg/tachiyomi-preview.svg?maxAge=3600&label=download)](https://github.com/tachiyomiorg/tachiyomi-preview/releases) | [![Translation status](https://hosted.weblate.org/widgets/tachiyomi/-/svg-badge.svg)](https://hosted.weblate.org/engage/tachiyomi/?utm_source=widget) | [![Discord](https://img.shields.io/discord/1195734228319617024.svg?label=discord&labelColor=7289da&color=2c2f33&style=flat)](https://discord.gg/mihon) |
|
||||||
|
|
||||||
# ![app icon](./.github/readme-images/app-icon.png)Mihon
|
# ![app icon](./.github/readme-images/app-icon.png)Mihon
|
||||||
Mihon is a free and open source manga reader for Android 6.0 and above.
|
Mihon is a free and open source manga reader for Android 8.0 and above.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 13 KiB |
@ -1,6 +1,5 @@
|
|||||||
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
|
||||||
@ -16,10 +15,7 @@ class UiPreferences(
|
|||||||
private val preferenceStore: PreferenceStore,
|
private val preferenceStore: PreferenceStore,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun themeMode() = preferenceStore.getEnum(
|
fun themeMode() = preferenceStore.getEnum("pref_theme_mode_key", ThemeMode.SYSTEM)
|
||||||
"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",
|
||||||
|
@ -2,7 +2,6 @@ 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
|
||||||
@ -173,14 +172,9 @@ 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(config, false),
|
it.bitmap.copy(Bitmap.Config.HARDWARE, false),
|
||||||
)
|
)
|
||||||
} ?: drawable
|
} ?: drawable
|
||||||
view.setImage(copy, ReaderPageImageView.Config(zoomDuration = 500))
|
view.setImage(copy, ReaderPageImageView.Config(zoomDuration = 500))
|
||||||
|
@ -3,7 +3,6 @@ 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
|
||||||
@ -84,60 +83,48 @@ 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 buildList {
|
return listOf(
|
||||||
addAll(
|
Preference.PreferenceItem.TextPreference(
|
||||||
listOf(
|
title = stringResource(MR.strings.pref_dump_crash_logs),
|
||||||
Preference.PreferenceItem.TextPreference(
|
subtitle = stringResource(MR.strings.pref_dump_crash_logs_summary),
|
||||||
title = stringResource(MR.strings.pref_dump_crash_logs),
|
onClick = {
|
||||||
subtitle = stringResource(MR.strings.pref_dump_crash_logs_summary),
|
scope.launch {
|
||||||
onClick = {
|
CrashLogUtil(context).dumpLogs()
|
||||||
scope.launch {
|
}
|
||||||
CrashLogUtil(context).dumpLogs()
|
},
|
||||||
}
|
),
|
||||||
},
|
Preference.PreferenceItem.SwitchPreference(
|
||||||
),
|
pref = networkPreferences.verboseLogging(),
|
||||||
Preference.PreferenceItem.SwitchPreference(
|
title = stringResource(MR.strings.pref_verbose_logging),
|
||||||
pref = networkPreferences.verboseLogging(),
|
subtitle = stringResource(MR.strings.pref_verbose_logging_summary),
|
||||||
title = stringResource(MR.strings.pref_verbose_logging),
|
onValueChanged = {
|
||||||
subtitle = stringResource(MR.strings.pref_verbose_logging_summary),
|
context.toast(MR.strings.requires_app_restart)
|
||||||
onValueChanged = {
|
true
|
||||||
context.toast(MR.strings.requires_app_restart)
|
},
|
||||||
true
|
),
|
||||||
},
|
Preference.PreferenceItem.TextPreference(
|
||||||
),
|
title = stringResource(MR.strings.pref_debug_info),
|
||||||
Preference.PreferenceItem.TextPreference(
|
onClick = { navigator.push(DebugInfoScreen()) },
|
||||||
title = stringResource(MR.strings.pref_debug_info),
|
),
|
||||||
onClick = { navigator.push(DebugInfoScreen()) },
|
Preference.PreferenceItem.TextPreference(
|
||||||
),
|
title = stringResource(MR.strings.pref_onboarding_guide),
|
||||||
Preference.PreferenceItem.TextPreference(
|
onClick = { navigator.push(OnboardingScreen()) },
|
||||||
title = stringResource(MR.strings.pref_onboarding_guide),
|
),
|
||||||
onClick = { navigator.push(OnboardingScreen()) },
|
Preference.PreferenceItem.TextPreference(
|
||||||
),
|
title = stringResource(MR.strings.pref_manage_notifications),
|
||||||
),
|
onClick = {
|
||||||
)
|
val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
|
||||||
add(
|
}
|
||||||
Preference.PreferenceItem.TextPreference(
|
context.startActivity(intent)
|
||||||
title = stringResource(MR.strings.pref_manage_notifications),
|
},
|
||||||
onClick = {
|
),
|
||||||
val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {
|
getBackgroundActivityGroup(),
|
||||||
putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
|
getDataGroup(),
|
||||||
}
|
getNetworkGroup(networkPreferences = networkPreferences),
|
||||||
context.startActivity(intent)
|
getLibraryGroup(),
|
||||||
},
|
getExtensionsGroup(basePreferences = basePreferences),
|
||||||
),
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
addAll(
|
|
||||||
listOf(
|
|
||||||
getBackgroundActivityGroup(),
|
|
||||||
getDataGroup(),
|
|
||||||
getNetworkGroup(networkPreferences = networkPreferences),
|
|
||||||
getLibraryGroup(),
|
|
||||||
getExtensionsGroup(basePreferences = basePreferences),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -60,7 +60,6 @@ object SettingsReaderScreen : SearchableSettings {
|
|||||||
pref = readerPref.trueColor(),
|
pref = readerPref.trueColor(),
|
||||||
title = stringResource(MR.strings.pref_true_color),
|
title = stringResource(MR.strings.pref_true_color),
|
||||||
subtitle = stringResource(MR.strings.pref_true_color_summary),
|
subtitle = stringResource(MR.strings.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(),
|
||||||
|
@ -13,18 +13,11 @@ import eu.kanade.domain.ui.model.ThemeMode
|
|||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
|
|
||||||
private val options = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
private val options = mapOf(
|
||||||
mapOf(
|
ThemeMode.SYSTEM to MR.strings.theme_system,
|
||||||
ThemeMode.SYSTEM to MR.strings.theme_system,
|
ThemeMode.LIGHT to MR.strings.theme_light,
|
||||||
ThemeMode.LIGHT to MR.strings.theme_light,
|
ThemeMode.DARK to MR.strings.theme_dark,
|
||||||
ThemeMode.DARK to MR.strings.theme_dark,
|
)
|
||||||
)
|
|
||||||
} else {
|
|
||||||
mapOf(
|
|
||||||
ThemeMode.LIGHT to MR.strings.theme_light,
|
|
||||||
ThemeMode.DARK to MR.strings.theme_dark,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun AppThemeModePreferenceWidget(
|
internal fun AppThemeModePreferenceWidget(
|
||||||
|
@ -23,12 +23,7 @@ fun rememberRequestPackageInstallsPermissionState(initialValue: Boolean = false)
|
|||||||
DisposableEffect(lifecycleOwner.lifecycle) {
|
DisposableEffect(lifecycleOwner.lifecycle) {
|
||||||
val observer = object : DefaultLifecycleObserver {
|
val observer = object : DefaultLifecycleObserver {
|
||||||
override fun onResume(owner: LifecycleOwner) {
|
override fun onResume(owner: LifecycleOwner) {
|
||||||
installGranted = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
installGranted = context.packageManager.canRequestPackageInstalls()
|
||||||
context.packageManager.canRequestPackageInstalls()
|
|
||||||
} else {
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
Settings.Secure.getInt(context.contentResolver, Settings.Secure.INSTALL_NON_MARKET_APPS) != 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lifecycleOwner.lifecycle.addObserver(observer)
|
lifecycleOwner.lifecycle.addObserver(observer)
|
||||||
|
@ -169,22 +169,19 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getPackageName(): String {
|
override fun getPackageName(): String {
|
||||||
// This causes freezes in Android 6/7 for some reason
|
try {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
// Override the value passed as X-Requested-With in WebView requests
|
||||||
try {
|
val stackTrace = Looper.getMainLooper().thread.stackTrace
|
||||||
// Override the value passed as X-Requested-With in WebView requests
|
val chromiumElement = stackTrace.find {
|
||||||
val stackTrace = Looper.getMainLooper().thread.stackTrace
|
it.className.equals(
|
||||||
val chromiumElement = stackTrace.find {
|
"org.chromium.base.BuildInfo",
|
||||||
it.className.equals(
|
ignoreCase = true,
|
||||||
"org.chromium.base.BuildInfo",
|
)
|
||||||
ignoreCase = true,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (chromiumElement?.methodName.equals("getAll", ignoreCase = true)) {
|
|
||||||
return WebViewUtil.SPOOF_PACKAGE_NAME
|
|
||||||
}
|
|
||||||
} catch (_: Exception) {
|
|
||||||
}
|
}
|
||||||
|
if (chromiumElement?.methodName.equals("getAll", ignoreCase = true)) {
|
||||||
|
return WebViewUtil.SPOOF_PACKAGE_NAME
|
||||||
|
}
|
||||||
|
} catch (_: Exception) {
|
||||||
}
|
}
|
||||||
return super.getPackageName()
|
return super.getPackageName()
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
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
|
||||||
@ -48,8 +47,7 @@ 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 -> true
|
ImageUtil.ImageType.AVIF, ImageUtil.ImageType.JXL, ImageUtil.ImageType.HEIF -> true
|
||||||
ImageUtil.ImageType.HEIF -> Build.VERSION.SDK_INT < Build.VERSION_CODES.O
|
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ 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.data.backup.restore.BackupRestoreJob
|
import eu.kanade.tachiyomi.data.backup.restore.BackupRestoreJob
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
@ -354,20 +353,18 @@ 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.
|
||||||
*/
|
*/
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
val groupKey = context.notificationManager.activeNotifications.find {
|
||||||
val groupKey = context.notificationManager.activeNotifications.find {
|
it.id == notificationId
|
||||||
it.id == notificationId
|
}?.groupKey
|
||||||
}?.groupKey
|
|
||||||
|
|
||||||
if (groupId != null && groupId != 0 && !groupKey.isNullOrEmpty()) {
|
if (groupId != null && groupId != 0 && !groupKey.isNullOrEmpty()) {
|
||||||
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
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ 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.extension.model.InstallStep
|
import eu.kanade.tachiyomi.extension.model.InstallStep
|
||||||
import eu.kanade.tachiyomi.util.system.getUriSize
|
import eu.kanade.tachiyomi.util.system.getUriSize
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
@ -50,11 +49,7 @@ 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 = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
val createCommand = "pm install-create --user current -r -i ${service.packageName} -S $size"
|
||||||
"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")
|
||||||
|
@ -14,11 +14,7 @@ import java.util.zip.ZipFile
|
|||||||
*/
|
*/
|
||||||
internal class ZipPageLoader(file: File) : PageLoader() {
|
internal class ZipPageLoader(file: File) : PageLoader() {
|
||||||
|
|
||||||
private val zip = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
private val zip = ZipFile(file, StandardCharsets.ISO_8859_1)
|
||||||
ZipFile(file, StandardCharsets.ISO_8859_1)
|
|
||||||
} else {
|
|
||||||
ZipFile(file)
|
|
||||||
}
|
|
||||||
|
|
||||||
override var isLocal: Boolean = true
|
override var isLocal: Boolean = true
|
||||||
|
|
||||||
|
@ -2,9 +2,7 @@ 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
|
||||||
|
|
||||||
@ -17,11 +15,7 @@ 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 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
return FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", this)
|
||||||
FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", this)
|
|
||||||
} else {
|
|
||||||
this.toUri()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -170,12 +170,8 @@ fun Context.isInstalledFromFDroid(): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun Context.launchRequestPackageInstallsPermission() {
|
fun Context.launchRequestPackageInstallsPermission() {
|
||||||
val intent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).apply {
|
||||||
Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).apply {
|
data = Uri.parse("package:$packageName")
|
||||||
data = Uri.parse("package:$packageName")
|
startActivity(this)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Intent(Settings.ACTION_SECURITY_SETTINGS)
|
|
||||||
}
|
}
|
||||||
startActivity(intent)
|
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,7 @@ 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
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> NetworkCapabilities.TRANSPORT_WIFI_AWARE
|
else -> NetworkCapabilities.TRANSPORT_WIFI_AWARE
|
||||||
else -> NetworkCapabilities.TRANSPORT_VPN
|
|
||||||
}
|
}
|
||||||
return (NetworkCapabilities.TRANSPORT_CELLULAR..maxTransport).any(networkCapabilities::hasTransport)
|
return (NetworkCapabilities.TRANSPORT_CELLULAR..maxTransport).any(networkCapabilities::hasTransport)
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,7 @@ data class NetworkState(
|
|||||||
val isValidated: Boolean,
|
val isValidated: Boolean,
|
||||||
val isWifi: Boolean,
|
val isWifi: Boolean,
|
||||||
) {
|
) {
|
||||||
val isOnline = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
val isOnline = isConnected && isValidated
|
||||||
isConnected && isValidated
|
|
||||||
} else {
|
|
||||||
isConnected
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@ -34,34 +30,18 @@ fun Context.activeNetworkState(): NetworkState {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
fun Context.networkStateFlow() = callbackFlow {
|
fun Context.networkStateFlow() = callbackFlow {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
val networkCallback = object : NetworkCallback() {
|
||||||
val networkCallback = object : NetworkCallback() {
|
override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
|
||||||
override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
|
trySend(activeNetworkState())
|
||||||
trySend(activeNetworkState())
|
|
||||||
}
|
|
||||||
override fun onLost(network: Network) {
|
|
||||||
trySend(activeNetworkState())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
override fun onLost(network: Network) {
|
||||||
connectivityManager.registerDefaultNetworkCallback(networkCallback)
|
trySend(activeNetworkState())
|
||||||
awaitClose {
|
|
||||||
connectivityManager.unregisterNetworkCallback(networkCallback)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val receiver = object : BroadcastReceiver() {
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
|
||||||
if (intent.action == ConnectivityManager.CONNECTIVITY_ACTION) {
|
|
||||||
trySend(activeNetworkState())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
registerReceiver(receiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
|
|
||||||
awaitClose {
|
|
||||||
unregisterReceiver(receiver)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connectivityManager.registerDefaultNetworkCallback(networkCallback)
|
||||||
|
awaitClose {
|
||||||
|
connectivityManager.unregisterNetworkCallback(networkCallback)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
tools:keep="@drawable/sc_collections_bookmark_48dp">
|
|
||||||
<background android:drawable="@color/accent_blue"/>
|
|
||||||
<foreground>
|
|
||||||
<vector
|
|
||||||
android:width="120dp"
|
|
||||||
android:height="120dp"
|
|
||||||
android:viewportWidth="56.0"
|
|
||||||
android:viewportHeight="56.0">
|
|
||||||
<group
|
|
||||||
android:translateX="16"
|
|
||||||
android:translateY="16">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFF"
|
|
||||||
android:pathData="M4,6H2v14c0,1.1 0.9,2 2,2h14v-2H4V6z"/>
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFF"
|
|
||||||
android:pathData="M20,2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM20,12l-2.5,-1.5L15,12L15,4h5v8z"/>
|
|
||||||
</group>
|
|
||||||
</vector>
|
|
||||||
</foreground>
|
|
||||||
</adaptive-icon>
|
|
@ -1,21 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
tools:keep="@drawable/sc_explore_48dp">
|
|
||||||
<background android:drawable="@color/accent_blue"/>
|
|
||||||
<foreground>
|
|
||||||
<vector
|
|
||||||
android:width="120dp"
|
|
||||||
android:height="120dp"
|
|
||||||
android:viewportWidth="56.0"
|
|
||||||
android:viewportHeight="56.0">
|
|
||||||
<group
|
|
||||||
android:translateX="16"
|
|
||||||
android:translateY="16">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFF"
|
|
||||||
android:pathData="M12,10.9c-0.61,0 -1.1,0.49 -1.1,1.1s0.49,1.1 1.1,1.1c0.61,0 1.1,-0.49 1.1,-1.1s-0.49,-1.1 -1.1,-1.1zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM14.19,14.19L6,18l3.81,-8.19L18,6l-3.81,8.19z" />
|
|
||||||
</group>
|
|
||||||
</vector>
|
|
||||||
</foreground>
|
|
||||||
</adaptive-icon>
|
|
@ -1,21 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
tools:keep="@drawable/sc_history_48dp">
|
|
||||||
<background android:drawable="@color/accent_blue"/>
|
|
||||||
<foreground>
|
|
||||||
<vector
|
|
||||||
android:width="120dp"
|
|
||||||
android:height="120dp"
|
|
||||||
android:viewportWidth="56.0"
|
|
||||||
android:viewportHeight="56.0">
|
|
||||||
<group
|
|
||||||
android:translateX="16"
|
|
||||||
android:translateY="16">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFF"
|
|
||||||
android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z" />
|
|
||||||
</group>
|
|
||||||
</vector>
|
|
||||||
</foreground>
|
|
||||||
</adaptive-icon>
|
|
@ -1,21 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
tools:keep="@drawable/sc_new_releases_48dp">
|
|
||||||
<background android:drawable="@color/accent_blue"/>
|
|
||||||
<foreground>
|
|
||||||
<vector
|
|
||||||
android:width="120dp"
|
|
||||||
android:height="120dp"
|
|
||||||
android:viewportWidth="56.0"
|
|
||||||
android:viewportHeight="56.0">
|
|
||||||
<group
|
|
||||||
android:translateX="16"
|
|
||||||
android:translateY="16">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFF"
|
|
||||||
android:pathData="M23,12l-2.44,-2.78 0.34,-3.68 -3.61,-0.82 -1.89,-3.18L12,3 8.6,1.54 6.71,4.72l-3.61,0.81 0.34,3.68L1,12l2.44,2.78 -0.34,3.69 3.61,0.82 1.89,3.18L12,21l3.4,1.46 1.89,-3.18 3.61,-0.82 -0.34,-3.68L23,12zM13,17h-2v-2h2v2zM13,13h-2L11,7h2v6z" />
|
|
||||||
</group>
|
|
||||||
</vector>
|
|
||||||
</foreground>
|
|
||||||
</adaptive-icon>
|
|
@ -1,24 +1,24 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:keep="@drawable/sc_collections_bookmark_48dp"
|
tools:keep="@drawable/sc_collections_bookmark_48dp">
|
||||||
android:width="48dp"
|
<background android:drawable="@color/accent_blue"/>
|
||||||
android:height="48dp"
|
<foreground>
|
||||||
android:viewportWidth="48"
|
<vector
|
||||||
android:viewportHeight="48">
|
android:width="120dp"
|
||||||
|
android:height="120dp"
|
||||||
<path
|
android:viewportWidth="56.0"
|
||||||
android:fillColor="@color/accent_blue"
|
android:viewportHeight="56.0">
|
||||||
android:pathData="M24,24m-22,0a22,22 0,1 1,44 0a22,22 0,1 1,-44 0" />
|
<group
|
||||||
|
android:translateX="16"
|
||||||
<group
|
android:translateY="16">
|
||||||
android:translateX="12"
|
<path
|
||||||
android:translateY="12">
|
android:fillColor="#FFF"
|
||||||
<path
|
android:pathData="M4,6H2v14c0,1.1 0.9,2 2,2h14v-2H4V6z"/>
|
||||||
android:fillColor="#FFF"
|
<path
|
||||||
android:pathData="M4,6H2v14c0,1.1 0.9,2 2,2h14v-2H4V6z" />
|
android:fillColor="#FFF"
|
||||||
<path
|
android:pathData="M20,2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM20,12l-2.5,-1.5L15,12L15,4h5v8z"/>
|
||||||
android:fillColor="#FFF"
|
</group>
|
||||||
android:pathData="M20,2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM20,12l-2.5,-1.5L15,12L15,4h5v8z" />
|
</vector>
|
||||||
</group>
|
</foreground>
|
||||||
</vector>
|
</adaptive-icon>
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:keep="@drawable/sc_explore_48dp"
|
tools:keep="@drawable/sc_explore_48dp">
|
||||||
android:width="48dp"
|
<background android:drawable="@color/accent_blue"/>
|
||||||
android:height="48dp"
|
<foreground>
|
||||||
android:viewportWidth="48"
|
<vector
|
||||||
android:viewportHeight="48">
|
android:width="120dp"
|
||||||
|
android:height="120dp"
|
||||||
<path
|
android:viewportWidth="56.0"
|
||||||
android:fillColor="@color/accent_blue"
|
android:viewportHeight="56.0">
|
||||||
android:pathData="M24,24m-22,0a22,22 0,1 1,44 0a22,22 0,1 1,-44 0" />
|
<group
|
||||||
|
android:translateX="16"
|
||||||
<group
|
android:translateY="16">
|
||||||
android:translateX="12"
|
<path
|
||||||
android:translateY="12">
|
android:fillColor="#FFF"
|
||||||
<path
|
android:pathData="M12,10.9c-0.61,0 -1.1,0.49 -1.1,1.1s0.49,1.1 1.1,1.1c0.61,0 1.1,-0.49 1.1,-1.1s-0.49,-1.1 -1.1,-1.1zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM14.19,14.19L6,18l3.81,-8.19L18,6l-3.81,8.19z" />
|
||||||
android:fillColor="#FFF"
|
</group>
|
||||||
android:pathData="M12,10.9c-0.61,0 -1.1,0.49 -1.1,1.1s0.49,1.1 1.1,1.1c0.61,0 1.1,-0.49 1.1,-1.1s-0.49,-1.1 -1.1,-1.1zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM14.19,14.19L6,18l3.81,-8.19L18,6l-3.81,8.19z" />
|
</vector>
|
||||||
</group>
|
</foreground>
|
||||||
</vector>
|
</adaptive-icon>
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:keep="@drawable/sc_history_48dp"
|
tools:keep="@drawable/sc_history_48dp">
|
||||||
android:width="48dp"
|
<background android:drawable="@color/accent_blue"/>
|
||||||
android:height="48dp"
|
<foreground>
|
||||||
android:viewportWidth="48"
|
<vector
|
||||||
android:viewportHeight="48">
|
android:width="120dp"
|
||||||
|
android:height="120dp"
|
||||||
<path
|
android:viewportWidth="56.0"
|
||||||
android:fillColor="@color/accent_blue"
|
android:viewportHeight="56.0">
|
||||||
android:pathData="M24,24m-22,0a22,22 0,1 1,44 0a22,22 0,1 1,-44 0" />
|
<group
|
||||||
|
android:translateX="16"
|
||||||
<group
|
android:translateY="16">
|
||||||
android:translateX="12"
|
<path
|
||||||
android:translateY="12">
|
android:fillColor="#FFF"
|
||||||
<path
|
android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z" />
|
||||||
android:fillColor="#FFF"
|
</group>
|
||||||
android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z" />
|
</vector>
|
||||||
</group>
|
</foreground>
|
||||||
</vector>
|
</adaptive-icon>
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:keep="@drawable/sc_new_releases_48dp"
|
tools:keep="@drawable/sc_new_releases_48dp">
|
||||||
android:width="48dp"
|
<background android:drawable="@color/accent_blue"/>
|
||||||
android:height="48dp"
|
<foreground>
|
||||||
android:viewportWidth="48"
|
<vector
|
||||||
android:viewportHeight="48">
|
android:width="120dp"
|
||||||
|
android:height="120dp"
|
||||||
<path
|
android:viewportWidth="56.0"
|
||||||
android:fillColor="@color/accent_blue"
|
android:viewportHeight="56.0">
|
||||||
android:pathData="M24,24m-22,0a22,22 0,1 1,44 0a22,22 0,1 1,-44 0" />
|
<group
|
||||||
|
android:translateX="16"
|
||||||
<group
|
android:translateY="16">
|
||||||
android:translateX="12"
|
<path
|
||||||
android:translateY="12">
|
android:fillColor="#FFF"
|
||||||
<path
|
android:pathData="M23,12l-2.44,-2.78 0.34,-3.68 -3.61,-0.82 -1.89,-3.18L12,3 8.6,1.54 6.71,4.72l-3.61,0.81 0.34,3.68L1,12l2.44,2.78 -0.34,3.69 3.61,0.82 1.89,3.18L12,21l3.4,1.46 1.89,-3.18 3.61,-0.82 -0.34,-3.68L23,12zM13,17h-2v-2h2v2zM13,13h-2L11,7h2v6z" />
|
||||||
android:fillColor="#FFF"
|
</group>
|
||||||
android:pathData="M23,12l-2.44,-2.78 0.34,-3.68 -3.61,-0.82 -1.89,-3.18L12,3 8.6,1.54 6.71,4.72l-3.61,0.81 0.34,3.68L1,12l2.44,2.78 -0.34,3.69 3.61,0.82 1.89,3.18L12,21l3.4,1.46 1.89,-3.18 3.61,-0.82 -0.34,-3.68L23,12zM13,17h-2v-2h2v2zM13,13h-2L11,7h2v6z" />
|
</vector>
|
||||||
</group>
|
</foreground>
|
||||||
</vector>
|
</adaptive-icon>
|
||||||
|
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 14 KiB |
@ -1,6 +1,6 @@
|
|||||||
object AndroidConfig {
|
object AndroidConfig {
|
||||||
const val compileSdk = 34
|
const val compileSdk = 34
|
||||||
const val minSdk = 23
|
const val minSdk = 26
|
||||||
const val targetSdk = 34
|
const val targetSdk = 34
|
||||||
const val ndk = "26.1.10909125"
|
const val ndk = "26.1.10909125"
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
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
|
||||||
@ -28,7 +26,6 @@ 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,
|
||||||
|
@ -3,7 +3,6 @@ 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
|
||||||
@ -35,15 +34,11 @@ object WebViewUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getVersion(context: Context): String {
|
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 webView = WebView.getCurrentWebViewPackage() ?: return "how did you get here?"
|
val pm = context.packageManager
|
||||||
val pm = context.packageManager
|
val label = webView.applicationInfo.loadLabel(pm)
|
||||||
val label = webView.applicationInfo.loadLabel(pm)
|
val version = webView.versionName
|
||||||
val version = webView.versionName
|
return "$label $version"
|
||||||
"$label $version"
|
|
||||||
} else {
|
|
||||||
"Unknown"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun supportsWebView(context: Context): Boolean {
|
fun supportsWebView(context: Context): Boolean {
|
||||||
|