NuvioTV/app/build.gradle.kts
2026-04-16 00:58:23 +05:30

365 lines
16 KiB
Text

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.androidx.baselineprofile)
alias(libs.plugins.hilt)
alias(libs.plugins.ksp)
alias(libs.plugins.kotlin.serialization)
}
import java.util.Properties
val localProperties = Properties().apply {
val localPropertiesFile = rootProject.file("local.properties")
if (localPropertiesFile.exists()) {
load(localPropertiesFile.inputStream())
}
}
val devProperties = Properties().apply {
val devPropertiesFile = rootProject.file("local.dev.properties")
if (devPropertiesFile.exists()) {
load(devPropertiesFile.inputStream())
}
}
fun env(name: String): String? = providers.environmentVariable(name).orNull
val useDebugReleaseSigning = env("CI_USE_DEBUG_SIGNING").equals("true", ignoreCase = true)
val releaseStoreFilePath = env("NUVIO_RELEASE_STORE_FILE")
?: localProperties.getProperty("NUVIO_RELEASE_STORE_FILE")
val releaseKeyAliasValue = env("NUVIO_RELEASE_KEY_ALIAS")
?: localProperties.getProperty("NUVIO_RELEASE_KEY_ALIAS", "nuviotv")
val releaseKeyPasswordValue = env("NUVIO_RELEASE_KEY_PASSWORD")
?: localProperties.getProperty("NUVIO_RELEASE_KEY_PASSWORD", "815787")
val releaseStorePasswordValue = env("NUVIO_RELEASE_STORE_PASSWORD")
?: localProperties.getProperty("NUVIO_RELEASE_STORE_PASSWORD", "815787")
android {
namespace = "com.nuvio.tv"
compileSdk = 36
defaultConfig {
applicationId = "com.nuvio.tv"
minSdk = 24
targetSdk = 36
versionCode = 54
versionName = "0.6.3-beta"
buildConfigField("String", "PARENTAL_GUIDE_API_URL", "\"${localProperties.getProperty("PARENTAL_GUIDE_API_URL", "")}\"")
buildConfigField("String", "INTRODB_API_URL", "\"${localProperties.getProperty("INTRODB_API_URL", "")}\"")
buildConfigField("String", "TRAILER_API_URL", "\"${localProperties.getProperty("TRAILER_API_URL", "")}\"")
buildConfigField("String", "IMDB_RATINGS_API_BASE_URL", "\"${localProperties.getProperty("IMDB_RATINGS_API_BASE_URL", "")}\"")
buildConfigField("String", "IMDB_TAPFRAME_API_BASE_URL", "\"${localProperties.getProperty("IMDB_TAPFRAME_API_BASE_URL", "")}\"")
buildConfigField("String", "TRAKT_CLIENT_ID", "\"${localProperties.getProperty("TRAKT_CLIENT_ID", "")}\"")
buildConfigField("String", "TRAKT_CLIENT_SECRET", "\"${localProperties.getProperty("TRAKT_CLIENT_SECRET", "")}\"")
buildConfigField("String", "TRAKT_API_URL", "\"${localProperties.getProperty("TRAKT_API_URL", "https://api.trakt.tv/")}\"")
buildConfigField("String", "TRAKT_REDIRECT_URI", "\"${localProperties.getProperty("TRAKT_REDIRECT_URI", "urn:ietf:wg:oauth:2.0:oob")}\"")
buildConfigField("String", "TMDB_API_KEY", "\"${localProperties.getProperty("TMDB_API_KEY", "")}\"")
buildConfigField("String", "TV_LOGIN_WEB_BASE_URL", "\"${localProperties.getProperty("TV_LOGIN_WEB_BASE_URL", "https://app.nuvio.tv/tv-login")}\"")
buildConfigField("String", "DONATIONS_BASE_URL", "\"${localProperties.getProperty("DONATIONS_BASE_URL", "")}\"")
buildConfigField("String", "DONATIONS_DONATE_URL", "\"${localProperties.getProperty("DONATIONS_DONATE_URL", "")}\"")
buildConfigField("String", "AVATAR_PUBLIC_BASE_URL", "\"${localProperties.getProperty("AVATAR_PUBLIC_BASE_URL", "")}\"")
// In-app updater (GitHub Releases)
buildConfigField("String", "GITHUB_OWNER", "\"tapframe\"")
buildConfigField("String", "GITHUB_REPO", "\"NuvioTV\"")
}
signingConfigs {
create("release") {
keyAlias = releaseKeyAliasValue
keyPassword = releaseKeyPasswordValue
storeFile = releaseStoreFilePath?.let(::file) ?: file("../nuviotv.jks")
storePassword = releaseStorePasswordValue
}
}
buildTypes {
debug {
signingConfig = signingConfigs.getByName("release")
isDebuggable = false
isMinifyEnabled = false
buildConfigField("boolean", "IS_DEBUG_BUILD", "true")
// Dev environment (from local.dev.properties)
buildConfigField("String", "SUPABASE_URL", "\"${devProperties.getProperty("SUPABASE_URL", "")}\"")
buildConfigField("String", "SUPABASE_ANON_KEY", "\"${devProperties.getProperty("SUPABASE_ANON_KEY", "")}\"")
buildConfigField("String", "TV_LOGIN_WEB_BASE_URL", "\"${devProperties.getProperty("TV_LOGIN_WEB_BASE_URL", "https://app.nuvio.tv/tv-login")}\"")
buildConfigField("String", "PARENTAL_GUIDE_API_URL", "\"${devProperties.getProperty("PARENTAL_GUIDE_API_URL", "")}\"")
buildConfigField("String", "INTRODB_API_URL", "\"${devProperties.getProperty("INTRODB_API_URL", "")}\"")
buildConfigField("String", "TRAILER_API_URL", "\"${devProperties.getProperty("TRAILER_API_URL", "")}\"")
buildConfigField("String", "IMDB_RATINGS_API_BASE_URL", "\"${devProperties.getProperty("IMDB_RATINGS_API_BASE_URL", "")}\"")
buildConfigField("String", "IMDB_TAPFRAME_API_BASE_URL", "\"${devProperties.getProperty("IMDB_TAPFRAME_API_BASE_URL", "")}\"")
buildConfigField("String", "DONATIONS_BASE_URL", "\"${devProperties.getProperty("DONATIONS_BASE_URL", localProperties.getProperty("DONATIONS_BASE_URL", ""))}\"")
buildConfigField("String", "DONATIONS_DONATE_URL", "\"${devProperties.getProperty("DONATIONS_DONATE_URL", localProperties.getProperty("DONATIONS_DONATE_URL", ""))}\"")
buildConfigField("String", "AVATAR_PUBLIC_BASE_URL", "\"${devProperties.getProperty("AVATAR_PUBLIC_BASE_URL", localProperties.getProperty("AVATAR_PUBLIC_BASE_URL", ""))}\"")
}
release {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
signingConfig = if (useDebugReleaseSigning) {
signingConfigs.getByName("debug")
} else {
signingConfigs.getByName("release")
}
buildConfigField("boolean", "IS_DEBUG_BUILD", "false")
// Production environment (from local.properties)
buildConfigField("String", "SUPABASE_URL", "\"${localProperties.getProperty("SUPABASE_URL", "")}\"")
buildConfigField("String", "SUPABASE_ANON_KEY", "\"${localProperties.getProperty("SUPABASE_ANON_KEY", "")}\"")
buildConfigField("String", "TV_LOGIN_WEB_BASE_URL", "\"${localProperties.getProperty("TV_LOGIN_WEB_BASE_URL", "https://app.nuvio.tv/tv-login")}\"")
buildConfigField("String", "PARENTAL_GUIDE_API_URL", "\"${localProperties.getProperty("PARENTAL_GUIDE_API_URL", "")}\"")
buildConfigField("String", "INTRODB_API_URL", "\"${localProperties.getProperty("INTRODB_API_URL", "")}\"")
buildConfigField("String", "TRAILER_API_URL", "\"${localProperties.getProperty("TRAILER_API_URL", "")}\"")
buildConfigField("String", "IMDB_RATINGS_API_BASE_URL", "\"${localProperties.getProperty("IMDB_RATINGS_API_BASE_URL", "")}\"")
buildConfigField("String", "IMDB_TAPFRAME_API_BASE_URL", "\"${localProperties.getProperty("IMDB_TAPFRAME_API_BASE_URL", "")}\"")
buildConfigField("String", "DONATIONS_BASE_URL", "\"${localProperties.getProperty("DONATIONS_BASE_URL", "")}\"")
buildConfigField("String", "DONATIONS_DONATE_URL", "\"${localProperties.getProperty("DONATIONS_DONATE_URL", "")}\"")
buildConfigField("String", "AVATAR_PUBLIC_BASE_URL", "\"${localProperties.getProperty("AVATAR_PUBLIC_BASE_URL", "")}\"")
}
create("benchmark") {
initWith(buildTypes.getByName("release"))
signingConfig = signingConfigs.getByName("debug")
isDebuggable = false
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
applicationIdSuffix = ".debug"
matchingFallbacks += "release"
}
}
splits {
abi {
isEnable = true
reset()
include("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
isUniversalApk = true
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
isCoreLibraryDesugaringEnabled = true
}
kotlin {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11)
}
}
buildFeatures {
compose = true
buildConfig = true
}
sourceSets {
getByName("main") {
jniLibs.srcDirs("src/main/jniLibs")
}
}
packaging {
jniLibs {
// Keep one consistent native set across dependencies.
pickFirsts += listOf(
"lib/*/libc++_shared.so",
"lib/*/libavcodec.so",
"lib/*/libavdevice.so",
"lib/*/libavfilter.so",
"lib/*/libavformat.so",
"lib/*/libavutil.so",
"lib/*/libswscale.so",
"lib/*/libswresample.so",
"lib/*/libtorrserver.so"
)
}
}
}
androidComponents {
onVariants(selector().withBuildType("debug")) { variant ->
variant.applicationId.set("com.nuviodebug.com")
}
}
composeCompiler {
// Enable Compose compiler metrics for performance analysis
metricsDestination = layout.buildDirectory.dir("compose_metrics")
reportsDestination = layout.buildDirectory.dir("compose_reports")
stabilityConfigurationFiles.add(rootProject.layout.projectDirectory.file("compose_stability_config.conf"))
}
// Globally exclude stock media3-exoplayer and media3-ui — replaced by forked local AARs
configurations.all {
exclude(group = "androidx.media3", module = "media3-exoplayer")
exclude(group = "androidx.media3", module = "media3-ui")
}
baselineProfile {
automaticGenerationDuringBuild = false
saveInSrc = true
mergeIntoMain = true
baselineProfileOutputDir = "src/main"
filter {
include("com.nuvio.tv.**")
}
}
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
val composeBom = platform("androidx.compose:compose-bom:2026.01.01")
baselineProfile(project(":baselineprofile"))
implementation(libs.androidx.core.ktx)
implementation("androidx.core:core-splashscreen:1.0.1")
implementation(libs.androidx.appcompat)
implementation(libs.androidx.profileinstaller)
implementation("androidx.recyclerview:recyclerview:1.4.0")
implementation(composeBom)
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.graphics)
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")
implementation("androidx.compose.foundation:foundation")
implementation("androidx.compose.material:material-icons-extended")
implementation("androidx.tv:tv-material:1.0.1")
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation("androidx.activity:activity-compose:1.11.0")
// Hilt
implementation(libs.hilt.android)
ksp(libs.hilt.compiler)
implementation(libs.hilt.navigation.compose)
// Networking
implementation(libs.retrofit)
implementation(libs.retrofit.moshi)
implementation(libs.okhttp)
implementation(libs.okhttp.logging)
implementation(libs.moshi)
ksp(libs.moshi.codegen)
// Coroutines
implementation(libs.coroutines.core)
implementation(libs.coroutines.android)
// Image Loading
implementation(libs.coil.compose)
implementation(libs.coil.gif)
implementation(libs.coil.svg)
// Navigation
implementation(libs.navigation.compose)
// DataStore
implementation(libs.datastore.preferences)
// ViewModel
implementation(libs.lifecycle.viewmodel.compose)
// Media3 ExoPlayer — using custom forked ExoPlayer from local AARs (like Just Player)
// The forked lib-exoplayer-release.aar replaces stock media3-exoplayer (globally excluded above)
// lib-ui-release.aar replaces stock media3-ui (globally excluded above)
implementation(libs.media3.exoplayer.hls)
implementation(libs.media3.exoplayer.dash)
implementation(libs.media3.exoplayer.smoothstreaming)
implementation(libs.media3.exoplayer.rtsp)
implementation(libs.media3.datasource)
implementation(libs.media3.datasource.okhttp)
implementation(libs.media3.decoder)
implementation(libs.media3.session)
implementation(libs.media3.common)
implementation(libs.media3.container)
implementation(libs.media3.extractor)
// Local AAR libraries from forked ExoPlayer (matching Just Player setup):
// - lib-exoplayer-release.aar — Custom forked ExoPlayer core (replaces media3-exoplayer)
// - lib-ui-release.aar — Custom forked ExoPlayer UI
// - lib-decoder-ffmpeg-release.aar — FFmpeg audio decoders (vorbis,opus,flac,alac,pcm,mp3,amr,aac,ac3,eac3,dca,mlp,truehd)
// - lib-decoder-av1-release.aar — AV1 software video decoder (libgav1)
// - lib-decoder-iamf-release.aar — IAMF immersive audio decoder
// - lib-decoder-mpegh-release.aar — MPEG-H 3D audio decoder
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("lib-*.aar"))))
// libass-android for ASS/SSA subtitle support (from Maven Central)
implementation("io.github.peerless2012:ass-media:0.4.0-beta01")
// Local nextlib-mediainfo fork (static FFmpeg; no libav*.so in final AAR)
implementation(files("libs/nextlib-mediainfo-local.aar"))
implementation("io.github.abdallahmehiz:mpv-android-lib:0.1.12")
implementation("dev.chrisbanes.haze:haze-android:0.7.3") {
exclude(group = "org.jetbrains.compose.ui")
exclude(group = "org.jetbrains.compose.foundation")
}
// Local Plugin System
implementation(libs.quickjs.kt)
implementation(libs.jsoup)
implementation(libs.gson)
// Jackson — required by CloudStream DEX extensions at runtime
implementation("com.fasterxml.jackson.core:jackson-databind:2.17.0")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.17.0")
// NiceHTTP — HTTP client used by CloudStream extensions via `app.get()`
implementation(libs.nicehttp)
// Conscrypt — TLS provider with browser-compatible fingerprint for Cloudflare bypass
implementation(libs.conscrypt.android)
// CloudStream library — provides core API classes for extension compatibility
implementation(libs.cloudstream.library) {
// Exclude heavy deps we don't need or that conflict
exclude(group = "org.mozilla", module = "rhino")
exclude(group = "com.github.AmarullisVFX", module = "newpipeextractor")
exclude(group = "com.github.AmaryllisVFX", module = "newpipeextractor")
exclude(group = "com.github.AmaryllisVFX.newpipeextractor")
exclude(group = "info.debatty", module = "java-string-similarity")
}
// Markdown rendering
implementation(libs.markdown.renderer.m3)
// Bundle real crypto-js (JS) for QuickJS plugins
implementation(libs.crypto.js)
// QR code + local server for addon management
implementation(libs.nanohttpd)
implementation(libs.zxing.core)
// Supabase
implementation(platform(libs.supabase.bom))
implementation(libs.supabase.auth)
implementation(libs.supabase.postgrest)
implementation(libs.ktor.client.okhttp)
// Kotlinx Serialization
implementation(libs.kotlinx.serialization.json)
// Performance profiling
implementation("androidx.metrics:metrics-performance:1.0.0-rc01") // JankStats
debugImplementation("androidx.compose.runtime:runtime-tracing")
// Bundle real crypto-js (JS) for QuickJS plugins
implementation("org.webjars.npm:crypto-js:4.2.0")
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
testImplementation("junit:junit:4.13.2")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1")
testImplementation("io.mockk:mockk:1.13.12")
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation(libs.androidx.compose.ui.test.manifest)
}