Compare commits
3 commits
23b7b6c6eb
...
7741898163
Author | SHA1 | Date | |
---|---|---|---|
7741898163 | |||
52483f05fd | |||
2e3a85ff38 |
27 changed files with 664 additions and 35 deletions
2
app/.gitignore
vendored
2
app/.gitignore
vendored
|
@ -1,2 +1,4 @@
|
|||
/build
|
||||
/src/main/rust/libsysinfo/target/
|
||||
/src/main/rust/libfshelper/target/
|
||||
/src/main/rust/libfshelper/.vscode/
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
|
|
BIN
app/src/main/jniLibs/arm64-v8a/libfshelper.so
Executable file
BIN
app/src/main/jniLibs/arm64-v8a/libfshelper.so
Executable file
Binary file not shown.
BIN
app/src/main/jniLibs/x86_64/libfshelper.so
Executable file
BIN
app/src/main/jniLibs/x86_64/libfshelper.so
Executable file
Binary file not shown.
|
@ -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"/>
|
||||
|
||||
|
|
12
app/src/main/res/drawable/outline_all_inclusive_24.xml
Normal file
12
app/src/main/res/drawable/outline_all_inclusive_24.xml
Normal 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>
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
5
app/src/main/rust/libfshelper/.cargo/config.toml
Normal file
5
app/src/main/rust/libfshelper/.cargo/config.toml
Normal 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
295
app/src/main/rust/libfshelper/Cargo.lock
generated
Normal 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"
|
11
app/src/main/rust/libfshelper/Cargo.toml
Normal file
11
app/src/main/rust/libfshelper/Cargo.toml
Normal 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"]
|
4
app/src/main/rust/libfshelper/build.rs
Normal file
4
app/src/main/rust/libfshelper/build.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
fn main() {
|
||||
println!("cargo:rustc-link-arg=-z");
|
||||
println!("cargo:rustc-link-arg=max-page-size={}",1024*16);
|
||||
}
|
109
app/src/main/rust/libfshelper/src/lib.rs
Normal file
109
app/src/main/rust/libfshelper/src/lib.rs
Normal 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])
|
||||
}
|
45
app/src/main/rust/libfshelper/src/main.rs
Normal file
45
app/src/main/rust/libfshelper/src/main.rs
Normal 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])
|
||||
}
|
Loading…
Reference in a new issue