SharedPreferences là cơ chế lưu trữ key-value đơn giản, phù hợp cho cài đặt app, user preferences, token, flag... Dữ liệu lưu trong file XML private trong internal storage.
Các phương thức chính
- edit() - Trả về Editor để sửa đổi
- putString/putInt/putBoolean/putFloat/putLong(key, value) - Lưu giá trị
- apply() - Lưu bất đồng bộ (khuyên dùng)
- commit() - Lưu đồng bộ (trả về boolean thành công)
- getString/getInt/getBoolean...(key, defaultValue) - Đọc giá trị
- remove(key) - Xóa key
- clear() - Xóa tất cả
- contains(key) - Kiểm tra key tồn tại
- getAll() - Lấy toàn bộ Map<String, ?>
Ví dụ cơ bản: Lưu/Đọc tên và số điện thoại
Bước 1: Layout activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<EditText
android:id="@+id/etName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Tên" />
<EditText
android:id="@+id/etPhone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Số điện thoại"
android:inputType="phone" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="16dp">
<Button
android:id="@+id/btnSave"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Lưu" />
<Button
android:id="@+id/btnRead"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Đọc" />
</LinearLayout>
<TextView
android:id="@+id/tvResult"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Kết quả sẽ hiển thị ở đây"
android:textSize="16sp" />
</LinearLayout>
Bước 2: MainActivity.java
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private SharedPreferences prefs;
private EditText etName, etPhone;
private TextView tvResult;
private static final String PREFS_NAME = "UserPrefs";
private static final String KEY_NAME = "name";
private static final String KEY_PHONE = "phone";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
etName = findViewById(R.id.etName);
etPhone = findViewById(R.id.etPhone);
tvResult = findViewById(R.id.tvResult);
findViewById(R.id.btnSave).setOnClickListener(v -> saveData());
findViewById(R.id.btnRead).setOnClickListener(v -> readData());
}
private void saveData() {
String name = etName.getText().toString().trim();
String phone = etPhone.getText().toString().trim();
if (name.isEmpty() && phone.isEmpty()) {
Toast.makeText(this, "Nhập ít nhất một trường", Toast.LENGTH_SHORT).show();
return;
}
SharedPreferences.Editor editor = prefs.edit();
if (!name.isEmpty()) editor.putString(KEY_NAME, name);
if (!phone.isEmpty()) editor.putString(KEY_PHONE, phone);
editor.apply(); // Bất đồng bộ
Toast.makeText(this, "Đã lưu", Toast.LENGTH_SHORT).show();
}
private void readData() {
String name = prefs.getString(KEY_NAME, "Chưa có tên");
String phone = prefs.getString(KEY_PHONE, "Chưa có SĐT");
tvResult.setText("Tên: " + name + "\nSĐT: " + phone);
}
}
Các chế độ truy cập (Mode)
- MODE_PRIVATE (0): Chỉ app của bạn truy cập được (mặc định, an toàn)
- MODE_WORLD_READABLE: Deprecated (API 17+), không an toàn
- MODE_WORLD_WRITEABLE: Deprecated, không an toàn
- MODE_MULTI_PROCESS: Deprecated, không tin cậy
SharedPreferences cho nhiều tiến trình (Multi-process)
Dùng androidx.datastore:datastore-preferences hoặc ContentProvider thay vì SharedPreferences MODE_MULTI_PROCESS.
Best Practices
- Dùng hằng số (constant) cho key tránh typo
- Luôn cung cấp default value khi get
- Dùng
apply()thay vìcommit()trên main thread - Gom nhóm key liên quan vào cùng file prefs (getSharedPreferences("name", MODE_PRIVATE))
- Không lưu dữ liệu nhạy cảm (password, token) → Dùng EncryptedSharedPreferences (Jetpack Security)
- Tránh lưu object phức tạp → Dùng Gson/JSON hoặc Room
EncryptedSharedPreferences (Bảo mật)
// build.gradle
implementation "androidx.security:security-crypto:1.1.0-alpha03"
// Sử dụng
val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
val sharedPrefs = EncryptedSharedPreferences.create(
context,
"secret_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
// Dùng như SharedPreferences bình thường
sharedPrefs.edit().putString("token", "abc123").apply()
Chạy ứng dụng
Nhập tên, SĐT → Nhấn "Lưu" → Nhấn "Đọc" hiển thị dữ liệu đã lưu. Đóng app, mở lại → Dữ liệu vẫn còn.
Lưu ý
- SharedPreferences không phù hợp cho dữ liệu lớn, cấu trúc phức tạp, cần query → Dùng Room Database
- File XML lưu tại:
/data/data/com.package.name/shared_prefs/filename.xml - Clear app data (Settings) sẽ xóa SharedPreferences
- Uninstall app cũng xóa