Professional Documents
Culture Documents
Chương 7
Chương 7
2
NỘI DUNG
1. Khái niệm về bộ nhớ
Bộ lưu trữ trong
Bộ lưu trữ ngoài
2. SQLITE
Giới thiệu SQLite DataBase
Xây dựng CSDL với SQLite
3
KHÁI NIỆM VỀ BỘ NHỚ
Tổng quan về các loại lưu trữ trong Android
Android có nhiều phương pháp lưu trữ dữ liệu
Mỗi phương pháp có mục đích sử dụng khác nhau (vì
vậy cần hiểu chính xác để sử dụng hợp lý nhất)
Cơ chế phân quyền và kiểm soát truy cập kiểu Linux
Local storages:
Raw: File services (memory, cached, internal card,
sdcard,…)
OS services: Shared preferences, SQLite, Content
providers
Extra services: Content providers
Remote storages: Internet services
4
KHÁI NIỆM VỀ BỘ NHỚ
Tổng quan về quá trình cài đặt ứng dụng
Ứng dụng Android ở dạng .apk
Từ API 8, có thể đặt ứng dụng ở SDCard bằng cách
thêm đoạn mã android:installLocation="preferExternal"
vào file AndroidManifest.xml
Quá trình cài đặt ứng dụng vào hệ thống:
Kiểm tra sự toàn vẹn của file .apk dựa trên chữ kí số
Chép file .apk vào thư mục ứng dụng
Tạo thư mục riêng cho ứng dụng đó (theo tên
package)
Thiết lập quyền phù hợp cho thư mục riêng
Cập nhật CSDL về các thành phần của ứng dụng
5
KHÁI NIỆM VỀ BỘ NHỚ
Tổng quan: một số Folder cơ bản trong Android
Theo thiết lập chuẩn của Android OS:
Ứng dụng hệ thống: /system/app
Ứng dụng thường: /data/app
Ứng dụng ở SDCard: /storage/sdcard0/.android_secure
Dữ liệu của ứng dụng: /data/data/<package_name>
Cơ chế phân quyền và kiểm soát truy cập kiểu Linux
• Folder “shared_prefs”: chứa SharedPreferences
• Folder “cache”: chứa các file tạm (Cache)
• Folder “databases”: chứa các CSDL SQLite
Dữ liệu ở SDCard: /Android/data/<package_name>/files/
Cần lấy các folder bằng API của hệ thống
6
KHÁI NIỆM VỀ BỘ NHỚ
Files trong Android
Android cung cấp khá nhiều cách để đọc và lưu trữ
dữ liệu từ/xuống các tập tin
Dựa trên các API về file của Java
Dựa trên một số dạng đặc biệt chỉ có trong Android
(các tập tin tài nguyên chẳng hạn)
Một số dạng tập tin phổ biến:
File trên bộ nhớ trong (internal storage)
File đệm (cached)
File trên bộ nhớ ngoài (external storage)
File tài nguyên: Resources và trong apk
7
BỘ LƯU TRỮ TRONG
Bộ nhớ trong
Bộ nhớ trong được cấp phát khi ứng dụng được cài
đặt trên thiết bị trên một thư mục riêng biệt:
Chỉ có ứng dụng mới có thể truy xuất được bộ nhớ
của ứng dụng đó.
Đường dẫn các tập tin được lưu trữ:
data/data/<pakage_name_app>/files
Phương thức truy xuất:
getFilesDir - File
8
BỘ LƯU TRỮ TRONG
Tập tin trên bộ nhớ trong
Mặc định thì tập tin này sẽ thuộc về ứng dụng tạo ra
nó và các ứng dụng khác không thể truy xuất đến nó
Ghi dữ liệu vào tập tin :
Gọi phương thức openFileOutput(String name, int
mode) trong đối tượng FileOutStream để nhận dữ
liệu về Stream, trong đó:
• name: tên tập tin
• mode: chế độ ghi tập tin, có 3 chế độ
MODE_PRIVATE: tập tin chỉ có thể được truy xuất bên trong
ứng dụng tạo ra nó
MODE_WORLD_READABLE: các ứng dụng khác có thể đọc
MODE_WORLD_WRITEABLE: các ứng dụng khác có thể đọc
và ghi
9
BỘ LƯU TRỮ TRONG
Tập tin trên bộ nhớ trong
Ghi dữ liệu vào tập tin:
Ghi dữ liệu vào tập tin: sử dụng phương thức
write(…)
Đóng Stream: sử dụng phương thức close()
Ví dụ:
String hello = “Hello Android!”;
FileOutStream fos = openFileOutput(“Hello_file.txt”,
MODE_APPEND);
fos.write(hello.getBytes());
fos.close();
10
BỘ LƯU TRỮ TRONG
Tập tin trên bộ nhớ trong
Đọc dữ liệu từ tập tin:
Gọi phương thức openFileInput(String name) trong
đối tượng FileInputStream nhận về dữ liệu Stream
Đọc dữ liệu từ tập tin: sử dụng phương thức read().
Đóng Stream: sử dụng phương thức close()
Ví dụ:
FileInputStream fis = openFileInput(“Hello_file.txt”);
int b = 0;
String s = “”;
while ((b = fis.read()) != 0) s += (char)b;
fis.close();
Log.d(“Noi dung xuat”, s);
11
BỘ LƯU TRỮ TRONG
Ví dụ:
Trả về số
byte đã đọc
từ File
12
BỘ LƯU TRỮ TRONG
Sử dụng tập tin Cache
Sử dụng khi muốn lưu trữ tập tin vào thư mục Cache
thay vì lưu trữ vĩnh viễn
Các tập tin này sẽ tự động bị xóa khi thiết bị thiếu bộ
nhớ trong
Sử dụng phương thức getCacheDir() để lấy về thư
mục Cache lưu trữ dữ liệu của ứng dụng
Thông thường là: data/data/<package_name>/cache
13
BỘ LƯU TRỮ TRONG
Ví dụ: ghi dữ liệu lên tập tin cache
14
BỘ LƯU TRỮ TRONG
Các thư mục chuẩn
Android SDK định nghĩa một số thư mục chuẩn
thành hằng số trong class android.os.Environment
DIRECTORY_ALARMS
DIRECTORY_DCIM (picture + video ở chế độ device
as camera)
DIRECTORY_DOCUMENTS
DIRECTORY_DOWNLOADS
DIRECTORY_MOVIES
DIRECTORY_MUSIC
DIRECTORY_NOTIFICATIONS
DIRECTORY_PICTURES
DIRECTORY_PODCASTS
DIRECTORY_RINGTONES
15
BỘ LƯU TRỮ TRONG
Ví dụ: một số hàm hữu ích
16
BỘ LƯU TRỮ NGOÀI
Bộ nhớ ngoài
Mỗi thiết bị Android cung cấp bộ nhớ ngoài cho
phép người dùng có thể lưu trữ và truy xuất trực tiếp
trên thiết bị hoặc thông qua máy tính khi kết nối USB
Storage.
Bộ lưu trữ ngoài bao gồm hai dạng:
Bộ nhớ thiết bị (non-removable)
Bộ nhớ ngoài (SD-Card, USB…)
Cần xin cấp quyền để truy xuất bộ nhớ này
android.permission.WRITE_EXTERNAL_STORAGE
17
BỘ LƯU TRỮ NGOÀI
Bộ nhớ ngoài
Ứng dụng được cấp phát bộ nhớ ngoài để lưu trữ dữ liệu
mặc định không thể truy xuất như tập tin Media.
Địa chỉ: /mnt/sdcard/Android/<package_name>/files
Phương thức truy xuất:
• getExternalFilesDir(String) File
• getExternalFilesDirs(String) File[] (API 19 - KITKAT)
• ContextCompat.getExternalFilesDirs(String) File[]
(Support Library)
Cấu hình cài đặt ứng dụng trên bộ nhớ trong hoặc ngoài
thông qua cặp thẻ <manifest/> trong AndroidManifest.
installLocation
• internalOnly
• Auto
• preferExternal
18
BỘ LƯU TRỮ NGOÀI
Bộ nhớ ngoài
Kiểm tra tình trạng bộ nhớ:
Cần kiểm tra tình trạng bộ nhớ ngoài trước khi thực
hiện các thao tác.
Truy xuất trạng thái bộ nhớ ngoài thông qua phương
thức getExternalStorageState trong đối tượng
Environment.
Các thông số được trả về bao gồm:
• MEDIA_UNKNOWN • MEDIA_MOUNTED
• MEDIA_REMOVED • MEDIA_MOUNTED_REA
• MEDIA_UNMOUNTED D_ONLY
• MEDIA_CHECKING • MEDIA_SHARED
• MEDIA_NOFS • MEDIA_BAD_REMOVAL
• MEDIA_UNMOUNTABLE
19
BỘ LƯU TRỮ NGOÀI
Bộ nhớ ngoài
Ví dụ: Bộ nhớ ngoài (external memory) là thiết bị lưu trữ
có thể tháo rời (thường là SDCard) nên cần tiến hành
kiểm tra trạng thái trước khi đọc và ghi dữ liệu
20
BỘ LƯU TRỮ NGOÀI
Bộ nhớ ngoài
Một số phương thức hỗ trợ duyệt tập tin trong bộ
nhớ ngoài:
isFile() boolean
isDirectory() boolean
getAbsolutePath() String
getPath() String
list() String[]
mkdir() boolean
mkdirs() boolean
delete() boolean
21
BỘ LƯU TRỮ NGOÀI
Bộ nhớ ngoài
Một số thư mục dùng chung:
DIRECTORY_ALARMS
DIRECTORY_DCIM
DIRECTORY_DOCUMENTS (API 19)
DIRECTORY_DOWNLOADS
DIRECTORY_MOVIES
DIRECTORY_MUSIC
DIRECTORY_NOTIFICATIONS
DIRECTORY_PICTURES
DIRECTORY_POSTCASTS
DIRECTORY_RINGTONES
22
BỘ LƯU TRỮ NGOÀI
Bộ nhớ ngoài
Ví dụ: Đọc từ thẻ nhớ
23
BỘ LƯU TRỮ NGOÀI
Bộ nhớ ngoài
Ví dụ: Ghi dữ liệu vào thẻ nhớ
24
SQLITE
Giới thiệu
SQLite là một CSDL nhỏ gọn, viết bằng C++ và
được tích hợp trên rất nhiều hệ điều hành di động
SQLite được tích hợp vào HĐH vì thế mọi ứng
dụng đều có thể làm việc được mà không cần thư
viện hỗ trợ
Mỗi CSDL SQLite thường là một file duy nhất. Việc
mở file đó (giống như mở file thông thường) sau
đó thực hiện các câu lệnh SQL để thao tác file
Không nên lạm dụng SQLite vì khá chậm (làm việc
trên text) và thiếu uyển chuyển
25
SQLITE
SQLite?
Thể hiện dữ liệu ở dạng bảng quan hệ:
Cột: thể hiện trường dữ liệu hoặc thuộc tính dữ
liệu
Dòng: một thể hiện dữ liệu
Ví dụ:
word app id frequency locale _ID
mapreduce user1 100 en_US 1
precompiler user14 200 fr_FR 2
applet user2 225 fr_CA 3
const user1 255 pt_BR 4
int user5 100 en_UK 5
26
SQLITE
SQLite?
SQLite là cơ sở dữ liệu mở được nhúng vào
Android, hỗ trợ các đặc điểm về quan hệ chuẩn của
cơ sở dữ liệu như cú pháp, transaction, các câu lệnh.
Sử dụng SQLite không yêu cầu về thiết lập bất cứ cơ
sở dữ liệu hoặc đòi hỏi quyền admin.
Hỗ trợ các kiểu dữ liệu : TEXT, INTEGER, REAL,
BLOB.
27
SQLITE
Kiểu dữ liệu SQLite
Some different than normal SQL data types so please
read: http://www.sqlite.org/datatype3.html
NULL: The value is a NULL value.
INTEGER: The value is a signed integer, stored in 1, 2, 3,
4, 6, or 8 bytes depending on the magnitude of the value.
REAL: The value is a floating point value, stored as an 8
byte IEEE floating point number.
TEXT: The value is a text string, stored using the database
encoding (UTF-8, UTF-16BE or UTF-16LE).
BLOB: The value is a blob of data, stored exactly as it was
input.
28
SQLITE
SQLite API
Gói android.database.sqlite chứa các class hỗ trợ làm
việc với CSDL SQLite 02 class quan trọng:
SQLiteDatabase: class giúp chúng ta làm việc trực
tiếp với file CSDL, thực thi các thao tác CSDL bằng
SQL hoặc bằng các phương thức hỗ trợ của class
SQLiteOpenHelper: class giúp lập trình viên quản lý
việc tạo và nâng cấp file CSDL
Android SDK cung cấp công cụ sqlite3 giúp tương
tác với CSDL thông qua dòng lệnh, chúng ta có thể
dùng công cụ này để kiểm tra lại kết quả làm việc với
file CSDL một cách nhanh chóng
29
SQLITE DATABASE
Các method của SQLiteDatabase
Tạo/Mở CSDL: openDatabase
Đóng CSDL: close
Thực thi SQL: execSQL
Chèn dữ liệu: insert
Cập nhật dữ liệu: update
Xóa dữ liệu: delete
Thực hiện truy vấn SELECT: rawQuery
30
SQLITE DATABASE
Tạo/mở CSDL
public static SQLiteDatabase .openDatabase
(String path, CursorFactory factory, int flags)
SQLiteDatabase db = SQLiteDatabase.openDatabase
("/data/data/<p ackage>/DB.db", null,
SQLiteDatabase.CREATE_IF_NECESSARY);
Flags:
OPEN_READWRITE
OPEN_READONLY
CREATE_IF_NECESSARY
31
SQLITE DATABASE
Tạo/mở CSDL
Ví dụ:
32
SQLITE DATABASE
Đóng CSDL
public void close()
Sử dụng khi đóng kết nối với CSDL
CSDL tự đóng khi ứng dụng kết thúc
Nên đóng CSDL ngay khi không dùng nữa
Ví dụ:
db = SQLiteDatabase.openDatabase(…);
// thao tác với CSDL
…
db.close();
33
SQLITE DATABASE
Thực thi SQL: execSQL(String strSQL)
Sử dụng khi muốn thực thi một câu lệnh SQL và
không quan tâm tới kết quả trả về
Không thực hiện được “multiple statements” SQL
Tài liệu của Google nói không thực hiện những câu
SQL có trả về kết quả (SELECT, INSERT,
UPDATE,…)
db.execSQL("CREATE TABLE Book (BookID
INTEGER PRIMARY KEY AUTOINCREMENT,
BookName TEXT);");
db.execSQL("INSERT INTO Book(BookName)
VALUES ('Test EXECSQL')");
34
SQLITE DATABASE
Chèn dữ liệu:
public long insert (String table,
String nullColumnHack, ContentValues values)
35
SQLITE DATABASE
Chèn dữ liệu:
Ví dụ:
ContentValues cv = new ContentValues();
cv.put("BookName", "SQLite");
cv.put("Price", "100");
db.insert("Book", null, cv);
36
SQLITE DATABASE
Cập nhật dữ liệu:
public int update (String table, ContentValues values,
String whereClause, String[] whereArgs)
37
SQLITE DATABASE
Cập nhật dữ liệu :
Ví dụ:
38
SQLITE DATABASE
Xóa dữ liệu:
public int delete (String table,
String whereClause, String[] whereArgs)
table: tên bảng muốn xóa
whereClause: điều kiện xóa
whereArgs: mảng giá trị ứng với whereClause
Ví dụ:
String [] whereArgs = {"2"};
int recAffected = db.delete("Book",
"BookID=?", whereArgs);
// db.delete("Book", "BookID=2", null);
39
SQLITE DATABASE
Truy vấn dữ liệu (Select):
public Cursor rawQuery(String sql,
String[] selectionArgs)
sql: câu lệnh truy vấn
selectionArgs: mảng giá trị các tham số trong câu lệnh
sql (nếu có)
Giá trị trả về: con trỏ đặc biệt hỗ trợ việc lấy dữ
liệu và duyệt mảng các giá trị trả về
40
SQLITE DATABASE
Truy vấn dữ liệu:
Ví dụ:
// dạng có tham số
String mySQL = "select count(*) as Total " + "from tblAmigo "
+ " where recID ? " + " and name = ?";
String[] args = {"1", "BBB"};
Cursor c1 = db.rawQuery(mySQL, args);
41
SQLITE DATABASE
Đối tượng Cursor
Cursor trỏ tới 1 dòng trong kết quả trả về
Dùng cursor để đọc giá trị trên các cột của dòng đó
Khởi đầu cursor ở vị trí before-first
Cursor có nhiều phương thức hỗ trợ:
Kiểm tra vị trí hiện tại: isFirst(), isLast(), isBeforeFirst(),
isAfterLast()
Dịch chuyển trong kết quả: moveToFirst(),
moveToLast(), moveToNext(), moveToPrevious(), move(n)
Lấy dữ liệu: getInt, getString, getFloat, getBlob,
getDate,…
Lấy cấu trúc bảng: getCount, getColumnName,
getColumnNames, getColumnIndex, getColumnCount,…
42
SQLITE DATABASE
Truy vấn dữ liệu:
Ví dụ:
// thực hiện truy vấn bằng SELECT, kết quả luôn là 1 mảng
// lúc này cs trỏ tới trước dòng đầu tiên
Cursor cs = db.rawQuery("SELECT * FROM Book", null);
while (cs.moveToNext()) { // dịch chuyển xuống dòng dưới
int id = cs.getInt(0); // đọc dữ liệu ở cột đầu tiên
String book = cs.getString(1); // đọc dữ liệu ở cột thứ hai
…
}
// đóng kết quả truy vấn
cs.close();
…
43
SQLITE OPENHELPER
SQLiteOpenHelper là phương pháp mà Google đề
nghị để thống nhất việc quản lý, tạo, truy xuất và cập
nhật cơ sở dữ liệu
SQLiteOpenHelper cần 3 phương thức cơ bản sau
để làm việc hiệu quả
Constructor: cung cấp các tham số cần thiết để làm việc
với cơ sở dữ liệu
onCreate(): phương thức được tự động gọi khi lần đầu
tạo file CSDL và tạo các bảng trong CSDL cũng như
khởi tạo dữ liệu ban đầu
onUpgrade(): phương thức được tự động gọi khi nâng
cấp CSDL từ các phiên bản cũ
44
SQLITE OPENHELPER
Các phương thức hữu ích của SQLiteOpenHelper
SQLiteDatabase getReadableDatabase(): lấy về CSDL ở
dạng “chỉ đọc”
SQLiteDatabase getWriteableDatabase(): lấy về CSDL ở
dạng “đọc và ghi”
String getDatabaseName(): lấy tên CSDL
Không dùng SQLiteOpenHelper cũng không có
vấn đề gì, nhưng sử dụng SQLiteOpenHelper thì ta
sẽ đỡ công sức viết code hơn, đặc biệt khi cập nhật
phiên bản ứng dụng kèm theo nâng cấp CSDL.
45
SQLITE OPENHELPER
Code: kế thừa SQLiteOpenHelper và viết lại 3
phương thức cơ bản
Cách thức sử dụng SQLiteOpenHelper:
Thay vì mở CSDL trực tiếp mở qua SQLiteOpenHelper
SQLiteOpenHelper kiểm tra xem CSDL đã có hay chưa
nếu chưa có thì sẽ tự động gọi onCreate để tạo.
SQLiteOpenHelper kiểm tra phiên bản của CSDL hiện tại
so với đề xuất có bằng nhau không nếu không thì tự động
gọi onUpgrade (hoặc onDowngrade, tùy tình huống)
Phương thức getReadableDatabase/ getWriteableDatabase
để lấy về CSDL đã sẵn sàng hoạt động.
46
SQLITE OPENHELPER
Ví dụ:
47
SQLITE OPENHELPER
Ví dụ:
48
SQLITE OPENHELPER
Ví dụ:
49
KINH NGHIỆM LÀ VIỆC VỚI CSDL
Viết class mô tả đối tượng cần thao tác (không liên
quan gì tới database) tạm gọi là các model
Dùng SQLiteOpenHelper xử lý ở cấp độ database
Viết class bọc ngoài các Table, cung cấp các thao tác
làm việc giữa Tables với model (data provider)
Sử dụng các data provider để làm việc bất kể khi
nào dùng tới database không trực tiếp làm việc
với database trong mọi trường hợp
Các string SQL nên đặt ngoài resource hoặc có thể
cập nhật online là tốt nhất
50
XÂY DỰNG CSDL VỚI SQLITE
Xây dựng ứng dụng quản lý sách với CSDL Books
Ứng dụng gồm các chức năng chính:
Thêm sách mới
Hiển thị danh sách các sách ra ListView
Sửa sách
Xóa sách
Tìm kiếm sách theo các trường hoặc theo các tiêu chuẩn
Upgrade lên DB lên phiên bản 2: bổ sung trường tags
gồm danh sách các từ khóa mô tả về sách
Cập nhật chức năng tìm kiếm theo tags
51
XÂY DỰNG CSDL VỚI SQLITE
Xây dựng CSDL Books
Bảng Books
BookID INT
BookName TEXT
Page INT
Price FLOAT
Description TEXT
Sau khi tạo xong bảng thì chèn 5 bản ghi vào bảng
Thực hiện các câu lệnh xóa có điều kiện
Cập nhập giá tiền, tên sách theo mã sách
Tìm kiếm sách lần lượt với các điều kiện như: BookID,
BookName gần đúng (sử dụng like), Price …
52
XÂY DỰNG CSDL VỚI SQLITE
Tạo Database bằng code
String sqltext = "DROP TABLE IF EXISTS BOOKS;\n"
+ "CREATE TABLE BOOKS(BookID integer PRIMARY KEY,
BookName text, Page integer, Price Float, Description text);\n"
+ "INSERT INTO BOOKS VALUES(1, 'Java', 100, 9.99, 'sách
về java');\n"
+ "INSERT INTO BOOKS VALUES(2, 'Android', 320, 19.00,
'Android cơ bản');\n"
+ "INSERT INTO BOOKS VALUES(3, 'Học làm giàu', 120,
0.99, 'sách đọc cho vui');\n"
+ "INSERT INTO BOOKS VALUES(4, 'Tử điển Anh-Việt',
1000, 29.50, 'Từ điển 100.000 từ');\n“
+ "INSERT INTO BOOKS VALUES(5, 'CNXH', 1, 1, 'chuyện
cổ tích');";
53
XÂY DỰNG CSDL VỚI SQLITE
Tạo Database bằng code
// tạo DB và thực hiện một số câu SQL
SQLiteDatabase db = openOrCreateDatabase(
"books.db", MODE_PRIVATE, null);
for (String sql : sqltext.split("\n"))
db.execSQL(sql);
db.close();
54
XÂY DỰNG CSDL VỚI SQLITE
Xem kết quả truy vấn SELECT
bPrev = (Button) findViewById(R.id.button1);
bNext = (Button) findViewById(R.id.button2);
bId = (TextView) findViewById(R.id.textView1);
bName = (TextView) findViewById(R.id.textView2);
bPage = (TextView) findViewById(R.id.textView3);
bPrice = (TextView) findViewById(R.id.textView4);
bDes = (TextView) findViewById(R.id.textView5);
55
XÂY DỰNG CSDL VỚI SQLITE
Xem kết quả truy vấn SELECT
try {
db = openOrCreateDatabase("books.db",
MODE_PRIVATE, null);
cs = db.rawQuery("SELECT * FROM BOOKS", null);
}
catch (Exception e) {
finish();
}
cs.moveToNext();
updateRecord();
56
XÂY DỰNG CSDL VỚI SQLITE
Xem kết quả truy vấn SELECT
void updateRecord() {
bId.setText(cs.getString(0));
bName.setText(cs.getString(1));
bPage.setText(cs.getString(2));
bPrice.setText(cs.getString(3));
bDes.setText(cs.getString(4));
bPrev.setEnabled(!cs.isFirst());
bNext.setEnabled(!cs.isLast());
}
57
XÂY DỰNG CSDL VỚI SQLITE
Xem kết quả truy vấn SELECT
public void btnPrev(View v) {
cs.moveToPrevious();
updateRecord();
}
public void btnNext(View v) {
cs.moveToNext();
updateRecord();
}
public void onBackPressed(){
cs.close();
db.close();
super.onBackPressed();
}
58
THẢO LUẬN NHÓM
59