Trang chủHướng dẫnKhai phá bộ nhớ ngoài Android: Bí quyết đọc, ghi, lưu tệp hiệu quả
Chuyên gia

Khai phá bộ nhớ ngoài Android: Bí quyết đọc, ghi, lưu tệp hiệu quả

CyStack blog 4 phút để đọc
CyStack blog10/06/2025
Locker Avatar

Chris Pham

Technical Writer

Locker logo social
Reading Time: 4 minutes

Bộ nhớ ngoài Android có thể được dùng để ghi và lưu dữ liệu, đọc các tệp cấu hình, v.v. Bài viết này là phần tiếp theo của hướng dẫn về bộ nhớ trong trong loạt bài hướng dẫn về lưu trữ dữ liệu có cấu trúc trên Android.

Bộ nhớ ngoài Android

Bộ nhớ ngoài Android

Bộ nhớ ngoài chẳng hạn như thẻ SD, cũng có thể được dùng để lưu trữ dữ liệu ứng dụng. Tuy nhiên, không có biện pháp bảo mật nào được áp dụng cho các tệp bạn lưu trên loại bộ nhớ này. Về cơ bản, có hai dạng bộ nhớ ngoài:

  • Bộ nhớ ngoài chính (Primary External Storage): Đây là bộ nhớ chia sẻ được tích hợp sẵn trong thiết bị, người dùng có thể truy cập bằng cách kết nối cáp USB và gắn nó làm ổ đĩa trên máy tính. Ví dụ, khi nhắc đến Nexus 5 32 GB, 32 GB chính là bộ nhớ ngoài chính.
  • Bộ nhớ ngoài phụ (Secondary External Storage): Đây là loại bộ nhớ rời, điển hình là thẻ SD.

Tất cả các ứng dụng đều có quyền đọc và ghi các tệp trên bộ nhớ ngoài, và người dùng có thể xóa chúng bất cứ lúc nào. Do đó, chúng ta cần kiểm tra xem thẻ SD có đang khả dụng và có thể ghi được không. Chỉ khi bộ nhớ ngoài sẵn sàng, chúng ta mới có thể lưu dữ liệu. Nếu không, tính năng lưu nên được vô hiệu hóa.

Cấu trúc dự án về bộ nhớ ngoài trên Android

Đầu tiên, cần đảm bảo ứng dụng có quyền đọc và ghi dữ liệu vào thẻ SD của người dùng. Mở tệp AndroidManifest.xml và thêm các quyền sau:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

Bộ nhớ ngoài có thể bị khóa khi người dùng kết nối nó dưới dạng thiết bị lưu trữ USB. Vì vậy, điều quan trọng là phải kiểm tra xem bộ nhớ đó có đang khả dụng và không ở trạng thái chỉ đọc hay không.

if (!isExternalStorageAvailable() || isExternalStorageReadOnly()) {
    saveButton.setEnabled(false);
}

private static boolean isExternalStorageReadOnly() {
    String extStorageState = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(extStorageState)) {
        return true;
    }
    return false;
}

private static boolean isExternalStorageAvailable() {
    String extStorageState = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(extStorageState)) {
        return true;
    }
    return false;
}

Phương thức getExternalStorageState() là một phương thức tĩnh của Environment để xác định xem bộ nhớ ngoài hiện có khả dụng hay không. Nếu điều kiện sai, tính năng lưu sẽ bị vô hiệu hóa.

Code mẫu cho bộ nhớ ngoài trên Android

Layout activity_main.xml có dạng như sau:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="<http://schemas.android.com/apk/res/android>"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Reading and Writing to External Storage"
        android:textSize="24sp"/>

    <EditText
        android:id="@+id/myInputText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:lines="5"
        android:minLines="3"
        android:gravity="top|left"
        android:inputType="textMultiline">
        <requestFocus />
    </EditText>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:weightSum="1.0"
        android:layout_marginTop="20dp">

        <Button
            android:id="@+id/saveExternalStorage"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="SAVE"
            android:layout_weight="0.5"/>
        <Button
            android:id="@+id/getExternalStorage"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="0.5"
            android:text="READ" />
    </LinearLayout>
    <TextView
        android:id="@+id/response"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:text=""
        android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>

Khác với hướng dẫn trước dùng Android Toast, ở đây chúng ta hiển thị kết quả lưu/đọc dữ liệu từ bộ nhớ ngoài trực tiếp trên một TextView, bên cạnh các nút chức năng. Dưới đây là code của class MainActivity.java:

package com.journaldev.externalstorage;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import android.os.Bundle;
import android.app.Activity;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

class MainActivity extends Activity {
    EditText inputText;
    TextView response;
    Button saveButton, readButton;

    private String filename = "SampleFile.txt";
    private String filepath = "MyFileStorage";
    File myExternalFile;
    String myData = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        inputText = (EditText) findViewById(R.id.myInputText);
        response = (TextView) findViewById(R.id.response);

        saveButton = (Button) findViewById(R.id.saveExternalStorage);
        saveButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    FileOutputStream fos = new FileOutputStream(myExternalFile);
                    fos.write(inputText.getText().toString().getBytes());
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                inputText.setText("");
                response.setText("SampleFile.txt saved to External Storage...");
            }
        });

        readButton = (Button) findViewById(R.id.getExternalStorage);
        readButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    FileInputStream fis = new FileInputStream(myExternalFile);
                    DataInputStream in = new DataInputStream(fis);
                    BufferedReader br = new BufferedReader(new InputStreamReader(in));
                    String strLine;
                    while ((strLine = br.readLine()) != null) {
                        myData = myData + strLine;
                    }
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                inputText.setText(myData);
                response.setText("SampleFile.txt data retrieved from Internal Storage...");
            }
        });

        if (!isExternalStorageAvailable() || isExternalStorageReadOnly()) {
            saveButton.setEnabled(false);
        } else {
            myExternalFile = new File(getExternalFilesDir(filepath), filename);
        }
    }

    private static boolean isExternalStorageReadOnly() {
        String extStorageState = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(extStorageState)) {
            return true;
        }
        return false;
    }

    private static boolean isExternalStorageAvailable() {
        String extStorageState = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(extStorageState)) {
            return true;
        }
        return false;
    }
}

  1. Environment.getExternalStorageState(): Trả về đường dẫn đến thẻ SD nội bộ, ví dụ: /mnt/sdcard.
  2. getExternalFilesDir(): Trả về đường dẫn đến thư mục files bên trong Android/data/data/application_package/ trên thẻ SD. Thư mục này được sử dụng để lưu trữ các tệp cần thiết cho ứng dụng (như hình ảnh tải từ web hoặc tệp cache). Khi ứng dụng bị gỡ cài đặt, mọi dữ liệu trong thư mục này cũng sẽ bị xóa.

Nếu bộ nhớ ngoài không khả dụng, chúng ta sẽ vô hiệu hóa nút lưu theo điều kiện if đã được giải thích ở phần trước. Dưới đây là hình ảnh ứng dụng đang chạy trên trình giả lập Android, minh họa quá trình ghi và đọc dữ liệu từ tệp.

Lưu ý: Đảm bảo rằng trình giả lập Android của bạn được cấu hình để có thẻ SD như trong hộp thoại AVD. Điều chỉnh bằng cách vào: Tools → Android → Android Virtual Device → Show Advance Settings, sau đó chỉnh sửa cấu hình.

Kết luận

Hướng dẫn này đã trình bày cách đọc, ghi và lưu tệp trên bộ nhớ ngoài của Android. Bằng cách kiểm tra trạng thái bộ nhớ ngoài và sử dụng các phương thức phù hợp, bạn có thể đảm bảo ứng dụng của mình hoạt động hiệu quả với các thiết bị lưu trữ ngoài.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.