Hướng dẫn này minh họa cách kiểm tra dung lượng lưu trữ trống (available space) trên thiết bị Android sử dụng Kotlin.
Bước 1: Tạo dự án mới
Mở Android Studio, chọn File → New Project và điền thông tin cần thiết.
Bước 2: Thiết kế giao diện (activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:text="Tutorials Point"
android:textAlignment="center"
android:textColor="@android:color/holo_green_dark"
android:textSize="32sp"
android:textStyle="bold" />
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textSize="24sp"
android:textStyle="bold" />
</RelativeLayout>
Bước 3: Viết code MainActivity.kt
import android.os.Bundle
import android.os.Environment
import android.os.StatFs
import android.text.format.Formatter
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import java.io.File
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
title = "KotlinApp"
val textView: TextView = findViewById(R.id.textView)
// External Storage (SD Card / Shared storage)
val stat = StatFs(Environment.getExternalStorageDirectory().path)
val totalBytes = stat.blockSizeLong * stat.blockCountLong
val availableBytes = stat.blockSizeLong * stat.availableBlocksLong
val freeBytes = stat.blockSizeLong * stat.freeBlocksLong
// Internal Storage (App private data)
val path: File = Environment.getDataDirectory()
val stat2 = StatFs(path.path)
val internalAvailable = stat2.blockSizeLong * stat2.availableBlocksLong
val externalTotal = Formatter.formatFileSize(this, totalBytes)
val externalAvailable = Formatter.formatFileSize(this, availableBytes)
val internalAvailableStr = Formatter.formatFileSize(this, internalAvailable)
textView.text = """
External Storage:
Total: $externalTotal
Available: $externalAvailable
Internal Storage:
Available: $internalAvailableStr
""".trimIndent()
}
}
Bước 4: Cấu hình AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="com.example.q11">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
</intent-filter>
</activity>
</application>
</manifest>
Chạy ứng dụng
Kết nối thiết bị, nhấn Run. TextView hiển thị dung lượng tổng và trống của External Storage (bộ nhớ chung) và Internal Storage (bộ nhớ riêng app).
Giải thích StatFs
| Phương thức | Ý nghĩa |
|---|---|
blockSizeLong | Kích thước một block (bytes) |
blockCountLong | Tổng số block |
availableBlocksLong | Block có sẵn cho app (non-root) |
freeBlocksLong | Block trống hoàn toàn (root) |
Android 10+ (API 29+): Scoped Storage
Từ Android 10, không thể truy cập trực tiếp Environment.getExternalStorageDirectory(). Nên dùng:
// App-specific directory (không cần permission)
val appDir = externalFilesDirs.firstOrNull()
val stat = StatFs(appDir?.path ?: return)
// Hoặc dùng StorageManager
val storageManager = getSystemService(StorageManager::class.java)
val volumes = storageManager.storageVolumes
for (volume in volumes) {
val uuid = volume.uuid
val stat = StatFs(volume.directory.path)
// ...
}
Formatter.formatFileSize()
Tự động format bytes thành KB/MB/GB dễ đọc: Formatter.formatFileSize(context, bytes)
Kiểm tra dung lượng trước khi ghi file lớn
fun hasEnoughSpace(requiredBytes: Long): Boolean {
val stat = StatFs(Environment.getExternalStorageDirectory().path)
val available = stat.blockSizeLong * stat.availableBlocksLong
return available > requiredBytes * 1.2 // Dự phòng 20%
}