Compare commits

...

3 commits

Author SHA1 Message Date
7741898163 feat: add native folder size calculator 2024-10-17 23:13:28 +08:00
52483f05fd feat: add new icon 2024-10-17 22:09:17 +08:00
2e3a85ff38 fix: default should show ext 2024-10-17 21:33:27 +08:00
27 changed files with 664 additions and 35 deletions

2
app/.gitignore vendored
View file

@ -1,2 +1,4 @@
/build
/src/main/rust/libsysinfo/target/
/src/main/rust/libfshelper/target/
/src/main/rust/libfshelper/.vscode/

View file

@ -7,6 +7,8 @@
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"

View file

@ -10,6 +10,7 @@ import android.view.View
import android.widget.AdapterView
import android.widget.GridView
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
@ -143,6 +144,11 @@ class document_page : AppCompatActivity() {
val adapter = DocumentAdapter(this@document_page, models)
documentGrid.setAdapter(adapter)
findViewById<TextView>(R.id.LoadingBlankText).visibility = View.GONE
findViewById<LinearLayout>(R.id.NothingFoundHint).visibility = if (models.isEmpty){ // 没有东西则显示空
View.VISIBLE
}else{
View.GONE
}
}
}
}
@ -274,6 +280,12 @@ class document_page : AppCompatActivity() {
runOnUiThread {
val grid = findViewById<GridView>(R.id.DocumentGrid)
grid.setAdapter(adapter)
findViewById<LinearLayout>(R.id.NothingFoundHint).visibility = if (models.isEmpty){ // 没有东西则显示空
View.VISIBLE
}else{
View.GONE
}
}
runSomethingMore?.invoke()
}

View file

@ -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,19 +137,23 @@ class WrappedFile(private val f: File, skipCalculateDirectorySize: Boolean = fal
}
fun getSizeString(): String {
if (size == 0L) {
if (type == Type.DIRECTORY) {
if (!isSizeCalculated) {
// Calculate Size
size = getFolderSize(f)
if (type == Type.DIRECTORY) { // 下面只对文件夹有效
if (size == 0L && !isSizeCalculated) {
// Calculate Size
try {
val sizeStr = getFolderSizeNativeMethod(f.path)
isSizeCalculated = true
} else {
return "0B"
return sizeStr
} catch (e: Exception) {
Log.e("getFolderSizeNativeMethod", "getSizeString: ${e.toString()}")
}
} else {
return "未知"
// 备用方法
isSizeCalculated = true
size = getFolderSize(f)
}
}
// 最后 format (fallback方法 + 普通文件)
return getSizeString(size.toULong())
}

View file

@ -31,10 +31,10 @@ class DocumentAdapter(context: Context, list: ArrayList<DocumentModel>) :
)
val model = getItem(position) ?: throw RuntimeException()
val card = listView.findViewById<TextView>(R.id.iconButton)
card.text = if (hideExtension == false) {
model.name
} else {
card.text = if (hideExtension == true) {
model.nameWithoutExt
} else {
model.name
}
return listView
}

View file

@ -39,10 +39,11 @@ class ImageAdapter(context: Context, list: ArrayList<ImageModel>) :
)
val model = getItem(position) ?: throw RuntimeException()
listView.findViewById<ImageView>(R.id.pictureCardImage).setImageBitmap(model.thumbnail)
listView.findViewById<TextView>(R.id.pictureCardText).text = if (hideExtension == false) {
model.name
} else {
val card = listView.findViewById<TextView>(R.id.pictureCardText)
card.text = if (hideExtension == true) {
model.nameWithoutExt
} else {
model.name
}
listView.setLayoutParams(LayoutParams(GridView.AUTO_FIT, 530))

View file

@ -31,10 +31,10 @@ class MusicAdapter(context: Context, list: ArrayList<MusicModel>) :
)
val model = getItem(position) ?: throw RuntimeException()
val card = listView.findViewById<TextView>(R.id.iconButton)
card.text = if (hideExtension == false) {
model.name
} else {
card.text = if (hideExtension == true) {
model.nameWithoutExt
} else {
model.name
}
return listView
}

View file

@ -42,10 +42,11 @@ class VideoAdapter(context: Context, list: ArrayList<VideoModel>) :
)
val model = getItem(position) ?: throw RuntimeException()
listView.findViewById<ImageView>(R.id.pictureCardImage).setImageBitmap(model.thumbnail)
listView.findViewById<TextView>(R.id.pictureCardText).text = if (hideExtension == false) {
model.name
} else {
val card = listView.findViewById<TextView>(R.id.pictureCardText)
card.text = if (hideExtension == true) {
model.nameWithoutExt
} else {
model.name
}
listView.setLayoutParams(LayoutParams(GridView.AUTO_FIT, 530))

View file

@ -9,6 +9,7 @@ import android.view.View
import android.widget.AdapterView
import android.widget.GridView
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
@ -18,6 +19,7 @@ import androidx.core.content.FileProvider
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsCompat.Type
import androidx.core.view.isVisible
import com.dazuoye.filemanager.fileSystem.adapters.MusicAdapter
import com.dazuoye.filemanager.fileSystem.adapters.MusicModel
import com.dazuoye.filemanager.compose.SearchActivity
@ -122,6 +124,11 @@ class music_page : AppCompatActivity() {
val adapter = MusicAdapter(this@music_page, models)
musicGrid.setAdapter(adapter)
findViewById<TextView>(R.id.LoadingBlankText).visibility = View.GONE
findViewById<LinearLayout>(R.id.NothingFoundHint).visibility = if (models.isEmpty){ // 没有东西则显示空
View.VISIBLE
}else{
View.GONE
}
}
}
}
@ -253,6 +260,12 @@ class music_page : AppCompatActivity() {
runOnUiThread {
val grid = findViewById<GridView>(R.id.MusicGrid)
grid.setAdapter(adapter)
findViewById<LinearLayout>(R.id.NothingFoundHint).visibility = if (models.isEmpty){ // 没有东西则显示空
View.VISIBLE
}else{
View.GONE
}
}
runSomethingMore?.invoke()
}

View file

@ -9,6 +9,7 @@ import android.view.View
import android.widget.AdapterView
import android.widget.GridView
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
@ -116,14 +117,19 @@ class picture_page : AppCompatActivity() {
val defaultText = loadingTextView.text
launch { loadingText(loadingTextView, defaultText) }
imageList = instance.dateOrderedList()
val imageModels = ArrayList<ImageModel>()
val models = ArrayList<ImageModel>()
for (path in imageList) {
imageModels.add(ImageModel(File(path)))
models.add(ImageModel(File(path)))
}
runOnUiThread {
val adapter = ImageAdapter(this@picture_page, imageModels)
val adapter = ImageAdapter(this@picture_page, models)
pictureGrid.setAdapter(adapter)
findViewById<TextView>(R.id.LoadingBlankText).visibility = View.GONE
findViewById<LinearLayout>(R.id.NothingFoundHint).visibility = if (models.isEmpty){ // 没有东西则显示空
View.VISIBLE
}else{
View.GONE
}
}
}
}
@ -247,14 +253,19 @@ class picture_page : AppCompatActivity() {
1 -> instance.sizeOrderedList()
else -> listOf()
}
val imageModels = ArrayList<ImageModel>()
val models = ArrayList<ImageModel>()
for (path in imageList) {
imageModels.add(ImageModel(File(path)))
models.add(ImageModel(File(path)))
}
val adapter = ImageAdapter(this, imageModels)
val adapter = ImageAdapter(this, models)
runOnUiThread {
val grid = findViewById<GridView>(R.id.PicturePageGrid)
grid.setAdapter(adapter)
findViewById<LinearLayout>(R.id.NothingFoundHint).visibility = if (models.isEmpty){ // 没有东西则显示空
View.VISIBLE
}else{
View.GONE
}
}
runSomethingMore?.invoke()
}

View file

@ -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);
}

View file

@ -9,6 +9,7 @@ import android.view.View
import android.widget.AdapterView
import android.widget.GridView
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
@ -115,14 +116,19 @@ class video_page : AppCompatActivity() {
val defaultText = loadingTextView.text
launch { loadingText(loadingTextView, defaultText) }
videoList = instance.dateOrderedList()
val videoModels = ArrayList<VideoModel>()
val models = ArrayList<VideoModel>()
for (path in videoList) {
videoModels.add(VideoModel(File(path)))
models.add(VideoModel(File(path)))
}
runOnUiThread {
val adapter = VideoAdapter(this@video_page, videoModels)
val adapter = VideoAdapter(this@video_page, models)
videoGrid.setAdapter(adapter)
findViewById<TextView>(R.id.LoadingBlankText).visibility = View.GONE
findViewById<LinearLayout>(R.id.NothingFoundHint).visibility = if (models.isEmpty){ // 没有东西则显示空
View.VISIBLE
}else{
View.GONE
}
}
}
}
@ -246,14 +252,19 @@ class video_page : AppCompatActivity() {
1 -> instance.sizeOrderedList()
else -> listOf()
}
val videoModels = ArrayList<VideoModel>()
val models = ArrayList<VideoModel>()
for (path in videoList) {
videoModels.add(VideoModel(File(path)))
models.add(VideoModel(File(path)))
}
val adapter = VideoAdapter(this, videoModels)
val adapter = VideoAdapter(this, models)
runOnUiThread {
val grid = findViewById<GridView>(R.id.VideoGrid)
grid.setAdapter(adapter)
findViewById<LinearLayout>(R.id.NothingFoundHint).visibility = if (models.isEmpty){ // 没有东西则显示空
View.VISIBLE
}else{
View.GONE
}
}
runSomethingMore?.invoke()
}

Binary file not shown.

Binary file not shown.

View file

@ -1,4 +1,4 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="40dp" android:tint="#FF00FF" android:viewportHeight="24" android:viewportWidth="24" android:width="40dp">
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="40dp" android:tint="#485B7A" android:viewportHeight="24" android:viewportWidth="24" android:width="40dp">
<path android:fillColor="@color/white" android:pathData="M5,20h14v-2H5V20zM19,9h-4V3H9v6H5l7,7L19,9z"/>

View file

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="128dp"
android:tint="#717171"
android:viewportHeight="960"
android:viewportWidth="960"
android:width="128dp">
<path
android:fillColor="@android:color/white"
android:pathData="M220,700Q128,700 64,636Q0,572 0,480Q0,388 64,324Q128,260 220,260Q257,260 291,273Q325,286 352,310L420,372L360,426L298,370Q282,356 262,348Q242,340 220,340Q162,340 121,381Q80,422 80,480Q80,538 121,579Q162,620 220,620Q242,620 262,612Q282,604 298,590L608,310Q635,286 669,273Q703,260 740,260Q832,260 896,324Q960,388 960,480Q960,572 896,636Q832,700 740,700Q703,700 669,687Q635,674 608,650L540,588L600,534L662,590Q678,604 698,612Q718,620 740,620Q798,620 839,579Q880,538 880,480Q880,422 839,381Q798,340 740,340Q718,340 698,348Q678,356 662,370L352,650Q325,674 291,687Q257,700 220,700Z" />
</vector>

View file

@ -98,4 +98,20 @@
android:textSize="78sp"
android:background="@color/WhiteSmoke"/>
<LinearLayout
android:id="@+id/NothingFoundHint"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="64sp"
android:text="@string/no_items"
app:drawableTopCompat="@drawable/outline_all_inclusive_24"
/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -98,4 +98,21 @@
android:textSize="78sp"
android:background="@color/WhiteSmoke"/>
<LinearLayout
android:id="@+id/NothingFoundHint"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="64sp"
android:text="@string/no_items"
app:drawableTopCompat="@drawable/outline_all_inclusive_24"
/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -107,5 +107,21 @@
android:background="@color/WhiteSmoke"/>
<LinearLayout
android:id="@+id/NothingFoundHint"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="64sp"
android:text="@string/no_items"
app:drawableTopCompat="@drawable/outline_all_inclusive_24"
/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -109,4 +109,20 @@
android:textSize="78sp"
android:background="@color/WhiteSmoke"/>
<LinearLayout
android:id="@+id/NothingFoundHint"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="64sp"
android:text="@string/no_items"
app:drawableTopCompat="@drawable/outline_all_inclusive_24"
/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -88,5 +88,6 @@
<string name="setting_hide_hidden_file">隐藏点文件</string>
<string name="setting_hide_hidden_file_description">隐藏所有以 . 开头的文件和文件夹\n. 开头的文件(或文件夹)通常表示隐藏文件(或文件夹)\n此选项只对查看全部文件功能有效</string>
<string name="no_items">无内容</string>
<string name="about">关于</string>
</resources>

View file

@ -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"

295
app/src/main/rust/libfshelper/Cargo.lock generated Normal file
View file

@ -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"

View file

@ -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"]

View file

@ -0,0 +1,4 @@
fn main() {
println!("cargo:rustc-link-arg=-z");
println!("cargo:rustc-link-arg=max-page-size={}",1024*16);
}

View file

@ -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])
}

View file

@ -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])
}