Scoped Storage là một tính năng bảo mật mới được giới thiệu trong Android 10 (API level 29), yêu cầu các ứng dụng phải giới hạn quyền truy cập của chúng vào các tệp trên bộ nhớ ngoài. Trước đây, các ứng dụng có thể truy cập toàn bộ bộ nhớ ngoài, nhưng với Scoped Storage, các ứng dụng chỉ có thể truy cập vào một phạm vi hạn chế của bộ nhớ ngoài mà không gây ảnh hưởng đến các tệp của ứng dụng khác.
Trong bài viết này, tôi sẽ hướng dẫn bạn chi tiết về cách làm việc với Scoped Storage trong Android.
1. Lý Do Scoped Storage Ra Đời
Trước khi Android 10 ra mắt, ứng dụng có thể truy cập bất kỳ tệp nào trên bộ nhớ ngoài của thiết bị, điều này tiềm ẩn rủi ro về bảo mật và quyền riêng tư. Android 10 đã thay đổi điều này bằng cách giới hạn phạm vi truy cập của các ứng dụng vào bộ nhớ ngoài, chỉ cho phép chúng truy cập vào các tệp mà chúng tạo ra hoặc được người dùng cấp phép rõ ràng.
2. Điều Kiện Để Sử Dụng Scoped Storage
- Android 10 trở lên (API level 29): Khi ứng dụng của bạn chạy trên Android 10 hoặc phiên bản cao hơn, hệ thống sẽ bắt buộc sử dụng Scoped Storage. Điều này có nghĩa là bạn phải thay đổi cách ứng dụng của mình xử lý tệp trong bộ nhớ ngoài.
- Android 9 trở xuống: Các ứng dụng vẫn có thể sử dụng cách truy cập bộ nhớ ngoài như trước.
3. Cách Thực Hiện Scoped Storage trong Android
Bước 1: Cập nhật AndroidManifest.xml
Từ Android 10 trở đi, nếu ứng dụng cần truy cập bộ nhớ ngoài, bạn phải chỉ định rõ quyền trong tệp AndroidManifest.xml
.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Tuy nhiên, đối với Scoped Storage, bạn không cần yêu cầu quyền READ_EXTERNAL_STORAGE và WRITE_EXTERNAL_STORAGE trừ khi ứng dụng của bạn sử dụng các tính năng cần quyền này như truy cập vào tệp hệ thống (ví dụ: với Intent để mở tệp).
Bước 2: Đọc và Ghi Tệp Trong Scoped Storage
Android cung cấp các API để bạn có thể truy cập vào các tệp mà ứng dụng của bạn đã tạo ra hoặc các tệp mà người dùng đã cấp quyền rõ ràng. Dưới đây là ví dụ về cách thực hiện việc đọc và ghi tệp trong phạm vi Scoped Storage.
Ghi Tệp Vào Thư Mục Được Chỉ Định
Bạn có thể sử dụng MediaStore hoặc Storage Access Framework (SAF) để thao tác với các tệp.
import android.content.ContentValues;
import android.net.Uri;
import android.provider.MediaStore;
import android.content.Context;
import java.io.OutputStream;
public void writeFile(Context context) {
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DISPLAY_NAME, "example.txt");
values.put(MediaStore.MediaColumns.MIME_TYPE, "text/plain");
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOCUMENTS); // Lưu vào thư mục Documents
Uri uri = context.getContentResolver().insert(MediaStore.Files.getContentUri("external"), values);
try (OutputStream outputStream = context.getContentResolver().openOutputStream(uri)) {
if (outputStream != null) {
String content = "Hello Scoped Storage!";
outputStream.write(content.getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
}
Ở ví dụ trên, tệp example.txt
sẽ được lưu vào thư mục Documents trong bộ nhớ ngoài.
Đọc Tệp Từ Bộ Nhớ Ngoài
Để đọc tệp từ bộ nhớ ngoài, bạn có thể sử dụng MediaStore hoặc Storage Access Framework (SAF).
import android.net.Uri;
import android.provider.MediaStore;
import android.content.Context;
import java.io.InputStream;
import java.io.IOException;
public void readFile(Context context) {
Uri uri = MediaStore.Files.getContentUri("external");
Uri fileUri = Uri.withAppendedPath(uri, "example.txt");
try (InputStream inputStream = context.getContentResolver().openInputStream(fileUri)) {
if (inputStream != null) {
StringBuilder stringBuilder = new StringBuilder();
int character;
while ((character = inputStream.read()) != -1) {
stringBuilder.append((char) character);
}
Log.d("ScopedStorage", "File content: " + stringBuilder.toString());
}
} catch (IOException e) {
e.printStackTrace();
}
}
Ở ví dụ trên, bạn đọc nội dung từ tệp example.txt
đã lưu trong bộ nhớ ngoài.
Bước 3: Sử Dụng Storage Access Framework (SAF)
Nếu bạn muốn cho người dùng chọn tệp để truy cập, bạn có thể sử dụng Storage Access Framework (SAF). SAF cho phép ứng dụng truy cập vào các tệp mà người dùng lựa chọn, đồng thời bảo vệ quyền riêng tư của người dùng.
Để sử dụng SAF, bạn sẽ mở một Intent để người dùng chọn tệp:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("text/plain");
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, REQUEST_CODE_OPEN_DOCUMENT);
Sau khi người dùng chọn tệp, bạn có thể sử dụng Uri trả về để truy cập vào tệp.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_OPEN_DOCUMENT && resultCode == RESULT_OK) {
Uri uri = data.getData();
// Bạn có thể sử dụng uri để đọc tệp
}
}
4. Sự Khác Biệt Giữa Scoped Storage và Truy Cập Tự Do Trước Đó
- Scoped Storage hạn chế khả năng truy cập vào toàn bộ bộ nhớ ngoài, chỉ cho phép truy cập vào các thư mục và tệp mà ứng dụng đã tạo ra hoặc được người dùng cấp quyền cụ thể.
- Trước Android 10, các ứng dụng có thể truy cập trực tiếp vào các thư mục và tệp bất kỳ trên bộ nhớ ngoài mà không bị giới hạn.
5. Lợi Ích và Hạn Chế
Lợi Ích:
- Bảo mật và quyền riêng tư: Scoped Storage bảo vệ dữ liệu của người dùng khỏi việc bị ứng dụng khác truy cập trái phép.
- Quản lý dễ dàng: Các tệp chỉ có thể được truy cập khi người dùng cấp quyền hoặc ứng dụng tạo ra chúng, giúp quản lý các tệp của ứng dụng dễ dàng hơn.
Hạn Chế:
- Khó khăn trong việc truy cập tệp của ứng dụng khác: Nếu ứng dụng của bạn cần truy cập tệp của ứng dụng khác, bạn cần phải sử dụng SAF và yêu cầu người dùng chọn tệp.
- Chỉ có thể truy cập những thư mục đã được chỉ định: Bạn không thể tự do truy cập vào các thư mục hệ thống như trước.
6. Tổng Kết
Scoped Storage là một thay đổi quan trọng trong cách Android xử lý quyền truy cập bộ nhớ ngoài. Với tính năng này, ứng dụng của bạn sẽ hoạt động bảo mật hơn, bảo vệ quyền riêng tư của người dùng, đồng thời cung cấp cách tiếp cận có tổ chức hơn trong việc truy cập và quản lý tệp trên bộ nhớ ngoài. Hãy chắc chắn rằng bạn cập nhật ứng dụng của mình để tuân thủ các yêu cầu về Scoped Storage khi phát triển cho Android 10 trở lên.