Để đồng hành cùng bài viết này, bạn cần những kỹ năng và các công cụ sau đây:
- Kiến thức cơ bản về công nghệ Java™ và cách sử dụng Eclipse (hoặc IDE yêu thích của bạn).
- JDK (phiên bản cần thiết là 5 hoặc 6).
- Eclipse (phiên bản 3.4 hoặc 3.5).
- SDK của Android và Trình cắm thêm ADT.
Để tải về và có thông tin thiết lập, hãy xem Tài nguyên ở cuối bài viết này.
Để làm nổi bật các khía cạnh lưu trữ cục bộ về việc phát triển ứng dụng Android, tôi trình bày một ứng dụng mẫu cho phép bạn thử nghiệm việc thực hiện các kiểu API. Mã nguồn có sẵn để tải về. Ứng dụng này hỗ trợ các hành động trong Hình 1.
Hình 1. Các trường hợp sử dụng (use cases)
Hình 1 liệt kê các trường hợp sử dụng sau:
- Quản lý và lưu trữ các sở thích.
- Nạp thông tin từ các tài sản ứng dụng.
- Xuất khẩu thông tin vào bộ nhớ trong, bộ nhớ ngoài và cơ sở dữ liệu cục bộ.
- Đọc thông tin từ bộ nhớ trong và cơ sở dữ liệu cục bộ.
- Xóa thông tin đã lưu trữ.
- Xem thông tin trên màn hình.
Bạn sử dụng lưu trữ cục bộ trong ứng dụng xuyên suốt bài viết này, như sau:
- Các sở thích được nắm bắt từ người sử dụng, được lưu trữ cục bộ và được sử dụng trong toàn bộ ứng dụng.
- Một hình ảnh của người sử dụng được lấy ra từ các tài sản của ứng dụng nội bộ, được lưu trữ trong bộ nhớ trong và bộ nhớ ngoài cục bộ và được biểu hiện trên màn hình.
- Một danh sách những người bạn trong JSON được lấy từ các tài sản của ứng dụng. Nó được phân tích cú pháp và được lưu trữ trong bộ nhớ trong cục bộ, bộ nhớ ngoài và cơ sở dữ liệu quan hệ và được biểu hiện trên màn hình.
Ứng dụng mẫu định nghĩa các lớp trong Bảng 1.
Bảng 1. Các lớp của ứng dụng mẫu
| Lớp | Mô tả |
|---|---|
MainActivity | Hoạt động chính; hầu hết các mã mẫu tập trung ở đây. |
Friend | Biểu diễn một người bạn. |
AppPreferenceActivity | Màn hình và Hoạt động Các sở thích. |
DBHelper | Một lớp trợ giúp để quản lý cơ sở dữ liệu SQLite. |
Ứng dụng ví dụ sử dụng hai kiểu dữ liệu. Kiểu đầu tiên là các sở thích của ứng dụng được lưu trữ như các cặp giá trị tên. Đối với các sở thích, hãy định nghĩa các thông tin sau đây:
- Một tên tệp, được dùng để nạp và lưu trữ danh sách các tên của những người bạn.
- Một tên tệp, được dùng để nạp và lưu trữ một hình ảnh cho người sử dụng.
- Một cờ, nếu được đặt, chỉ báo tự động xóa tất cả dữ liệu được lưu khi khởi động ứng dụng.
Kiểu dữ liệu thứ hai là một danh sách những người bạn. Ban đầu danh sách những người bạn được trình bày theo định dạng JSON API biểu đồ của Facebook (Facebook Graph API JSON), bao gồm một mảng các đối tượng name (tên) và friend (người bạn) (xem Liệt kê 1).
Liệt kê 1. Danh sách những người bạn (theo định dạng Facebook Graph API JSON)
{
"data": [
{
"name": "Edmund Troche",
"id": "500067699"
}
]
}
|
Định dạng đơn giản ở trên làm cho đối tượng
Friend (người bạn) và lược đồ cơ sở dữ liệu đơn
giản. Liệt kê 2 cho thấy lớp
Friend.
Liệt kê 2. Lớp
Friend
package com.cenriqueortiz.tutorials.datastore;
import android.graphics.Bitmap;
/**
* Represents a Friend
*/
public class Friend {
public String id;
public String name;
public byte[] picture;
public Bitmap pictureBitmap;;
}
|
Ngoài ID (mã định danh) và tên, ứng dụng mẫu cũng duy trì các tham chiếu tới hình ảnh người bạn. Mặc dù ứng dụng mẫu chưa sử dụng các tham chiếu đó, bạn có thể dễ dàng mở rộng ứng dụng mẫu để lấy hình ảnh từ Facebook và hiển thị nó trong màn hình chính.
Lược đồ cơ sở dữ liệu bao gồm một bảng duy nhất để lưu trữ thông tin của người bạn. Bảng này có ba cột:
- ID hoặc khóa duy nhất.
- ID của Facebook.
- Tên của người bạn.
Liệt kê 3 cho thấy câu lệnh SQL để khai báo bảng quan hệ tương ứng.
Liệt kê 3. Bảng cơ sở dữ liệu người bạn
db.execSQL("create table " + TABLE_NAME + " (_id integer primary key autoincrement, "
+ " fid text not null, name text not null) ");
|
Dựa trên thông tin này, bạn có thể hiển thị tên của trên màn hình chính và bằng cách sử dụng ID, bạn có thể lấy thêm thông tin chi tiết cho người dùng được chọn. Trong ứng dụng mẫu này, bạn chỉ hiển thị tên. Việc lấy thêm thông tin còn dành lại cho bạn tự thử nghiệm. Lưu ý rằng bạn có thể dễ dàng thay đổi mã để trực tiếp đi vào Facebook.
Lưu trữ các sở thích của ứng dụng
Phần này trình bày API các sở thích (API Preferences) và các màn hình. API
Android cung cấp một số cách để xử lý các sở thích. Có một cách tiếp cận
là trực tiếp sử dụng SharedPreferences (Các sở
thích chia sẻ) và sử dụng thiết kế màn hình riêng của bạn và quản lý của
các sở thích. Cách tiếp cận thứ hai là sử dụng một PreferenceActivity (Hoạt động các sở thích). Một PreferenceActivity tự động chăm lo về các sở
thích được hiển thị trên màn hình như thế nào (theo mặc định chúng trông
giống như các sở thích của hệ thống) và tự động lưu trữ hoặc sao lưu các
sở thích khi người dùng tương tác với từng sở thích thông qua việc sử dụng
SharedPreferences.
Để đơn giản hóa ứng dụng mẫu, hãy sử dụng một
PreferenceActivity để quản lý các sở thích và
màn hình sở thích (xem Hình 2). Màn hình các sở thích
hiển thị hai phần: Các tài sản và các giá trị cài đặt tự động. Trong Các
tài sản, bạn có thể nhập các tên tệp cho cả hai tùy chọn Danh sách những
người bạn và Hình ảnh. Trong Các giá trị cài đặt tự động, bạn có thể đánh
dấu chọn một hộp kiểm tra để xóa thông tin lúc khởi động.
Hình 2. Màn hình Các sở thích khi được cài đặt
Trong Hình 2, cách bố trí đã được định nghĩa bằng cách sử dụng cách tiếp cận khai báo thông qua XML (thay vì lập trình); XML khai báo được ưa thích vì nó giữ mã nguồn sạch sẽ và dễ đọc.Liệt kê 4 cho thấy khai báo XML cho giao diện người dùng Các sở thích (Preferences UI).
Liệt kê 4. Khai báo XML của màn hình Các sở thích
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/prefs_screen"
android:key="preferencescreen"
>
<PreferenceCategory android:title="Assets">
<EditTextPreference
android:key="@string/prefs_assetname_friendslist_key"
android:title="Friends List"
android:summary="Please enter filename"
android:defaultValue="friends.txt"
/>
<EditTextPreference
android:key="@string/prefs_assetname_picture_key"
android:title="Picture"
android:summary="Please enter filename"
android:defaultValue="pict2.jpg"
/>
</PreferenceCategory>
<PreferenceCategory android:title="Auto Settings">
<CheckBoxPreference
android:key="@string/prefs_autodelete_key"
android:title="Delete at Startup"
android:summary="Check to clear at startup"
android:defaultValue="false"
/>
</PreferenceCategory>
</PreferenceScreen>
|
PreferenceScreen (Màn hình các sở thích) bao gồm
hai cá thể EditTextPreference, một là
CheckBoxPreference và hai nhóm thể loại theo
như định nghĩa của PreferenceCategory (một cho
Asset và một cho
Auto Settings).
Trong ứng dụng mẫu này, thiết kế yêu cầu màn hình các sở thích được gọi ra
bằng cách sử dụng một mục trình đơn. Để làm việc này, hãy sử dụng một
thông báo Intent để gọi Hoạt động của Màn hình Các sở thích (Preference
Screen Activity) có tên là
AppPreferenceActivity (xem Liệt kê 5). Lưu ý rằng tôi không trình bày Intent hoạt động cụ
thể như thế nào. Xem phần Tài nguyên để biết thêm
thông tin về các Intent.
Liệt kê 5.
AppPreferenceActivity
/*
* AppPreferenceActivity is a basic PreferenceActivity
* C. Enrique Ortiz | http://CEnriqueOrtiz.com
*/
package com.cenriqueortiz.tutorials.datastore;
import android.os.Bundle;
import android.preference.PreferenceActivity;
public class AppPreferenceActivity extends PreferenceActivity {
/**
* Default Constructor
*/
public AppPreferenceActivity() {}
/**
* Called when the activity is first created.
* Inflate the Preferences Screen XML declaration.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.prefs); // Inflate the XML declaration
}
}
|
Trong ứng dụng mẫu này, hãy gọi Intent như trong Liệt kê 6, từ bên trong trình xử lý mục Trình đơn.
Liệt kê 6. Gọi hoạt động Preferences bằng cách sử dụng một Intent
/**
* Invoked when a menu item has been selected
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Case: Bring up the Preferences Screen
case R.id.menu_prefs: // Preferences
// Launch the Preference Activity
Intent i = new Intent(this, AppPreferenceActivity.class);
startActivity(i);
break;
case R.id.menu...:
:
break;
}
return true;
}
|
Ngoài ra, bạn phải định nghĩa tất cả các Intent trong tệp XML AndroidManifest như trong Liệt kê 7.
Liệt kê 7. Định nghĩa Intent trong tệp AndroidManifest.xml
:
<application android:icon="@drawable/icon" android:label="@string/app_name">
:
:
<activity
android:name="AppPreferenceActivity"
android:label="Preferences">
</activity>
:
</application>
|
Nhớ lại rằng PreferenceActivity sử dụng
SharedPreferences để lưu trữ tự động các sở
thích khi người dùng tương tác với màn hình các sở thích. Sau đó ứng dụng
sử dụng các sở thích này khi nó thực thi để thực hiện các nhiệm vụ khác
nhau của nó. Liệt kê 8 cho thấy cách sử dụng trực
tiếp SharedPreferences để nạp các sở thích đã
lưu, bạn có thể tham khảo mã mẫu đi kèm về cách sử dụng các sở thích đã
nạp trong xuyên suốt toàn bộ mã mẫu như thế nào. Ngoài ra, Liệt kê 8 cũng cho thấy cách lưu trữ trực tiếp các
sở thích bằng SharedPreferences khi sử dụng một
Editor (trình soạn thảo) trong trường hợp bạn
thích tự quản lý các sở thích của mình (và không thông qua
PrefenceActivity).
Liệt kê 8 cho thấy cách sử dụng
SharedPreferences để nạp các sở thích đã lưu
trữ và cách thay đổi các sở thích đã lưu bằng cách sử dụng một
Editor.
Liệt kê 8. Sử dụng
SharedPreferences
/////////////////////////////////////////////////////////////
// The following methods show how to use the SharedPreferences
/////////////////////////////////////////////////////////////
/**
* Retrieves the Auto delete preference
* @return the value of auto delete
*/
public boolean prefsGetAutoDelete() {
boolean v = false;
SharedPreferences sprefs =
PreferenceManager.getDefaultSharedPreferences(appContext);
String key = appContext.getString(R.string.prefs_autodelete_key);
try {
v = sprefs.getBoolean(key, false);
} catch (ClassCastException e) {
}
return v;
}
/**
* Sets the auto delete preference
* @param v the value to set
*/
public void prefsSetAutoDelete(boolean v) {
SharedPreferences sprefs =
PreferenceManager.getDefaultSharedPreferences(appContext);
Editor e = sprefs.edit();
String key = appContext.getString(R.string.prefs_autodelete_key);
e.putBoolean(key, v);
e.commit();
}
|
Tiếp theo, bạn sẽ thấy cách sử dụng một cơ sở dữ liệu để lưu dữ liệu.
Sử dụng các cơ sở dữ liệu SQLite
Android cung cấp sự hỗ trợ cho cơ sở dữ liệu quan hệ cục bộ thông qua SQLite. Bảng này (được định nghĩa trong các liệt kê sau đây) tóm tắt các lớp cơ sở dữ liệu quan trọng được sử dụng trong ứng dụng mẫu.
Đối với ứng dụng mẫu, một lớp DBHelper được dùng
để gói một số phép toán của cơ sở dữ liệu (xem Liệt kê
9).
Liệt kê 9. Lớp
DBHelper
package com.cenriqueortiz.tutorials.datastore;
import java.util.ArrayList;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DBHelper extends SQLiteOpenHelper {
|
Một số hằng số được định nghĩa cho phiên bản cơ sở dữ liệu, tên cơ sở dữ liệu và tên bảng (xem Liệt kê 10).
Liệt kê 10. Khởi tạo lớp
DBHelper
private SQLiteDatabase db;
private static final int DATABASE_VERSION = 1;
private static final String DB_NAME = "sample.db";
private static final String TABLE_NAME = "friends";
/**
* Constructor
* @param context the application context
*/
public DBHelper(Context context) {
super(context, DB_NAME, null, DATABASE_VERSION);
db = getWritableDatabase();
}
|
Phương thức onCreate() được gọi khi đã sẵn sàng
để tạo ra cơ sở dữ liệu. Trong phương thức này, các bảng được tạo ra (xem
Liệt kê 11).
Liệt kê 11. Tạo bảng cơ sở dữ liệu
/**
* Called at the time to create the DB.
* The create DB statement
* @param the SQLite DB
*/
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(
"create table " + TABLE_NAME + " (_id integer primary key autoincrement,
" + " fid text not null, name text not null) ");
}
|
Phương thức insert() được
MainActivity gọi ra khi xuất khẩu thông tin tới
cơ sở dữ liệu (xem Liệt kê 12).
Liệt kê 12. Chèn một hàng
/**
* The Insert DB statement
* @param id the friends id to insert
* @param name the friend's name to insert
*/
public void insert(String id, String name) {
db.execSQL("INSERT INTO friends('fid', 'name') values ('"
+ id + "', '"
+ name + "')");
}
|
Phương thức deleteAll() được
MainActivity gọi ra khi xóa cơ sở dữ liệu. Nó
xóa bảng (xem Liệt kê 13).
Liệt kê 13. Xóa bảng cơ sở dữ liệu
/**
* Wipe out the DB
*/
public void clearAll() {
db.delete(TABLE_NAME, null, null);
}
|
Hai phương thức SELECT ALL (Chọn tất cả) được
cung cấp: cursorSelectAll(), trả về một con trỏ
và listSelectAll(), trả về một
ArrayList của các đối tượng
Friend. Các phương thức này được
MainActivity gọi ra khi nạp thông tin từ cơ sở
dữ liệu (xem Liệt kê 14).
Liệt kê 14. Chạy một phương thức
Select All để trả về một ArrayList
/**
* Select All returns a cursor
* @return the cursor for the DB selection
*/
public Cursor cursorSelectAll() {
Cursor cursor = this.db.query(
TABLE_NAME, // Table Name
new String[] { "fid", "name" }, // Columns to return
null, // SQL WHERE
null, // Selection Args
null, // SQL GROUP BY
null, // SQL HAVING
"name"); // SQL ORDER BY
return cursor;
}
|
Phương thức listSelectAll() trả về hàng đã chọn
trong một thùng chứa ArrayList được
MainActivity sử dụng để ràng buộc nó vào
MainScreen
ListView (xem Liệt kê 15).
Liệt kê 15. Chạy một phương thức
Select All để trả về một con trỏ
/**
* Select All that returns an ArrayList
* @return the ArrayList for the DB selection
*/
public ArrayList<Friend> listSelectAll() {
ArrayList<Friend> list = new ArrayList<Friend>();
Cursor cursor = this.db.query(TABLE_NAME, new String[] { "fid", "name" },
null, null, null, null, "name");
if (cursor.moveToFirst()) {
do {
Friend f = new Friend();
f.id = cursor.getString(0);
f.name = cursor.getString(1);
list.add(f);
} while (cursor.moveToNext());
}
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
return list;
}
|
Phương thức onUpgrade() được gọi nếu phát hiện
ra một phiên bản cơ sở dữ liệu thay đổi (xem Liệt kê
16).
Liệt kê 16. Phát hiện xem có thay đổi phiên bản cơ sở dữ liệu không
/**
* Invoked if a DB upgrade (version change) has been detected
*/
@Override
/**
* Invoked if a DB upgrade (version change) has been detected
*/
@Override
public void onUpgrade(SQLiteDatabase db,
int oldVersion, int newVersion) {
// Here add any steps needed due to version upgrade
// for example, data format conversions, old tables
// no longer needed, etc
}
}
|
Xuyên suốt MainActivity,
DBHelper được sử dụng khi bạn xuất khẩu thông
tin đến cơ sở dữ liệu, nạp thông tin từ cơ sở dữ liệu và khi bạn xóa cơ sở
dữ liệu. Việc đầu tiên là khởi tạo DBHelper khi
đã tạo MainActivity. Các nhiệm vụ khác được
thực hiện tại phương thức onCreate() bao gồm
việc khởi tạo các khung nhìn màn hình khác nhau (xem Liệt kê 17).
Liệt kê 17. Phương thức
MainActivity onCreate() khởi tạo cơ sở dữ liệu
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appContext = this;
setContentView(R.layout.main);
dbHelper = new DBHelper(this);
listView = (ListView) findViewById(R.id.friendsview);
friendsArrayAdapter = new FriendsArrayAdapter(
this, R.layout.rowlayout, friends);
listView.setAdapter(friendsArrayAdapter);
:
:
}
|
Liệt kê 18 cho thấy cách nạp danh sách những người bạn từ các tài sản và cách phân tích cú pháp và chèn nó vào trong cơ sở dữ liệu.
Liệt kê 18.
MainActivity đang chèn vào trong cơ sở dữ liệu
String fname = prefsGetFilename();
if (fname != null && fname.length() > 0) {
buffer = getAsset(fname);
// Parse the JSON file
String friendslist = new String(buffer);
final JSONObject json = new JSONObject(friendslist);
JSONArray d = json.getJSONArray("data");
int l = d.length();
for (int i2=0; i2<l; i2++) {
JSONObject o = d.getJSONObject(i2);
String n = o.getString("name");
String id = o.getString("id");
dbHelper.insert(id, n);
}
// Only the original owner thread can touch its views
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
friendsArrayAdapter.notifyDataSetChanged();
}
});
}
|
Liệt kê 19 cho thấy cách thực hiện một
SELECT ALL (Chọn tất cả) và cách ràng buộc dữ
liệu vào ListView của màn hình chính.
Liệt kê 19.
Select All của MainActivity và ràng buộc dữ liệu vào ListView
final ArrayList<Friend> dbFriends = dbHelper.listSelectAll();
if (dbFriends != null) {
// Only the original owner thread can touch its views
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
friendsArrayAdapter =
new FriendsArrayAdapter(
MainActivity.this, R.layout.rowlayout, dbFriends);
listView.setAdapter(friendsArrayAdapter);
friendsArrayAdapter.notifyDataSetChanged();
}
});
}
|
Tiếp theo, hãy xem xét việc sử dụng API lưu trữ trong với ứng dụng ví dụ.
Sử dụng lưu trữ trong của thiết bị cho dữ liệu riêng tư
Với API lưu trữ dữ liệu, bạn có thể lưu trữ dữ liệu bằng cách sử dụng lưu
trữ trong. Thông tin có thể riêng tư và bạn có tùy chọn cho phép các ứng
dụng khác có quyền đọc hoặc viết vào nó. Phần này trình bày API để lưu trữ
dữ liệu cá nhân khi sử dụng
android.content.Context.openFileInput,
openFileOutput, và
getCacheDir() để lưu dữ liệu vào bộ nhớ nhanh
(cache) thay vì lưu trữ nó lâu bền.
Đoạn mã được hiển thị trong Liệt kê 20 cho thấy cách
đọc từ bộ nhớ riêng bên trong. Việc sử dụng phương thức
openFileOutput() với
MODE_PRIVATE (Chế độ_ riêng tư) để làm cho lưu
trữ thành riêng tư.
Liệt kê 20. Đọc từ lưu trữ riêng cục bộ
/**
* Writes content to internal storage making the content private to
* the application. The method can be easily changed to take the MODE
* as argument and let the caller dictate the visibility:
* MODE_PRIVATE, MODE_WORLD_WRITEABLE, MODE_WORLD_READABLE, etc.
*
* @param filename - the name of the file to create
* @param content - the content to write
*/
public void writeInternalStoragePrivate(
String filename, byte[] content) {
try {
//MODE_PRIVATE creates/replaces a file and makes
// it private to your application. Other modes:
// MODE_WORLD_WRITEABLE
// MODE_WORLD_READABLE
// MODE_APPEND
FileOutputStream fos =
openFileOutput(filename, Context.MODE_PRIVATE);
fos.write(content);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
|
Đoạn mã trong Liệt kê 21 cho thấy cách đọc từ lưu trữ
riêng bên trong; hãy xem cách sử dụng phương thức
openFileInput().
Liệt kê 21. Đọc từ lưu trữ riêng bên trong
/**
* Reads a file from internal storage
* @param filename the file to read from
* @return the file content
*/
public byte[] readInternalStoragePrivate(String filename) {
int len = 1024;
byte[] buffer = new byte[len];
try {
FileInputStream fis = openFileInput(filename);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int nrb = fis.read(buffer, 0, len); // read up to len bytes
while (nrb != -1) {
baos.write(buffer, 0, nrb);
nrb = fis.read(buffer, 0, len);
}
buffer = baos.toByteArray();
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return buffer;
}
|
Liệt kê 22 cho thấy cách xóa khỏi lưu trữ riêng bên trong.
Liệt kê 22. Xóa khỏi lưu trữ riêng bên trong
/**
* Delete internal private file
* @param filename - the filename to delete
*/
public void deleteInternalStoragePrivate(String filename) {
File file = getFileStreamPath(filename);
if (file != null) {
file.delete();
}
}
|
Bây giờ bạn có thể thấy cách sử dụng lưu trữ ngoài cho dữ liệu công cộng.
Sử dụng lưu trữ ngoài cho dữ liệu công cộng
Với các API lưu trữ dữ liệu, bạn có thể lưu trữ dữ liệu bằng cách sử dụng
lưu trữ ngoài. Thông tin có thể là riêng tư và bạn có tùy chọn cho phép
các ứng dụng khác có quyền đọc hoặc viết vào nó. Trong phần này, bạn viết
mã lệnh API để lưu trữ dữ liệu công cộng bằng cách sử dụng một số trong
các API bao gồm getExternalStorageState(),
getExternalFilesDir(),
getExternalStorageDirectory() và
getExternalStoragePublicDirectory(). Bạn sử
dụng đường dẫn sau đây cho dữ liệu công cộng:
/Android/data/<package_name>/files/.
Trước khi sử dụng lưu trữ ngoài, bạn phải xem nó có sẵn chưa và có cho phép ghi vào không. Hai đoạn mã sau đây cho thấy các phương thức của trình trợ giúp để kiểm tra các điều kiện như vậy. Liệt kê 23 kiểm tra xem liệu lưu trữ ngoài đã có sẵn chưa.
Liệt kê 23. Kiểm tra xem lưu trữ ngoài đã có sẵn chưa
/**
* Helper Method to Test if external Storage is Available
*/
public boolean isExternalStorageAvailable() {
boolean state = false;
String extStorageState = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(extStorageState)) {
state = true;
}
return state;
}
|
Liệt kê 24 kiểm tra xem lưu trữ ngoài là chỉ đọc hay không.
Liệt kê 24. Kiểm tra xem lưu trữ ngoài là chỉ đọc hay không
/**
* Helper Method to Test if external Storage is read only
*/
public boolean isExternalStorageReadOnly() {
boolean state = false;
String extStorageState = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(extStorageState)) {
state = true;
}
return state;
}
|
Liệt kê 25 cho thấy cách ghi vào lưu trữ ngoài để lưu trữ dữ liệu công cộng.
Liệt kê 25. Viết vào bộ nhớ ngoài
/**
* Write to external public directory
* @param filename - the filename to write to
* @param content - the content to write
*/
public void writeToExternalStoragePublic(String filename, byte[] content) {
// API Level 7 or lower, use getExternalStorageDirectory()
// to open a File that represents the root of the external
// storage, but writing to root is not recommended, and instead
// application should write to application-specific directory, as shown below.
String packageName = this.getPackageName();
String path = "/Android/data/" + packageName + "/files/";
if (isExternalStorageAvailable() &&
!isExternalStorageReadOnly()) {
try {
File file = new File(path, filename);
file.mkdirs();
FileOutputStream fos = new FileOutputStream(file);
fos.write(content);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
|
Liệt kê 26 cho thấy cách đọc từ bộ nhớ ngoài.
Liệt kê 26. Đọc từ bộ nhớ ngoài
/**
* Reads a file from internal storage
* @param filename - the filename to read from
* @return the file contents
*/
public byte[] readExternallStoragePublic(String filename) {
int len = 1024;
byte[] buffer = new byte[len];
String packageName = this.getPackageName();
String path = "/Android/data/" + packageName + "/files/";
if (!isExternalStorageReadOnly()) {
try {
File file = new File(path, filename);
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int nrb = fis.read(buffer, 0, len); //read up to len bytes
while (nrb != -1) {
baos.write(buffer, 0, nrb);
nrb = fis.read(buffer, 0, len);
}
buffer = baos.toByteArray();
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return buffer;
}
|
Đoạn mã trong Liệt kê 27 cho thấy cách xóa một tệp khỏi bộ nhớ ngoài.
Liệt kê 27. Xóa một tệp khỏi bộ nhớ ngoài
/**
* Delete external public file
* @param filename - the filename to write to
*/
void deleteExternalStoragePublicFile(String filename) {
String packageName = this.getPackageName();
String path = "/Android/data/" + packageName + "/files/"+filename;
File file = new File(path, filename);
if (file != null) {
file.delete();
}
}
|
Làm việc với bộ nhớ ngoài đòi hỏi phải có quyền hạn đặc biệt, cần phải yêu
cầu WRITE_EXTERNAL_STORAGE, thông qua tệp
AndroidManifest.xml (xem Liệt kê 28).
Liệt kê 28.
WRITE_EXTERNAL_STORAGE<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> |
API lưu trữ ngoài cho phép bạn lưu trữ công cộng các tệp bằng cách lưu trữ các tệp trong các thư mục được xác định trước dựa vào các kiểu của chúng như các hình ảnh, các nhạc chuông và v.v. Cách tiếp cận này không được trình bày trong bài viết này, nhưng bạn nên biết rõ về nó. Ngoài ra, hãy nhớ rằng các tệp trong lưu trữ ngoài có thể bị xóa bất cứ lúc nào.
Nếu bạn có các tệp tạm thời không cần lưu giữ lâu dài, bạn có thể lưu trữ các tệp đó trong một bộ nhớ nhanh (cache) . Cache là một bộ nhớ đặc biệt có ích để lưu trữ dữ liệu cỡ vừa hoặc nhỏ (ít hơn một megabyte), nhưng bạn phải nhận thức được rằng nội dung của bộ nhớ cache có thể bị xóa bất cứ lúc nào tùy thuộc vào có sẵn bao nhiêu bộ nhớ.
Liệt kê 29 cho thấy một phương thức của trình trợ giúp để trả về đường dẫn đến bộ nhớ lưu trữ nhanh trong bộ nhớ trong.
Liệt kê 29. Lấy ra đường dẫn đến bộ nhớ lưu trữ nhanh của bộ nhớ trong
/**
* Helper method to retrieve the absolute path to the application
* specific internal cache directory on the file system. These files
* will be ones that get deleted when the application is uninstalled or when
* the device runs low on storage. There is no guarantee when these
* files will be deleted.
*
* Note: This uses a Level 8+ API.
*
* @return the absolute path to the application specific cache
* directory
*/
public String getInternalCacheDirectory() {
String cacheDirPath = null;
File cacheDir = getCacheDir();
if (cacheDir != null) {
cacheDirPath = cacheDir.getPath();
}
return cacheDirPath;
}
|
Liệt kê 30 cho thấy một phương thức của trình trợ giúp để trả về đường dẫn đến bộ nhớ lưu trữ nhanh trong bộ nhớ ngoài.
Liệt kê 30. Lấy ra đường dẫn đến bộ nhớ lưu trữ nhanh của bộ nhớ ngoài
/**
* Helper method to retrieve the absolute path to the application
* specific external cache directory on the file system. These files
* will be ones that get deleted when the application is uninstalled or when
* the device runs low on storage. There is no guarantee when these
* files will be deleted.
*
* Note: This uses a Level 8+ API.
*
* @return the absolute path to the application specific cache
* directory
*/
public String getExternalCacheDirectory() {
String extCacheDirPath = null;
File cacheDir = getExternalCacheDir();
if (cacheDir != null) {
extCacheDirPath = cacheDir.getPath();
}
return extCacheDirPath;
}
|
Thông qua cách sử dụng ứng dụng ví dụ này, bây giờ bạn đã có một sự hiểu biết tốt về cách sử dụng lưu trữ ngoài của thiết bị cho dữ liệu công cộng.
Bài viết này đã trình bày các API lưu trữ của Android, từ các sở thích đến việc sử dụng SQLite và bộ nhớ trong và bộ nhớ ngoài. Với API các sở thích, bạn có thể cho ứng dụng của bạn để thu thập và lưu trữ thông tin sở thích đơn giản. Khi sử dụng API SQLite, bạn có thể lưu trữ nhiều dữ liệu phức tạp hơn và với lưu trữ trong và lưu trữ ngoài, bạn có thể lưu trữ các tệp riêng tư với ứng dụng hoặc lưu trữ các tệp công cộng có sẵn tới các ứng dụng khác. Dữ liệu đã lưu trữ vẫn còn tồn tại trên các phiên làm việc cho phép ứng dụng của bạn làm việc ngay cả khi ngắt kết nối khỏi mạng. Bây giờ bạn sẽ có chuyên môn để tận dụng lợi thế của tất cả các loại thiết bị lưu trữ khi bạn phát triển ứng dụng Android.
| Mô tả | Tên | Kích thước | Phương thức tải |
|---|---|---|---|
| Article source code | android.storage.source.zip | 38KB | HTTP |
Học tập
- Trang web di
động Facebook: Tìm hiểu cách kết hợp Facebook vào ứng dụng di động
riêng của bạn bằng cách sử dụng các API tương tự như các API được cung cấp
cho tất cả các trang web, được định dạng cho phù hợp với điện thoại di
động.
- Tạo một ứng dụng - Các
nhà phát triển Facebook: Đăng ký ứng dụng Facebook của
bạn.
- Các quyền hạn mở rộng - Các nhà phát triển Facebook: Yêu cầu các
quyền hạn mở rộng khi ứng dụng của bạn cần phải truy cập vào các phần khác
của hồ sơ người dùng có thể có tính riêng tư hoặc khi ứng dụng của bạn cần
xuất bản nội dung đến Facebook nhân danh người dùng.
- Tài liệu chính thức của
nhà phát triển Facebook: Tìm hiểu các API mạnh mẽ cho phép bạn tạo
ra những kinh nghiệm xã hội để thúc đẩy tăng trưởng và sự tham gia vào
trang web của bạn.
- Xác thực
Facebook: Tìm hiểu về xác thực và cấp phép khi sử dụng nền tảng
Facebook để phát triển các ứng dụng của bạn.
- Lộ trình của nhà phát
triển Facebook: Sử dụng lộ trình này để lên kế hoạch cho những
thay đổi có thể đòi hỏi những sự sửa đổi mã lệnh.
- Phát triển các ứng dụng Android với Eclipse (Frank Ableson,
developerWorks, 02.2008): Cách dễ dàng nhất để phát triển các ứng dụng
Android là sử dụng với Eclipse. Hãy tìm hiểu tất cả về chủ đề này trong
hướng dẫn này của developerWorks.
- Giới thiệu về phát triển Android (Frank Ableson, developerWorks,
05.2009): Xem phần mở đầu về nền tảng Android và tìm hiểu cách mã hóa một
ứng dụng Android cơ bản.
- Kết nối mạng với Android (Frank Ableson, developerWorks,
06.2009): Tìm hiểu các khả năng nối mạng của Android.
- Làm
việc với XML trên Android (Michael Galpin, developerWorks,
06.2009): Tìm hiểu về các tùy chọn khác nhau để làm việc với XML trên
Android và cách sử dụng chúng để xây dựng các ứng dụng của Android riêng
của bạn.
- Dưới Mái che của các ứng dụng Web được thiết kế riêng cho
Android: Tìm hiểu về các ứng dụng lai trong Android.
- Mở
khóa Android (Frank Ableson, Manning Publications, 2010): Trình
bày tất cả các khía cạnh về phát triển Android trong cuốn sách này của tác
giả.
- Thiết kế và Phát
triển di động (Brian Fling, O'Reilly Media, 2009): Tìm hiểu về các
hướng dẫn thực hành, các tiêu chuẩn, các kỹ thuật và các thực hành tốt
nhất để xây dựng các sản phẩm di động trong cuốn sách này.
- Đọc Hướng dẫn phát triển lưu trữ dữ liệu: Chọn giải pháp đúng để lưu
dữ liệu ứng dụng lâu bền như được lưu ý trên trang web chính thức của nhà
phát triển Android.
- Intents: Tìm hiểu về mô tả trừu tượng này của một hoạt động được
thực hiện từ trang web của nhà phát triển Android.
- Tài liệu
SDK của Android: Thu thập các thông tin mới nhất trong tài liệu
tham khảo API của Android.
- The Open Handset
Alliance: Truy cập nhà tài trợ của Android.
- Thêm nhiều bài báo của tác giả này (C. Enrique Ortiz,
developerWorks, 04.2002 đến nay): Đọc các bài viết về các ứng dụng
Android, các ứng dụng di động, các dịch vụ web và các công nghệ
khác.
- Vùng XML trên
developerWorks: Thu thập các tài nguyên mà bạn cần để nâng cao các
kỹ năng của bạn trong lĩnh vực XML.
- My
developerWorks: Cá nhân hoá kinh nghiệm developerWorks của
bạn.
- Chứng chỉ XML
của IBM: Tìm hiểu cách bạn có thể trở thành một nhà phát triển có
chứng chỉ IBM về XML và các công nghệ có liên quan.
- Thư
viện kỹ thuật XML: Xem Vùng XML của developerWorks với một loạt
các bài báo và thủ thuật kỹ thuật, các hướng dẫn, các tiêu chuẩn và các
sách Đỏ của IBM. Ngoài ra, hãy xem chi tiết các thủ thuật XML.
- Các sự
kiện kỹ thuật và Webcast: Theo sát với công nghệ trong các phiên
này.
- developerWorks trên
Twitter: Tham gia ngày hôm nay để theo sát các bài viết ngắn
(tweets) của developerWorks.
- developerWorks
podcasts: Nghe các cuộc phỏng vấn và các cuộc thảo luận thú vị
dành cho các nhà phát triển phần mềm.
- Các chương
trình trình diễn theo yêu cầu của developerWorks: Xem một dải từ
cài đặt và thiết lập sản phẩm cho nhưng người mới bắt đầu đến chức năng
cao cấp cho các nhà phát triển có kinh nghiệm.
Lấy sản phẩm và công nghệ
- Facebook
Android SDK (Hiện nay có bản phát hành Alpha): Làm việc với thư
viện này để tích hợp Facebook vào ứng dụng di động Android của
bạn.
- Nền tảng Facebook: Mở rộng
khả năng của bạn để xây dựng các ứng dụng xã hội trên Facebook và các
trang web.
- Các API còn
lại trước kia của Facebook (Phiên bản trước của API biểu đồ):
Tương tác với các trang web Facebook bằng lập trình thông qua các yêu cầu
HTTP đơn giản.
- API Biểu đồ
Facebook (phiên bản hiện hành): Đi sâu vào API nền tảng lõi
Facebook này.
- Đặc tả kỹ
thuật giao thức OAuth 2.0 (07.2010): Làm việc với việc xác thực
OAuth, được nền tảng Facebook hỗ trợ.
- Android SDK: Tải về SDK, truy
cập tài liệu tham khảo API và nhận các tin tức mới nhất về Android từ
trang Web chính thức của các nhà phát triển Android. Phiên bản 1.5 và mới
hơn sẽ hoạt động.
- Dự án nguồn mở Android: Tìm các
thông tin nguồn mở và mã nguồn mà bạn cần để xây dựng một thiết bị tương
thích với Android.
- Bản cập nhật 21 của JDK 6: Nhận nền tảng Java, ấn bản tiêu
chuẩn.
- Eclipse: Nhận lấy bản IDE của Eclipse
mới nhất.
- Các phiên bản đánh
giá sản phẩm của IBM: Tải về hoặc khám
phá các thử nghiệm trực tuyến trong SOA Sandbox của IBM và nhận
các công cụ phát triển ứng dụng thực hành của bạn và các sản phẩm phần mềm
trung gian từ DB2®, Lotus®, Rational®, Tivoli® và
WebSphere®.
Thảo luận
- Các
diễn đàn thảo vùng XML: Tham gia vào bất kỳ trong số các cuộc thảo
luận có liên quan đến XML.
- developerWorks
blogs: Đọc các blog này và dành tâm trí cho nó.