Fixed: Compilation issues in unit test cases. The issue was in Gradle itself, which was preventing us from merging or excluding duplicate META-INF files.

* Upgraded Gradle to `8.11.0-alpha03` for better support for Android 16.
* Upgraded the Gradle wrapper to `8.13`, the latest version.
* Fixed: Some deprecated methods in the custom app's Gradle. The new methods for registering tasks are better than the previous ones, which is why Gradle deprecated the older methods.
* Refactored the `createDynamically` task for custom apps according to new gradle.
* Fixed: Some lint and detekt issues.
This commit is contained in:
MohitMaliFtechiz 2025-03-31 15:27:31 +05:30
parent 993c13f85e
commit 05e231579b
14 changed files with 50 additions and 46 deletions

View File

@ -1,3 +1,4 @@
import com.android.build.gradle.internal.tasks.factory.dependsOn
import com.slack.keeper.optInToKeeper
import org.w3c.dom.Element
import plugin.KiwixConfigurationPlugin
@ -130,7 +131,7 @@ dependencies {
androidTestImplementation(Libs.leakcanary_android_instrumentation)
testImplementation(Libs.kotlinx_coroutines_test)
}
task("generateVersionCodeAndName") {
tasks.register("generateVersionCodeAndName") {
val file = File("VERSION_INFO")
if (!file.exists()) file.createNewFile()
file.printWriter().use {
@ -138,7 +139,7 @@ task("generateVersionCodeAndName") {
}
}
task("renameTarakFile") {
tasks.register("renameTarakFile") {
val taraskFile = File("$rootDir/core/src/main/res/values-b+be+tarask/strings.xml")
val mainStringsFile = File("$rootDir/core/src/main/res/values/strings.xml")
@ -214,6 +215,10 @@ fun elementToString(element: Element): String {
return result.writer.toString()
}
tasks.build {
dependsOn("renameTarakFile")
gradle.projectsEvaluated {
tasks.forEach { task ->
if (task.name != "renameTarakFile") {
task.dependsOn("renameTarakFile")
}
}
}

View File

@ -1,3 +1,5 @@
import org.gradle.kotlin.dsl.register
buildscript {
repositories {
google()
@ -28,6 +30,6 @@ allprojects {
}
}
tasks.create<Delete>("clean") {
tasks.register<Delete>("clean") {
delete(rootProject.layout.buildDirectory)
}

View File

@ -11,7 +11,7 @@ repositories {
}
dependencies {
implementation("com.android.tools.build:gradle:8.10.0-alpha08")
implementation("com.android.tools.build:gradle:8.11.0-alpha03")
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-alpha08"
const val com_android_tools_build_gradle: String = "8.11.0-alpha03"
const val de_fayard_buildsrcversions_gradle_plugin: String = "0.7.0"

View File

@ -24,7 +24,7 @@ import org.json.simple.JSONObject
import org.json.simple.parser.JSONParser
import java.io.File
typealias ProductFlavors = NamedDomainObjectContainer<ProductFlavor>
typealias ProductFlavors = NamedDomainObjectContainer<out ProductFlavor>
object CustomApps {

View File

@ -91,7 +91,9 @@ internal class NewBookDaoTest {
}
}
private fun expectEmissionOfExistingAndNotExistingBook(isInTrashFolder: Boolean = false): Pair<BookOnDiskEntity, BookOnDiskEntity> {
private fun expectEmissionOfExistingAndNotExistingBook(
isInTrashFolder: Boolean = false
): Pair<BookOnDiskEntity, BookOnDiskEntity> {
val query: Query<BookOnDiskEntity> = mockk()
every { box.query().build() } returns query
val zimReaderSourceThatExists = mockk<ZimReaderSource>()

View File

@ -18,17 +18,17 @@
package org.kiwix.kiwixmobile.core.dao
import org.junit.jupiter.api.Test
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import io.objectbox.Box
import io.objectbox.query.Query
import io.objectbox.query.QueryBuilder
import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity_
import org.junit.jupiter.api.Test
import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity
import org.kiwix.kiwixmobile.core.page.bookmark
import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity_
import org.kiwix.kiwixmobile.core.page.adapter.Page
import org.kiwix.kiwixmobile.core.page.bookmark
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
@ -69,7 +69,6 @@ internal class NewBookmarksDaoTest {
every { bookmarkItem.zimName } returns ""
every { bookmarkItem.databaseId } returns 0L
newBookmarksDao.getCurrentZimBookmarksUrl(zimFileReader)
val bookmarkEntity: BookmarkEntity = mockk()
every {
query.property(BookmarkEntity_.bookmarkUrl).findStrings().toList().distinct()
} returns listOf("")

View File

@ -27,13 +27,12 @@ class MetaLinkNetworkEntityTest {
@Throws(Exception::class)
fun testDeserialize() {
val serializer = Persister()
val result =
serializer.read(
MetaLinkNetworkEntity::class.java,
MetaLinkNetworkEntityTest::class.java.classLoader!!.getResourceAsStream(
"wikipedia_af_all_nopic_2016-05.zim.meta4"
)
val result = serializer.read(
MetaLinkNetworkEntity::class.java,
MetaLinkNetworkEntityTest::class.java.classLoader!!.getResourceAsStream(
"wikipedia_af_all_nopic_2016-05.zim.meta4"
)
)
result?.urls?.let {
MetaLinkNetworkEntityUrlAssert(it).hasItems(
listOf(
@ -68,9 +67,7 @@ class MetaLinkNetworkEntityTest {
}
// Basic file attributes
assertThat(result.file?.name).isEqualTo("wikipedia_af_all_nopic_2016-05.zim")
assertThat(result.file?.size).isEqualTo(63973123L)
// File hashes
assertThat(result.file?.getHash("md5")).isEqualTo("6f06866b61c4a921b57f28cfd4307220")
assertThat(
@ -103,21 +100,17 @@ class MetaLinkNetworkEntityTest {
*/
class MetaLinkNetworkEntityUrlAssert(
actual: List<MetaLinkNetworkEntity.Url>
) :
AbstractAssert<MetaLinkNetworkEntityUrlAssert, List<MetaLinkNetworkEntity.Url>>(
actual,
MetaLinkNetworkEntityUrlAssert::class.java
) {
) : AbstractAssert<MetaLinkNetworkEntityUrlAssert, List<MetaLinkNetworkEntity.Url>>(
actual,
MetaLinkNetworkEntityUrlAssert::class.java
) {
private fun <S, T> intersectionWith(
first: List<S>,
second: List<T>,
function: (S, T) -> Boolean
): Boolean {
val filtered = first.filter { a -> second.any { b -> function(a, b) } }
if (filtered.isNotEmpty()) {
return true
}
return false
return filtered.isNotEmpty()
}
fun hasItems(items: List<DummyUrl>): Boolean {

View File

@ -43,8 +43,9 @@ internal class SearchStateTest {
val estimatedMatches = 100
every { suggestionSearchWrapper.estimatedMatches } returns estimatedMatches.toLong()
// Settings list to hasNext() to ensure it returns true only for the first call.
// Otherwise, if we do not set this, the method will always return true when checking if the iterator has a next value,
// causing our test case to get stuck in an infinite loop due to this explicit setting.
// Otherwise, if we do not set this, the method will always return true when
// checking if the iterator has a next value, causing our test case to get stuck
// in an infinite loop due to this explicit setting.
every { searchIteratorWrapper.hasNext() } returnsMany listOf(true, false)
every { searchIteratorWrapper.next() } returns entryWrapper
every { entryWrapper.title } returns searchTerm
@ -119,7 +120,8 @@ internal class SearchStateTest {
every { entryWrapper.path } returns "path"
every { suggestionSearchWrapper.getResults(any(), any()) } returns searchIteratorWrapper
val searchResultsWithTerm = SearchResultsWithTerm(searchTerm, suggestionSearchWrapper, mockk())
val searchResultsWithTerm =
SearchResultsWithTerm(searchTerm, suggestionSearchWrapper, mockk())
val searchState = SearchState(searchTerm, searchResultsWithTerm, emptyList(), FromWebView)
var list: List<SearchListItem.RecentSearchListItem>? = emptyList()
var list1: List<SearchListItem.RecentSearchListItem>? = emptyList()

View File

@ -50,7 +50,6 @@ import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem.RecentSearchListItem
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem.ZimSearchResultListItem
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ActivityResultReceived
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ClickedSearchInText
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ConfirmedDelete
@ -123,7 +122,6 @@ internal class SearchViewModelTest {
@Test
fun `SearchState combines sources from inputs`() =
runTest {
val item = ZimSearchResultListItem("", "")
val searchTerm = "searchTerm"
val searchOrigin = FromWebView
val suggestionSearch: SuggestionSearch = mockk()

View File

@ -21,7 +21,9 @@ package org.kiwix.kiwixmobile.core.search.viewmodel
import org.kiwix.libzim.SuggestionIterator
class SuggestionIteratorWrapper : SuggestionIterator() {
override fun remove() {}
override fun remove() {
// Do nothing just to ignore the EmptyFunctionBlock detekt error.
}
override fun hasNext(): Boolean = super.hasNext()
override fun next(): SuggestionItemWrapper = super.next() as SuggestionItemWrapper

View File

@ -60,8 +60,8 @@ android {
}
}
fun ProductFlavor.createDownloadTask(file: File): Task {
return tasks.create(
fun ProductFlavor.createDownloadTask(file: File): TaskProvider<Task> {
return tasks.register(
"download${
name.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it"
@ -157,8 +157,8 @@ fun writeZimFileDataInChunk(
outputStream?.close()
}
fun ProductFlavor.createDownloadTaskForPlayAssetDelivery(file: File): Task {
return tasks.create(
fun ProductFlavor.createDownloadTaskForPlayAssetDelivery(file: File): TaskProvider<Task> {
return tasks.register(
"download${
name.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it"
@ -206,10 +206,10 @@ val String.removeAuthenticationFromUrl: String
fun ProductFlavor.createPublishApkWithExpansionTask(
file: File,
applicationVariants: DomainObjectSet<ApplicationVariant>
): Task {
): TaskProvider<Task> {
val capitalizedName =
name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it" }
return tasks.create("publish${capitalizedName}ReleaseApkWithExpansionFile") {
return tasks.register("publish${capitalizedName}ReleaseApkWithExpansionFile") {
group = "publishing"
description = "Uploads $capitalizedName to the Play Console with an Expansion file"
doLast {
@ -237,10 +237,10 @@ fun DomainObjectSet<ApplicationVariant>.releaseVariantsFor(productFlavor: Produc
.filter { !it.outputFileName.contains("universal") }
.sortedBy { it.versionCodeOverride }
fun ProductFlavor.createPublishBundleWithAssetPlayDelivery(): Task {
fun ProductFlavor.createPublishBundleWithAssetPlayDelivery(): TaskProvider<Task> {
val capitalizedName =
name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it" }
return tasks.create("publish${capitalizedName}ReleaseBundleWithPlayAssetDelivery") {
return tasks.register("publish${capitalizedName}ReleaseBundleWithPlayAssetDelivery") {
group = "publishing"
description = "Uploads $capitalizedName to the Play Console with an Play Asset delivery mode"
doLast {
@ -250,7 +250,7 @@ fun ProductFlavor.createPublishBundleWithAssetPlayDelivery(): Task {
.transactionWithCommit(packageName) {
val generatedBundleFile =
File(
"$buildDir/outputs/bundle/${capitalizedName.lowercase(Locale.getDefault())}" +
"${layout.buildDirectory}/outputs/bundle/${capitalizedName.lowercase(Locale.getDefault())}" +
"Release/custom-${capitalizedName.lowercase(Locale.getDefault())}-release.aab"
)
if (generatedBundleFile.exists()) {

View File

@ -1,6 +1,6 @@
#Mon Dec 19 16:13:45 IST 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

View File

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