Lưu tập tin ở bộ nhớ ngoài (External Storage)
Cũng giống như Lưu tập tin ở bộ nhớ trong (internal storage), chúng ta có thể lưu và đọc dữ liệu từ bộ nhớ ngoài (external storage) của thiết bị như sdcard. Hai lớp FileInputStream and FileOutputStream được sử dụng để đọc và ghi dữ liệu vào tập tin.
Chú ý: Để có thể đọc/ghi trong tập tin lưu trong bộ nhớ ngoài, chúng ta cần phân quyền trong tập tin AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Các phương thức để lưu trữ dữ liệu
1.getExternalStorageState(): Nên luôn kiểm tra tính sẵn sàng cho phép truy xuất của bộ nhớ ngoài thông qua hàm getExternalStorageState() – trả về trạng thái hiện tại của bộ nhớ ngoài. Vì bộ nhớ ngoài (thẻ nhớ, SDCard) có thể sẽ không cho phép các ứng dụng trên thiết bị truy xuất đến nó nếu đang ở tình trạng tháo ra khỏi thiết bị hoặc đang được “mount” với một thiết bị khác như PC, laptop chẳng hạn.
String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { // External storage is available for read and write // TODO: } if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { External storage is available to at least read // TODO: }
2. getExternalFileDir(String type): Đối tượng File có đường dẫn thư mục nội bộ bên trong thư mục dữ liệu của ứng dụng đặt trong bộ nhớ ngoài. Nếu bạn thông số truyền vào là Null, thì kết quả trả về là thư mục gốc của thư mục dữ liệu của ứng dụng trong bộ nhớ ngoài.
// Truy xuất thư mục pictures trong thư mục ứng dụng trong bộ nhớ ngoài File file = new File(context.getExternalFilesDir( Environment.DIRECTORY_PICTURES), "UserPrivatePicturesDirectory"); if (!file.mkdirs()) { Log.e("ITLog", "Directory not created"); }
3. Environment.getExternalStoragePublicDirectory(): Đối tượng File có đường dẫn thư mục trong bộ nhớ ngoài dùng chung, vì mục đích chia sẻ, các tập tin này sẽ không bị xóa đi khi gỡ ứng dụng ra khỏi thiết bị. Ví dụ như, ứng dụng bạn dùng camera để chụp ảnh, và những file ảnh này nên được giữ lại cho người dùng dù ứng dụng của bạn đã được gỡ ra khỏi thiết bị rồi.
// Truy xuất thư mục pictures trong bộ nhớ ngoài dùng chung. File file = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES), "UserPublicPicturesDirectory"); if (!file.mkdirs()) { Log.e("ITLog", "Directory not created"); }
Phương thức trên nhận đối số là chuỗi giá trị đường dẫn của thư mục con chứa các tập tin theo từng loại (âm thanh, hình ảnh, tập tin dạng text, …) bên trong thư mục dữ liệu của ứng dụng. Những giá trị đường dẫn này là các hằng giá trị được định nghĩa trong lớp Environment:
- DIRECTORY_ALARMS — Các file âm thanh được dung làm báo thức
- DIRECTORY_DCIM — Hình ảnh và video được chụp hoặc quay bằng thiết bị
- DIRECTORY_DOWNLOADS — chứa các file được tải về
- DIRECTORY_MOVIES — chứa các file video
- DIRECTORY_MUSIC — Chứa các file âm thanh cho chương trình nghe nhạc
- DIRECTORY_NOTIFICATIONS — Các file âm thanh cho các thông báo tin nhắn
- DIRECTORY_PICTURES — Chứa các file hình ảnh
- DIRECTORY_RINGTONES — Các file âm thanh được dung làm nhạc chuông
Bảng kết quả dưới đây chạy trên thiết bị mô phỏng.
Phương thức | Trả về |
getDataDirectory() | /data |
getDownloadCacheDirectory() | /cache |
getExternalStorageState() | mounted |
getExternalStoragePublicDirectory(Environment.Music): | /storage/emulated/0/Music |
getDownloadCacheDirectory() | /cache |
getRootDirectory() | /system |
Ví dụ: Trong ví dụ này chúng ta sẽ làm ứng dụng để lưu trữ dữ liệu trong bộ nhớ ngoài. Trong ứng dụng có 2 Activity, Activity đầu tiên lưu trữ dữ liệu, Activity 2 dùng để đọc dữ liệu. Tiến hành tạo project, vào thư mục res /layout -> activity_main.xml thiết kế giao diện sau:
Bước 1: Tạo một project tên là ExternalStorage: File->New->Android Application Project điền các thông tin ->Next ->Finish
Bước 2: Mở res -> layout -> xml (hoặc) activity_main.xml và thêm code trong Relaytive Layout.
Trong code chúng ta thêm textview, edittext và button có sự kiện onclick.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="hiepsiit.com.externalstorage.MainActivity" > <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginTop="46dp" android:gravity="center" android:text="@string/add_text" android:textSize="18sp" android:textStyle="bold|italic" /> <Button android:id="@+id/button4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/button" android:layout_alignParentBottom="true" android:layout_alignStart="@+id/button" android:layout_marginBottom="52dp" android:layout_marginLeft="10dp" android:layout_marginStart="96dp" android:onClick="next" android:text="@string/click_to_view" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/button4" android:layout_alignRight="@+id/editText2" android:layout_marginBottom="22dp" android:onClick="savePublic" android:textSize="13dp" android:text="@string/save_as_public" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/button2" android:layout_alignParentLeft="true" android:layout_toLeftOf="@+id/button2" android:onClick="savePrivate" android:textSize="13dp" android:text="@string/save_as_private" /> <EditText android:id="@+id/editText2" android:layout_width="match_parent" android:layout_height="300px" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_below="@+id/textView" android:layout_marginTop="16dp" android:ems="10" android:gravity="center_vertical|center" android:inputType="textMultiLine" /> </RelativeLayout>
Bước 3: Trong tập tin strings.xml
chúng ta định nghĩa các nhãn cho textview, edittext và button.
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="action_settings">Settings</string> <string name="app_name">External Storage Example</string> <string name="back">Back</string> <string name="show_private_data">SHOW PRIVATE DATA</string> <string name="show_public_data">SHOW PUBLIC DATA</string> <string name="add_text">ADD TEXT</string> <string name="click_to_view">Click To View</string> <string name="save_as_private">SAVE AS PRIVATE</string> <string name="save_as_public">SAVE AS PUBLIC</string> <string name="title_activity_main2">Main2Activity</string> <string name="hello_world">Hello world!</string> </resources>
Bước 4: Mở app -> src ->MainActivity.java và thêm code. Trong bước này chúng ta mở MainActivity.java và thêm các phương thức cho 3 button "SAVE AS PRIVATE", "SAVE AS PUBLIC" và "Click To View". Ở đây chúng ta xây dựng 2 phương thức savePrivate() và savePublic(), 2 phương thức này lấy dữ liệu từ edittext và lưu nó vào tập tin theo định dạng là byte. Chúng ta cũng hiển thị đường dẫn tập tin thông qua đối tượng Toast. Phương thức cho button "Click To View" mở Activity 2.
package hiepsiit.com.externalstorage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import android.Manifest; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Environment; import android.support.v4.app.ActivityCompat; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { EditText editText; private int STORAGE_PERMISSION_CODE = 23; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText = (EditText) findViewById(R.id.editText2); } public void next(View view) { Intent intent = new Intent(MainActivity.this, Main2Activity.class); startActivity(intent); } public void savePublic(View view) { //Permission to access external storage ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSION_CODE); String info = editText.getText().toString(); File folder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_ALARMS);// Folder Name File myFile = new File(folder, "myData1.txt");// Filename writeData(myFile, info); editText.setText(""); } public void savePrivate(View view) { String info = editText.getText().toString(); File folder = getExternalFilesDir("HiepSiIT");// Folder Name File myFile = new File(folder, "myData2.txt");// Filename writeData(myFile, info); editText.setText(""); } private void writeData(File myFile, String data) { FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(myFile); fileOutputStream.write(data.getBytes()); Toast.makeText(this, "Done" + myFile.getAbsolutePath(), Toast.LENGTH_SHORT).show(); } catch (Exception e) { e.printStackTrace(); } finally { if (fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
Bước 5: Tạo thêm Activity Android đặt tên Main2Activity . Mở res -> layout -> xml (hoặc) activity_main2.xml và thêm code:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="hiepsiit.com.externalstorage.Main2Activity" > <TextView android:id="@+id/getText" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:layout_marginTop="33dp" android:gravity="center" android:text="" android:textSize="18sp" android:textStyle="bold|italic" /> <Button android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/button5" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_toRightOf="@+id/button2" android:onClick="getPublic" android:textSize="11dp" android:text="@string/show_public_data" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/getText" android:layout_below="@+id/getText" android:layout_marginTop="178dp" android:onClick="getPrivate" android:text="@string/show_private_data" android:textSize="13dp" tools:ignore="UnknownId" /> <Button android:id="@+id/button5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/button2" android:layout_centerHorizontal="true" android:layout_marginTop="59dp" android:onClick="backMe" android:text="@string/back" /> </RelativeLayout>
Bước 6: Mở src -> package -> Main2Activity.java. Trong bước này chúng ta mở Main2Activity.java thêm các phương thức cho 3 button "SHOW PRIVATE DATA", "SAVE PUBLIC DATA" và "BACK". Ở đây chúng ta xây dựng 2 phương thức getPrivate() và getPublic() lấy dữ liệu từ tập tin và lưu nó vào đối tượng StringBuffer, sau đó hiển thị nó lên textview. Phương thức cho button "Back" mở MainActivity.
package hiepsiit.com.externalstorage; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Environment; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.TextView; public class Main2Activity extends Activity { TextView showText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); showText = (TextView) findViewById(R.id.getText); } public void backMe(View view) { Intent intent = new Intent(Main2Activity.this, MainActivity.class); startActivity(intent); } public void getPublic(View view) { File folder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_ALARMS); // Folder Name File myFile = new File(folder, "myData1.txt"); // Filename String text = getdata(myFile); if (text != null) { showText.setText(text); } else { showText.setText("No Data"); } } public void getPrivate(View view) { File folder = getExternalFilesDir("HiepSiIT"); // Folder Name File myFile = new File(folder, "myData2.txt"); // Filename String text = getdata(myFile); if (text != null) { showText.setText(text); } else { showText.setText("No Data"); } } private String getdata(File myfile) { FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(myfile); int i = -1; StringBuffer buffer = new StringBuffer(); while ((i = fileInputStream.read()) != -1) { buffer.append((char) i); } return buffer.toString(); } catch (Exception e) { e.printStackTrace(); } finally { if (fileInputStream != null) { try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } }
Ứng dụng này được phát triển bởi adt bundle, android 4.2 sử dụng minimum sdk 8 and target sdk 21.
Kết quả khi chạy ứng dụng:
Cập nhật công nghệ từ Youtube tại link: https://www.youtube.com/channel/UCOxeYcvZPGf-mGLYSl_1LuA/videos
Để tham gia khóa học công nghệ truy cập link: http://thuvien.hocviendaotao.com
Mọi hỗ trợ về công nghệ email: dinhanhtuan68@gmail.com