From e82cfb6e9786c47db6535518c0554b17af1a2b66 Mon Sep 17 00:00:00 2001 From: iHsin Date: Sun, 26 Apr 2026 14:20:53 +0800 Subject: [PATCH 01/11] test ci --- .github/workflows/ci.yml | 9 +++++++++ core/build.gradle.kts | 24 ++++++++++++++++++++++-- uniffi/.cargo/config.toml | 4 ++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f8a8ff..0685dc5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,6 +69,15 @@ jobs: - name: Run sccache-cache uses: mozilla-actions/sccache-action@v0.0.9 + + - name: Pre-build cargo dependencies (generate classes.jar) + run: | + cd uniffi + cargo fetch + cargo build -p rustls-platform-verifier-android + env: + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: "sccache" - name: Cache Gradle dependencies uses: actions/cache@v5 diff --git a/core/build.gradle.kts b/core/build.gradle.kts index ed42e20..1059928 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -8,8 +8,10 @@ plugins { } fun findRustlsPlatformVerifierClasses(): File { + val uniffiDir = File(project.rootDir, "uniffi") + val dependencyJson = providers.exec { - workingDir = File(project.rootDir, "uniffi") + workingDir = uniffiDir commandLine("cargo", "metadata", "--format-version", "1") }.standardOutput.asText @@ -23,7 +25,25 @@ fun findRustlsPlatformVerifierClasses(): File { }.let { it as Map<*, *> }["manifest_path"] as String val manifestFile = File(path) - return File(manifestFile.parentFile, "classes.jar") + val jarFile = File(manifestFile.parentFile, "classes.jar") + + if (!jarFile.exists()) { + val buildDir = File(uniffiDir, "target") + if (buildDir.exists()) { + val existing = buildDir.walkTopDown() + .maxDepth(12) + .firstOrNull { it.name == "classes.jar" } + if (existing != null) return existing + } + + logger.warn("classes.jar not found for rustls-platform-verifier-android, building...") + project.exec { + workingDir = uniffiDir + commandLine("cargo", "build", "-p", "rustls-platform-verifier-android") + } + } + + return jarFile } android { diff --git a/uniffi/.cargo/config.toml b/uniffi/.cargo/config.toml index ddc54ff..f1e692d 100644 --- a/uniffi/.cargo/config.toml +++ b/uniffi/.cargo/config.toml @@ -7,12 +7,16 @@ RUSTC_BOOTSTRAP = { value = "1" } [target.aarch64-linux-android] linker = "aarch64-linux-android23-clang" +rustflags = ["-C", "link-arg=--rtlib=compiler-rt"] [target.armv7-linux-androideabi] linker = "armv7a-linux-androideabi23-clang" +rustflags = ["-C", "link-arg=--rtlib=compiler-rt"] [target.i686-linux-android] linker = "i686-linux-android23-clang" +rustflags = ["-C", "link-arg=--rtlib=compiler-rt"] [target.x86_64-linux-android] linker = "x86_64-linux-android23-clang" +rustflags = ["-C", "link-arg=--rtlib=compiler-rt"] From df3b7e8c35db96ebec52d8c3b529aa2c72b5e870 Mon Sep 17 00:00:00 2001 From: Dude so hot Date: Sun, 26 Apr 2026 14:40:39 +0800 Subject: [PATCH 02/11] Fix build --- app/build.gradle.kts | 1 + build.gradle.kts | 2 +- core/build.gradle.kts | 26 +++++++++++--------------- gradle/libs.versions.toml | 4 ++-- 4 files changed, 15 insertions(+), 18 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 61ecbfc..36ed58e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -23,6 +23,7 @@ fun Project.exec(command: String): String = fun env(key: String): String? = System.getenv(key).let { if (it.isNullOrEmpty()) null else it } android { + buildToolsVersion = rootProject.extra["buildToolsVersion"] as String val keystore = env("KEYSTORE_FILE") namespace = "rs.clash.android" diff --git a/build.gradle.kts b/build.gradle.kts index 1dcea04..5aa46ac 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ plugins { alias(libs.plugins.android.library) apply false alias(libs.plugins.kotlin.android) apply false alias(libs.plugins.kotlin.compose) apply false - alias(libs.plugins.cargo.ndk) apply false + alias(libs.plugins.rust.android) apply false alias(libs.plugins.ksp) apply false alias(libs.plugins.ktlint) apply false } diff --git a/core/build.gradle.kts b/core/build.gradle.kts index ed42e20..3aec749 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -4,7 +4,7 @@ plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.compose) - alias(libs.plugins.cargo.ndk) + alias(libs.plugins.rust.android) } fun findRustlsPlatformVerifierClasses(): File { @@ -23,7 +23,7 @@ fun findRustlsPlatformVerifierClasses(): File { }.let { it as Map<*, *> }["manifest_path"] as String val manifestFile = File(path) - return File(manifestFile.parentFile, "classes.jar") + return File(manifestFile.parentFile, "maven/rustls/rustls-platform-verifier/0.1.1/rustls-platform-verifier-0.1.1.aar") } android { @@ -65,9 +65,9 @@ dependencies { androidTestImplementation(libs.androidx.espresso.core) } -cargoNdk { - module = "uniffi" // Directory containing Cargo.toml - librariesNames = arrayListOf("libclash_android_ffi.so") +cargo { + module = "../uniffi" // Directory containing Cargo.toml + libname = "clash_android_ffi" extraCargoBuildArguments = arrayListOf("-p", "clash-android-ffi").apply { // Enable jemallocator feature on Linux @@ -76,14 +76,15 @@ cargoNdk { add("jemallocator") } } - buildType = "release" + targets = listOf("arm64", "arm", "x86", "x86_64") + profile = "release" } android { buildToolsVersion = rootProject.extra["buildToolsVersion"] as String compileOptions { - sourceCompatibility = JavaVersion.VERSION_25 - targetCompatibility = JavaVersion.VERSION_25 + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 } libraryVariants.all { val variant = this @@ -93,11 +94,11 @@ android { workingDir = file("../uniffi") commandLine( "cargo", "run", "-p", "uniffi-bindgen", "generate", - "--library", "../core/src/main/jniLibs/arm64-v8a/libclash_android_ffi.so", + "--library", "../core/build/rustJniLibs/android/arm64-v8a/libclash_android_ffi.so", "--language", "kotlin", "--out-dir", bDir.asFile.absolutePath ) - dependsOn("buildCargoNdk${variantName}") + dependsOn("cargoBuild") } // Make Java compilation depend on generating UniFFI bindings @@ -107,10 +108,5 @@ android { tasks.named("compile${variantName}Kotlin").configure { dependsOn(generateBindings) } - - // And connectedDebugAndroidTest -// tasks.named("connected${variantName}AndroidTest").configure { -// dependsOn(generateBindings) -// } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 87a569c..a5dc42a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] agp = "8.13.2" kotlin = "2.3.21" -cargo-ndk = "0.5.3" +rust-android-gradle = "0.10.1" coreKtx = "1.17.0" junit = "4.13.2" junitVersion = "1.3.0" @@ -53,7 +53,7 @@ androidx-compose-material3 = { group = "androidx.compose.material3", name = "mat android-application = { id = "com.android.application", version.ref = "agp" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } -cargo-ndk = { id = "com.gemwallet.cargo-ndk", version.ref = "cargo-ndk" } +rust-android = { id = "net.mullvad.rust-android", version.ref = "rust-android-gradle" } android-library = { id = "com.android.library", version.ref = "agp" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp-plugin" } ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" } From 5ff6402b81d6dfd37257d51d92224beaaa2f0cbd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <99822064+revonateB0T@users.noreply.github.com> Date: Sun, 26 Apr 2026 14:42:35 +0800 Subject: [PATCH 03/11] Revert --- core/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 3aec749..e4fd5ee 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -83,8 +83,8 @@ cargo { android { buildToolsVersion = rootProject.extra["buildToolsVersion"] as String compileOptions { - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 } libraryVariants.all { val variant = this From 37914249aacf10ef4f02d2722613ecdf6ec792cf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <99822064+revonateB0T@users.noreply.github.com> Date: Sun, 26 Apr 2026 14:57:54 +0800 Subject: [PATCH 04/11] Fix Restored CI workflow configuration with necessary steps for building and releasing APKs, including setup for Java, Gradle, Rust, and caching. --- .github/workflows/ci.yml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0685dc5..30a3539 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,22 +63,9 @@ jobs: rustup target add i686-linux-android rustup target add x86_64-linux-android - - uses: taiki-e/install-action@v2 - with: - tool: cargo-ndk - - name: Run sccache-cache uses: mozilla-actions/sccache-action@v0.0.9 - - name: Pre-build cargo dependencies (generate classes.jar) - run: | - cd uniffi - cargo fetch - cargo build -p rustls-platform-verifier-android - env: - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" - - name: Cache Gradle dependencies uses: actions/cache@v5 with: From 0b3728635c015ec37130ffdaceb2ad27cf4a8294 Mon Sep 17 00:00:00 2001 From: Dude so hot Date: Sun, 26 Apr 2026 15:28:07 +0800 Subject: [PATCH 05/11] Fix build --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 30a3539..9b4578d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -102,7 +102,7 @@ jobs: - name: Gen binding run: | touch local.properties - ./gradlew assembleDebug -Prust-target=arm64 + ./gradlew app:assembleDebug -Prust-target=arm64 ./gradlew clean cd uniffi cargo clean From c2ee68fc2877a86f1abe04a3a8d87d3836f4d62e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <99822064+revonateB0T@users.noreply.github.com> Date: Sun, 26 Apr 2026 15:55:04 +0800 Subject: [PATCH 06/11] Fix again --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9b4578d..2aa0f40 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -102,7 +102,7 @@ jobs: - name: Gen binding run: | touch local.properties - ./gradlew app:assembleDebug -Prust-target=arm64 + ./gradlew core:generateDebugUniFFIBindings -Prust-target=arm64 ./gradlew clean cd uniffi cargo clean @@ -116,7 +116,7 @@ jobs: SCCACHE_GHA_ENABLED: "true" RUSTC_WRAPPER: "sccache" run: | - ./gradlew assembleDebug + ./gradlew app:assembleDebug - name: Build Release APKs if: github.event_name != 'pull_request' @@ -131,7 +131,7 @@ jobs: RUSTC_WRAPPER: "sccache" run: | rm -rf app/build/outputs/apk - ./gradlew assembleRelease + ./gradlew app:assembleRelease - name: Organize APKs if: github.event_name != 'pull_request' From 261d8409319c5416441031450161b28eadd0c172 Mon Sep 17 00:00:00 2001 From: iHsin Date: Sun, 26 Apr 2026 15:56:30 +0800 Subject: [PATCH 07/11] remove jemalloc --- core/build.gradle.kts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index f289356..ecc174c 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -71,13 +71,7 @@ cargo { module = "../uniffi" // Directory containing Cargo.toml libname = "clash_android_ffi" - extraCargoBuildArguments = arrayListOf("-p", "clash-android-ffi").apply { - // Enable jemallocator feature on Linux - if (System.getProperty("os.name").lowercase().contains("linux")) { - add("--features") - add("jemallocator") - } - } + extraCargoBuildArguments = arrayListOf("-p", "clash-android-ffi") targets = listOf("arm64", "arm", "x86", "x86_64") profile = "release" } From c08765b0c1091dae70857d93ebb66b6e32d66e3f Mon Sep 17 00:00:00 2001 From: iHsin Date: Sun, 26 Apr 2026 16:40:14 +0800 Subject: [PATCH 08/11] =?UTF-8?q?=E4=BD=BF=E7=94=A8=20just=20=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=20bindings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 28 ++++++++++------------------ README.md | 4 ++++ core/build.gradle.kts | 25 +------------------------ justfile | 9 +++++++-- 4 files changed, 22 insertions(+), 44 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2aa0f40..a483e8c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,9 +63,13 @@ jobs: rustup target add i686-linux-android rustup target add x86_64-linux-android - - name: Run sccache-cache + - name: Setup sccache-cache uses: mozilla-actions/sccache-action@v0.0.9 + - uses: taiki-e/install-action@v2 + with: + tool: cargo-ndk,just + - name: Cache Gradle dependencies uses: actions/cache@v5 with: @@ -98,26 +102,16 @@ jobs: else echo "version=dev-$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT fi - - - name: Gen binding + + - name: Generate Rust bindings run: | - touch local.properties - ./gradlew core:generateDebugUniFFIBindings -Prust-target=arm64 - ./gradlew clean - cd uniffi - cargo clean - env: - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" - + just generate-bindings + - name: Build Debug APK if: github.event_name == 'pull_request' - env: - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" run: | ./gradlew app:assembleDebug - + - name: Build Release APKs if: github.event_name != 'pull_request' env: @@ -127,8 +121,6 @@ jobs: KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} ANDROID_SPLIT_ABI_ENABLE: true ANDROID_SPLIT_ABI_UNIVERSAL_APK: true - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" run: | rm -rf app/build/outputs/apk ./gradlew app:assembleRelease diff --git a/README.md b/README.md index e3f5eda..4626fed 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ # clash-android +# Develop + +每次修改 Rust 部分后使用 `generate-bindings` 更新绑定。 + # Requirements Android SDK & NDK diff --git a/core/build.gradle.kts b/core/build.gradle.kts index ecc174c..585a284 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -73,7 +73,7 @@ cargo { extraCargoBuildArguments = arrayListOf("-p", "clash-android-ffi") targets = listOf("arm64", "arm", "x86", "x86_64") - profile = "release" + profile = "release" } android { @@ -82,27 +82,4 @@ android { sourceCompatibility = JavaVersion.VERSION_25 targetCompatibility = JavaVersion.VERSION_25 } - libraryVariants.all { - val variant = this - val variantName = variant.name.replaceFirstChar(Char::titlecase) - val bDir = layout.projectDirectory.dir("src/main/java") - val generateBindings = tasks.register("generate${variantName}UniFFIBindings", Exec::class) { - workingDir = file("../uniffi") - commandLine( - "cargo", "run", "-p", "uniffi-bindgen", "generate", - "--library", "../core/build/rustJniLibs/android/arm64-v8a/libclash_android_ffi.so", - "--language", "kotlin", - "--out-dir", bDir.asFile.absolutePath - ) - dependsOn("cargoBuild") - } - - // Make Java compilation depend on generating UniFFI bindings - variant.javaCompileProvider.get().dependsOn(generateBindings) - - // Also hook into Kotlin compilation - tasks.named("compile${variantName}Kotlin").configure { - dependsOn(generateBindings) - } - } } diff --git a/justfile b/justfile index a7126bc..d9b53ed 100644 --- a/justfile +++ b/justfile @@ -1,4 +1,9 @@ -gen: - ./gradlew assembleDebug -Prust-target=arm64 +generate-bindings: + cd uniffi && cargo ndk -t arm64-v8a build -p clash-android-ffi + cd uniffi && cargo run -p uniffi-bindgen generate \ + --library target/aarch64-linux-android/debug/libclash_android_ffi.so \ + --language kotlin \ + --out-dir ../core/src/main/java + build: ./gradlew assembleDebug \ No newline at end of file From 5c4721e506c0561944f4f6dde1b95db73480240d Mon Sep 17 00:00:00 2001 From: Dude so hot Date: Sun, 26 Apr 2026 16:57:02 +0800 Subject: [PATCH 09/11] Fix --- core/build.gradle.kts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 585a284..a4fd167 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -82,4 +82,15 @@ android { sourceCompatibility = JavaVersion.VERSION_25 targetCompatibility = JavaVersion.VERSION_25 } + libraryVariants.all { + val variantName = name.replaceFirstChar(Char::titlecase) + + // Make Java compilation depend on generating UniFFI bindings + javaCompileProvider.get().dependsOn("cargoBuild") + + // Also hook into Kotlin compilation + tasks.named("compile${variantName}Kotlin").configure { + dependsOn("cargoBuild") + } + } } From 509fa2012847a32c7c67f2047a35a363466996b9 Mon Sep 17 00:00:00 2001 From: iHsin Date: Sun, 26 Apr 2026 17:12:55 +0800 Subject: [PATCH 10/11] evil code --- core/build.gradle.kts | 23 +---------------------- deps/rustls-platform-verifier-0.1.1.aar | Bin 0 -> 9287 bytes gradle/gradle-daemon-jvm.properties | 13 +++++++++++++ settings.gradle.kts | 3 +++ 4 files changed, 17 insertions(+), 22 deletions(-) create mode 100644 deps/rustls-platform-verifier-0.1.1.aar create mode 100644 gradle/gradle-daemon-jvm.properties diff --git a/core/build.gradle.kts b/core/build.gradle.kts index a4fd167..5d5207d 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -7,27 +7,6 @@ plugins { alias(libs.plugins.rust.android) } -fun findRustlsPlatformVerifierClasses(): File { - val uniffiDir = File(project.rootDir, "uniffi") - - val dependencyJson = providers.exec { - workingDir = uniffiDir - commandLine("cargo", "metadata", "--format-version", "1") - }.standardOutput.asText - - val jsonSlurper = JsonSlurper() - val jsonData = jsonSlurper.parseText(dependencyJson.get()) as Map<*, *> - val packages = jsonData["packages"] as List<*> - val path = packages - .first { element -> - val pkg = element as Map<*, *> - pkg["name"] == "rustls-platform-verifier-android" - }.let { it as Map<*, *> }["manifest_path"] as String - - val manifestFile = File(path) - return File(manifestFile.parentFile, "maven/rustls/rustls-platform-verifier/0.1.1/rustls-platform-verifier-0.1.1.aar") -} - android { namespace = "rs.clash.android.ffi" compileSdk = 36 @@ -54,7 +33,7 @@ kotlin { } dependencies { - implementation(files(findRustlsPlatformVerifierClasses())) + implementation(files("../deps/rustls-platform-verifier-0.1.1.aar")) implementation(libs.androidx.core.ktx) implementation(libs.androidx.appcompat) implementation(libs.androidx.runtime) diff --git a/deps/rustls-platform-verifier-0.1.1.aar b/deps/rustls-platform-verifier-0.1.1.aar new file mode 100644 index 0000000000000000000000000000000000000000..8acc8b5fe0b36db4fb45ad8ac4a8f8c3b24fc0c5 GIT binary patch literal 9287 zcmbulRa6~7v!;!^ySux)JHcHx?(PH$Y#_K3T*AiP9fG^N6WrZhC+Ez?{O4Q$Tut|S zySi6*)#|FtT92v%BoqP|7#tiJ7?}7!fq_B%_X-9E{m-hiczAn2f~o$GN5LV+#AW|3 zzy1mHpTwOk+?;JKluVs$tt{O=SiBt_EaSxyg4wX7o@}I2R$sJ zjHe{n)dRhZi46^1Zk#^$es6GHhht^aGIeYIg}?+fVI5_CLjKRp^z5&m)XBlXLMg$( z5dURn?qKTfZt2cqXX;kvYpF=QUeBXWcX@e9xZJtgsu3lK#q;lQslQ$&=Sr`-9^L*! zVYX9&9_2}x|LJhQV>B)6$E`49Qe}q4G4ltBPhOB zeJQ?HuK?-njmoxlp$%c8^)>?{G7{}6r#Pcjr)KTuR40SER40;vjR|s+RDmyIbC-}6 zKv(edi`~cGFN6Vjvk#qw@cDJ{-AhoJZDkazJeZ7Tt>q$F>$3iBVVL=%RH5Wbd`#Y= zdL$jr596khAHb8I;UisIT&y|TG&(OlmQ5AMRm?B+Z~Y!lp6!rb8?IknNq2q$j}gec zp%Q;2m6)9{ljX~ZzW#cMZ%WKVKjqyw+Pt>SDMJ0{PmXW=@A@8j6Whh-zTQ6ZR*VIB7VzEN z%CC%dunSIYn1a*S5xyKrt+$Z9!w-TOIMtj#YL}qDU**a@QYCrF73VAzPNBsG9uK2b zW_@EZ)?E($c>(E@S5-WUm`CFlbeX-MEoX zIJ!Ub3U_PowLO96{q@c=!D5p6hh##GPCk9_>6-^Vb%gZ0C;HPJc+On)IJX(umUdCg z^Xp4dVf2C%M?~9)w%o;5tIuhn69joka63d#FZ}yf+lvau5~Lb6U0hmCab1_I;5PY; zKK*S{xPLGEMdCL}{ec2Cj3FU?Mv@@!a1&)$BhdWhTT^-91@cG6j~CC((=+#Fw!MAS zB^|~09AD$L;I?lTqA2(h-%21cdz!O>?`Hby1`#NP<>_w)zI40 zUhj?M{w4d2>a6PJ)Ki18Rqg|th3U?zjy7~FBWk43Zb^<*TB*=TbX-o}UK(9VHR8pFyshD`ZYLF|I`X=143hdghUM~A1R`Q=U9y#lV|{2OX>c}nNJQj zudY2kdfjiE9x<7pZY`P{)r6uYXgNX5@$F5bMo4`CrlfTk#uRgznfa`OKA)rV?H%vv z4#Pve;)O(%?%zJ}(+6fr76iW?w!C&|#ZT58Dnu5U8w!y24x93)^L&U!^HW^{cx2Im z;dm2#-fD}g73kz>GG57FmSIreoHwL-S=Q>%*qFttzOp5Kzg+|S2nRQdC7B!FrqzfM zQ2?pc2Tx6yOZ;8e5&~?-X4twQ&O!fy2t^(7zs&N%#inF&{ki6|DzzYmwkdr;kawpl zU$kf9#$;7((rUJ=ny9+t1|vi4C5N`LNc?%)JDJ}W4ST9X*4o_TGgAz7F4G~2hMyVQ z&aR%4$`WA1<0t1%pBsy4HKqs{^~A*;c6FgKAqL|8aj9ZlBFwj;$$tL$ugtFuI!9T| zyrqG}{(U;0kihajb|*F3^w6rBlG-QBu2`7EktkpyRk$ig&-AiA;KUQ?TUSMLolRQm zHaD@I7r)%!#2O^wgk8XFxLe=&-7_OOood+mJcdL(pX2oxQy#sQd#yz-v0WyTW^Thz zLmTL+cA_1mO-|;37ZO%Mqq;@&f{U1h#NCl@8UyAxx#^y^3vDl-ND5RA!d$f_Y}Pbq zg`#?fVqpr|B-;7!?(t}yEK7UCH*EBxDVsF&l^~XK9sijrnrJ-=Q9%oT-TA))6Xw=` zec$O-h}xAE^NBA{y1rw0-QnC+OogsBFH3f0+GbK0#$j8N#Oq9t!ZVr?hR|i`5~)~# zd`cc7R=p<*!ILdh@kJ)EXEQZ0USsxV$i{t4OT^lw!Z}j3myHVk61i&!c=m^fSylim zhERX+yEw5oQEef~M;NL=_`_XiLco%TH?|3w(|OUkCr>z?o^Q959Y zfBsmi35ja1EnP-g8_&|iwz?v$9$8dv@H`@5JUM3S{ zF)_1AZC;NU@PbUI^P%-&JSf4Q4sC&9HC9y=xBL;E-+q;etDSE%2&5*?Sq?xy)A*G< zyR0uuTSxGnecq<}x3+=oD z+0nE>1I3+ zj~88Ga3gBpuC6i30{HHIc!~1oUJ`$w0nOrP(y>c)%MJ|wFF}I*cJCuT^wx_VccT68 z9Y^2sodzFQ>xhazhA}9d_)j@-Q@iN3_qt<=0RnOb!-`v>LstdJ@X2G2;upcYnjgY5 zcyI`@GDH9{Jthigj{vQu-DAzl1Z3oy?X_&775ePHr&oOo6P-l4Gbpf_dUl;Rak^Aj zVkz4d^D9*^3fs+1YJE9L2W>mBx~`r#$22kVD7srN;R;_%+;@lr!n+o1?c6HyL*f|5 zwTFlhjRwU>-vYyX#=9xNt3XN;eqJ6QEx)R>6$Fx6*rlw?Tv8~of9m5I0*;`QHv}h; za;fsVr;KPvoPkD%qToF3nB-2lS+hRsOxOMJ4Iw=(KVRUA(5z^lEU2WFsSVq(02tlfS>z5D*1~~|R$zp+Td3~B%d2XHUI!8>x(rZCy9qLVfr%riS#Pge zqPzkFG*!ZcWNPHa%!F+?xmTDSw=ofjHEZO0^yH|mW0t>Wnf{8;sKCv^bf}8yH^`>8 zh1qUC4?{mDJ)sZ-W^BvN2&p*fc|jd47WU;_-FMz49+!CNhO zZIks{wH7F*#DHe?8HNEH-^>@kudNSnrIxWP&&Zjvy1KR5FLygl-U&lKE$#LnyxRIhtj~D!)$@>OjkiIok8i@>J0KDUzw)wC08wP?(Q=7yq$iEAcOWG@lwv%SmTN< z2iTS}2oxSKC4jgXHGcu&iHa&g!7iY&gB-aTWz|2O`mk+!IM`kS8|M16iwhV+rz2R7 zCNl2hC8s%{llwrWi^7Z0^)*w=AK!*BFA=rxc+*9)On5^>;%Jl0uIA2$6KXAk1d+em ze(f2g&E>Yghmcy4$_K;Hjac^`<9qF&gdlkRrm^bIxyy}@XyoEuu5{V-Cg)IQ=GMb$ z!IlbkjS;AOOvmDe;ShIz@4hmENpx1FgOR0qdq3BpS={Vs1VoX>)Q@+ZO~;F)@rt21-@$76ptsBg1{B*{X)x zY<~1}xhm?*!Q-fTcxJS6E4Wrr0Xc5LuvWqOm8^te_M+dtY(NFJzlm&ym>ur?Dulxl zA1wSSPJ4eMk^7x`KZBRw7-niWILsmXiCVVjlQlrVAH%g12xa9ym8KlUUn-)z0fOUC zhdg=CCZa=sFPf_>j6IZZSYHkdYi?XF7BrDOHyqL&cF^r2TqAJ%{j~*fYDlOKiN$I0 zK=>DZ=SizUviol0zW{~?JJ@QPCwOe=+;?2X2dY571~%q)n|Pt=QAYq1(NOd0d~mK( z)G3Bryv^{a5H7u{C#+51i{or6gG4wveMj}Ejo=&LjA0S>t^@!=H>hzX+1K~lj#|z+ zuSZwmB-AlIH1jQxicwNLYXZK|$&E_2cH);R3bUwM1?lGQIKI{G(3{3!&~k6q{R`o>(FtZiRQ_4|fwEY^ zH8~oT+tGn5<+1G`6p3Oq9%07=&k_Yq~omCupnWKcGG8)75r>UL_pq8Uvy%Q#MjD zN}WH>1GCkG9u)+OG1%lB+2y~vXE z?%uTn%P+~WadnEY8crG2`(1e}@5`s$Kkg%z3b{i?@^jEI1!}{#oE0ZOkVu_jniNu8 znsRi_J5m9dKytXz5cZj*pVkU@kQ0T13iT! zF<`l_q`GsS_a2@`!CkypO^815{E9Qru?;&@xelepo~Mv*mt|XBanKid97;JSLE-qH zjDa)*#GyQzkpyvEh^|WKbVYMqHG5&b!+95JK3SigfEk48HP^8k^JWX)&e?u`AeAcX z61(J?%jj-~ujw(4Q6nLNHQE^If{b-TxSV!rPJ8$1HqBx++T7g~xffI!s?h?r4(2m5 z6p7`*xs@{eU*lx~(Y`RVd$iMsj2G1aA<+;;pr-!MYe6TpGglrT&Q08PyU$UvF@Bl$F)@H7}}IOIu&L z4B%h`t4iqmA6=qk&QqZMH{PUFz3wPV{WpS((5n9Qv@D&d-e0rt?&nQ=u~>+Yu5>fk zzoX=ZjbhF2=2Eh6XJ5~|G1z*rL3aQRjlPn?dP%zrs!Y}os}}pyQOgB132DI`L})-t zYwS7-QTDZfxg?2Xzxnz_RQrQEVX!5+Q`a%i@sZ>W>8X#`=`&LJA z2FB;^&n)qD_fenc*=Zl_YW$o-wwA}01Rs5tIxr3VMQkMo+AM?e0w>9+%2$=*y?13B zEP?l27)g?+(4|;uiyE(ek|-=xlmk1>+6+=EvGf8HRpaJ*D4n&c-#T0~O9rT_gydLF zsapb&S4$rz>h!P|+I_;M@1J~?ajWb_pUSgR*o_e|ihZU1B=gx~bqL`S)MWF$KoGvZ z(?xY5pA^7CTAR@`Ud0lM`0nR{h3L!J<^@qO3Tqlw$c6%!52Ar_=6GGGM>0tXzb@UD z>1bqVt-KqT0iJOTx*QOB)mR9XN!{$g!%rY*dFxMQ88yd3E{+_&HUvoVDg-p_h5Ba1 z{|*nyjckxJX*I_Ej2E0g1vKXZt_FNN|PDa=o{p@8icFbF-#KlXwKR)p9mhJlQE zLr#Zx@4RqA1%+zWZXqfBqwzAK&g`UOZ`^OrU#b*N^vMggJ!(!JSv$72zY-PdQsiY} zexNd6Io7)Xgp7)O+VlRc@W*}L4RNWnY@(XS-T@`AY~rl5d9(`x`~bKxmtZ6KZN8!k zf$*5ft8kb|{RoFFTzH32q7uYS)=_h17zj`N>u_}Y+uGi= zFl-BMb|5}dy-dF8UsyQ-ENnzpK7u<4mGjifIGXfnNe$Dz@KFulbDi)xu%RY!J&q{` zZm;J*Y}u}d^rHG7eZuW*ch1BNuo8-FlKV%7YvBWEaSj?$A~$k3TY4}33kqawJ;6?Y*0B z9OTd`4_Q~!H2d;A@M%#ETJkZo=DB>Nk94WS?F?o8o>zv9;8fGc&M=YDs7I13eyc)${ zoN7=Bv^}{)Z0vSH9!v-odTmA(j0t^txp><^dOU4e zH;1q5=XiYHns4>>y1uh=0+diA!b{p48$u66Wt$@P!!qydp;&=VkHJKEud?EPH;-`W zu>d)a-^a=VMyGJqt)35!h4zh@cn~J?ar8Zf@Al~pD<4MQcV$Ucj-k`eJ|BG&npiUD z)KwHuHD+4n(plYJ#yLh2k_M1gxwsmu`_VL%E!~iZgtI36BI3JdPz_nb_sj&6D2r~EOV>rX*_Z~%28c{)M=*FZwn{)Kyevqq_8DaSYeVV z-IlF6APoIsCh86e_H7nw2CD5`zesd~oC^1q7w{{y!A{Ycc|uHJkHdNO1j*MPAl;Hu zELP=ow^B{NB&NSP=TgQw(XK?60a5oy71LPHVjYITZ)yC!smV2nTaa^n+?h(51z*h! z;5c8W{HtRx7z4F`$>67Lyz7Z0;y6v8>P|(4hwaxX%lk z0`Bgmy7D25g`7D2W%V`E7j(&&*@V*DRTHnRiczyRdWz0zL5wbtPZ2n1s>ssd9W_dG zqch-;96AWqWw7i4j-|55f_C~hMpNAW&r(0tNXJ3^57eWnw^`U%P|*2&Pug9aK@gBR z!&uiVxzik4QkJ)pOyYJ{0v{BpYsxcz?#2bsIgZx}Et1ZkVHv#VgN3 z-JDT3j=G}`95a~9cgdIUvV`=Kx9-bw0DqeB#=r5RbsaWjYWBh3W|*b~Nw=D-kaRZ7 zA;(DEsC?-4?!!5Mi}Q_%CLvLcJQMr>smE$L*hwgLN~liSVTt%!E(%sm#E6#X6f0Av zdMIP%P!<-)f$@rH*ZRINUhk&xx&bde@icptjs9FQE3rSk8M%?QJTv!O{L2d1Wpz%b z#~g3=aph&ax0xj*H)7=uE|UFTR!apH;Kp-MNsX>I0sE-fm&Y3ZS<5aOhf+6hpO|M|NE1 zy$PsB$XhOq&CriRa4j!UaHjcOxz@Hi=RFJMk`*>}jK%Wi8BbK)FPL&M;=8l+m7bGb zj>L6B@|uM7H~vRe{a_-=Z8me04L@zRz4Q(v$7OR2f_a`D##m2Gcbjg1!z~k)Mm!vj zR?iwKttcGAZF@e}(!5iUVuk*a|vF}1N^GRM+zQZ7L0FE4+L zWwA06$&lbP$*|zPFXQ`@oM?S4RNVzOHb9*@5ffU2it2ZN*f8i&+*I6B0a*l}sTSZ8#4JBu3{dy2Y>=u+v~qvy_IVa_@;DaI5}uI18>=X4GRY9;&z&k?Qgvkzm^%Gs<0kT6?s8LJMl3cl#M zsu-ADWaKVyN;>f7Uj~em@sI+E)`oJ1z{b5f_xddh4LH!x)So#N9DdlHLADC5QKFE< znxv21)5a{uT(vspBKJ_5(Oh+QUV$RP~6TyfBYC7QSgeh04i}b~(V&$Ek!jK=gt`qru zuq;(4<*~CB?41dMrR89IR^Ue!?Lz`sIYBMApFCq5;fEoaLz)r2brxkF+b`T^QFEKl zci)=?tmXNY!Fk@4U3T`NPKjJ9QRKbvr5|$B1ybAily6O4gI6y5K;Z?LNi>aF;(SUcK%bFWp)#y<&5WOy1QQSlcH(j?c%`Dde-?F^7 zS>X}VSR;KDc0)izl3Nn>5t!K@DPseYPnRSB_{*>;f=F9)csKeLaPB!p9r zN&K%hopq(ozem!mXwPRwznZt9_$#K~OM27+D-Z$)D%blLHiG=tSkh06T_VoNh$xi4 zVei*J0LC}tKDnZcy}se)2!^(n3~2Z<9L36=QrT%;0!7BMw(-&;Om0#*P9>3vPQo`( z_IabuVL`ntH@l!|i7P3BRjqv^Wm!RN$>KIUfdoISJEL~%OOnN}!X%3T#S;q`Y`wN2 z1?OGMeel+?%u(XsQD5zB_gld6!LM=3m+_EK4s1PU`M}*DZC~23Jzu4e+X4H%1Cw*T z7`slRwpZsnCTAAA#|}FuCbmv?c6JYGo$Q!WR%)DCoWa2w8ey_zfo}l;ZO>lsU+;l8 zPh$bbrC*3Ia9=yVA6L|$n_nM@c2r+2PS;l%U)Aeh5Xrlu^Ecf(&w|jO(3)#s>1cLi zawA`ILHEl(LE*vfMIYf$#{Uz&P}3J$SNw-unEVs}KPgFTiZjbA%dna|JF=SoZ^DGt z%+uDvg4Np1)WX4%)zs9D+0oL&)WX!ml*Pr(*~QY$!`9MWL6OOAoOMiz30{GjVQON! zfqQ{-`oevhrv%H`ERBoqE(Qr^b3ThK8Fuq}#W7 z&btH;um`Yz+zU7a7UcgOkNNk{{~m=w|7HFgmibSY|Ab}!w*wehVG#Ad?f(xt^Pd6! ylS%nM0sf1>`Tr0q|LORj75zVsz7+ot^;K1XhWW2hQ2! Date: Sun, 26 Apr 2026 17:23:35 +0800 Subject: [PATCH 11/11] revert dns --- .gitignore | 1 + uniffi/clash-android-ffi/src/lib.rs | 25 +++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 410836d..c81bb4a 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,4 @@ replay_pid* local.properties signing.properties uniffi/.vscode/settings.json +.claude diff --git a/uniffi/clash-android-ffi/src/lib.rs b/uniffi/clash-android-ffi/src/lib.rs index 66254ed..443b04a 100644 --- a/uniffi/clash-android-ffi/src/lib.rs +++ b/uniffi/clash-android-ffi/src/lib.rs @@ -226,19 +226,40 @@ async fn run_clash( .clone() .unwrap_or_default() }; + // 需要 clash-rs 实现 dns 路由 + // let nameserver = if config.dns.nameserver.is_empty() { + // vec![ + // NameServer { + // net: DNSNetMode::DoT, + // host: Host::Domain("one.one.one.one".to_string()), + // port: 853, + // interface: None, + // proxy: None, + // }, + // NameServer { + // net: DNSNetMode::DoT, + // host: Host::Domain("dns.google".to_string()), + // port: 853, + // interface: None, + // proxy: None, + // }, + // ] + // } else { + // config.dns.nameserver.clone() + // }; let nameserver = if config.dns.nameserver.is_empty() { vec![ NameServer { net: DNSNetMode::DoT, - host: Host::Domain("one.one.one.one".to_string()), + host: Host::Domain("dns.alidns.com".to_string()), port: 853, interface: None, proxy: None, }, NameServer { net: DNSNetMode::DoT, - host: Host::Domain("dns.google".to_string()), + host: Host::Domain("dot.pub".to_string()), port: 853, interface: None, proxy: None,