diff --git a/app/.gitignore b/app/.gitignore index 4cddb63..66582af 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -1,2 +1,4 @@ /build /src/main/rust/libsysinfo/target/ +/src/main/rust/libfshelper/target/ +/src/main/rust/libfshelper/.vscode/ diff --git a/app/src/main/java/com/dazuoye/filemanager/fileSystem/WrappedFile.kt b/app/src/main/java/com/dazuoye/filemanager/fileSystem/WrappedFile.kt index c35641c..8907477 100644 --- a/app/src/main/java/com/dazuoye/filemanager/fileSystem/WrappedFile.kt +++ b/app/src/main/java/com/dazuoye/filemanager/fileSystem/WrappedFile.kt @@ -3,10 +3,13 @@ package com.dazuoye.filemanager.fileSystem import android.content.Context import android.icu.text.DecimalFormat import android.text.format.DateFormat +import android.util.Log import com.dazuoye.filemanager.fileSystem.byTypeFileLister.DocumentLister import com.dazuoye.filemanager.fileSystem.byTypeFileLister.ImageLister import com.dazuoye.filemanager.fileSystem.byTypeFileLister.MusicLister import com.dazuoye.filemanager.fileSystem.byTypeFileLister.VideoLister +import com.dazuoye.filemanager.utils.FSHelper.getFolderSizeBytesNativeMethod +import com.dazuoye.filemanager.utils.FSHelper.getFolderSizeNativeMethod import java.io.File import java.net.URLConnection import java.nio.file.Files @@ -14,6 +17,7 @@ import java.nio.file.attribute.BasicFileAttributes import java.sql.Date import java.sql.Timestamp import java.time.Instant +import kotlin.math.log class WrappedFile(private val f: File, skipCalculateDirectorySize: Boolean = false) { companion object { @@ -111,7 +115,11 @@ class WrappedFile(private val f: File, skipCalculateDirectorySize: Boolean = fal isSizeCalculated = false 0 } else { - getFolderSize(f) + try { + getFolderSizeBytesNativeMethod(f.path) + } catch (_: Exception) { + getFolderSize(f) + } } } @@ -129,13 +137,23 @@ class WrappedFile(private val f: File, skipCalculateDirectorySize: Boolean = fal } fun getSizeString(): String { - if (size == 0L && type == Type.DIRECTORY && !isSizeCalculated) { - // Calculate Size - size = getFolderSize(f) - isSizeCalculated = true - } else { - return "0B" + if (type == Type.DIRECTORY) { // 下面只对文件夹有效 + if (size == 0L && !isSizeCalculated) { + // Calculate Size + try { + val sizeStr = getFolderSizeNativeMethod(f.path) + isSizeCalculated = true + + return sizeStr + } catch (e: Exception) { + Log.e("getFolderSizeNativeMethod", "getSizeString: ${e.toString()}") + } + // 备用方法 + isSizeCalculated = true + size = getFolderSize(f) + } } + // 最后 format (fallback方法 + 普通文件) return getSizeString(size.toULong()) } diff --git a/app/src/main/java/com/dazuoye/filemanager/utils/FSHelper.java b/app/src/main/java/com/dazuoye/filemanager/utils/FSHelper.java new file mode 100644 index 0000000..f919561 --- /dev/null +++ b/app/src/main/java/com/dazuoye/filemanager/utils/FSHelper.java @@ -0,0 +1,17 @@ +package com.dazuoye.filemanager.utils; + +public class FSHelper { + static { + System.loadLibrary("fshelper"); + } + + public static String getFolderSizeNativeMethod(String dir) { + return getFolderSizeNative(dir); + } + public static long getFolderSizeBytesNativeMethod(String dir) { + return getFolderSizeBytesNative(dir); + } + + private static native String getFolderSizeNative(String dir); + private static native long getFolderSizeBytesNative(String dir); +} diff --git a/app/src/main/jniLibs/arm64-v8a/libfshelper.so b/app/src/main/jniLibs/arm64-v8a/libfshelper.so new file mode 100755 index 0000000..7683238 Binary files /dev/null and b/app/src/main/jniLibs/arm64-v8a/libfshelper.so differ diff --git a/app/src/main/jniLibs/x86_64/libfshelper.so b/app/src/main/jniLibs/x86_64/libfshelper.so new file mode 100755 index 0000000..e812a89 Binary files /dev/null and b/app/src/main/jniLibs/x86_64/libfshelper.so differ diff --git a/app/src/main/rust/libfshelper/.cargo/config.toml b/app/src/main/rust/libfshelper/.cargo/config.toml new file mode 100644 index 0000000..b2d1889 --- /dev/null +++ b/app/src/main/rust/libfshelper/.cargo/config.toml @@ -0,0 +1,5 @@ +[target.aarch64-linux-android] +linker = "/home/kagura/Programs/AndroidStudio/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android35-clang" + +[target.x86_64-linux-android] +linker = "/home/kagura/Programs/AndroidStudio/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android35-clang" diff --git a/app/src/main/rust/libfshelper/Cargo.lock b/app/src/main/rust/libfshelper/Cargo.lock new file mode 100644 index 0000000..13d279e --- /dev/null +++ b/app/src/main/rust/libfshelper/Cargo.lock @@ -0,0 +1,295 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bytes" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "fshelper" +version = "0.1.0" +dependencies = [ + "jni", + "walkdir", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "proc-macro2" +version = "1.0.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "syn" +version = "2.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/app/src/main/rust/libfshelper/Cargo.toml b/app/src/main/rust/libfshelper/Cargo.toml new file mode 100644 index 0000000..e804655 --- /dev/null +++ b/app/src/main/rust/libfshelper/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "fshelper" +version = "0.1.0" +edition = "2021" + +[dependencies] +jni = "0.21.1" +walkdir = "2.5.0" + +[lib] +crate-type = ["cdylib"] diff --git a/app/src/main/rust/libfshelper/build.rs b/app/src/main/rust/libfshelper/build.rs new file mode 100644 index 0000000..be2f036 --- /dev/null +++ b/app/src/main/rust/libfshelper/build.rs @@ -0,0 +1,4 @@ +fn main() { + println!("cargo:rustc-link-arg=-z"); + println!("cargo:rustc-link-arg=max-page-size={}",1024*16); +} diff --git a/app/src/main/rust/libfshelper/src/lib.rs b/app/src/main/rust/libfshelper/src/lib.rs new file mode 100644 index 0000000..cde4892 --- /dev/null +++ b/app/src/main/rust/libfshelper/src/lib.rs @@ -0,0 +1,109 @@ +use jni::objects::{JClass, JString}; +use jni::sys::{jlong, jstring}; +use jni::JNIEnv; +use std::{fs, i64}; +use walkdir::WalkDir; + +#[no_mangle] +pub extern "system" fn Java_com_dazuoye_filemanager_utils_FSHelper_getFolderSizeNative<'local>( + mut env: JNIEnv<'local>, + _: JClass<'local>, + input: JString<'local>, +) -> jstring { + let dir: String = env + .get_string(&input) + .expect("failed to parse input") + .into(); + + if !fs::exists(&dir).expect(format!("Cannot stat {}", dir).as_str()) { + return env + .new_string(format!("{} not exists!", dir)) + .expect("Couldn't create java string!") + .into_raw(); + } + // 从这里保证文件至少存在了 + + let mut size: u64 = 0; + for entry in WalkDir::new(dir) { + match entry { + Ok(item) => { + match item.metadata() { + Ok(metadata) => size += metadata.len(), + Err(e) => { + eprintln!("Error getting metadata for item: {:?}", e); + continue; + } + } + }, + Err(e) => { + eprintln!("Error walking directory: {:?}", e); + continue; + } + } + } + + + let output = env + .new_string(format_size(size)) + .expect("Couldn't create java string!"); + + output.into_raw() +} + +#[no_mangle] +pub extern "system" fn Java_com_dazuoye_filemanager_utils_FSHelper_getFolderSizeBytesNative<'local>( + mut env: JNIEnv<'local>, + _: JClass<'local>, + input: JString<'local>, +) -> jlong { + let dir: String = env + .get_string(&input) + .expect("failed to parse input") + .into(); + + if !fs::exists(&dir).expect(format!("Cannot stat {}", dir).as_str()) { + return 0; + } + // 从这里保证文件至少存在了 + + let mut size: u64 = 0; + for entry in WalkDir::new(dir) { + match entry { + Ok(item) => { + match item.metadata() { + Ok(metadata) => size += metadata.len(), + Err(e) => { + eprintln!("Error getting metadata for item: {:?}", e); + continue; + } + } + }, + Err(e) => { + eprintln!("Error walking directory: {:?}", e); + continue; + } + } + } + + + match i64::try_from(size) { + Ok(compatible) => compatible, + Err(_) => i64::MAX + } +} + +fn format_size(size: u64) -> String { + // 定义单位 + let units = ["B", "KB", "MB", "GB", "TB", "PB"]; + let mut size = size as f64; + let mut unit_index = 0; + + // 按 1024 递减计算,直到找到合适的单位 + while size >= 1024.0 && unit_index < units.len() - 1 { + size /= 1024.0; + unit_index += 1; + } + + // 保留两位小数格式化输出 + format!("{:.2} {}", size, units[unit_index]) +} \ No newline at end of file diff --git a/app/src/main/rust/libfshelper/src/main.rs b/app/src/main/rust/libfshelper/src/main.rs new file mode 100644 index 0000000..c075bea --- /dev/null +++ b/app/src/main/rust/libfshelper/src/main.rs @@ -0,0 +1,45 @@ +use std::fs; +use walkdir::WalkDir; +fn main() { + let dir: String = String::from("."); + + if !fs::exists(&dir).expect(format!("Cannot stat {}", dir).as_str()) { + return; + } + // 从这里保证文件至少存在了 + + let mut size: u64 = 0; + for entry in WalkDir::new(dir) { + match entry { + Ok(item) => match item.metadata() { + Ok(metadata) => size += metadata.len(), + Err(e) => { + eprintln!("Error getting metadata for item: {:?}", e); + continue; + } + }, + Err(e) => { + eprintln!("Error walking directory: {:?}", e); + continue; + } + } + } + + println!("{}", format_size(size)) +} + +fn format_size(size: u64) -> String { + // 定义单位 + let units = ["B", "KB", "MB", "GB", "TB", "PB"]; + let mut size = size as f64; + let mut unit_index = 0; + + // 按 1024 递减计算,直到找到合适的单位 + while size >= 1024.0 && unit_index < units.len() - 1 { + size /= 1024.0; + unit_index += 1; + } + + // 保留两位小数格式化输出 + format!("{:.2} {}", size, units[unit_index]) +}