Refactored the java.util.Locale constructor, which is deprecated in Android 16. * Created to utilize the methods introduced in this Android version. * Upgraded AGP to , which supports Android 16. * Replaced targetSdkVersion and compileSdkVersion with targetSdkPreview and compileSdkPreview to add support for Android 16. * After upgrading the gradle lint showing some new errors so we have fixed those lint errors that required us to use the KTX extension functions, as they internally utilize the same functions we were using.

This commit is contained in:
MohitMaliFtechiz 2025-03-26 21:06:09 +05:30
parent fbe7712b03
commit e472d11dc2
21 changed files with 126 additions and 60 deletions

View File

@ -21,6 +21,7 @@ import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.database.DataSetObserver
import android.graphics.Canvas
@ -776,13 +777,17 @@ class CustomPageIndicator @JvmOverloads constructor(
val density = context.resources.displayMetrics.density.toInt()
// Load attributes
val a =
getContext().obtainStyledAttributes(attrs, R.styleable.CustomPageIndicator, defStyle, 0)
dotDiameter =
a.getDimensionPixelSize(
R.styleable.CustomPageIndicator_ipi_dotDiameter,
DEFAULT_DOT_SIZE * density
)
@SuppressLint("UseKtx")
val a = getContext().obtainStyledAttributes(
attrs,
R.styleable.CustomPageIndicator,
defStyle,
0
)
dotDiameter = a.getDimensionPixelSize(
R.styleable.CustomPageIndicator_ipi_dotDiameter,
DEFAULT_DOT_SIZE * density
)
dotRadius = (dotDiameter / 2).toFloat()
halfDotRadius = dotRadius / 2
gap =

View File

@ -366,18 +366,17 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
}
private fun showFileChooser() {
val intent =
Intent().apply {
action = Intent.ACTION_OPEN_DOCUMENT
type = "*/*"
addCategory(Intent.CATEGORY_OPENABLE)
if (sharedPreferenceUtil.prefIsTest) {
putExtra(
"android.provider.extra.INITIAL_URI",
"content://com.android.externalstorage.documents/document/primary:Download".toUri()
)
}
val intent = Intent().apply {
action = Intent.ACTION_OPEN_DOCUMENT
type = "*/*"
addCategory(Intent.CATEGORY_OPENABLE)
if (sharedPreferenceUtil.prefIsTest) {
putExtra(
"android.provider.extra.INITIAL_URI",
"content://com.android.externalstorage.documents/document/primary:Download".toUri()
)
}
}
try {
fileSelectLauncher.launch(Intent.createChooser(intent, "Select a zim file"))
} catch (_: ActivityNotFoundException) {

View File

@ -135,11 +135,10 @@ class KiwixReaderFragment : CoreReaderFragment() {
// Update the reader screen title to prevent showing the previously set title
// when creating the new archive object.
updateTitle()
val filePath =
FileUtils.getLocalFilePathByUri(
requireActivity().applicationContext,
zimFileUri.toUri()
)
val filePath = FileUtils.getLocalFilePathByUri(
requireActivity().applicationContext,
zimFileUri.toUri()
)
if (filePath == null || !File(filePath).isFileExist()) {
// Close the previously opened book in the reader. Since this file is not found,
// it will not be set in the zimFileReader. The previously opened ZIM file

View File

@ -11,7 +11,7 @@ repositories {
}
dependencies {
implementation("com.android.tools.build:gradle:8.10.0-alpha05")
implementation("com.android.tools.build:gradle:8.10.0-alpha06")
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.0")
implementation("com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:2.0.0-1.0.24")
implementation("org.jacoco:org.jacoco.core:0.8.12")

View File

@ -48,7 +48,7 @@ object Versions {
const val android_arch_lifecycle_extensions: String = "1.1.1"
const val com_android_tools_build_gradle: String = "8.10.0-alpha05"
const val com_android_tools_build_gradle: String = "8.10.0-alpha06"
const val de_fayard_buildsrcversions_gradle_plugin: String = "0.7.0"

View File

@ -155,6 +155,7 @@ class AllProjectConfigurer {
add("UnusedResources")
add("NonConstantResourceId")
add("NotifyDataSetChanged")
add("Aligned16KB") // TODO: Remove when properly migrated to Android 16.
}
lintConfig = target.rootProject.file("lintConfig.xml")
}

View File

@ -23,6 +23,7 @@ import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import android.net.ConnectivityManager
import java.util.Locale
/**
* This interface defines a set of functions that are not available on all platforms.
@ -76,4 +77,6 @@ interface Compat {
fun isNetworkAvailable(connectivity: ConnectivityManager): Boolean
fun isWifi(connectivity: ConnectivityManager): Boolean
fun convertToLocal(language: String): Locale
}

View File

@ -28,7 +28,8 @@ import android.os.Build
class CompatHelper private constructor() {
// Note: Needs ": Compat" or the type system assumes `Compat21`
private val compatValue: Compat = when {
sdkVersion >= Build.VERSION_CODES.TIRAMISU -> CompatV33()
Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA -> CompatV36()
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> CompatV33()
else -> CompatV25()
}
@ -36,10 +37,6 @@ class CompatHelper private constructor() {
/** Singleton instance of [CompatHelper] */
private val instance by lazy(::CompatHelper)
/** Get the current Android API level. */
val sdkVersion: Int
get() = Build.VERSION.SDK_INT
val compat get() = instance.compatValue
/**
@ -79,5 +76,7 @@ class CompatHelper private constructor() {
fun ConnectivityManager.isWifi(): Boolean =
compat.isWifi(this)
fun String.convertToLocal() = compat.convertToLocal(this)
}
}

View File

@ -26,6 +26,7 @@ import android.content.pm.ResolveInfo
import android.net.ConnectivityManager
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
import android.net.NetworkCapabilities.TRANSPORT_WIFI
import java.util.Locale
open class CompatV25 : Compat {
override fun queryIntentActivities(
@ -61,4 +62,6 @@ open class CompatV25 : Compat {
return connectivity.getNetworkCapabilities(connectivity.activeNetwork)
?.hasTransport(TRANSPORT_WIFI) == true
}
override fun convertToLocal(language: String): Locale = Locale(language)
}

View File

@ -18,17 +18,17 @@
package org.kiwix.kiwixmobile.core.compat
import android.annotation.TargetApi
import android.content.Intent
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.pm.PackageManager.PackageInfoFlags
import android.content.pm.ResolveInfo
import android.net.ConnectivityManager
import android.os.Build.VERSION_CODES.TIRAMISU
import androidx.annotation.RequiresApi
import java.util.Locale
const val API_33 = 33
@TargetApi(API_33)
@RequiresApi(TIRAMISU)
open class CompatV33 : Compat {
private val compatV25 = CompatV25()
override fun queryIntentActivities(
@ -52,4 +52,6 @@ open class CompatV33 : Compat {
override fun isWifi(connectivity: ConnectivityManager): Boolean =
compatV25.isWifi(connectivity)
override fun convertToLocal(language: String): Locale = compatV25.convertToLocal(language)
}

View File

@ -0,0 +1,53 @@
/*
* Kiwix Android
* Copyright (c) 2025 Kiwix <android.kiwix.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.kiwix.kiwixmobile.core.compat
import android.content.Intent
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import android.net.ConnectivityManager
import android.os.Build.VERSION_CODES.BAKLAVA
import androidx.annotation.RequiresApi
import java.util.Locale
@RequiresApi(BAKLAVA)
open class CompatV36 : Compat {
private val compatV33 = CompatV33()
override fun queryIntentActivities(
packageManager: PackageManager,
intent: Intent,
flags: ResolveInfoFlagsCompat
): List<ResolveInfo> = compatV33.queryIntentActivities(packageManager, intent, flags)
override fun getPackageInformation(
packageName: String,
packageManager: PackageManager,
flag: Int
): PackageInfo =
compatV33.getPackageInformation(packageName, packageManager, flag)
override fun isNetworkAvailable(connectivity: ConnectivityManager): Boolean =
compatV33.isNetworkAvailable(connectivity)
override fun isWifi(connectivity: ConnectivityManager): Boolean =
compatV33.isWifi(connectivity)
override fun convertToLocal(language: String): Locale = Locale.of(language)
}

View File

@ -22,6 +22,7 @@ import io.objectbox.annotation.Convert
import io.objectbox.annotation.Entity
import io.objectbox.annotation.Id
import io.objectbox.converter.PropertyConverter
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.convertToLocal
import org.kiwix.kiwixmobile.core.zim_manager.Language
import java.util.Locale
@ -35,7 +36,7 @@ data class LanguageEntity(
) {
constructor(language: Language) : this(
0,
Locale(language.languageCode),
language.languageCode.convertToLocal(),
language.active,
language.occurencesOfLanguage
)
@ -49,5 +50,5 @@ class StringToLocaleConverter : PropertyConverter<Locale, String> {
entityProperty?.isO3Language ?: Locale.ENGLISH.isO3Language
override fun convertToEntityProperty(databaseValue: String?): Locale =
databaseValue?.let(::Locale) ?: Locale.ENGLISH
databaseValue?.convertToLocal() ?: Locale.ENGLISH
}

View File

@ -33,6 +33,9 @@ import android.util.TypedValue
import android.widget.Toast
import androidx.annotation.AttrRes
import androidx.core.content.ContextCompat
import androidx.core.graphics.createBitmap
import androidx.core.graphics.drawable.toDrawable
import androidx.core.graphics.scale
import org.kiwix.kiwixmobile.core.base.BaseBroadcastReceiver
import java.util.Locale
@ -87,14 +90,9 @@ fun Context.getResizedDrawable(resourceId: Int, width: Int, height: Int): Drawab
val drawable = ContextCompat.getDrawable(this, resourceId)
return if (drawable != null) {
val bitmap = Bitmap.createScaledBitmap(
getBitmapFromDrawable(drawable),
width,
height,
false
)
val bitmap = getBitmapFromDrawable(drawable).scale(width, height, false)
BitmapDrawable(resources, bitmap).apply {
bitmap.toDrawable(resources).apply {
bounds = drawable.bounds
}
} else {
@ -107,11 +105,7 @@ fun Context.getBitmapFromDrawable(drawable: Drawable): Bitmap {
return drawable.bitmap
}
val bitmap = Bitmap.createBitmap(
drawable.intrinsicWidth,
drawable.intrinsicHeight,
Bitmap.Config.ARGB_8888
)
val bitmap = createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight)
val canvas = Canvas(bitmap)
drawable.setBounds(0, 0, canvas.width, canvas.height)
drawable.draw(canvas)

View File

@ -72,6 +72,7 @@ import androidx.constraintlayout.widget.Group
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.content.edit
import androidx.core.net.toUri
import androidx.core.view.GravityCompat
import androidx.core.view.MenuHost
@ -2516,7 +2517,6 @@ abstract class CoreReaderFragment :
SharedPreferenceUtil.PREF_KIWIX_MOBILE,
0
)
val editor = settings.edit()
val webViewHistoryEntityList = arrayListOf<WebViewHistoryEntity>()
webViewList.forEachIndexed { index, view ->
if (view.url == null) return@forEachIndexed
@ -2525,9 +2525,10 @@ abstract class CoreReaderFragment :
withContext(Dispatchers.IO) {
repositoryActions?.saveWebViewPageHistory(webViewHistoryEntityList)
}
editor.putString(TAG_CURRENT_FILE, zimReaderContainer?.zimReaderSource?.toDatabase())
editor.putInt(TAG_CURRENT_TAB, currentWebViewIndex)
editor.apply()
settings.edit {
putString(TAG_CURRENT_FILE, zimReaderContainer?.zimReaderSource?.toDatabase())
putInt(TAG_CURRENT_TAB, currentWebViewIndex)
}
Log.d(
TAG_KIWIX,
"Save current zim file to preferences: " +

View File

@ -18,6 +18,7 @@
package org.kiwix.kiwixmobile.core.qr
import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.graphics.Color
import com.google.zxing.BarcodeFormat
@ -39,6 +40,7 @@ class GenerateQR @Inject constructor() {
* @param foregroundColor The color of the QR code.
* @param backgroundColor The background color of the QR code.
*/
@SuppressLint("UseKtx")
fun createQR(
code: String,
size: Int = 512,

View File

@ -46,6 +46,7 @@ import org.kiwix.kiwixmobile.core.CoreApp.Companion.coreComponent
import org.kiwix.kiwixmobile.core.CoreApp.Companion.instance
import org.kiwix.kiwixmobile.core.DarkModeConfig
import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.convertToLocal
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.getPackageInformation
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.getVersionCode
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks
@ -169,9 +170,7 @@ abstract class CorePrefsFragment :
if (selectedLang == Locale.ROOT.toString()) {
getString(R.string.device_default)
} else {
Locale(
selectedLang
).displayLanguage
selectedLang.convertToLocal().displayLanguage
}
languagePref.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { _, newValue ->
@ -206,7 +205,7 @@ abstract class CorePrefsFragment :
val entries = arrayOfNulls<String>(languageCodeList.size)
entries[0] = getString(R.string.device_default)
for (i in 1 until languageCodeList.size) {
val locale = Locale(languageCodeList[i])
val locale = languageCodeList[i].convertToLocal()
entries[i] = locale.displayLanguage + " (" + locale.getDisplayLanguage(locale) + ") "
}
return entries
@ -389,7 +388,7 @@ abstract class CorePrefsFragment :
}
try {
fileSelectLauncher.launch(Intent.createChooser(intent, "Select a bookmark file"))
} catch (ex: ActivityNotFoundException) {
} catch (_: ActivityNotFoundException) {
activity.toast(
resources.getString(R.string.no_app_found_to_select_bookmark_file),
Toast.LENGTH_SHORT

View File

@ -18,6 +18,7 @@
package org.kiwix.kiwixmobile.core.utils
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.convertToLocal
import java.util.Locale
class LanguageContainer private constructor(val languageCode: String, val languageName: String) {
@ -25,7 +26,7 @@ class LanguageContainer private constructor(val languageCode: String, val langua
companion object {
private fun chooseLanguageName(languageCode: String): String {
val displayLanguage = Locale(languageCode).displayLanguage
val displayLanguage = languageCode.convertToLocal().displayLanguage
return if (displayLanguage.length == 2 || displayLanguage.isEmpty()) {
Locale.ENGLISH.displayLanguage
} else {

View File

@ -55,6 +55,7 @@ import java.io.File
import java.io.FileInputStream
import java.io.FileNotFoundException
import java.io.IOException
import androidx.core.net.toUri
object FileUtils {
private val fileOperationMutex = Mutex()

View File

@ -20,6 +20,7 @@ package org.kiwix.kiwixmobile.core.zim_manager
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.convertToLocal
import java.util.Locale
@Parcelize
@ -51,7 +52,7 @@ data class Language constructor(
languageCode: String,
active: Boolean,
occurrencesOfLanguage: Int
) : this(Locale(languageCode), active, occurrencesOfLanguage)
) : this(languageCode.convertToLocal(), active, occurrencesOfLanguage)
override fun equals(other: Any?): Boolean =
(other as Language).language == language && other.active == active

View File

@ -18,6 +18,7 @@
package org.kiwix.kiwixmobile.core.zim_manager.fileselect_view
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.convertToLocal
import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity
import org.kiwix.kiwixmobile.core.dao.entities.DownloadRoomEntity
import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity
@ -50,7 +51,7 @@ sealed class BooksOnDiskListItem {
override val id: Long = databaseId
) : BooksOnDiskListItem() {
val locale: Locale by lazy {
Locale(book.language)
book.language.convertToLocal()
}
constructor(bookOnDiskEntity: BookOnDiskEntity) : this(

View File

@ -52,4 +52,5 @@
<ignore path="**/androidTest/**.kt" />
</issue>
<issue id="PrivateResource" severity="warning" />
<issue id="AnnotateVersionCheck" severity="warning" />
</lint>