From 0934f62fe70f85a6ba55b8d11382eb71a25e1146 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Tue, 14 Oct 2025 23:04:51 +0800 Subject: [PATCH 1/6] Revert "Add snippet to ensure baseline.profm file is sorted" This reverts commit 7e5c5f5e7f594e84943b6ffeda3664381722faff. The issue has been long resolved making this fix no longer required. --- app/build.gradle | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 38765476a..784f11ee7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,7 +1,3 @@ -import com.android.tools.profgen.ArtProfileKt -import com.android.tools.profgen.ArtProfileSerializer -import com.android.tools.profgen.DexFile - plugins { id "com.android.application" id "kotlin-android" @@ -336,25 +332,3 @@ static String getGitWorkingBranch() { return "" } } - -// fix reproducible builds -project.afterEvaluate { - tasks.compileReleaseArtProfile.doLast { - outputs.files.each { file -> - if (file.toString().endsWith(".profm")) { - println("Sorting ${file} ...") - def version = ArtProfileSerializer.valueOf("METADATA_0_0_2") - def profile = ArtProfileKt.ArtProfile(file) - def keys = new ArrayList(profile.profileData.keySet()) - def sortedData = new LinkedHashMap() - Collections.sort keys, new DexFile.Companion() - keys.each { key -> sortedData[key] = profile.profileData[key] } - new FileOutputStream(file).with { - write(version.magicBytes$profgen) - write(version.versionBytes$profgen) - version.write$profgen(it, sortedData, "") - } - } - } - } -} From 87c6e1025ae89c0e9d5cfa88e45f9fab3fb4727b Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Tue, 14 Oct 2025 23:02:42 +0800 Subject: [PATCH 2/6] Migrate build scripts to kotlin DSL Ref: https://developer.android.com/build/migrate-to-kotlin-dsl Signed-off-by: Aayush Gupta --- app/build.gradle | 334 ------------------------------------------- app/build.gradle.kts | 320 +++++++++++++++++++++++++++++++++++++++++ build.gradle | 25 ---- build.gradle.kts | 12 ++ settings.gradle | 11 -- settings.gradle.kts | 32 +++++ 6 files changed, 364 insertions(+), 370 deletions(-) delete mode 100644 app/build.gradle create mode 100644 app/build.gradle.kts delete mode 100644 build.gradle create mode 100644 build.gradle.kts delete mode 100644 settings.gradle create mode 100644 settings.gradle.kts diff --git a/app/build.gradle b/app/build.gradle deleted file mode 100644 index 784f11ee7..000000000 --- a/app/build.gradle +++ /dev/null @@ -1,334 +0,0 @@ -plugins { - id "com.android.application" - id "kotlin-android" - id "kotlin-kapt" - id "kotlin-parcelize" - id "checkstyle" - id "org.sonarqube" version "4.0.0.2929" -} - -android { - compileSdk 36 - namespace 'org.schabi.newpipe' - - defaultConfig { - applicationId "org.schabi.newpipe" - resValue "string", "app_name", "NewPipe" - minSdk 21 - targetSdk 35 - if (System.properties.containsKey('versionCodeOverride')) { - versionCode System.getProperty('versionCodeOverride') as Integer - } else { - versionCode 1005 - } - versionName "0.28.0" - if (System.properties.containsKey('versionNameSuffix')) { - versionNameSuffix System.getProperty('versionNameSuffix') - } - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - - javaCompileOptions { - annotationProcessorOptions { - arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] - } - } - } - - buildTypes { - debug { - debuggable true - - // suffix the app id and the app name with git branch name - def workingBranch = getGitWorkingBranch() - def normalizedWorkingBranch = workingBranch.replaceFirst("^[^A-Za-z]+", "").replaceAll("[^0-9A-Za-z]+", "") - if (normalizedWorkingBranch.isEmpty() || workingBranch == "master" || workingBranch == "dev") { - // default values when branch name could not be determined or is master or dev - applicationIdSuffix ".debug" - resValue "string", "app_name", "NewPipe Debug" - } else { - applicationIdSuffix ".debug." + normalizedWorkingBranch - resValue "string", "app_name", "NewPipe " + workingBranch - archivesBaseName = 'NewPipe_' + normalizedWorkingBranch - } - } - - release { - if (System.properties.containsKey('packageSuffix')) { - applicationIdSuffix System.getProperty('packageSuffix') - resValue "string", "app_name", "NewPipe " + System.getProperty('packageSuffix') - archivesBaseName = 'NewPipe_' + System.getProperty('packageSuffix') - } - minifyEnabled true - shrinkResources false // disabled to fix F-Droid's reproducible build - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - archivesBaseName = 'app' - } - } - - lint { - checkReleaseBuilds false - // Or, if you prefer, you can continue to check for errors in release builds, - // but continue the build even when errors are found: - abortOnError false - // suppress false warning ("Resource IDs will be non-final in Android Gradle Plugin version - // 5.0, avoid using them in switch case statements"), which affects only library projects - disable 'NonConstantResourceId' - } - - compileOptions { - // Flag to enable support for the new language APIs - coreLibraryDesugaringEnabled true - - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - encoding 'utf-8' - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17 - } - - sourceSets { - androidTest.assets.srcDirs += files("$projectDir/schemas".toString()) - } - - androidResources { - generateLocaleConfig = true - } - - buildFeatures { - viewBinding true - buildConfig true - } - - packagingOptions { - resources { - // remove two files which belong to jsoup - // no idea how they ended up in the META-INF dir... - excludes += ['META-INF/README.md', 'META-INF/CHANGES', - // 'COPYRIGHT' belongs to RxJava... - 'META-INF/COPYRIGHT'] - } - } -} - -ext { - checkstyleVersion = '10.12.1' - - androidxLifecycleVersion = '2.6.2' - androidxRoomVersion = '2.6.1' - androidxWorkVersion = '2.8.1' - - stateSaverVersion = '1.4.1' - exoPlayerVersion = '2.18.7' - googleAutoServiceVersion = '1.1.1' - groupieVersion = '2.10.1' - markwonVersion = '4.6.2' - - leakCanaryVersion = '2.12' - stethoVersion = '1.6.0' -} - -configurations { - checkstyle - ktlint -} - -checkstyle { - getConfigDirectory().set(rootProject.file("checkstyle")) - ignoreFailures false - showViolations true - toolVersion = checkstyleVersion -} - -tasks.register('runCheckstyle', Checkstyle) { - source 'src' - include '**/*.java' - exclude '**/gen/**' - exclude '**/R.java' - exclude '**/BuildConfig.java' - exclude 'main/java/us/shandian/giga/**' - - classpath = configurations.checkstyle - - showViolations true - - reports { - xml.getRequired().set(true) - html.getRequired().set(true) - } -} - -def outputDir = "${project.buildDir}/reports/ktlint/" -def inputFiles = project.fileTree(dir: "src", include: "**/*.kt") - -tasks.register('runKtlint', JavaExec) { - inputs.files(inputFiles) - outputs.dir(outputDir) - getMainClass().set("com.pinterest.ktlint.Main") - classpath = configurations.ktlint - args "src/**/*.kt" - jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED") -} - -tasks.register('formatKtlint', JavaExec) { - inputs.files(inputFiles) - outputs.dir(outputDir) - getMainClass().set("com.pinterest.ktlint.Main") - classpath = configurations.ktlint - args "-F", "src/**/*.kt" - jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED") -} - -afterEvaluate { - if (!System.properties.containsKey('skipFormatKtlint')) { - preDebugBuild.dependsOn formatKtlint - } - preDebugBuild.dependsOn runCheckstyle, runKtlint -} - -sonar { - properties { - property "sonar.projectKey", "TeamNewPipe_NewPipe" - property "sonar.organization", "teamnewpipe" - property "sonar.host.url", "https://sonarcloud.io" - } -} - -dependencies { -/** Desugaring **/ - coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs_nio:2.0.4' - -/** NewPipe libraries **/ - // You can use a local version by uncommenting a few lines in settings.gradle - // Or you can use a commit you pushed to GitHub by just replacing TeamNewPipe with your GitHub - // name and the commit hash with the commit hash of the (pushed) commit you want to test - // This works thanks to JitPack: https://jitpack.io/ - implementation 'com.github.TeamNewPipe:nanojson:e9d656ddb49a412a5a0a5d5ef20ca7ef09549996' - // WORKAROUND: if you get errors with the NewPipeExtractor dependency, replace `v0.24.3` with - // the corresponding commit hash, since JitPack sometimes deletes artifacts. - // If there’s already a git hash, just add more of it to the end (or remove a letter) - // to cause jitpack to regenerate the artifact. - implementation 'com.github.TeamNewPipe:NewPipeExtractor:0023b22095a2d62a60cdfc87f4b5cd85c8b266c3' - implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0' - -/** Checkstyle **/ - checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}" - ktlint 'com.pinterest:ktlint:0.45.2' - -/** Kotlin **/ - implementation "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}" - -/** AndroidX **/ - implementation 'androidx.appcompat:appcompat:1.7.1' - implementation 'androidx.cardview:cardview:1.0.0' - implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'androidx.core:core-ktx:1.12.0' - implementation 'androidx.documentfile:documentfile:1.0.1' - implementation 'androidx.fragment:fragment-ktx:1.6.2' - implementation "androidx.lifecycle:lifecycle-livedata-ktx:${androidxLifecycleVersion}" - implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:${androidxLifecycleVersion}" - implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0' - implementation 'androidx.media:media:1.7.0' - implementation 'androidx.preference:preference:1.2.1' - implementation 'androidx.recyclerview:recyclerview:1.3.2' - implementation "androidx.room:room-runtime:${androidxRoomVersion}" - implementation "androidx.room:room-rxjava3:${androidxRoomVersion}" - kapt "androidx.room:room-compiler:${androidxRoomVersion}" - implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' - // Newer version specified to prevent accessibility regressions with RecyclerView, see: - // https://developer.android.com/jetpack/androidx/releases/viewpager2#1.1.0-alpha01 - implementation 'androidx.viewpager2:viewpager2:1.1.0-beta02' - implementation "androidx.work:work-runtime-ktx:${androidxWorkVersion}" - implementation "androidx.work:work-rxjava3:${androidxWorkVersion}" - implementation 'com.google.android.material:material:1.11.0' - implementation "androidx.webkit:webkit:1.9.0" - -/** Third-party libraries **/ - // Instance state boilerplate elimination - implementation 'com.github.livefront:bridge:v2.0.2' - implementation "com.evernote:android-state:$stateSaverVersion" - kapt "com.evernote:android-state-processor:$stateSaverVersion" - - // HTML parser - implementation "org.jsoup:jsoup:1.17.2" - - // HTTP client - implementation "com.squareup.okhttp3:okhttp:4.12.0" - - // Media player - implementation "com.google.android.exoplayer:exoplayer-core:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-dash:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-database:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-datasource:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-hls:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-smoothstreaming:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:exoplayer-ui:${exoPlayerVersion}" - implementation "com.google.android.exoplayer:extension-mediasession:${exoPlayerVersion}" - - // Metadata generator for service descriptors - compileOnly "com.google.auto.service:auto-service-annotations:${googleAutoServiceVersion}" - kapt "com.google.auto.service:auto-service:${googleAutoServiceVersion}" - - // Manager for complex RecyclerView layouts - implementation "com.github.lisawray.groupie:groupie:${groupieVersion}" - implementation "com.github.lisawray.groupie:groupie-viewbinding:${groupieVersion}" - - // Image loading - //noinspection NewerVersionAvailable,GradleDependency --> 2.8 is the last version, not 2.71828! - implementation "com.squareup.picasso:picasso:2.8" - - // Markdown library for Android - implementation "io.noties.markwon:core:${markwonVersion}" - implementation "io.noties.markwon:linkify:${markwonVersion}" - - // Crash reporting - implementation "ch.acra:acra-core:5.11.3" - - // Properly restarting - implementation 'com.jakewharton:process-phoenix:2.1.2' - - // Reactive extensions for Java VM - implementation "io.reactivex.rxjava3:rxjava:3.1.8" - implementation "io.reactivex.rxjava3:rxandroid:3.0.2" - // RxJava binding APIs for Android UI widgets - implementation "com.jakewharton.rxbinding4:rxbinding:4.0.0" - - // Date and time formatting - implementation "org.ocpsoft.prettytime:prettytime:5.0.8.Final" - -/** Debugging **/ - // Memory leak detection - debugImplementation "com.squareup.leakcanary:leakcanary-object-watcher-android:${leakCanaryVersion}" - debugImplementation "com.squareup.leakcanary:plumber-android:${leakCanaryVersion}" - debugImplementation "com.squareup.leakcanary:leakcanary-android-core:${leakCanaryVersion}" - // Debug bridge for Android - debugImplementation "com.facebook.stetho:stetho:${stethoVersion}" - debugImplementation "com.facebook.stetho:stetho-okhttp3:${stethoVersion}" - -/** Testing **/ - testImplementation 'junit:junit:4.13.2' - testImplementation 'org.mockito:mockito-core:5.6.0' - - androidTestImplementation "androidx.test.ext:junit:1.1.5" - androidTestImplementation "androidx.test:runner:1.5.2" - androidTestImplementation "androidx.room:room-testing:${androidxRoomVersion}" - androidTestImplementation "org.assertj:assertj-core:3.24.2" -} - -static String getGitWorkingBranch() { - try { - def gitProcess = "git rev-parse --abbrev-ref HEAD".execute() - gitProcess.waitFor() - if (gitProcess.exitValue() == 0) { - return gitProcess.text.trim() - } else { - // not a git repository - return "" - } - } catch (IOException ignored) { - // git was not found - return "" - } -} diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 000000000..4bbb8ad93 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,320 @@ +/* + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +plugins { + id("com.android.application") + id("kotlin-android") + id("kotlin-kapt") + id("kotlin-parcelize") + id("org.sonarqube") + checkstyle +} + +val gitWorkingBranch = providers.exec { + commandLine("git", "rev-parse", "--abbrev-ref", "HEAD") +}.standardOutput.asText.map { it.trim() } + +android { + compileSdk = 36 + namespace = "org.schabi.newpipe" + + defaultConfig { + applicationId = "org.schabi.newpipe" + resValue("string", "app_name", "NewPipe") + minSdk = 21 + targetSdk = 35 + + versionCode = System.getProperty("versionCodeOverride")?.toInt() ?: 1005 + + versionName = "0.28.0" + System.getProperty("versionNameSuffix")?.let { versionNameSuffix = it } + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + + javaCompileOptions { + annotationProcessorOptions { + arguments["room.schemaLocation"] = "$projectDir/schemas" + } + } + } + + buildTypes { + debug { + isDebuggable = true + + // suffix the app id and the app name with git branch name + val defaultBranches = listOf("master", "dev") + val workingBranch = gitWorkingBranch.getOrElse("") + val normalizedWorkingBranch = workingBranch + .replaceFirst("^[^A-Za-z]+".toRegex(), "") + .replace("[^0-9A-Za-z]+".toRegex(), "") + + if (normalizedWorkingBranch.isEmpty() || workingBranch in defaultBranches) { + // default values when branch name could not be determined or is master or dev + applicationIdSuffix = ".debug" + resValue("string", "app_name", "NewPipe Debug") + } else { + applicationIdSuffix = ".debug.$normalizedWorkingBranch" + resValue("string", "app_name", "NewPipe $workingBranch") + setProperty("archivesBaseName", "NewPipe_$normalizedWorkingBranch") + } + } + + release { + System.getProperty("packageSuffix")?.let { suffix -> + applicationIdSuffix = suffix + resValue("string", "app_name", "NewPipe $suffix") + setProperty("archivesBaseName", "NewPipe_" + System.getProperty("packageSuffix")) + } + isMinifyEnabled = true + isShrinkResources = false // disabled to fix F-Droid"s reproducible build + proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + setProperty("archivesBaseName", "app") + } + } + + lint { + checkReleaseBuilds = false + // Or, if you prefer, you can continue to check for errors in release builds, + // but continue the build even when errors are found: + abortOnError = false + // suppress false warning ("Resource IDs will be non-final in Android Gradle Plugin version + // 5.0, avoid using them in switch case statements"), which affects only library projects + disable += "NonConstantResourceId" + } + + compileOptions { + // Flag to enable support for the new language APIs + isCoreLibraryDesugaringEnabled = true + + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + encoding = "utf-8" + } + + kotlinOptions { + jvmTarget = "17" + } + + sourceSets { + getByName("androidTest") { + assets.srcDir("$projectDir/schemas") + } + } + + androidResources { + generateLocaleConfig = true + } + + buildFeatures { + viewBinding = true + buildConfig = true + } + + packaging { + resources { + // remove two files which belong to jsoup + // no idea how they ended up in the META-INF dir... + excludes += setOf( + "META-INF/README.md", + "META-INF/CHANGES", + "META-INF/COPYRIGHT" // "COPYRIGHT" belongs to RxJava... + ) + } + } +} + +val checkstyleVersion = "10.12.1" + +val androidxLifecycleVersion = "2.6.2" +val androidxRoomVersion = "2.6.1" +val androidxWorkVersion = "2.8.1" + +val stateSaverVersion = "1.4.1" +val exoPlayerVersion = "2.18.7" +val googleAutoServiceVersion = "1.1.1" +val groupieVersion = "2.10.1" +val markwonVersion = "4.6.2" + +val leakCanaryVersion = "2.12" +val stethoVersion = "1.6.0" + +val ktlint by configurations.creating + +checkstyle { + configDirectory = rootProject.file("checkstyle") + isIgnoreFailures = false + isShowViolations = true + toolVersion = checkstyleVersion +} + +tasks.register("runCheckstyle") { + source("src") + include("**/*.java") + exclude("**/gen/**") + exclude("**/R.java") + exclude("**/BuildConfig.java") + exclude("main/java/us/shandian/giga/**") + + classpath = configurations.getByName("checkstyle") + + isShowViolations = true + + reports { + xml.required = true + html.required = true + } +} + +val outputDir = project.layout.buildDirectory.dir("reports/ktlint/") +val inputFiles = fileTree("src") { include("**/*.kt") } + +tasks.register("runKtlint") { + inputs.files(inputFiles) + outputs.dir(outputDir) + mainClass.set("com.pinterest.ktlint.Main") + classpath = configurations.getByName("ktlint") + args = listOf("src/**/*.kt") + jvmArgs = listOf("--add-opens", "java.base/java.lang=ALL-UNNAMED") +} + +tasks.register("formatKtlint") { + inputs.files(inputFiles) + outputs.dir(outputDir) + mainClass.set("com.pinterest.ktlint.Main") + classpath = configurations.getByName("ktlint") + args = listOf("-F", "src/**/*.kt") + jvmArgs = listOf("--add-opens", "java.base/java.lang=ALL-UNNAMED") +} + +afterEvaluate { + tasks.named("preDebugBuild").configure { + if (!System.getProperties().containsKey("skipFormatKtlint")) { + dependsOn("formatKtlint") + } + dependsOn("runCheckstyle", "runKtlint") + } +} + +sonar { + properties { + property("sonar.projectKey", "TeamNewPipe_NewPipe") + property("sonar.organization", "teamnewpipe") + property("sonar.host.url", "https://sonarcloud.io") + } +} + +dependencies { + /** Desugaring **/ + coreLibraryDesugaring("com.android.tools:desugar_jdk_libs_nio:2.0.4") + + /** NewPipe libraries **/ + implementation("com.github.TeamNewPipe:nanojson:e9d656ddb49a412a5a0a5d5ef20ca7ef09549996") + // WORKAROUND: if you get errors with the NewPipeExtractor dependency, replace `v0.24.3` with + // the corresponding commit hash, since JitPack sometimes deletes artifacts. + // If there’s already a git hash, just add more of it to the end (or remove a letter) + // to cause jitpack to regenerate the artifact. + implementation("com.github.TeamNewPipe:NewPipeExtractor:0023b22095a2d62a60cdfc87f4b5cd85c8b266c3") + implementation("com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0") + + /** Checkstyle **/ + checkstyle("com.puppycrawl.tools:checkstyle:$checkstyleVersion") + ktlint("com.pinterest:ktlint:0.45.2") + + /** AndroidX **/ + implementation("androidx.appcompat:appcompat:1.7.1") + implementation("androidx.cardview:cardview:1.0.0") + implementation("androidx.constraintlayout:constraintlayout:2.1.4") + implementation("androidx.core:core-ktx:1.12.0") + implementation("androidx.documentfile:documentfile:1.0.1") + implementation("androidx.fragment:fragment-ktx:1.6.2") + implementation("androidx.lifecycle:lifecycle-livedata-ktx:$androidxLifecycleVersion") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$androidxLifecycleVersion") + implementation("androidx.localbroadcastmanager:localbroadcastmanager:1.1.0") + implementation("androidx.media:media:1.7.0") + implementation("androidx.preference:preference:1.2.1") + implementation("androidx.recyclerview:recyclerview:1.3.2") + implementation("androidx.room:room-runtime:$androidxRoomVersion") + implementation("androidx.room:room-rxjava3:$androidxRoomVersion") + kapt("androidx.room:room-compiler:$androidxRoomVersion") + implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") + // Newer version specified to prevent accessibility regressions with RecyclerView, see: + // https://developer.android.com/jetpack/androidx/releases/viewpager2#1.1.0-alpha01 + implementation("androidx.viewpager2:viewpager2:1.1.0-beta02") + implementation("androidx.work:work-runtime-ktx:$androidxWorkVersion") + implementation("androidx.work:work-rxjava3:$androidxWorkVersion") + implementation("com.google.android.material:material:1.11.0") + implementation("androidx.webkit:webkit:1.9.0") + + /** Third-party libraries **/ + implementation("com.github.livefront:bridge:v2.0.2") + implementation("com.evernote:android-state:$stateSaverVersion") + kapt("com.evernote:android-state-processor:$stateSaverVersion") + + // HTML parser + implementation("org.jsoup:jsoup:1.17.2") + + // HTTP client + implementation("com.squareup.okhttp3:okhttp:4.12.0") + + // Media player + implementation("com.google.android.exoplayer:exoplayer-core:$exoPlayerVersion") + implementation("com.google.android.exoplayer:exoplayer-dash:$exoPlayerVersion") + implementation("com.google.android.exoplayer:exoplayer-database:$exoPlayerVersion") + implementation("com.google.android.exoplayer:exoplayer-datasource:$exoPlayerVersion") + implementation("com.google.android.exoplayer:exoplayer-hls:$exoPlayerVersion") + implementation("com.google.android.exoplayer:exoplayer-smoothstreaming:$exoPlayerVersion") + implementation("com.google.android.exoplayer:exoplayer-ui:$exoPlayerVersion") + implementation("com.google.android.exoplayer:extension-mediasession:$exoPlayerVersion") + + // Metadata generator for service descriptors + compileOnly("com.google.auto.service:auto-service-annotations:$googleAutoServiceVersion") + kapt("com.google.auto.service:auto-service:$googleAutoServiceVersion") + + // Manager for complex RecyclerView layouts + implementation("com.github.lisawray.groupie:groupie:$groupieVersion") + implementation("com.github.lisawray.groupie:groupie-viewbinding:$groupieVersion") + + // Image loading + //noinspection NewerVersionAvailable,GradleDependency --> 2.8 is the last version, not 2.71828! + implementation("com.squareup.picasso:picasso:2.8") + + // Markdown library for Android + implementation("io.noties.markwon:core:$markwonVersion") + implementation("io.noties.markwon:linkify:$markwonVersion") + + // Crash reporting + implementation("ch.acra:acra-core:5.11.3") + + // Properly restarting + implementation("com.jakewharton:process-phoenix:2.1.2") + + // Reactive extensions for Java VM + implementation("io.reactivex.rxjava3:rxjava:3.1.8") + implementation("io.reactivex.rxjava3:rxandroid:3.0.2") + // RxJava binding APIs for Android UI widgets + implementation("com.jakewharton.rxbinding4:rxbinding:4.0.0") + + // Date and time formatting + implementation("org.ocpsoft.prettytime:prettytime:5.0.8.Final") + + /** Debugging **/ + // Memory leak detection + debugImplementation("com.squareup.leakcanary:leakcanary-object-watcher-android:$leakCanaryVersion") + debugImplementation("com.squareup.leakcanary:plumber-android:$leakCanaryVersion") + debugImplementation("com.squareup.leakcanary:leakcanary-android-core:$leakCanaryVersion") + // Debug bridge for Android + debugImplementation("com.facebook.stetho:stetho:$stethoVersion") + debugImplementation("com.facebook.stetho:stetho-okhttp3:$stethoVersion") + + /** Testing **/ + testImplementation("junit:junit:4.13.2") + testImplementation("org.mockito:mockito-core:5.6.0") + + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test:runner:1.5.2") + androidTestImplementation("androidx.room:room-testing:$androidxRoomVersion") + androidTestImplementation("org.assertj:assertj-core:3.24.2") +} diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 3cdc0dc59..000000000 --- a/build.gradle +++ /dev/null @@ -1,25 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - ext.kotlin_version = '1.9.25' - repositories { - google() - mavenCentral() - } - dependencies { - classpath 'com.android.tools.build:gradle:8.13.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - google() - mavenCentral() - maven { url "https://jitpack.io" } - maven { url "https://repo.clojars.org" } - } -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 000000000..d08a3cda5 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +plugins { + id("com.android.application") version "8.13.0" apply false + id("org.jetbrains.kotlin.android") version "1.9.25" apply false + id("org.jetbrains.kotlin.kapt") version "1.9.25" apply false + id("org.jetbrains.kotlin.plugin.parcelize") version "1.9.25" apply false + id("org.sonarqube") version "4.0.0.2929" apply false +} diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 0338fde6c..000000000 --- a/settings.gradle +++ /dev/null @@ -1,11 +0,0 @@ -include ':app' - -// Use a local copy of NewPipe Extractor by uncommenting the lines below. -// We assume, that NewPipe and NewPipe Extractor have the same parent directory. -// If this is not the case, please change the path in includeBuild(). - -//includeBuild('../NewPipeExtractor') { -// dependencySubstitution { -// substitute module('com.github.TeamNewPipe:NewPipeExtractor') using project(':extractor') -// } -//} diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 000000000..d9e899151 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +pluginManagement { + repositories { + gradlePluginPortal() + google() + mavenCentral() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + maven(url = "https://jitpack.io") + maven(url = "https://repo.clojars.org") + } +} +include (":app") + +// Use a local copy of NewPipe Extractor by uncommenting the lines below. +// We assume, that NewPipe and NewPipe Extractor have the same parent directory. +// If this is not the case, please change the path in includeBuild(). + +//includeBuild('../NewPipeExtractor') { +// dependencySubstitution { +// substitute module('com.github.TeamNewPipe:NewPipeExtractor') using project(':extractor') +// } +//} From 2e79d7387db56e023ab4f604ddb926170aa1af5f Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Wed, 15 Oct 2025 12:58:54 +0800 Subject: [PATCH 3/6] Migrate to build version catalog Ref: https://developer.android.com/build/migrate-to-catalogs Signed-off-by: Aayush Gupta --- app/build.gradle.kts | 163 +++++++++++++++++--------------------- build.gradle.kts | 10 +-- gradle/libs.versions.toml | 130 ++++++++++++++++++++++++++++++ 3 files changed, 206 insertions(+), 97 deletions(-) create mode 100644 gradle/libs.versions.toml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4bbb8ad93..e5f9ce3e4 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -4,11 +4,11 @@ */ plugins { - id("com.android.application") - id("kotlin-android") - id("kotlin-kapt") - id("kotlin-parcelize") - id("org.sonarqube") + alias(libs.plugins.android.application) + alias(libs.plugins.jetbrains.kotlin.android) + alias(libs.plugins.jetbrains.kotlin.kapt) + alias(libs.plugins.jetbrains.kotlin.parcelize) + alias(libs.plugins.sonarqube) checkstyle } @@ -126,28 +126,14 @@ android { } } -val checkstyleVersion = "10.12.1" - -val androidxLifecycleVersion = "2.6.2" -val androidxRoomVersion = "2.6.1" -val androidxWorkVersion = "2.8.1" - -val stateSaverVersion = "1.4.1" -val exoPlayerVersion = "2.18.7" -val googleAutoServiceVersion = "1.1.1" -val groupieVersion = "2.10.1" -val markwonVersion = "4.6.2" - -val leakCanaryVersion = "2.12" -val stethoVersion = "1.6.0" - +// Custom dependency configuration for ktlint val ktlint by configurations.creating checkstyle { configDirectory = rootProject.file("checkstyle") isIgnoreFailures = false isShowViolations = true - toolVersion = checkstyleVersion + toolVersion = libs.versions.checkstyle.get() } tasks.register("runCheckstyle") { @@ -208,113 +194,106 @@ sonar { dependencies { /** Desugaring **/ - coreLibraryDesugaring("com.android.tools:desugar_jdk_libs_nio:2.0.4") + coreLibraryDesugaring(libs.android.desugar) /** NewPipe libraries **/ - implementation("com.github.TeamNewPipe:nanojson:e9d656ddb49a412a5a0a5d5ef20ca7ef09549996") - // WORKAROUND: if you get errors with the NewPipeExtractor dependency, replace `v0.24.3` with - // the corresponding commit hash, since JitPack sometimes deletes artifacts. - // If there’s already a git hash, just add more of it to the end (or remove a letter) - // to cause jitpack to regenerate the artifact. - implementation("com.github.TeamNewPipe:NewPipeExtractor:0023b22095a2d62a60cdfc87f4b5cd85c8b266c3") - implementation("com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0") + implementation(libs.newpipe.nanojson) + implementation(libs.newpipe.extractor) + implementation(libs.newpipe.filepicker) /** Checkstyle **/ - checkstyle("com.puppycrawl.tools:checkstyle:$checkstyleVersion") - ktlint("com.pinterest:ktlint:0.45.2") + checkstyle(libs.puppycrawl.checkstyle) + ktlint(libs.pinterest.ktlint) /** AndroidX **/ - implementation("androidx.appcompat:appcompat:1.7.1") - implementation("androidx.cardview:cardview:1.0.0") - implementation("androidx.constraintlayout:constraintlayout:2.1.4") - implementation("androidx.core:core-ktx:1.12.0") - implementation("androidx.documentfile:documentfile:1.0.1") - implementation("androidx.fragment:fragment-ktx:1.6.2") - implementation("androidx.lifecycle:lifecycle-livedata-ktx:$androidxLifecycleVersion") - implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$androidxLifecycleVersion") - implementation("androidx.localbroadcastmanager:localbroadcastmanager:1.1.0") - implementation("androidx.media:media:1.7.0") - implementation("androidx.preference:preference:1.2.1") - implementation("androidx.recyclerview:recyclerview:1.3.2") - implementation("androidx.room:room-runtime:$androidxRoomVersion") - implementation("androidx.room:room-rxjava3:$androidxRoomVersion") - kapt("androidx.room:room-compiler:$androidxRoomVersion") - implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") - // Newer version specified to prevent accessibility regressions with RecyclerView, see: - // https://developer.android.com/jetpack/androidx/releases/viewpager2#1.1.0-alpha01 - implementation("androidx.viewpager2:viewpager2:1.1.0-beta02") - implementation("androidx.work:work-runtime-ktx:$androidxWorkVersion") - implementation("androidx.work:work-rxjava3:$androidxWorkVersion") - implementation("com.google.android.material:material:1.11.0") - implementation("androidx.webkit:webkit:1.9.0") + implementation(libs.androidx.appcompat) + implementation(libs.androidx.cardview) + implementation(libs.androidx.constraintlayout) + implementation(libs.androidx.core) + implementation(libs.androidx.documentfile) + implementation(libs.androidx.fragment) + implementation(libs.androidx.lifecycle.livedata) + implementation(libs.androidx.lifecycle.viewmodel) + implementation(libs.androidx.localbroadcastmanager) + implementation(libs.androidx.media) + implementation(libs.androidx.preference) + implementation(libs.androidx.recyclerview) + implementation(libs.androidx.room.runtime) + implementation(libs.androidx.room.rxjava3) + kapt(libs.androidx.room.compiler) + implementation(libs.androidx.swiperefreshlayout) + implementation(libs.androidx.viewpager2) + implementation(libs.androidx.work.runtime) + implementation(libs.androidx.work.rxjava3) + implementation(libs.google.android.material) + implementation(libs.androidx.webkit) /** Third-party libraries **/ - implementation("com.github.livefront:bridge:v2.0.2") - implementation("com.evernote:android-state:$stateSaverVersion") - kapt("com.evernote:android-state-processor:$stateSaverVersion") + implementation(libs.livefront.bridge) + implementation(libs.evernote.statesaver.core) + kapt(libs.evernote.statesaver.compiler) // HTML parser - implementation("org.jsoup:jsoup:1.17.2") + implementation(libs.jsoup) // HTTP client - implementation("com.squareup.okhttp3:okhttp:4.12.0") + implementation(libs.squareup.okhttp) // Media player - implementation("com.google.android.exoplayer:exoplayer-core:$exoPlayerVersion") - implementation("com.google.android.exoplayer:exoplayer-dash:$exoPlayerVersion") - implementation("com.google.android.exoplayer:exoplayer-database:$exoPlayerVersion") - implementation("com.google.android.exoplayer:exoplayer-datasource:$exoPlayerVersion") - implementation("com.google.android.exoplayer:exoplayer-hls:$exoPlayerVersion") - implementation("com.google.android.exoplayer:exoplayer-smoothstreaming:$exoPlayerVersion") - implementation("com.google.android.exoplayer:exoplayer-ui:$exoPlayerVersion") - implementation("com.google.android.exoplayer:extension-mediasession:$exoPlayerVersion") + implementation(libs.google.exoplayer.core) + implementation(libs.google.exoplayer.dash) + implementation(libs.google.exoplayer.database) + implementation(libs.google.exoplayer.datasource) + implementation(libs.google.exoplayer.hls) + implementation(libs.google.exoplayer.mediasession) + implementation(libs.google.exoplayer.smoothstreaming) + implementation(libs.google.exoplayer.ui) // Metadata generator for service descriptors - compileOnly("com.google.auto.service:auto-service-annotations:$googleAutoServiceVersion") - kapt("com.google.auto.service:auto-service:$googleAutoServiceVersion") + compileOnly(libs.google.autoservice.annotations) + kapt(libs.google.autoservice.compiler) // Manager for complex RecyclerView layouts - implementation("com.github.lisawray.groupie:groupie:$groupieVersion") - implementation("com.github.lisawray.groupie:groupie-viewbinding:$groupieVersion") + implementation(libs.lisawray.groupie.core) + implementation(libs.lisawray.groupie.viewbinding) // Image loading - //noinspection NewerVersionAvailable,GradleDependency --> 2.8 is the last version, not 2.71828! - implementation("com.squareup.picasso:picasso:2.8") + implementation(libs.squareup.picasso) // Markdown library for Android - implementation("io.noties.markwon:core:$markwonVersion") - implementation("io.noties.markwon:linkify:$markwonVersion") + implementation(libs.noties.markwon.core) + implementation(libs.noties.markwon.linkify) // Crash reporting - implementation("ch.acra:acra-core:5.11.3") + implementation(libs.acra.core) // Properly restarting - implementation("com.jakewharton:process-phoenix:2.1.2") + implementation(libs.jakewharton.phoenix) // Reactive extensions for Java VM - implementation("io.reactivex.rxjava3:rxjava:3.1.8") - implementation("io.reactivex.rxjava3:rxandroid:3.0.2") + implementation(libs.reactivex.rxjava) + implementation(libs.reactivex.rxandroid) // RxJava binding APIs for Android UI widgets - implementation("com.jakewharton.rxbinding4:rxbinding:4.0.0") + implementation(libs.jakewharton.rxbinding) // Date and time formatting - implementation("org.ocpsoft.prettytime:prettytime:5.0.8.Final") + implementation(libs.ocpsoft.prettytime) /** Debugging **/ // Memory leak detection - debugImplementation("com.squareup.leakcanary:leakcanary-object-watcher-android:$leakCanaryVersion") - debugImplementation("com.squareup.leakcanary:plumber-android:$leakCanaryVersion") - debugImplementation("com.squareup.leakcanary:leakcanary-android-core:$leakCanaryVersion") + debugImplementation(libs.squareup.leakcanary.watcher) + debugImplementation(libs.squareup.leakcanary.plumber) + debugImplementation(libs.squareup.leakcanary.core) // Debug bridge for Android - debugImplementation("com.facebook.stetho:stetho:$stethoVersion") - debugImplementation("com.facebook.stetho:stetho-okhttp3:$stethoVersion") + debugImplementation(libs.facebook.stetho.core) + debugImplementation(libs.facebook.stetho.okhttp3) /** Testing **/ - testImplementation("junit:junit:4.13.2") - testImplementation("org.mockito:mockito-core:5.6.0") + testImplementation(libs.junit) + testImplementation(libs.mockito.core) - androidTestImplementation("androidx.test.ext:junit:1.1.5") - androidTestImplementation("androidx.test:runner:1.5.2") - androidTestImplementation("androidx.room:room-testing:$androidxRoomVersion") - androidTestImplementation("org.assertj:assertj-core:3.24.2") + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.runner) + androidTestImplementation(libs.androidx.room.testing) + androidTestImplementation(libs.assertj.core) } diff --git a/build.gradle.kts b/build.gradle.kts index d08a3cda5..e79ccc3e0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,9 +4,9 @@ */ plugins { - id("com.android.application") version "8.13.0" apply false - id("org.jetbrains.kotlin.android") version "1.9.25" apply false - id("org.jetbrains.kotlin.kapt") version "1.9.25" apply false - id("org.jetbrains.kotlin.plugin.parcelize") version "1.9.25" apply false - id("org.sonarqube") version "4.0.0.2929" apply false + alias(libs.plugins.android.application) apply false + alias(libs.plugins.jetbrains.kotlin.android) apply false + alias(libs.plugins.jetbrains.kotlin.kapt) apply false + alias(libs.plugins.jetbrains.kotlin.parcelize) apply false + alias(libs.plugins.sonarqube) apply false } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 000000000..f0718d4fb --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,130 @@ +# +# SPDX-FileCopyrightText: 2025 NewPipe e.V. +# SPDX-License-Identifier: GPL-3.0-or-later +# + +[versions] +acra = "5.11.3" +agp = "8.13.0" +appcompat = "1.7.1" +assertj = "3.24.2" +autoservice = "1.1.1" +bridge = "v2.0.2" +cardview = "1.0.0" +checkstyle = "10.12.1" +constraintlayout = "2.1.4" +core = "1.12.0" +desugar = "2.0.4" +documentfile = "1.0.1" +exoplayer = "2.18.7" +extractor = "0023b22095a2d62a60cdfc87f4b5cd85c8b266c3" +filepicker = "5.0.0" +fragment = "1.6.2" +groupie = "2.10.1" +jsoup = "1.17.2" +junit = "4.13.2" +junit-ext = "1.1.5" +kotlin = "1.9.25" +ktlint = "0.45.2" +leakcanary = "2.12" +lifecycle = "2.6.2" +localbroadcastmanager = "1.1.0" +markwon = "4.6.2" +material = "1.11.0" +media = "1.7.0" +mockitoCore = "5.6.0" +nanojson = "e9d656ddb49a412a5a0a5d5ef20ca7ef09549996" +okhttp = "4.12.0" +phoenix = "2.1.2" +#noinspection NewerVersionAvailable,GradleDependency --> 2.8 is the last version, not 2.71828! +picasso = "2.8" +preference = "1.2.1" +prettytime = "5.0.8.Final" +recyclerview = "1.3.2" +room = "2.6.1" +runner = "1.5.2" +rxandroid = "3.0.2" +rxbinding = "4.0.0" +rxjava = "3.1.8" +sonarqube = "4.0.0.2929" +statesaver = "1.4.1" +stetho = "1.6.0" +swiperefreshlayout = "1.1.0" +# Newer version specified to prevent accessibility regressions with RecyclerView +# see: https://developer.android.com/jetpack/androidx/releases/viewpager2#1.1.0-alpha01 +viewpager2 = "1.1.0-beta02" +webkit = "1.9.0" +work = "2.8.1" + +[libraries] +acra-core = { module = "ch.acra:acra-core", version.ref = "acra" } +android-desugar = { module = "com.android.tools:desugar_jdk_libs_nio", version.ref = "desugar" } +androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" } +androidx-cardview = { module = "androidx.cardview:cardview", version.ref = "cardview" } +androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" } +androidx-core = { module = "androidx.core:core-ktx", version.ref = "core" } +androidx-documentfile = { module = "androidx.documentfile:documentfile", version.ref = "documentfile" } +androidx-fragment = { module = "androidx.fragment:fragment-ktx", version.ref = "fragment" } +androidx-junit = { module = "androidx.test.ext:junit", version.ref = "junit-ext" } +androidx-lifecycle-livedata = { module = "androidx.lifecycle:lifecycle-livedata-ktx", version.ref = "lifecycle" } +androidx-lifecycle-viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycle" } +androidx-localbroadcastmanager = { module = "androidx.localbroadcastmanager:localbroadcastmanager", version.ref = "localbroadcastmanager" } +androidx-media = { module = "androidx.media:media", version.ref = "media" } +androidx-preference = { module = "androidx.preference:preference", version.ref = "preference" } +androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerview" } +androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" } +androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" } +androidx-room-rxjava3 = { module = "androidx.room:room-rxjava3", version.ref = "room" } +androidx-room-testing = { module = "androidx.room:room-testing", version.ref = "room" } +androidx-runner = { module = "androidx.test:runner", version.ref = "runner" } +androidx-swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version.ref = "swiperefreshlayout" } +androidx-viewpager2 = { module = "androidx.viewpager2:viewpager2", version.ref = "viewpager2" } +androidx-webkit = { module = "androidx.webkit:webkit", version.ref = "webkit" } +androidx-work-runtime = { module = "androidx.work:work-runtime-ktx", version.ref = "work" } +androidx-work-rxjava3 = { module = "androidx.work:work-rxjava3", version.ref = "work" } +assertj-core = { module = "org.assertj:assertj-core", version.ref = "assertj" } +evernote-statesaver-compiler = { module = "com.evernote:android-state-processor", version.ref = "statesaver" } +evernote-statesaver-core = { module = "com.evernote:android-state", version.ref = "statesaver" } +facebook-stetho-core = { module = "com.facebook.stetho:stetho", version.ref = "stetho" } +facebook-stetho-okhttp3 = { module = "com.facebook.stetho:stetho-okhttp3", version.ref = "stetho" } +google-android-material = { module = "com.google.android.material:material", version.ref = "material" } +google-autoservice-annotations = { module = "com.google.auto.service:auto-service-annotations", version.ref = "autoservice" } +google-autoservice-compiler = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" } +google-exoplayer-core = { module = "com.google.android.exoplayer:exoplayer-core", version.ref = "exoplayer" } +google-exoplayer-dash = { module = "com.google.android.exoplayer:exoplayer-dash", version.ref = "exoplayer" } +google-exoplayer-database = { module = "com.google.android.exoplayer:exoplayer-database", version.ref = "exoplayer" } +google-exoplayer-datasource = { module = "com.google.android.exoplayer:exoplayer-datasource", version.ref = "exoplayer" } +google-exoplayer-hls = { module = "com.google.android.exoplayer:exoplayer-hls", version.ref = "exoplayer" } +google-exoplayer-mediasession = { module = "com.google.android.exoplayer:extension-mediasession", version.ref = "exoplayer" } +google-exoplayer-smoothstreaming = { module = "com.google.android.exoplayer:exoplayer-smoothstreaming", version.ref = "exoplayer" } +google-exoplayer-ui = { module = "com.google.android.exoplayer:exoplayer-ui", version.ref = "exoplayer" } +jakewharton-phoenix = { module = "com.jakewharton:process-phoenix", version.ref = "phoenix" } +jakewharton-rxbinding = { module = "com.jakewharton.rxbinding4:rxbinding", version.ref = "rxbinding" } +jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" } +junit = { module = "junit:junit", version.ref = "junit" } +lisawray-groupie-core = { module = "com.github.lisawray.groupie:groupie", version.ref = "groupie" } +lisawray-groupie-viewbinding = { module = "com.github.lisawray.groupie:groupie-viewbinding", version.ref = "groupie" } +livefront-bridge = { module = "com.github.livefront:bridge", version.ref = "bridge" } +mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockitoCore" } +newpipe-extractor = { module = "com.github.TeamNewPipe:NewPipeExtractor", version.ref = "extractor" } +newpipe-filepicker = { module = "com.github.TeamNewPipe:NoNonsense-FilePicker", version.ref = "filepicker" } +newpipe-nanojson = { module = "com.github.TeamNewPipe:nanojson", version.ref = "nanojson" } +noties-markwon-core = { module = "io.noties.markwon:core", version.ref = "markwon" } +noties-markwon-linkify = { module = "io.noties.markwon:linkify", version.ref = "markwon" } +ocpsoft-prettytime = { module = "org.ocpsoft.prettytime:prettytime", version.ref = "prettytime" } +pinterest-ktlint = { module = "com.pinterest:ktlint", version.ref = "ktlint" } +puppycrawl-checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" } +reactivex-rxandroid = { module = "io.reactivex.rxjava3:rxandroid", version.ref = "rxandroid" } +reactivex-rxjava = { module = "io.reactivex.rxjava3:rxjava", version.ref = "rxjava" } +squareup-leakcanary-core = { module = "com.squareup.leakcanary:leakcanary-android-core", version.ref = "leakcanary" } +squareup-leakcanary-plumber = { module = "com.squareup.leakcanary:plumber-android", version.ref = "leakcanary" } +squareup-leakcanary-watcher = { module = "com.squareup.leakcanary:leakcanary-object-watcher-android", version.ref = "leakcanary" } +squareup-okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } +squareup-picasso = { module = "com.squareup.picasso:picasso", version.ref = "picasso" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "agp" } +jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +jetbrains-kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } +jetbrains-kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } +sonarqube = { id = "org.sonarqube", version.ref = "sonarqube" } From 7be0c6377306ac2600b38e65ed10fae24c2114e7 Mon Sep 17 00:00:00 2001 From: Jie Li Date: Tue, 26 Nov 2024 18:32:44 +0000 Subject: [PATCH 4/6] Gradle script to enforce dependencies order Signed-off-by: Aayush Gupta --- app/build.gradle.kts | 4 ++- app/check-dependencies.gradle.kts | 59 +++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 app/check-dependencies.gradle.kts diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e5f9ce3e4..8dd1594f2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -12,6 +12,8 @@ plugins { checkstyle } +apply(from = "check-dependencies.gradle.kts") + val gitWorkingBranch = providers.exec { commandLine("git", "rev-parse", "--abbrev-ref", "HEAD") }.standardOutput.asText.map { it.trim() } @@ -180,7 +182,7 @@ afterEvaluate { if (!System.getProperties().containsKey("skipFormatKtlint")) { dependsOn("formatKtlint") } - dependsOn("runCheckstyle", "runKtlint") + dependsOn("runCheckstyle", "runKtlint", "checkDependenciesOrder") } } diff --git a/app/check-dependencies.gradle.kts b/app/check-dependencies.gradle.kts new file mode 100644 index 000000000..fc77148db --- /dev/null +++ b/app/check-dependencies.gradle.kts @@ -0,0 +1,59 @@ +/* + * SPDX-FileCopyrightText: 2024 NewPipe contributors + * SPDX-FileCopyrightText: 2025 NewPipe e.V. + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +tasks.register("checkDependenciesOrder") { + group = "verification" + description = "Checks that each section in libs.versions.toml is sorted alphabetically" + + val tomlFile = file("../gradle/libs.versions.toml") + + doLast { + if (!tomlFile.exists()) { + throw GradleException("TOML file not found") + } + + val lines = tomlFile.readLines() + val nonSortedBlocks = mutableListOf>() + var currentBlock = mutableListOf() + var prevLine = "" + var prevIndex = 0 + + lines.forEachIndexed { lineIndex, line -> + if (line.trim().isNotEmpty() && !line.startsWith("#")) { + if (line.startsWith("[")) { + prevLine = "" + } else { + val currIndex = lineIndex + 1 + if (prevLine > line) { + if (currentBlock.isNotEmpty() && currentBlock.last() == "$prevIndex: $prevLine") { + currentBlock.add("$currIndex: $line") + } else { + if (currentBlock.isNotEmpty()) { + nonSortedBlocks.add(currentBlock) + currentBlock = mutableListOf() + } + currentBlock.add("$prevIndex: $prevLine") + currentBlock.add("$currIndex: $line") + } + } + prevLine = line + prevIndex = lineIndex + 1 + } + } + } + + if (currentBlock.isNotEmpty()) { + nonSortedBlocks.add(currentBlock) + } + + if (nonSortedBlocks.isNotEmpty()) { + throw GradleException( + "The following lines were not sorted:\n" + + nonSortedBlocks.joinToString("\n\n") { it.joinToString("\n") } + ) + } + } +} From 3784dbd4ca827d2bff664a7912d0ca861c36baf0 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Thu, 16 Oct 2025 22:27:56 +0800 Subject: [PATCH 5/6] Drop deprecated non-working archivesBaseName property Signed-off-by: Aayush Gupta --- app/build.gradle.kts | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8dd1594f2..e4c186e50 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -60,7 +60,6 @@ android { } else { applicationIdSuffix = ".debug.$normalizedWorkingBranch" resValue("string", "app_name", "NewPipe $workingBranch") - setProperty("archivesBaseName", "NewPipe_$normalizedWorkingBranch") } } @@ -68,12 +67,10 @@ android { System.getProperty("packageSuffix")?.let { suffix -> applicationIdSuffix = suffix resValue("string", "app_name", "NewPipe $suffix") - setProperty("archivesBaseName", "NewPipe_" + System.getProperty("packageSuffix")) } isMinifyEnabled = true isShrinkResources = false // disabled to fix F-Droid"s reproducible build proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - setProperty("archivesBaseName", "app") } } From fef0e02a4d3219cf1b0ab73d649494742ab6f491 Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Fri, 17 Oct 2025 16:25:51 +0800 Subject: [PATCH 6/6] Specify JDK toolchain directly Specifying JDK toolchain in the java block lets us avoid specifying same version again and again for different options while ensuring everything is on the same version Ref: https://developer.android.com/build/jdks#toolchain Signed-off-by: Aayush Gupta --- app/build.gradle.kts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e4c186e50..037c3cb53 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -18,6 +18,12 @@ val gitWorkingBranch = providers.exec { commandLine("git", "rev-parse", "--abbrev-ref", "HEAD") }.standardOutput.asText.map { it.trim() } +java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } +} + android { compileSdk = 36 namespace = "org.schabi.newpipe" @@ -87,16 +93,9 @@ android { compileOptions { // Flag to enable support for the new language APIs isCoreLibraryDesugaringEnabled = true - - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 encoding = "utf-8" } - kotlinOptions { - jvmTarget = "17" - } - sourceSets { getByName("androidTest") { assets.srcDir("$projectDir/schemas")