Giới thiệu
Ví dụ minh họa cách tạo file text trong bộ nhớ nội bộ (Internal Storage) của ứng dụng và ghi dữ liệu từ EditText vào file đó bằng Kotlin. File này riêng tư cho app, bị xóa khi gỡ cài đặt.
Các bước thực hiện
Bước 1: Tạo dự án mới
Android Studio > File > New Project.
Bước 2: Layout (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:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="70dp"
android:background="#008080"
android:padding="5dp"
android:text="TutorialsPoint"
android:textColor="#fff"
android:textSize="24sp"
android:textStyle="bold" />
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/textView"
android:layout_marginTop="40dp"
android:ems="10">
<requestFocus />
</EditText>
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/editText"
android:layout_centerInParent="true"
android:layout_margin="5dp"
android:background="@android:color/holo_orange_light"
android:onClick="saveTextFile"
android:text="Lưu File"
android:textColor="@android:color/background_dark"
android:textStyle="bold" />
</RelativeLayout>
Bước 3: MainActivity.kt - Ghi file
import android.content.Context
import android.os.Bundle
import android.view.View
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import java.io.FileOutputStream
import java.io.OutputStreamWriter
class MainActivity : AppCompatActivity() {
private lateinit var editText: EditText
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
title = "KotlinApp"
editText = findViewById(R.id.editText)
}
fun saveTextFile(view: View) {
try {
// Mở file output stream ở chế độ PRIVATE (chỉ app này truy cập)
val fos: FileOutputStream = openFileOutput("mytextfile.txt", Context.MODE_PRIVATE)
val writer = OutputStreamWriter(fos)
writer.write(editText.text.toString())
writer.close()
Toast.makeText(baseContext, "Đã lưu file thành công!", Toast.LENGTH_SHORT).show()
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(baseContext, "Lỗi khi lưu file", Toast.LENGTH_SHORT).show()
}
}
}
Bước 4: AndroidManifest.xml
Lưu ý: Quyền WRITE_EXTERNAL_STORAGE trong manifest gốc là không cần thiết cho internal storage (openFileOutput). Chỉ cần khi ghi ra External Storage (SD card).
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="com.example.textfile">
<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>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Chạy và kiểm tra
Nhập văn bản, nhấn "Lưu File". Toast hiện "Đã lưu file thành công!". File nằm tại /data/data/com.example.textfile/files/mytextfile.txt (xem qua Device File Explorer trong Android Studio).
Mở rộng: Đọc file & External Storage
Đọc file internal storage
fun readTextFile(): String {
val fis = openFileInput("mytextfile.txt")
val reader = InputStreamReader(fis)
val buffer = StringBuilder()
var ch: Int
while (reader.read().also { ch = it } != -1) {
buffer.append(ch.toChar())
}
reader.close()
return buffer.toString()
}
Ghi file External Storage (Public Documents) - Android 10+ (Scoped Storage)
// Cần quyền WRITE_EXTERNAL_STORAGE (API < 29) hoặc dùng MediaStore (API 29+)
val resolver = contentResolver
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, "myfile.txt")
put(MediaStore.MediaColumns.MIME_TYPE, "text/plain")
put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOCUMENTS)
}
val uri = resolver.insert(MediaStore.Files.getContentUri("external"), contentValues)!!
resolver.openOutputStream(uri).use { it?.write("Nội dung".toByteArray()) }
Tóm tắt lưu trữ
| Loại | API | Phạm vi | Xóa khi uninstall? |
|---|---|---|---|
| Internal Storage | openFileOutput/Input | Riêng app | Có |
| External Storage (App-specific) | getExternalFilesDir() | Riêng app, public | Có |
| External Storage (Public) | MediaStore / SAF | Chung, user thấy | Không |