Zero org.schabi.newpipe classes in straw Kotlin. strawcore (Rust + rustypipe via UniFFI) is the only extractor. Deletions: - strawApp/src/main/kotlin/com/sulkta/straw/extractor/NewPipeDownloader.kt (was the OkHttp adapter; STRAW_USER_AGENT + strawHttpClient() in net/Http.kt cover its role) - strawApp/src/main/kotlin/com/sulkta/straw/util/Thumbnails.kt (rustypipe surfaces a pre-picked thumbnail URL; no helper needed) Build: - libs.newpipe.extractor dependency removed from strawApp/build.gradle.kts Call-site swaps: - net/RydClient.kt, net/SponsorBlockClient.kt: NewPipeDownloader.client() + .USER_AGENT → strawHttpClient() + STRAW_USER_AGENT - feature/player/PlayerScreen.kt, feature/player/PlaybackService.kt, feature/detail/VideoDetailScreen.kt: ExoPlayer DefaultHttpDataSource.Factory now reads STRAW_USER_AGENT from net/Http - StrawApp.kt: NewPipe.init() call gone; History/Settings/Subscriptions bootstrap unchanged net/Http.kt gains STRAW_USER_AGENT const + strawHttpClient() lazy OkHttpClient with the same shape NewPipeDownloader had (15s connect, 30s read, follow redirects).
206 lines
7.5 KiB
Kotlin
206 lines
7.5 KiB
Kotlin
/*
|
|
* SPDX-FileCopyrightText: 2026 Sulkta-Coop
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*
|
|
* :strawApp — thin Android application shell. Day-2: pulls NewPipeExtractor,
|
|
* Media3, Ktor-style HTTP-via-OkHttp + kotlinx-serialization JSON for the
|
|
* search → detail → player → SponsorBlock + RYD flow. We keep our deps in
|
|
* this module, NOT in the shared libs.versions.toml, so upstream NewPipe
|
|
* stays cleanly mergeable.
|
|
*/
|
|
|
|
import com.android.build.api.dsl.ApplicationExtension
|
|
|
|
plugins {
|
|
alias(libs.plugins.android.application)
|
|
alias(libs.plugins.jetbrains.kotlin.compose)
|
|
alias(libs.plugins.jetbrains.kotlinx.serialization)
|
|
}
|
|
|
|
kotlin {
|
|
jvmToolchain(21)
|
|
}
|
|
|
|
configure<ApplicationExtension> {
|
|
compileSdk {
|
|
version = release(NEWPIPE_VERSION_SDK_COMPILE_MAJOR) {
|
|
minorApiLevel = NEWPIPE_VERSION_SDK_COMPILE_MINOR
|
|
}
|
|
}
|
|
namespace = STRAW_APPLICATION_ID
|
|
|
|
defaultConfig {
|
|
applicationId = STRAW_APPLICATION_ID
|
|
minSdk { version = release(24) }
|
|
targetSdk { version = release(NEWPIPE_VERSION_SDK_TARGET) }
|
|
versionCode = STRAW_VERSION_CODE
|
|
versionName = STRAW_VERSION_NAME
|
|
resValue("string", "app_name", "Straw")
|
|
}
|
|
|
|
buildTypes {
|
|
debug {
|
|
isDebuggable = true
|
|
applicationIdSuffix = ".debug"
|
|
resValue("string", "app_name", "Straw debug")
|
|
}
|
|
release {
|
|
isMinifyEnabled = false
|
|
}
|
|
}
|
|
|
|
compileOptions {
|
|
sourceCompatibility = JavaVersion.VERSION_21
|
|
targetCompatibility = JavaVersion.VERSION_21
|
|
}
|
|
|
|
buildFeatures {
|
|
compose = true
|
|
buildConfig = true
|
|
resValues = true
|
|
}
|
|
|
|
packaging {
|
|
resources {
|
|
excludes += setOf(
|
|
"META-INF/README.md",
|
|
"META-INF/CHANGES",
|
|
"META-INF/COPYRIGHT",
|
|
"META-INF/INDEX.LIST",
|
|
"META-INF/io.netty.versions.properties",
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
// Compose + AndroidX core
|
|
implementation(libs.androidx.activity)
|
|
implementation(libs.androidx.core)
|
|
implementation(libs.jetbrains.compose.runtime)
|
|
implementation(libs.jetbrains.compose.foundation)
|
|
implementation(libs.jetbrains.compose.material3)
|
|
implementation(libs.jetbrains.compose.ui)
|
|
implementation("androidx.compose.material:material-icons-core:1.7.5")
|
|
|
|
// Lifecycle + ViewModel for Compose
|
|
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.10.0")
|
|
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.10.0")
|
|
|
|
// Coroutines
|
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.11.0")
|
|
|
|
// Image loading
|
|
implementation(libs.coil.compose)
|
|
implementation(libs.coil.network.okhttp)
|
|
|
|
// NewPipeExtractor (JVM/Android-only) + its OkHttp dep
|
|
// libs.newpipe.extractor — REMOVED in Path C-6. Extractor is now strawcore
|
|
// (Rust + rustypipe via UniFFI). See rust/strawcore/ + the cargoBuild +
|
|
// uniffiBindgen Gradle tasks below.
|
|
implementation(libs.squareup.okhttp)
|
|
|
|
// JSON for SponsorBlock + Return YouTube Dislike clients
|
|
implementation(libs.kotlinx.serialization.json)
|
|
|
|
// Media3 ExoPlayer
|
|
implementation("androidx.media3:media3-exoplayer:1.4.1")
|
|
implementation("androidx.media3:media3-exoplayer-dash:1.4.1")
|
|
implementation("androidx.media3:media3-exoplayer-hls:1.4.1")
|
|
implementation("androidx.media3:media3-ui:1.4.1")
|
|
// Media3 session — MediaSessionService for background audio + lock-screen controls.
|
|
implementation("androidx.media3:media3-session:1.4.1")
|
|
// Guava ListenableFuture support for awaiting MediaController connect.
|
|
implementation("androidx.concurrent:concurrent-futures-ktx:1.2.0")
|
|
|
|
// strawcore — Rust YouTube extractor via UniFFI/JNA. Built by the
|
|
// cargoBuild + uniffiBindgen tasks below; phase U-2+ exposes search /
|
|
// streamInfo / channelInfo to replace NewPipeExtractor.
|
|
implementation("net.java.dev.jna:jna:5.14.0@aar")
|
|
}
|
|
|
|
// =============================================================================
|
|
// Phase U-1 / Path-C-2 — Rust core build glue.
|
|
//
|
|
// Two tasks chain into the Android build:
|
|
// cargoBuild — cross-compiles rust/strawcore for the four Android ABIs
|
|
// via cargo-ndk and drops the .so files in strawApp/src/main/jniLibs/.
|
|
// uniffiBindgen — generates the Kotlin bindings from the freshly-built lib
|
|
// into strawApp/src/main/java/uniffi/strawcore/.
|
|
//
|
|
// Both depend on:
|
|
// - cargo + rustup with the four Android targets installed
|
|
// - cargo-ndk on PATH
|
|
// - ANDROID_NDK_HOME pointing at an NDK with the right toolchains
|
|
// All of that lives in the crafting-table container.
|
|
// =============================================================================
|
|
|
|
val rustRoot = file("../rust").absolutePath
|
|
val jniLibsDir = file("src/main/jniLibs").absolutePath
|
|
val bindingsDir = file("src/main/java").absolutePath
|
|
|
|
val cargoHome: String = System.getenv("CARGO_HOME") ?: "/caches/cargo"
|
|
val cargoBin: String = "$cargoHome/bin/cargo"
|
|
val ndkHome: String = System.getenv("ANDROID_NDK_HOME")
|
|
?: System.getenv("ANDROID_NDK_ROOT")
|
|
?: "/caches/android-sdk/ndk/27.2.12479018"
|
|
// Honor CARGO_TARGET_DIR if set (we redirect it to /caches on crafting-table
|
|
// because the container's writable rootfs hits 100% before the cross-compile
|
|
// for 4 ABIs finishes). Falls back to the default `<workspace>/target`.
|
|
val cargoTargetDir: String = System.getenv("CARGO_TARGET_DIR")
|
|
?: "$rustRoot/target"
|
|
|
|
val cargoBuild by tasks.registering(Exec::class) {
|
|
group = "rust"
|
|
description = "Cross-compile strawcore for all Android ABIs via cargo-ndk."
|
|
workingDir = file(rustRoot)
|
|
environment("ANDROID_NDK_HOME", ndkHome)
|
|
environment("PATH", "$cargoHome/bin:${System.getenv("PATH") ?: ""}")
|
|
commandLine = listOf(
|
|
cargoBin, "ndk",
|
|
"-t", "arm64-v8a",
|
|
"-t", "armeabi-v7a",
|
|
"-t", "x86",
|
|
"-t", "x86_64",
|
|
"-o", jniLibsDir,
|
|
"build", "--release", "-p", "strawcore",
|
|
)
|
|
standardOutput = System.out
|
|
errorOutput = System.err
|
|
}
|
|
|
|
val cargoBuildHost by tasks.registering(Exec::class) {
|
|
group = "rust"
|
|
description = "Build host-arch debug strawcore so bindgen can read its UniFFI metadata."
|
|
workingDir = file(rustRoot)
|
|
environment("PATH", "$cargoHome/bin:${System.getenv("PATH") ?: ""}")
|
|
commandLine = listOf(cargoBin, "build", "-p", "strawcore")
|
|
standardOutput = System.out
|
|
errorOutput = System.err
|
|
}
|
|
|
|
val uniffiBindgen by tasks.registering(Exec::class) {
|
|
group = "rust"
|
|
description = "Generate Kotlin bindings for strawcore via uniffi-bindgen."
|
|
dependsOn(cargoBuildHost)
|
|
workingDir = file(rustRoot)
|
|
environment("PATH", "$cargoHome/bin:${System.getenv("PATH") ?: ""}")
|
|
commandLine = listOf(
|
|
cargoBin, "run", "--quiet", "--bin", "uniffi-bindgen", "--",
|
|
"generate",
|
|
"--library", "$cargoTargetDir/debug/libstrawcore.so",
|
|
"--crate", "strawcore",
|
|
"--language", "kotlin",
|
|
"--no-format",
|
|
"--out-dir", bindingsDir,
|
|
)
|
|
standardOutput = System.out
|
|
errorOutput = System.err
|
|
}
|
|
|
|
// Make sure Android's JNI-libs merge picks up the freshly built .so files,
|
|
// and Kotlin compilation can resolve the generated bindings.
|
|
tasks.matching { it.name.startsWith("merge") && it.name.endsWith("JniLibFolders") }
|
|
.configureEach { dependsOn(cargoBuild) }
|
|
tasks.matching { it.name.startsWith("compile") && it.name.endsWith("Kotlin") }
|
|
.configureEach { dependsOn(uniffiBindgen) }
|