Professional Documents
Culture Documents
Android: Lập Trình Thiết Bị Di Động Trên
Android: Lập Trình Thiết Bị Di Động Trên
TÀI LIỆU
Tháng 06/2015
Trung Tâm Tin Học Đại Học Khoa Học Tự Nhiên TP.HCM
Bài 1
TỔNG QUAN VỀ LẬP TRÌNH ANDROID
VÀ MÔI TRƯỜNG PHÁT TRIỂN
Thời gian
Phiên bản API Đặc điểm nổi bật
phát hành
Thanh thông báo kéo từ trên xuống, màn hình
Android 1.0 1 10/2008 chính phong phú, tích hợp chặt chẽ với Gmail, giao
diện đơn giản nhưng khá đẹp mắt thời bấy giờ.
Tải và cài đặt bản cập nhật ngay trên thiết bị,
Android 1.1 2 02/2009 không cần kết nối với máy tính (phương thức Over
The Air).
Là bản Android đầu tiên được Google gọi tên theo
các món đồ ăn với chữ cái bắt đầu được xếp theo
thứ tự alphabet. Với các tính năng: bàn phím ảo,
Android 1.5 mở rộng khả năng cho widget – khả năng tùy biến
3 05/2009
Cupcake giao diện của Android được đẩy mạnh, cải tiến
clipboard, có khả năng quay phim, cho phép tải
ảnh, video lên YouTube, truy cập danh bạ trong
Google Talk,…
Một vài điểm trong giao diện được cải thiện, hỗ trợ
mạng CDMA, hỗ trợ các thành phần đồ họa độc
lập với độ phân giải, tính năng Quick Search Box –
Android 1.5
4 09/2009 tìm kiếm tất cả mọi thứ chỉ trong một hộp tìm
Donut
kiếm, Android Market – hiển thị các ứng dụng
miễn phí và trả phí hàng đầu. Camera được cải
thiện, tích hợp trình xem ảnh tốt hơn.
Hỗ trợ nhiều tài khoản người dùng, tính năng
Quick Contact, cải tiến bàn phím ảo. Trình duyệt
Android 2.0 – mới: hỗ trợ HTML5, phát video ở chế độ toàn màn
11/2009
Android 2.0.1 5, 6 hình, hộp địa chỉ kết hợp với thanh tìm kiếm, cho
- 12/2009
Eclair phép phóng to, thu nhỏ bằng cách chạm tay vào
màn hình. Giao diện đẹp, sang trọng và gọn gàng
hơn trước.
Android 2.1 Hỗ trợ Live Wallpaper, chuyển giọng nói thành
7 01/2010
Eclair văn bản và một màn hình khóa mới.
Từ 3 màn hình chính tăng lên thành 5 màn hình.
Dãy nút kích hoạt nhanh chế độ gọi điện, web và
Android 2.2 App Drawer xuất hiện. Khả năng hiển thị hình ảnh
8 06/2010
Froyo 3D. Tính năng trạm phát Wifi xuất hiện. Hỗ trợ
duyệt web với Flash. Tính năng di chuyển một
phần ứng dụng từ bộ nhớ máy sang thẻ nhớ.
Security (mạng xã hội và bảo mật), Mobility (công nghệ di động), Analytics Big Data
(phân tích dữ liệu lớn), Cloud (Điện toán đám mây).
- Trên thế giới:
o Tháng 01/2014, trang WeAreSocial đã đưa ra báo cáo về “Bối cảnh dữ liệu toàn
cầu” với những chỉ số phát triển rất đang kinh ngạc của Thế Giới Số. Cụ thể số
liệu thống kê của WeAreSocial cho thấy:
Số lượng đăng kí sử dụng di động đang hoạt động vào khoảng 93% của
dân số thế giới.
Tỉ lệ người kết nối Internet toàn cầu đạt 35%, tương đương 2,5 tỉ người.
Các kênh Mạng xã hội tiếp tục phát triển mạnh mẽ trong 12 tháng qua,
khi đạt tỉ lệ thâm nhập người dùng là 26%.
Hơn 4 tỉ người trên khắp thế giới hiện đang sở hữu ít nhất một chiếc điện
thoại di động.
Hình 1.3. Chỉ số về Internet trên di động tại Việt Nam năm 2014 - Nguồn: Theo thống kê Cục
Thương mại điện tử và công nghệ thông tin (VECITA), Bộ Công thương.
- Tỉ lệ truy cập Internet qua các thiết bị di động: 36% tổng số dân.
- Tỉ lệ truy cập Internet có tham gia mua sắm online 57%.
- Một người Việt Nam truy cập Internet 5,6 giờ/ngày, 6,4 ngày/tuần - Tổng số thời gian
36 giờ/tuần.
Hình 1.4. Thống kê các chỉ số người dùng smartphone tại Việt Nam năm 2014 - Nguồn: Theo
thống kê Cục Thương mại điện tử và công nghệ thông tin (VECITA), Bộ Công thương.
Hình 1.5. Thống kê chỉ số điện thoại di động và các loại hình thanh toán tại Việt Nam năm
2014 - Nguồn: Theo thống kê Cục Thương mại điện tử và công nghệ thông tin (VECITA), Bộ
Công thương.
- Với mục tiêu tạo ra môi trường phát triển tất cả trong một, trải nghiệm nhanh và mượt
hơn các IDE khác, Android Studio không ngừng ra đời các phiên bản cải tiến.
3.2. Thiết lập môi trường phát triển:
- Như đã nói ở trên, ứng dụng Android được thực thi trên máy ảo Dalvik nên chúng ta có
thể lập trình trên nhiều phiên bản của các hệ điều hành. Cụ thể như sau:
o Microsoft® Windows® 8/7/Vista/2003 (32 or 64-bit).
o 2 GB RAM trở lên.
o Dung lượng ổ đĩa ứng còn trống ít nhất 400 MB.
o Ít nhất 1 GB cho Android SDK, emulator system images và caches.
o Độ phân giảm tối thiểu 1280 x 800.
o Java Development Kit (JDK) 7 trở lên.
o Tùy chọn thêm cho accelerated emulator: hỗ trợ bộ xử lý Intel® với các phiên
bản: Intel® VT-x, Intel® EM64T (Intel® 64), và tính năng Execute Disable
(XD) Bit.
- Để bắt đầu viết ứng dụng với Android Studio, chúng ta cần tải và cài đặt hai bộ phần
mềm sau:
o Java JDK: http://java.sun.com/javase/downloads/index.jsp (Cài đặt trước hết và
nên chọn phiên bản mới nhất).
o Android Studio: http://developer.android.com/sdk/index.html - tải gói Android
Studio, gói này sẽ chứa các thành phần:
o Android Studio IDE.
o Android SDK tools.
o Android 5.0 (Lollipop) Platform.
o Android 5.0 emulator system image with Google APIs.
Hình 1.7
- Sau khi tải bộ cài Android Studio thành công, chúng ta chạy tập tin android – studio –
bundle để tiến hành cài đặt Android Studio → màn hình Welcome to Android Studio
Setup xuất hiện → Next:
Hình 1.8.
- Nếu hệ thống không phát hiện ra JDK trong máy tính của bạn, một hộp thoại yêu cầu
chỉ rõ đường dẫn hoặc cài đặt JDK xuất hiện:
Hình 1.9
Nếu đã có JDK thì tìm đường dẫn đến nơi cài đặt. Sau đó, nhấn Next. Hộp thoại lựa chọn cấu
hình cài đặt sẽ mở ra → chọn (check) đủ các thành phần như hình bên dưới → Next:
Hình 1.10
- Xuất hiện hộp loại thông báo các điều khoản và một số lưu ý khi sử dụng Android
Studio → chọn I Agree:
Hình 1.11.
- Xuất hiện hộp thoại yêu cầu chọn nơi cài đặt Android Studio và Android SDK như sau:
Hình 1.12.
- Sau đó, nhấn Next để tiếp tục quá trình cài đặt. Hộp thoại chọn Start Menu xuất hiện,
chọn Android Studio và nhấn vào Installl để tiếp tục quá trình cài đặt:
Hình 1.13.
- Khi quá trình cài đặt hoàn tất, nhấn Next để tiếp tục:
Hình 1.14.
- Hộp thoại cuối cùng của quá trình cài dặt xuất hiện, chọn Finish để kết thúc quá trình
cài đặt:
Hình 1.15.
Ở lần khởi động đầu tiên, một hộp thoại “import” bản Android Studio cũ xuất hiện, nếu bạn
cài đặt mới thì chọn như hình dưới → chọn OK:
Hình 1.16.
- Vì là lần đầu tiên khởi động nên Android Studio phải cập nhật một vài thứ cho quá
trình làm việc sau này:
Hình 1.17.
- Khi hoàn tất quá trình cập nhật, nhấn Finish để kết thúc và hoàn thành quá trình cài đặt.
3.3. Tạo ứng dụng đầu tiên
3.3.1. Khởi tạo dự án
- Khởi chạy Android Studio, xuất hiện màn hình “Welcome to Android Studio” → chọn
Start a new Android Studio project để tạo dự án Android Studio (Android Studio
project) mới như sau:
Hình 1.18.
- Hộp thoại tiếp theo xuất hiện yêu cầu đặt tên cho ứng dụng và tên domain như hình sau:
Hình 1.19.
Hình 1.20.
- Chọn như hình trên nếu muốn phát triển ứng dụng trên điện thoại (phone) và tablet. Sau
đó nhấn, Next để tiếp tục.
o Chú ý: Minimum SDK là phiên bản thấp nhất được chỉ định để chạy ứng dụng
và một số các phương thức API sẽ được gọi bổ sung trong phần thư viện hỗ trợ.
Hình 1.21.
- Chọn Blank Activity và nhấn Next. Hộp thoại nhập thông tin của Activity xuất hiện
như sau:
Hình 1.22.
Hình 1.23.
- Ở hình trên, màn hình làm việc được chia thành 7 phần – 7 phần này, chúng ta sẽ tương
tác thường với chúng với các chức năng cụ thể như sau:
o Phần 1: thanh công cụ này rất tiện lợi. Nó giúp chúng ta thao tác nhanh các chức
năng thường dùng khi lập trình, chi tiết như sau:
Biểu tượng dùng để mở một tập tin (file) hay một dự án (Project).
Biểu tượng dùng dể lưu lại tất cả các tập tin trong dự án (Save All).
Chúng ta cũng có thể dùng phím Ctrl + S để thực hiện chức năng này thay
vì chọn biểu tượng.
Biểu tượng cho phép đồng bộ tập tin. Chức năng này sẽ tìm tất cả các
tập tin đã thay đổi từ bên ngoài và tải lại (reload) chúng từ ổ đĩa cứng.
Chúng ta có thể dùng phím Ctrl + All +Y để thực hiện chức năng này
thay vì chọn biểu tượng này.
Hai biểu tượng cho phép chúng ta quay lại hành động đã làm trước
hoặc sau (Undo – Redo). Chúng ta cũng có thể sử dụng phím Ctrl + Z và
Ctrl + Shift + Z để sử dụng chức năng này.
Biểu tượng để “cut” tập tin hoặc hình ảnh đến Clipboad. Có thể sử
dụng phím Ctrl + X để thực hiện chức năng này thay vì chọn biểu tượng
này.
Biểu tượng để sao chép (copy) tập tin hoặc hình ảnh đến Clipboad. Có
thể sử dụng phím Ctrl + C để thực hiện chức năng này thay vì chọn biểu
tượng này.
Biểu tượng để dán (paste) tập tin hoặc hình ảnh từ Clipboad. Có thể sử
dụng phím Ctrl + V để thực hiện chức năng này thay vì chọn biểu tượng
này.
Biểu tượng để chạy (run) ứng dụng. Chúng ta cũng có thể dùng phím
Shift + F10 thay vì chọn biểu tượng này.
Biểu tượng để “debug” ứng dụng. Chúng ta cũng có thể dùng phím
Shift + F9 thay vì chọn biểu tượng này.
Biểu tượng là Android Virtual Device Manager (AVD Manager) cho
phép tạo và quản lý các thiết bị ảo.
Biểu tượng là SDK Manager có chức năng quản lí các phiên bản
Android.
- Đó là các biểu tượng với các chức năng thường sử dụng trong khi lập trình, ngoài ra
còn các biểu tượng khác, bạn có thể tự tìm hiểu thêm.
o Phần 2: là phần dành cho cấu trúc hệ thống của ứng dụng:
Hình 1.24.
Chúng ta cũng có thể thay đổi cách hiển thị (thường đặt mặc định là
Android).
Hình 1.25.
Cấu trúc dự án có thể chia thành phần sau:
Thư mục:
src: Thư mục này chứa các file mã nguồn .java cho dự án
của bạn.
gen: Thư mục này chứa file R.java - 1 file được trình biên
dịch sinh ra có khả năng tham chiếu tới tất cả các tài nguyên
trong dự án. Bạn không nên chỉnh sửa file này.
bin: Thư mục này chứa các file *.apk (Android Package
file) được build bởi ADT.
res/drawable-hdpi: Đây là thư mục chứa các đối tượng
drawble được thiết kế dành cho các màn hình có độ phân
giải cao.
res/layout: Đây là thư mục chứa các file layout cho việc
thiết kế giao diện.
res/values: Đây là thư mục dành cho các file XML khác
chứa 1 tập hợp các tài nguyên, ví dụ như: các định nghĩa về
strings, colors.
Tập tin:
AndroidManifest.xml: chứa thông tin cài đặt ứng dụng.
Ngoài ra còn có thư mục assets chứa tất cả các tập tin không biên dịch
như: âm thanh, hình ảnh, tập tin CSDL của ứng dụng…
o Phần 3: nó khá quan trọng cho những bạn mới bắt đầu lập trình. Đây là nơi hiển
thị các điều khiển (control) mà Android hỗ trợ, cho phép bạn kéo thả trực tiếp
vào phần 4 (Giao diện thiết bị) để thiết kế.
Hình 1.26.
Hình 1.27.
o Phần 4: là vùng giao diện thiết bị, cho phép các điều khiển (control) kéo thả vào
đây. Chúng ta có thể chọn cách hiển thị theo nằm ngang - nằm đứng, phóng to -
thu nhỏ, căn chỉnh điều khiển, lựa chọn loại thiết bị hiển thị, ...
o Phần 5: Khi màn hình của bạn có nhiều điều khiển (control) thì phần 5 này rất
cần thiết. Nó hiển thị giao diện theo dạng cấu trúc cây nên bạn dễ dàng quan sát
và lựa chọn điều khiển khi chúng bị chồng lập trên giao diện.
Hình 1.28.
o Phần 6: cho phép thiết lập trạng thái hay thuộc tính cho các điều khiển trên giao
diện.
Hình 1.29.
3.3.3. AndroidManifest
- Vai trò của tập tin AndroidManifest.xml:
- Lưu trữ thông tin tên gói ứng dụng, tồn tại duy nhất một tên gói cho mỗi ứng dụng.
o Ví dụ: com.htsi.myfirstapp
- Cho biết ứng dụng sử dụng các thành phần nào, mỗi thành phần được khai trong một
cặp thẻ.
o Ví dụ: <activity>….</activity>
- Định nghĩa tiến trình quản lý các thành phần ứng dụng.
- Định nghĩa các quyền sử dụng API và truy xuất ứng dụng khác.
- Qui định các yêu cầu khi được ứng dụng khác truy xuất.
- Khai báo cấp độ API tối thiểu xây dựng ứng dụng.
- Khai báo các thư viện có liên quan.
3.4. Cập nhật Android API
- Như đã đề cập ở phần cấu trúc dự án (3.3.2 – Phần 1) để cập nhật Android API, chúng
ta sử dụng công cụ SDK Manager.
Hình 1.30.
- SDK Manager quản lí các phiên bản Android. Ứng với từng phiên bản là các tài liệu
hướng dẫn, các ví dụ minh họa và các phương thức API... Nhấn vào biểu tượng để khởi
động SDK Manager và ADT sẽ tự động cập nhật các gói mới, bạn có thể lựa chọn
phiên bản Android hoặc các công cụ cần thiết và ấn Install Pakages.
Hình 1.32.
- Xuất hiện hộp thoại “Virtual Device Configuration” cho phép bạn chọn thiết bị muốn
tạo như sau:
Hình 1.33.
- Chú ý: chúng ta có thể tùy chỉnh lại tên, loại thiết bị, dung lượng bộ nhớ, … cho thiết bị
muốn tạo bằng cách chọn nút Clone Device → xuất hiện hộp thoại Configure Hardware
Profile như sau:
Hình 1.34.
- Trong đó:
o Device Name: tên thiết ảo cần tạo (thường đặt tên theo phiên bản).
o Device Type: loại thiết bị muốn tạo, có các lựa chọn: Phone/ Tablet, Android
Wear, Android TV.
o Screen: độ rộng và độ phân giải cho màn hình.
o Memory: bộ nhớ thiết bị.
- Tiếp theo, chúng ta chọn Next để tiếp tục quá trình tạo máy ảo → xuất hiện hộp thoại
cho phép chọn phiên bản hệ điều hành muốn tạo:
Hình 1.35.
Hình 1.36.
- Để cấu hình nâng cao, chúng ta chọn Show Advanced Settings.
- Chọn Finish để hoàn thành quá trình tạo máy ảo.
Bài 2
CÁC THÀNH PHẦN ỨNG DỤNG ANDROID
1.7. Context
- Context thuộc gói android.content (android.content.Context).
- Là một lớp cơ bản chứa hầu hết thông tin về môi trường ứng dụng của android, có
nghĩa là mọi thao tác, tương tác với hệ điều hành điều phải qua lớp này.
- Nó cung cấp các phương thức để các lớp khác có thể tương tác với hệ thống Android.
- Nó cho phép truy cập tới các nguồn tài nguyên (resources) đã được định nghĩa và các
lớp khác. Có thể nói Context là một lớp ở mức ứng dụng (Application level- liên quan
tới hệ thống).
- Hầu hết các lớp có liên quan tới UI (layout, button, textview, imageview, listview,…)
đều phải “super” tới Context vì bản thân Context đảm nhiệm việc truy cập tài nguyên
(R.id, R.layout,…). Nếu chúng ta không tham chiếu tới lớp Context thì không thể dùng
tới các tài nguyên mà chúng ta đã tạo ra.
- Tóm lại, Context giúp chúng ta dễ dàng truy cập và tương tác tới các tài nguyên của hệ
thống, các thông tin, các dịch vụ (services), các thông số cấu hình, dữ liệu, danh bạ,
cuộc gọi, kết nối, chế độ rung (vibrator), ...
1.8. Notification
- Thành phần cho phép gửi các thông báo đến người dùng mà không chiếm quá nhiều
việc điều khiển của người dùng trên thiết bị. Ví dụ, khi nhận được một tin nhắn hay một
thư điện tử , thiết bị sẽ sử dụng Notification để thông báo người dùng thông qua nhạc
chuông, đèn nền, thể hiện biểu tượng trên thanh tác vụ…
- Notification được xây dựng cho mục đích gửi các thông báo đến người dùng thông qua
thanh trạng thái.
- Giao diện Notification không thuộc giao diện ứng dụng, nhưng có thể tuỳ chỉnh giao
diện Notification thông qua các phương thức có sẵn.
đổi qua lại giữ các Activity với nhau đồng thời truyền dữ liệu trừ Activity trước sang Activity
mới để có thể xử lý.
- Mỗi Activity đại diện cho một màn hình ứng dụng. Ta sẽ thực hiện tạo Activity cho
ứng dụng theo các bước sau:
o Tạo mới lớp kế thừa từ lớp Activity.
o Thực thi các phương thức quản lý trạng thái Activity.
o Xây dựng giao diện trong tài nguyên res/layout.
o Khai báo Activity trong tập tin AndroidManifest.xml.
Ví dụ:
public class MyFirstActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
o Foreground process: là process của ứng dụng hiện thời đang được người dùng
tương tác.
o Visible process: là process của ứng dụng mà activity đang hiển thị đối với người
dùng (onPaused() của activity được gọi).
o Service process: là Service đang chạy.
o Background process: là process của ứng dụng mà các activity của nó không
hiển thị với người dùng (onStoped() của activity được gọi).
o Empty process: process không có bất cứ 1 thành phần nào active.
- Theo chế độ ưu tiên thì khi cần tài nguyên, Android sẽ tự động kill process, trước tiên
là các empty process.
Bài 3
GIAO DIỆN NGƯỜI DÙNG
VÀ XỬ LÝ SỰ KIỆN
- Đối tượng mặc định vị trí top-left trên FrameLayout, có thể sử dụng thuộc tính Gravity
để thiết lập lại vị trí.
- Frame Layout có thể chứa nhiều View và các View này có thể sắp chồng lên nhau. Và
các View nằm dưới có thể bị các View nằm trên che khuất. Vì vậy, thường Frame Layout
chỉ chứa một View.
- Ví dụ khai báo:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent”" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/android" />
</FrameLayout>
android:layout_height="match_parent”" >
</ViewFlipper>
o ScrollView: đối tượng cho phép thực hiện hiển thị các đối tượng ở chế độ cuộn
màn hình, chỉ cho phép chứa một đối tượng ở một thời điểm.
Ví dụ khai báo:
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent” >
</ScrollView>
</TableLayout>
- Có thể kéo dãn độ rộng một cột với thuộc tính: android: layout_span.
2. VIEW VÀ VIEWGROUP
2.1. Tổng quan
Trong Android, để tạo giao diện, chúng ta phải sử dụng hai lớp cốt lõi là: View và ViewGroup.
Chúng rất quan trọng và được sử dụng thường xuyên trong quá trình phát triển ứng dụng
Android.
View và ViewGroup là hai lớp Java kế thừa từ lớp Java Object.
View là một lớp cha trên cùng. ViewGroup, TextView, AnalogClock, ImageView,… là các lớp
con kế thừa từ lớp cha View. Và các lớp: Frame Layout, Linear layout và Relative Layout lại
kế thừa từ ViewGroup. Tương tự, TextView cũng có 3 lớp con: EditText, Button và
CheckedTextView.
DataPicker
FrameLayout
View TimePicker
CalendarView
ViewGroup TableLayout
LinearLayout
RadioGroup
RelativeLayout
EditText
CheckBox
TextView Button CompoundButton
View RadioButton
AnalogClock ChekedTextView
RatingBar
ProgressBar AbsSeekBar
SeekBar
ImageButton
ImageView
QuickContactBadge
SurfaceView VideoView
Hình 3.5. Các đối tượng View trong thư viện Android.
- View được sử dụng để tạo ra các điều khiển trên màn hình cho phép nhận các tương tác
từ người dùng cũng như hiển thị các thông tin cần thiết.
- View bao gồm hai dạng:
o View: các điều khiển đơn lẻ .
o ViewGroup: tập hợp nhiều điều khiển đơn lẻ.
- Các đối tượng View được thể hiện trên màn hình giao diện như một hình chữ nhật tuỳ
thuộc vị trí, kích thước, màu sắc và nhận vào cũng như xử lý các tương tác có liên quan.
- Thuộc tính Id được đi kèm với đối tượng View khi khai báo trong XML cho phép truy
xuất trong Java Code khi cần. Ví dụ:
2.2.2. Thuộc tính vị trí: cho biết toạ độ hiển thị cho View trên giao diện.
- Phương thức thiết lập :
o layout
o setLeft
o setTop
o setRight
o setBottom
- Phương thức truy xuất:
o getLeft
o getTop
o getRight
o getBottom
- Vị trí của View tuỳ thuộc vào thuộc tính của đối tượng Layout.
o Kích thước: bao gồm chiều ngang và chiều cao của một đối tượng View. Kích
thước của đối tượng View có thể thiết lập qua các thông số:
WRAP_CONTENT
MATCH_PARENT (API 8 trở lên)
FILL_PARENT
Các thông số trên là một con số bất kỳ (tính theo dp/px/dip).
- Phương thức thiết lập:
o Thiết lập thông qua đối tượng LayoutParams
Thuộc tính thiết lập trong XML:
layout_width
layout_height
Phương thức truy xuất:
getWidth
getHeight
getMeasuredWidth
getMeasureHeight
o Canh lề nội dung trong JavaCode:
Phương thức thiết lập:
setPadding
Phương thức truy xuất:
getPaddingTop
getPaddingLeft
getPaddingRight
getPaddingBottom
Trong XML:
android:text="Đối tượng TextView"
- TextView được hổ trợ các phương thức để thực hiện các siêu liên kết (Linkify). Cơ chế
tự động thiết lập hành động cho các siêu liên kết, bao gồm:
o Web
o Email
o Phone
o Map
- Phương thức thiết lập:
Trong Java code:
textView.setAutoLinkMask(Linkify.PHONE_NUMBERS);
Trong XML:
android:autoLink="phone"
- TextView cho phép hiển thị hình ảnh theo văn bản ở hai dạng:
o Theo bố cục văn bản: Left, Top, Right, Bottom.
o Theo đoạn văn bản: Start, End.
- Phương thức thiết lập:
Trong Java code:
textView.setCompoundDrawables(Left,Top, Right, Bottom);
Trong XML:
android:drawableLeft=“@drawable/ic_launcher”
- EditText là lớp kế thừa từ TextView, được dùng thay đổi nội dung text, chứa tất cả thuộc
tính của TextView.
@Override
public void onClick(View v) {
//do something
}
});
default:
break;
}
}
3.4. Checkbox:
- CheckBox là đối tượng nút bấm hai trạng thái “được chọn” và “bỏ chọn”.
- Phương thức lắng nghe sự kiện thay đổi trạng thái:
checkBox.setOnCheckedChangeListener(new OnCheckedChangeLisntener() {
@Override
public void onCheckedChangeListener(CompoundButton v, boolean isChecked)
{
Log.i(“CompoundButton”, “onChecked”);
}
});
3.5. RadioButton: đối tượng nút bấm hai trạng thái “được chọn” và “bỏ chọn”, không thể
“bỏ chọn” khi đã “được chọn”.
- Thường xử lý trên nhóm nút nhiều trạng thái.
- Phương thức lắng nghe sự kiện thay đổi trạng thái trên nhóm nút:
radioGroup.setOnCheckedChangeListener(new OnCheckedChangeLisntener() {
@Override
public void onCheckedChangeListener(RadioGroup group, int checkedId)
{
Log.i(“CompoundButton”, “Checked at id:” + checkedId);
}
});
3.6. ToggleButton: đối tượng nút bấm hai trạng thái “bật” và “tắt”, thể hiện trạng thái
trên đối tượng.
- Thuộc tính quan trọng:
o textOn: trạng thái nút đang bật
o textOff: trạng thái nút đang tắt
- Phương thức lắng nghe sự kiện thay đổi trạng thái trên nhóm nút:
toggleButton.setOnCheckedChangeListener(new OnCheckedChangeLisntener() {
@Override
public void onCheckedChangeListener(CompoundButton v, boolean isChecked)
{
Log.i(“CompoundButton”, “onChecked”); }
});
3.7. Switch: đối tượng nút bấm hai trạng thái “bật” và “tắt”, có thể thao tác bằng cách
trượt ngón tay trên đối tượng.
- Thuộc tính quan trọng:
o textOn: trạng thái nút đang bật
o textOff: trạng thái nút đang tắt
- Phương thức lắng nghe sự kiện thay đổi trạng thái trên nhóm nút:
switchButton.setOnCheckedChangeListener(new OnCheckedChangeLisntener() {
@Override
public void onCheckedChangeListener(CompoundButton v, boolean isChecked)
{
Log.i(“CompoundButton”, “onChecked”);
}
});
Ngoài cách thiết lập các thuộc tính cho layout và các điều khiển trong tập tin xml như các ví
dụ trên, chúng ta có thể điền các giá trị muốn thiết lập vào giao diện được hổ trợ sẵn.
Hình 3.10. Minh họa thiết lập giá trị layout width trên giao diện tương tác.
Ngoài ra, ta còn có thể khảo sát được sự phóng to, thu nhỏ của màn hình ( sử dụng công cụ
Pixel Perfect). Công cụ này có ích trong việc phát triển giao diện ứng dụng dòi hỏi độ chính
xác cao về hình ảnh hay tinh chỉnh lại hình ảnh, màu sắc, độ trong suốt cho hợp lý hơn.
Bài 4
TÀI NGUYÊN ỨNG DỤNG
TRONG ANDROID
1. TỔNG QUAN
1.1. Tài nguyên
- Tài nguyên là một dạng dữ liệu được xây dựng nhằm đáp ứng các yêu cầu về hiển thị
bao gồm hình ảnh, âm thanh, văn bản, các bố cục…tương thích cho từng thiết bị riêng
biệt. Cho phép khai báo một lần và sử dụng trong phạm vi toàn ứng dụng, dễ dàng thay
đổi theo ngữ cảnh.
- Android cung cấp cho chúng ta khá nhiều cách thức để có thể sử dụng đa dạng tài
nguyên như hình ảnh, các chuỗi hằng, chuyển hoạt, bố cục giao diện…mà không cần
phụ thuộc quá nhiều vào các dòng mã lệnh. Điều này giúp chúng ta đơn giản hóa lưu
trữ, quản lý và cập nhật. Trong thiết kế cũng giúp chúng ta linh động hơn trong việc
điều chỉnh cho nhiều thiết bị phần cứng khác nhau.
- Hệ thống tự động tạo thư mục /res dùng để chứa các thư mục của từng loại tài nguyên.
- Các file tài nguyên sẽ được chứa trong các thư mục tùy thuộc vào định dạng của tài
nguyên đó.
- Chúng ta cần tạo ra các thư mục tài nguyên theo đúng định dạng của một ứng dụng
Android. Tài nguyên ứng dụng được định nghĩa trong thư mục res của dự án, bao gồm
các dạng tài nguyên sau:
o Animator: Các dạng tài nguyên chuyển hoạt. (property animation)
o Anim: Các dạng tài nguyên chuyển hoạt. (property animation)
o Color: Các dạng tài nguyên màu sắc.
o Drawable: Các dạng tài nguyên hình ảnh.
o Layout: Các dạng tài nguyên giao diện.
o Menu: Các dạng tài nguyên chỉ mục.
o Raw: Các dạng tài nguyên không biên dịch.
o Values: Các dạng tài nguyên cơ bản. Ví dụ: String, Integer, Boolean…
o XML: Các dạng tài nguyên xml khác.
Hình 4.1. Thư mục chứa tài nguyên ứng dụng Android.
1.2. Định nghĩa tài nguyên
- Có quá nhiều thiết bị có cấu hình khác nhau về kích thước màn hình, độ phân giải,
phím vật lý…
- Mỗi thiết bị có thể hoạt động ở nhiều chế độ khác nhau: nằm ngang, nằm đứng, thay
đổi ngôn ngữ…
- Từ hạn định: dùng để tạo ra các tài nguyên khác nhau cho nhiều thiết bị có cấu hình
khác nhau hoạt động ở các chế độ khác nhau. Khi vừa tạo mới một Project, trong thư
mục res ta sẽ thấy có đến bốn thư mục drawable và ba thư mục values chỉ khác nhau ở
phần ngăn cách bởi “-“. Phần hậu tố này chúng ta gọi là từ hạn định, dùng để phân biệt
tài nguyên dành cho các cấu hình khác nhau. Khi ứng dụng được cài lên thiết bị hệ
thống sẽ tự tìm các tài nguyên phù hợp với phần cứng thiết bị đó.
o Screen Pixel Density – mật độ điểm ảnh trên một inch (dpi – dot per inch ).
Dùng để phân biệt các dạng tài nguyên cho các màn hình có độ phân giải khác
nhau bao gồm ldpi (low - 120dpi), mdpi (medium - 160dpi), hdpi (high - 240dpi)
và xhdpi (extra high – 320dpi).
o Touchscreen Type – từ hạn định dành cho các tài nguyên liên quan đến điều
khiển cảm ứng gồm notouch (không hỗ trợ cảm ứng), stylus (dùng bút vẽ) và
finger (cảm ứng điện dung).
o Keyboard Availability - từ hạn định dành cho các tài nguyên liên quan đến bàn
phím nhập liệu gồm keyexposed (bàn phím cứng), keyshidden (bàn phím trượt)
và keysoft (bàn phím ảo).
o Keyboard Input Type - từ hạn định dành cho các tài nguyên liên quan đến kiểu
nhập liệu bao gồm nokeys (không bàn phím), qwerty (bàn phím máy tính cá
nhân) và 12key (bàn phím số).
o Navigation Key Availability – từ hạn định dành cho các tài nguyên liên quan đến
phím điều hướng bao gồm navexposed (phím cứng) và navhidden (phím trượt).
o UI Navigation Type - từ hạn định dành cho các tài nguyên liên quan đến kiểu
điều hướng bao gồm nonav (không hỗ trợ điều hướng), dpad (bàn rê), trackball
(bi lăn) và wheel (bánh xe).
o Platform Version – cho phép chỉ định các tài nguyên chạy trên các phiên bản có
API khác nhau. Ví dụ: v7 chỉ định các phiên bản có API 7 (Android 2.1).
- Chúng ta có thể sử dụng cùng lúc nhiều từ hạn định cho các thư mục tài nguyên khác
nhau và ngăn cách bởi dấu “-“. Tuy nhiên cần lưu ý là các từ hạn định phải theo độ ưu
tiên (trong tài liệu này độ ưu tiên từ trên xuống dưới) và không được phép sử dụng hai
từ hạn định cùng loại ở cùng một thư mục.
- Ví dụ: các thư mục tài nguyên sau là không được phép:
o layout-rUS-en (không theo thứ tự)
o layout-vn-en (hai từ hạn định cùng loại)
o XML:
@[<package_name.>:]<resource_type>/<resource_name>
o Trong đó:
Package_name: tên gói ứng dụng
Resource_type: dạng tài nguyên
Resource_name:
Tên tài nguyên cần truy xuất không bao gồm phần mở rộng tập tin
Thuộc tính android:name dành cho các tài nguyên cơ bản (string,
color…).
3.2. Tài nguyên Alias
- Tài nguyên Alias cho phép tạo ra tài nguyên từ tài nguyên có sẵn, phục vụ cho nhiều
cấu hình thiết bị nhưng không phải là tài nguyên mặc định.
- Ví dụ:
Vấn đề: tạo biểu tượng ứng dụng khác nhau cho các ngôn ngữ khác nhau, đối với tiếng
Anh và tiếng Việt thì cùng biểu tượng.
o Giải quyết vấn đề (không dùng Alias):
Tạo thư mục tài nguyên cho từng ngôn ngữ.
Chép hình ảnh khác nhau cho từng thư mục, hai thư mục có từ hạn định
en và vi có hình ảnh giống nhau.
o Giải quyết vấn đề (dùng Alias):
Tạo thư mục tài nguyên cho từng ngôn ngữ.
Chép hình ảnh khác nhau cho từng thư mục.
Thư mục có từ hạn định en tạo tài nguyên Alias từ thư mục vi.
- Trong đó:
o string_name: định danh dùng để truy xuất trong XML và Java Code.
o text_string: nội dung lưu trữ.
Ví dụ: tạo tập tin strings.xml
<resource>
<string name=“hello”>Hello world!</string>
</resource>
4.2. Bool
- Cú pháp
<?xml version="1.0" encoding="utf-8"?>
<resources>
<boolname="bool_name">[true | false]</bool>
</resources>
- Ví dụ: res/values-small/bools.xml
<resources>
<bool name="screen_small">true</bool>
<bool name="adjust_view_bounds">true</bool>
</resources>
4.3. Color
- Thư mục tài nguyên:
/res/values/filename.xml
4.4. Id
- Thư mục tài nguyên:
/res/values/filename.xml
- Cú pháp khai báo:
<resources>
<item type=“id” name=“id_name”/>
…
</resources>
4.5. Dimen
- Khai báo tài nguyên sử dụng cho các đại lượng kích thước trong ứng dụng.
- Có thể sử dụng các đại lượng kích thước sau: dp – dip, sp, pt, px, mm, in.
- Khai báo:
<dimen name=“dimen_name”>size</dimen>
- Trong đó:
o dimen_name: định danh dùng để truy xuất trong XML và Java Code.
o size: đại lượng đi kèm định dạng
- Ví dụ: tập tin dimens.xml
<?xml version=“1.0” encoding=“utf-8”?>
<resource>
<dimen name=“text_size”>20sp</dimen>
</resource>
- Ví dụ truy xuất và sử dụng: Khai báo Button và thiết lập kích thước văn bản thông qua
thuộc tính textSize.
o Truy xuất trong XML:
<TextView
…
android:textSize=“@dimen/text_size” />
4.6. Integer
- Thư mục tài nguyên:
/res/values/filename.xml
- Ví dụ: res/values/arrays.xml
<resources>
<array name="icons">
<item>@drawable/home</item>
<item>@drawable/settings</item>
<item>@drawable/logout</item> </array>
<array name="colors">
<item>#FFFF0000</item>
<item>#FF00FF00</item>
<item>#FF0000FF</item>
</array>
</resources>
o Trong XML:
<ImageView
android:layout_width=“50dp”
android:layout_height=“50dp”
android:src=“@drawable/ic_launcher” />
<ImageButton
android:layout_width=“50dp”
android:layout_height=“50dp”
android:background=“@drawable/ic_launcher” />
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:mipMap="false"
android:src="@drawable/caro"
android:tileMode="repeat" > </bitmap>
5.3. Shape
- Tài nguyên hình ảnh cho các đối tượng đa giác được vẽ bằng XML, bao gồm:
o Rectangle
o Oval
o Line
o Ring
- Tham chiếu biên dịch tài nguyên thông qua đối tượng GradientDrawable.
- Sử dụng các thuộc tính để cấu tạo đối tượng:
o Corners (Rectangle) - Integer
radius
topLeftRadius
topRightRadius
bottomLeftRadius
o bottomRadius Padding (Rectangle) – Integer
left
top
right
bottom
o Gradient
angle - integer
centerX - integer
centerY - integer
centerColor - integer
endColor - color
gradientRadius – integer
startColor – color
type – linear | radial | sweep
useLevel – true | false
o Size – integer
width – integer
height – integer
Solid – integer
color – color
o Stroke – integer
width - integer
color – color
dashWith – integer
dashGap – integer
o Một số thuộc tính chỉ sử dụng cho đối tượng Ring:
innerRadius
innerRadiusRatio
thickness
thicknessRatio
useLevel (false)
- Ví dụ:
<shape xmlns:android=http://schemas.android.com/apk/res/android
android:shape="rectangle" >
<gradient
android:angle="90"
android:startColor="@android:color/holo_blue_bright"
android:type="linear" />
<corners android:radius="20dp"/>
<size
android:height="80dp"
android:width="80dp" />
</shape>
5.4. LayerList
- Tài nguyên hình ảnh cho phép quản lý mảng các đối tượng hình ảnh được vẽ chồng lên
nhau, mỗi đối tượng hình ảnh được qui ước là một item.
- Mỗi item bao gồm:
o drawable – resource
o Id – resource id
o top - integer
o right - integer
o bottom - integer
o left - integer
- Tham chiếu biên dịch tài nguyên thông qua đối tượng LayerDrawable.
5.5. StateList
- Tài nguyên hình ảnh cho phép quản lý mảng các đối tượng hình ảnh được vẽ theo trạng
thái của đối tượng thể hiện.
- Một item bao gồm: drawable – resource
- Tập các trạng thái có thể có:
o Pressed
o Focused
o Hovered
o Selected
o Checkable
o Enable
o Activated
o Window focused
5.6. LevelList
- Tài nguyên hình ảnh cho phép quản lý mảng các đối tượng hình ảnh, mỗi đối tượng
hình ảnh được qui ước là một item, hiển thị ảnh theo cấp độ tương ứng đã khai báo.
- Một item bao gồm:
o drawable – resource
o maxLevel
o minLevel
- Tham chiếu biên dịch tài nguyên thông qua đối tượng LevelListDrawable.
- Ví dụ:
<?xml version="1.0" encoding="utf-8"?>
<level-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/status_off" android:maxLevel="0" />
<item android:drawable="@drawable/status_on" android:maxLevel="1" />
</level-list>
5.7. Transition
- Tài nguyên hình ảnh cho phép thực hiện chuyển đổi (hiệu ứng “biến bóng”) giữa hai
đối tượng hình ảnh.
- Mỗi item bao gồm:
o drawable – resource
o Id – resource id
o top - integer
o right - integer
o bottom - integer
o left – integer
- Các phương thức xử lý chính:
o startTransition
o reverserTransition
o resetTransition.
- Ví dụ:
<?xml version="1.0" encoding="utf-8"?>
<transition
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/on" />
<item android:drawable="@drawable/off" />
</transition>
5.8. Inset
- Tài nguyên hình ảnh cho phép thực hiện lồng đối tượng hình ảnh theo một ví trí cho
trước.
o insetBottom - integer
o insetLeft – integer
- Tham chiếu biên dịch tài nguyên thông qua đối tượng InsetDrawable.
5.9. Clip
- Tài nguyên hình ảnh cho phép thực hiện cắt một đối tượng hình ảnh theo thông số vị trí
cho trước, có thể thay đổi thông số cắt trong quá trình hoạt động.
- Tham chiếu biên dịch tài nguyên thông qua đối tượng ClipDrawable.
- Các thuộc tính bao gồm:
o drawable – resource
o clipOrientation – integer
o Gravity
- Các phương thức xử lý chính:
o setLevel (min:0 – max: 10.000)
o getLevel
o scaleWidth - %
o scaleHeight - %
- Tham chiếu biên dịch tài nguyên thông qua đối tượng ScaleDrawable.
5.11. Nine-Patch
- Tài nguyên hình ảnh cho phép thực hiện tạo đối tượng hình ảnh (PNG) có kích thước co
dãn theo tỉ lệ đối tượng thể hiện.
Bài 5
INTENT
- Extras: bao gồm biến Bundle chứa các giá trị bổ sung cần thiết cho thành phần nhận xử
lý Intent.
- Có hai cách gửi dữ liệu vào Intent:
o Trực tiếp: dùng phương thức putExtra(Key, Value) thiết lập trực tiếp vào Intent.
o Thông qua Bundle: tạo một đối tượng Bundle, dùng phương thức
set<KDL>(Key, Value) vào đối tượng Bundle. Sau dó, ta dùng phương thức
putExtras() gửi Bundle vào Intent.
- Truy xuất:
o Truy xuất dữ liệu trực tiếp Extras:
Dùng phương thức get<KDL>Extra(Key, DefaultValue) để truy xuất dữ
liệu Intent.
o Thông qua Bundle:
Dùng phương thức getExtras() để truy xuất đối tượng Bundle trong Intent.
Dùng phương thức get<KDL>(Key, DefaultValue) để truy xuất dữ liệu
trong Bundle.
o Ví dụ: truy xuất số nguyên được gửi trong Intent
Trực tiếp:
Intent intent = getIntent();
int soNguyenX = intent.getIntExtra(“SoNguyenX”, 0);
Khởi tạo đối tượng Intent, thiết lập các thuộc tính cần thiết: action,
category…
Gửi dữ liệu phản hồi trực tiếp vào Intent hoặc thông qua biến
Bundle.
Gọi phương thức setResult với tham số truyền vào là Intent.
Bước 3: Gọi phương thức onActivityResult() truy xuất ba tham số:
requestCode: mã yêu cầu giải quyết với intent tương ứng.
resultCode: mã kết quả nhận về từ phía phản hồi.
Intent: dữ liệu nhận về từ phía phản hồi.
2. INTENT FILTER
2.1. Mô tả
- Thực hiện mô tả cấu trúc Intent, cho phép thực hiện chỉ nhận các Intent theo đúng cấu
trúc đã mô tả.
- Có thể lọc Intent theo ba thuộc tính:
o Action
o Data (type, scheme, authority & path)
o Category
2.2. Quy tắc thiết lập
- IntentFilter thực hiện lọc Intent theo thứ tự ưu tiên khi có nhiều thuộc tính được thiết
lập và có những qui tắc nhất định:
o Nếu không thiết lập Action, chỉ nhận các Intent không có Action.
o Nếu thiết lập thuộc tính Action và không thiết lập thuộc tính Data, chỉ cho phép
lọc các Intent không có Data.
- IntentFilter cho phép nhận các Intent có bất kỳ dữ liệu nào có liên quan đến thuộc tính
Action.
2.3. Xây dựng IntentFilter
- Có thể khởi tạo đối tượng IntentFilter như sau:
- Trong java Code:
o Các phương thức khởi tạo:
IntentFilter()
IntentFilter(String Action)
IntentFilter(String Action, URI data)
IntentFilter(IntentFilter o)
- Trong tập tin AndroidManifest.xml:
o Khai báo thẻ cặp thẻ <intentfilter><intentfilter/>
o Trong cặp thẻ có thể chứa các thẻ sau: <action/>, <data/>, <category/>
2.3.1. Action:
- Các thuộc tính:
<action android:name=“string” />
o Trong đó:
android:name: sử dụng các thuộc tính trong lớp Intent.ACTION_string
hoặc tự định nghĩa chuỗi action.
2.3.2. Data:
- Các thuộc tính:
<data
android:scheme="string"
android:host="string"
android:port="string"
android:path="string"
android:pathPattern="string"
android:pathPrefix="string"
android:mimeType="string" />
2.3.3. Category
- Các thuộc tính:
<category android:name=“string” />
o Trong đó:
android:name: Intent.CATEGORY_string. Khai báo theo cấu trúc
android.intent.category.string
- Ví dụ khai báo:
<category android:name=“android.intent.category.DEFAULT” />
<category android:name=“android.intent.category.LAUNCHER” />
Bài 7
CÁC ĐIỀU KHIỂN HIỂN THỊ DANH SÁCH
2.1. BaseAdapter
- BaseAdpater là lớp adpater cơ sở cho các Adapter thường dùng khác như
ArrayAdapter<T>, CursorAdapter, SimpleAdapter…
- Ví dụ:
o Tạo một ArrayAdapter chứa các dữ liệu chuỗi.
String arr[]={"One","Two","Three","Four"};
ArrayAdapter<String> adapter = new
ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, arr));
o Trong đó:
android.R.layout.simple_list_item_1: là layout mặc định do Android xây
dựng sẵn cho 1 item của ListView.
- Tuy nhiên, nếu muốn sử dụng với những giao diện phức tạp hơn như ImageView, hoặc
nhiều TextView ta nên ghi đè lại getView (int, View, ViewGroup) để trả lại kiểu giao
diện mà bạn muốn.
2.2. SimpleCursorAdapter
- SimpleCursorAdapter là lớp Adapter lấy dữ liệu từ một Cursor ra một điều khiển hiển
thị ví dụ ListView, GridView, ... Cursor phải có chứa tên định danh cho các cột, nếu
không sẽ không thực hiện được.
- Dữ liệu từ mảng chứa dữ liệu sẽ được gắn vào ArrayAdapter, ArrayAdapter sẽ gắn vào
ListView.
- Giải thích ý nghĩa các đối số trong phương thức ArrayAdapter:
o Đối số thứ 1: this
Đại diện cho context của Activity hiện tại, bạn có thể viết
MainActivity.this (nếu bạn viết như thế này thì ở bất kỳ vị trí nào nó cũng
hiểu là context của MainActivity).
o Đối số thứ 2: android.R.layout.simple_list_item_1
Là layout Listview mà được Android xây dựng sẵn. Nó được lưu trong
SDK/ platforms/ android-api(x)/ data/ res/ layout/
simple_list_item_1.xml.
o Đối số thứ 3: [tenMangDuLieu]
Là mảng chứa dữ liệu cần hiển thị lên ListView.
- Thuộc tính XML quan trọng:
o listSelector: drawable
o divider: drawable
o dividerHeight: dimen
o entries: string-array
- Một số phương thức quan trọng:
o setAdapter(Class Extends <T implements Adapter>)
o addHeaderView(View) – removeHeaderView(View)
o addFooterView(View) – removeFooterView(View)
o setSelection(int)
o smoothScrollToPosition(int)
- Ví dụ: Tạo ListView hiển thị danh sách tên các quốc gia.
Bước 1: Tạo dữ liệu
- Chúng ta tạo mảng dữ liệu để hiển thị trên listview thông qua một tập tin xml bằng cách
tạo mới một tập tin list_data.xml trong / res/ values với nội dung sau:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="countries">
<item>Sri Lanka</item>
<item>Tokelau</item>
<item>United Kingdom</item>
<item>Uruguay</item>
<item>Vatican</item>
<item>Vietnam</item>
</string-array>
</resources>
Bước 3: Đưa dữ liệu vào mảng, tạo đối tượng ArrayAdapter, đưa dữ liệu từ mảng vào
ArrayAdapter, hiển thị nội dung lên ListView
- Chúng ta vào Activity để thao tác như sau:
//Đưa dữ liệu v{o mảng
String[] countries = getResources().getStringArray(R.array.countries);
//lấy listview thông qua id của listview
ListView lvCountry=(ListView)findViewById(R.id.lvCountry);
//Tạo đối tượng ArrayAdapter v{ đưa dữ liệu từ mảng v{o ArrayAdapter
ArrayAdapter<String> adapter = new ArrayAdapter<String>
(this,android.R.layout.simple_list_item_1, countries);
//đổ dữ liệu lên listview
lvCountry.setAdapter(adapter);
Cách khác: chúng ta còn có thể thiết lập sự kiện trên cho listView bằng cách cho Activity kế
thừa lớp ListActivity để trở thành một Activity dạng list:
public class ListViewActivity extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] countries =getResources().getStringArray(R.array.countries);
setListAdapter(new ArrayAdapter<String>
(this,android.R.layout.simple_list_item_1,android.R.id.text1,countries));
getListView().setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int
position, long id) {
// Ghi log
Log.d("ListView","onItemClick- POS :" +position+"+ ID : " +id);
}
});
}
}
3.3. GridView
- GridView giống với ListView nhưng có chức năng hỗ trợ hiển thị dữ liệu theo dạng
lưới. GridView cũng cần một đối tượng Adapter để quản lý và giúp hiển thị dữ liệu.
- Gridview cũng dựa vào Adapter để gắn kết các dữ liệu bên dưới.
String[] adobe_products =
getResources().getStringArray(R.array.adobe_products);
GridView gvAdobe = (GridView) findViewById(R.id.gvAdobe);
- Điểm khác nhau là GridView có thiết lập số cột. Dữ liệu luôn đưa vào dưới dạng hình
ống (mảng, list một chiều), nhưng dựa vào số cột ta thiết lập mà nó tự động ngắt hàng
dựa vào thuộc tính numColums trong layout.
<GridView
android:id="@+id/gvAdobe"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:numColumns="3" >
</GridView>
3.4. Spinner
- Spinner là đối tượng điều khiển hiển thị một danh mục ở một thời điểm, người dùng có
thể lựa chọn một trong nhiều danh mục để hiển thị.
- Bao gồm hai chế độ hiển thị pop-up lựa chọn (spinnerMode):
o Dialog
o Dropdown
o setPopupBackgroundResource(int)
o setPopupBackgroundDrawable(Drawable)
R.array.countries,
android.R.layout.simple_dropdown_item_1line);
// Tham chiếu điều khiển
Spinner spinner = (Spinner)findViewById(R.id.spinner);
// Thiết lập Adapter cho điều khiển
spinner.setAdapter(adapter);
Sri Lanka
Tokelau
United Kingdom
Uruguay
Vatican
VietNam
Sau đây là ví dụ về cách tạo Custom Layout cho ListView (lấy ví dụ ở phần III.1).
- Tạo layout trong Activity như sau:
<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="nghialt.demo.democustomlistview.MainActivity" >
<ListView
android:id="@+id/lvCountries"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
</RelativeLayout>
<ImageView
android:id="@+id/imgvFlag"
android:layout_width="80dp"
android:layout_height="80dp"
android:contentDescription="@null"
android:src="@drawable/flag_japan" />
<LinearLayout
android:layout_width="120dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginLeft="20dp"
android:padding="10dp" >
<TextView
android:id="@+id/tvEnName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@null"
android:textColor="#357B6A"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@+id/tvViName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@null"
/>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<CheckBox
android:id="@+id/checkBox1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="16dp" />
</RelativeLayout>
</LinearLayout>
- Custom lại Adapter bằng cách tạo một class kế thừa từ class ArrayAdapter gọi là
CountryAdapter
public class CountryAdapter extends ArrayAdapter<Country> {
Context context;
int resId;
ArrayList<Country> countries;
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Country c = countries.get(position);
if (c != null) {
tvEnName.setText(c.getEnName());
tvViName.setText(c.getViName());
imgvFlag.setImageResource(c.getImg_id());
}
return view;
}
}
3.6. AutoCompleteTextView
- Đối tượng kế thừa từ EditText.
- Cho phép xây dựng dữ liệu mẫu hỗ trợ người dùng hoàn chỉnh quá trình nhập liệu trên
EditText.
- Thực hiện xây dựng AutoCompleteTextView:
- Khai báo dữ liệu mẫu.
- Khai báo giao diện hiển thị cho dữ liệu.
- Xây dựng Adapter thông qua phương thức khởi tạo tương ứng với dữ liệu và giao diện
hiển thị.
- Thiết lập Adapter cho đối tượng AutoCompleteTextView
3.7. MultiAutoCompleteTextView
- Đối tượng kế thừa từ đối tượng AutoCompleteTextView.
- Cho phép xây dựng dữ liệu mẫu hỗ trợ người dùng hoàn chỉnh quá trình nhập liệu trên
EditText.
- Dữ liệu được hỗ trợ hoàn chỉnh nhiều lần, cách nhau bằng một Tokenizer.
- Thực hiện xây dựng MultiAutoCompleteTextView:
- Khai báo dữ liệu mẫu.
- Khai báo giao diện hiển thị cho dữ liệu.
- Xây dựng Adapter thông qua phương thức khởi tạo tương ứng với dữ liệu và giao diện
hiển thị.
- Thiết lập Adapter cho đối tượng MultiAutoCompleteTextView.
- Thiết lập đối tượng Tokenizer.
Bài 6
QUẢN LÝ ASSET –
SHARED PREFERENCES –
BỘ NHỚ THIẾT BỊ
1. BỘ QUẢN LÝ ASSET
1.1. Giới thiệu
- Asset là thư mục chứa dữ liệu đầu vào. Ví dụ: âm thanh, hình ảnh, tập tin CSDL hoặc
tập tin có đuôi khác ... Những tập tin này sẽ không được biên dịch khi ứng dụng được
đóng gói.
- AssetManager là lớp cung cấp quyền truy cập vào các tập tin không biên dịch của ứng
dụng. AssetManager cho phép bạn mở và đọc file nguyên gốc dưới dạng một luồng
byte.
- Cú pháp khởi tạo AssetManager:
AssetManager assetManager = Context.getAssets();
- Để truy xuất phông chữ thông qua thư mục Asset ta sử dụng phương thức
createFromAsset.
- Ví dụ:
Typeface arial = Typeface.createFromAsset(getAssets(), “font/arial.ttf”);
textView.setTypeface(arial);
android:layout_height="wrap_content"
android:id="@+id/imgAssets"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/txtFileName" />
</LinearLayout>
</ScrollView>
input.close();
// byte buffer into a string
String text = new String(buffer)
txtContent.setText(text);
} catch (IOException e) {
e.printStackTrace();
}
// To load image
try {
InputStream ims = assetManager.open("android_logo_small.jpg");
2. SHARED PREFERENCES
2.1. Giới thiệu
- Shared Preferences là một dạng lưu trữ nhanh bằng file XML.
- SharedPreferences dùng lưu trữ dữ liệu dạng cơ bản.
- Chỉ hỗ trợ một số kiểu dữ liệu cơ bản : booleans, float, int, long, string.
- Hoạt động theo kiểu lưu trữ cũng như truy xuất thông qua cặp giá trị key/value.
- Dữ liệu vẫn được bảo toàn ngay cả khi ứng dụng bị đóng hoàn toàn.
- Các dữ liệu được lưu trữ và truy xuất qua từng phiên (Session) tương tác của ứng dụng
với người dùng.
- Lưu trữ và truy xuất trạng thái ứng dụng
2.2. Lưu trữ
- Sử dụng đối tượng của lớp SharedPreferences thông qua phương thức:
GetSharedPreferences(String, int);
- Tạo đối tượng SharedPreferences: sử dụng phương thức getSharedPreferences().
o Trong đó:
PREFS_NAME: tên của sharedPreference cần tạo
Mode: kiểu ghi dữ liệu
MODE_PRIVATE: mode ghi mặc định, chỉ có duy nhất ứng dụng tạo ra
tập tin được phép truy cập vào.
MODE_WORLD_READABLE: cho phép các ứng dụng khác truy cập
vào.
MODE_WORLD_WRITEABLE: cho phép các ứng dụng khác truy cập
và sửa đổi.
MODE_MULTI_PROCESS: cho phép nhiều tiến trình trên ứng dụng
cùng truy xuất vào cùng một thời điểm.
- Bổ sung thông tin cho đối tượng SharedPreferences: thông qua đối tượng Editor và
put<Type> tùy theo dữ liệu.
- Tạo đối tượng Editor từ phương thứ edit() của Preference.
- Các giá trị lưu trữ được truy xuất thông qua phương thức get<KDL>:
o getBoolean(Key, DefValue)
o getFloat(Key, DefValue)
o getInt(Key, DefValue)
o getLong(Key, DefValue)
o getString(Key, DefValue)
- Ví dụ:
SharedPreferences.Editor editor = sharedPre.edit();
editor.putBoolean(“isTrue”, true);
editor.putFloat(“lastFloat”, 1f);
editor.putInt(“number”, 2);
editor.putLong(“aNumber”, 3l);
editor.putString(“textEntryValue”, “Not Empty”);
//Sau cùng, để lưu SharedPreference dùng lệnh commit()
editor.commit();
- Lấy dữ liệu trong SharedPreferences(): sử dụng phương thức get<Type> tùy theo từng
loại dữ liệu.
boolean isTrue = sharedPre.getBoolean(“isTrue”, false);
float lastFloat = sharedPre.getFloat(“lastFloat”, 0f);
int number = sharedPre.getInt(“number”, 1);
long aNumber = sharedPre.getLong(“aNumber”, 0);
String stringPreference = sharedPre.getString(“textEntryValue”, “”);
- Giá trị mặc định: là giá trị sẽ được trả về mặc định khi get<Type> không trả về được
value thích hợp từ key truyền vào.
o Ví dụ:
//Nếu không tìm thấy giá trị tương ứng với từ khóa “number” truyền vào thì
Default Value là 1
int number = sharedPre.getInt(“number”, 1);
3. BỘ NHỚ THIẾT BỊ
3.1. Bộ lưu trữ trong
- Lưu dữ liệu riêng trên bộ nhớ thiết bị.
- Khi ứng dụng được cài đặt, hệ thống cung cấp 1 vùng bộ nhớ trong dành cho việc lưu
trữ dữ liệu cho mỗi ứng dụng riêng (sandbox).
- Khi người dùng gỡ bỏ ứng dụng, vùng bộ nhớ này sẽ được xóa.
- Chỉ có ứng dụng mới có thể truy xuất được bộ nhớ của ứng dụng đó.
- Ứ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ỉ lưu trữ:
/mnt/sdcard/Android/<package_name>/files
Bài 8
XÂY DỰNG GIAO DIỆN VỚI FRAGMENT
VẤN ĐỀ ACTIVITY VÀ FRAGMENT
1. NỆ N
1.1. r gment v phi n n h tr
- r gment đư c giới thiệu trong phiên b n Android 3.0 Honeycom , tuy nhi n do đư c
h tr trong gói Android Support Library nên ta có thể sử dụng trong các phiên b n từ
Android 1.6 trở lên.
- r gment l đối tư ng đư c nhúng trong Activity, cho phép thực hiện nhận tương tác,
có vòng đời riêng và thực hiện trao đổi thông tin với Activity và các Fragment khác.
- Yếu tố chính trong việc sử dụng Fragment là nó có thể giúp chúng ta xây dựng các giao
diện một cách chủ động và linh hoạt để có thể thích ứng với các kiểu màn hình có kích
thước khác nhau từ điện thoại cho đến máy tính b ng, nói chính xác hơn l tối ưu hó
giao diện cho từng loại thiết bị, kích thước v độ phân gi i.
Hình 8.1. Xây dựng giao diện ứng dụng trên điện thoại với Fragment.
- Tính linh động của Fragment cho phép chúng ta bố cục lại các phần giao diện của một
ứng dụng theo cách h p lý nhất.
Tài liệu Lập trình thiết bị di động trên Android – Module 2 | 100
Trung Tâm Tin Học Đại Học Khoa Học Tự Nhiên TP.HCM
Hình 8.2. Xây dựng giao diện ứng dụng trên máy tính bảng với Fragment.
- M i Fragment sẽ không bị bó buộc trong một Activity nhất định và có thể tái sử dụng
nhiều lần, giúp chủ động hơn trong việc xây dựng giao diện từ việc thêm hoặc xóa các
thành phần vào các cửa sổ khác nhau.
- Các lớp Fragment:
- Fragment
o ListFragment
o DialogFragment
o PreferenceFragment
o WebViewFragment
- Trong bộ Android SDK tích h p một số lớp con từ lớp r gment cho phép đóng gói v
thực thi một số r gment thường dùng. Ta có thể liệt kê một số lớp như s u:
- DialogFragment – Fragment cho phép thể hiện ở dạng hộp thoại trên Activity. Chúng ta
có thể thực hiện các tùy chỉnh về giao diện cho Fragment dạng này thông qua các
phương thức có sẵn trong lớp Fragment.
- ListFragment – dạng Fragment tích h p sẵn điều khiển ListView v các phương thức
dùng để thực kết nối dữ liệu.
- WebViewFragment – dùng để hiện các kết nối và hiển thị nội dung tr ng we tr n đối
tư ng WebView.
1.2. i o diện
- Để tạo mới đối tư ng Fragment ta cần tạo lớp kế thừa từ lớp Fragment, khai báo các
điều khiển và thực thi các chức năng.
- Hầu như khi l m việc với Fragment, ta cần tạo ra các giao diện cho nó bằng cách gắn
các điều khiển, tuy nhi n t cũng có thể cung cấp giao diện cho Fragment một cách trực
tiếp từ XML giống như t l m việc với Activity bằng phương thức setContentView().
- Các thuộc tính quan trọng:
Tài liệu Lập trình thiết bị di động trên Android – Module 2 | 101
Trung Tâm Tin Học Đại Học Khoa Học Tự Nhiên TP.HCM
Ở đây, t có thể dùng phương thức onCre teView() để thực hiện điều tương tự.
public class MyFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container,Bundle savedInstanceState) {
return inflater.inflate(R.layout.activity_main, container, false);
}
}
- Chúng ta hoàn có thể xây dựng giao diện trong mã J v thông qu đối tư ng
ViewGroup, tuy nhiên cách tốt hơn hết là dùng xây dựng tập tin giao diện XML và gán
vào Fragment.
- Không giống như Activity, r gment không cần ph i khai báo trong Manifest bởi vì
Fragment chỉ tồn tại khi nhúng nó vào một Activity v vòng đời sống cũng phụ thuộc
Activity này.
1.3. Vòng đời củ một r gment
Tài liệu Lập trình thiết bị di động trên Android – Module 2 | 102
Trung Tâm Tin Học Đại Học Khoa Học Tự Nhiên TP.HCM
- Vòng đời của một Fragment sẽ đư c qu n lý bởi các phương thức giống như một
Activity. Chúng cũng có các phương thức khởi tạo (created), bắt đầu thực thi (started),
phục hồi trạng thái (resumed), tạm dừng tương tác (p used), đóng (stopped) v hủy
(destroyed). Bên cạnh đó các phương thức đư c gọi thực thi lại từ lớp Activity sẽ đư c
dùng để cho biết việc kết nối và hủy kết nối r gment đến Activity, khởi tạo và hủy
khởi tạo các điều khiển trên Fragment, thông báo việc hoàn thành việc khởi tạo Activity
chứa Fragment. Có thể xem lư c đồ s o để hiểu thêm chi tiết.
- Hầu hết các phương thức n y đều khá giống so với các phương thức qu n lý vòng đời
củ Activity m t đã tìm hiểu trong chương 3. Chúng có v i trò chỉ định cách thức hoạt
động củ r gment v cách r gment đư c gắn vào một Activity.
- Vòng đời của một Fragment bắt đầu từ lúc chúng đư c gắn lên một Activity và kết thúc
khi đư c gỡ bỏ. Hai sự kiện này sẽ đư c giám sát bởi h i phương thức tương ứng là
onAttach và onDetach.
- Tất c phương thức qu n lý sẽ đư c gọi sau khi Fragment/Activity vào trạng thái tương
tác, tuy nhi n Phương thức onDetach có thể sẽ không đư c gọi lên nếu Activity chứa
Fragment bị hủy m chư ho n th nh vòng đời của nó.
- Phương thức onAtt ch đã đư c gọi l n trước khi giao diện r gment đư c khởi tạo,
trước c sự khởi tạo của Fragment và Activity chứ r gment. Thường thì phương thức
n y đư c dùng để tạo có tham chiếu đến Activity để chuẩn bị các khởi tạo xử lý khác.
- Việc tạo ra một Fr gment đư c thực hiện bởi phương thức onCreate và kết thúc bằng
phương thức onDestroy. Khi dùng trong Activity, chúng ta nên khởi tạo Fragment trong
onCreate của Activity.
1.4. Lưu trữ Fragment (BackStack)
- Việc lưu trữ Fragment bao gồm h i gi i đoạn:
o Lưu trữ trạng thái Fragment thông qua biến Bundle:
Truy xuất biến Bundle trong phương thức onSaveInstanceState
Truyền các thông tin cần lưu trữ vào biến Bundle
Tài liệu Lập trình thiết bị di động trên Android – Module 2 | 103
Trung Tâm Tin Học Đại Học Khoa Học Tự Nhiên TP.HCM
o Đư r gment v o St ck:
Thực hiện khai báo Fragment
Cho phép nhúng Fragment vào Activity
Dùng phương thức ddToB ckSt ck(String T g) trong đối tư ng qu n lý
r gment để đư r gment v o St ck.
Có thể truy xuất lại đối tư ng Fragment thông qua Tag, hoặc khi phím
“B ck” tr n thiết bị đư c nhấn.
2. ỰN N N
2.1. Thực hiện xây dựng Fragment:
- Khai báo lớp kế thừa từ lớp Fragment
o Gọi phương thức onCreateView thực hiện tạo giao diện cho Fragment.
o Ví dụ về tạo lớp Fragment và giao diện:
public class ImageFragment extends Fragment {
public View onCreateView(LayoutInflater inflater,ViewGroup parent, Bundle b )
{
View rootView = inflater.inflat(R.layout.fragment_main, null);
return rootView;
}
}
- Đối tư ng này sẽ cung cấp một số phương thức như th m, gỡ bỏ và cập nhật Fragment
vào Activity, qu n lý các phiên làm việc củ r gment…
- Các đơn gi n nhất để thêm một vào một Activity là khai báo thẻ fragment trong tập tin
giao diện củ Activity đó. r gment đư c xem như một đối tư ng View roup khi đư c
gắn v o trong L yout. Thường chúng ta sẽ sử dụng cách n y để định nghĩ một tập các
giao diện tĩnh cho các m n hình có kích cỡ khác nhau.
- Trong trường h p ta cần th y đổi giao diện dựa trên trạng thái của ứng dụng thì cách tốt
nhất ta nên sử dụng các giao diện động dựa trên FragmentTransaction.
Tài liệu Lập trình thiết bị di động trên Android – Module 2 | 104
Trung Tâm Tin Học Đại Học Khoa Học Tự Nhiên TP.HCM
Lớp FragmentTransaction h tr chúng ta trong việc thêm, gỡ bỏ hoặc thay thế các
Fragment trên Activity ngay khi ứng dụng đ ng thực thi. Dự v o các tương tác củ người
dùng mà ta có thể xây dựng các giao diện h p lý. Ngo i r , để giúp cho ứng dụng có thể
đáp ứng các tr i nghiệm người dùng, các chuyển hoạt cũng đư c sử dụng giữa các phiên
làm việc của Fragment Transaction và các Transaction sẽ đư c lưu trữ trong st ck để tái sử
dụng.
- M i phiên làm việc củ r gmentTr ns ction đư c khởi tạo bằng phương thức
beginTransaction. Các hoạt động của Fragment sẽ đư c định nghĩ ằng các phương
thức add, remove hoặc repl ce. S u đó chúng t có thể tùy chỉnh các chuyển hoạt hoặc
cách thức hoạt động trong st ck trước khi thực hiện phương thức commit để thêm
Tr ns ction v o h ng đ i.
- Ví dụ, để thực hiện thêm một Fragment mới đơn gi n ta chỉ cần chỉ định Fragment cần
th m v đối tư ng sẽ chứa Fragment này.
FragmentTransaction frTransaction = frManager.beginTransaction();
frTransaction.add(R.id.ui_container, new MyFragment());
frTransaction.commit()
- Đối với các phương thức remove và replace t cũng thực hiện tương tự.
- Để thực hiện các chuyển hoạt cho các Fragment trong một Transaction ta có 2 cách,
một l dùng phương thức setTransaction và truyền vào các tham số có sẵn trong lớp
FragmentTransaction. Ví dụ:
frTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
- Cách thứ hai là chúng ta sẽ sử dụng phương thức setCustomAnimations và thực hiện
tạo các chuyển hoạt ở các tập tin XML . Phương thức yêu cầu truyền vào hai tham số,
một d nh cho khi r gment đư c thêm vào và một cho r gment đư c gỡ bỏ. Ví dụ:
frTransaction.setCustomAnimations(android.R.animatior.fade_in,
android.R.animator.fade_out);
Tài liệu Lập trình thiết bị di động trên Android – Module 2 | 105
Trung Tâm Tin Học Đại Học Khoa Học Tự Nhiên TP.HCM
- Trong lớp Fragment h tr phương thức getActivity cho phép chúng có thể truy cập vào
các đối tư ng củ Activity m chúng đư c nhúng v o. Điều này giúp chúng ta có thể
lấy về các View mà ta cần tương tác ng y trong lớp Fragment. Ví dụ:
TextView textView = (TextView) getActivity().findViewById(R.id.fragEdit);
- Mặc dù chúng ta vẫn có dùng lớp r gmentM n ger để liên lạc giữa Fragment với
Activity nhưng cách tốt hơn l xây dựng một Interface mà ở đó Activity như một thành
phần trung gian và các Fragment sẽ không phụ thuộc v o Activity m nó đư c nhúng
v o. Thường thì chúng ta sẽ thực hiện tạo kết nối Interf ce trong phương thức onAttach
của Fragment. Có thể xem ví dụ s u để hiểu thêm.
o Xây dựng Interface
public interface OnNewItemAddedListener{
public void OnNewItemAdded(String newItem);
}
@Override
public void onAttach(Activity activity){
super.onAttach(activity);
try{
onNewItemAddedListener = (OnNewItemAddedListener) activity;
}catch(ClassCastException e){
Throw new ClassCastExeption(activity.toString() + “ must
implement onNewItemAddedListener.”);
}
}
@Override
public void onNewItemAdded(String newItem){
//Do Something with newItem
}
Tài liệu Lập trình thiết bị di động trên Android – Module 2 | 106
Trung Tâm Tin Học Đại Học Khoa Học Tự Nhiên TP.HCM
Mục lục
Bài 1: Tổng quan về Lập trình Android và môi trường phát triển ................................ 1
Tài liệu Lập trình thiết bị di động trên Android – Module 2 | 107
Trung Tâm Tin Học Đại Học Khoa Học Tự Nhiên TP.HCM
Bài 8: Xây dựng giao diện với Fragment – Vấn đề Activity và Fragment ..................... 100
Tài liệu Lập trình thiết bị di động trên Android – Module 2 | 108
TRUNG TÂM TIN HỌC - ĐẠI HỌC KHOA HỌC TỰ NHIÊN
TÀI LIỆU
Tháng 06/2015
Trung Tâm Tin Học Đại Học Khoa Học Tự Nhiên TP.HCM
Bài 1
LƢU TRỮ, TRUY VẤN
VÀ SẮP XẾP DỮ LIỆU VỚI SQLITE
- Với bộ thư viện được tích hợp sẵn SQLite sẽ giúp các lập trình viên có thể lưu trữ và
phục hồi dữ liệu bất cứ lúc nào. Tuy chỉ là phiên bản rút gọn nhưng SQLite có thể đáp
ứng được hầu hết các nhu cầu về xử lý dữ liệu. Tính linh động trong SQLite cũng giúp
ta thể kiểm soát được các thông tin dữ liệu.
- 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.
- SQLite hỗ trợ các kiểu dữ liệu : TEXT, INTEGER, REAL.
- Đường dẫn của cơ sở dữ liệu:
DATA/data/<PACKAGE_NAME>/databases/FILENAME
- Thể hiện dữ liệu ở dạng bảng quan hệ:
o Cột: thể hiện trường dữ liệu (hoặc thuộc tính dữ liệu).
o Dòng: một thể hiện dữ liệu.
- Mặc định mỗi ứng dụng sẽ được cấp phát một thư mục cho việc lưu trữ cơ sở dữ liệu và
nó chỉ có thể được dùng bởi ứng dụng đó. Nếu muốn chia sẻ dữ liệu dùng chung giữa
các ứng dụng ta có thể sử dụng Content Provider.
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int
newVersion) {
}
3.2. Mở Cơ sở dữ liệu
- Dùng cú pháp getReadableDatabase() và getWriteableDatabase() để trả về đối tượng
SQLiteDatabase cần sử dụng.
- SQLiteDatabase là đối tượng để truy cập cơ sở dữ liệu (Read và Write).
- SQLiteDatabase cung cấp phương thức insert(), update(), delete(), hoặc execSQL() cho
phép thực hiện truy xuất dữ liệu.
- Nếu cơ sở dữ liệu đã tồn tại thì lớp SQLiteOpenHelper sẽ không tạo thêm mà chỉ mở
kết nối đến cơ sở dữ liệu đó.
SELECT dùng để đọc thông tin từ cơ sở dữ liệu theo trường hợp quy định
hay những biểu thức cho trường hợp đó.
FROM chỉ ra tên một bảng hay những bảng có liên quan cần truy vấn
thông tin.
WHERE để tạo nên điều kiện cần lọc mẩu tin theo tiêu chuẩn được định
nghĩa. Thông thường, WHERE dùng cột (trường) để so sánh với giá trị
cột khác, hay biểu thức chứa cột (trường) bất kỳ có trong bảng (table).
4.2. Quản lý
- Lớp SQLiteDatabase cung cấp các phương thức như: insert(), update(), delete() hoặc
execSQL() cho phép người dùng có thể quản lý và truy xuất dữ liệu.
4.2.1. Insert
- Tạo một dòng mới để insert dữ liệu:
ContentValues newValues = new ContentValues();
- Gán giá trị vào mỗi cột trong dòng vừa tạo:
newValues.put(COLUMN_NAME,values);
- Ví dụ:
newValues.put(COL_EN_NAME, “Germany”);
newValues.put(COL_VI_NAME, “Đức”);
//Thêm dòng đó vào database
database.insert(TABLE_NAME, null, newValues);
4.2.2. Update
- Tạo một dòng mới để update dữ liệu:
ContentValues newValues = new ContentValues();
- Gán giá trị vào mỗi cột trong dòng vừa tạo:
newValues.put(COLUMN_NAME, values);
- Ví dụ:
newValues.put(COL_EN_NAME,”Germany2”);
o Cập nhật lại dòng vừa tạo với đúng mệnh đề WHERE:
String where = “_id=” + rowId;
database.update(TABLE_NAME, newValues, where, null);
4.2.3. Delete
- Sử dụng câu truy vấn delete truyền vào tên bảng và chỉ số của hàng cần xóa trong mệnh
đề WHERE.
- Nếu mệnh đề WHERE không có sẽ thực hiện xóa tất cả các dòng:
database.delete(TABLE_NAME, “_id=” + rowID, null);
- Ví dụ:
o Truy vấn với câu lệnh SQL:
SELECT * FROM COUNTRY ORDER BY enName DESC
o Gom nhóm các bài hát có MaSo lớn hơn 55500 bằng cú pháp GROUP BY và
mệnh đề HAVING với cú pháp:
SELECT column1, column2
FROM table1, table2
WHERE [ conditions ]
GROUP BY column1, column2
HAVING [ conditions ]
o Kết quả:
Bài 2
QUẢN LÝ DỮ LIỆU
VỚI CONTENT PROVIDER
Android cung cấp một số các gói Content Provider dùng cho việc lưu trữ chung như
- Browser.
- CallLog.
- Contact (people, phones, photos, group ).
- MediaStore (music, video, image).
- Setting.
Cần khai báo trong file AndroidManifest.xml cho biết ứng dụng sử dụng những Content
Provider nào.
<provider
android:name= “SomeProvider”
android:authorities= “com.your-company.SomeProvider”>
<provider
android:name= “NotePadProvider”
android:authorities= “com.your-company.NodePad”>
Ví dụ truy xuất dữ liệu danh bạ trên thiết bị có tên bắt đầu bằng “M” và sắp xếp theo theo ID.
- Phương thức Insert, Update được thực hiện thông qua tham số dữ liệu ContentValues:
o ContentValues: cho phép định nghĩa dữ liệu khi thao tác, thông qua phương thức
put(Key, Value).
o Trong đó
Key tên trường dữ liệu (cột). - String
Value: dữ liệu tương ứng với trường dữ liệu – String, Float, Long…
- Phương thức Insert:
Cú pháp:
o insert(Uri, ContentValues)
Uri đường dẫn truy xuất dữ liệu. – URI.
ContentValues: dữ liệu cần thêm vào. - ContentValues.
Kết quả trả về:
o URI đường dẫn đến dữ liệu vừa thêm vào.
- Phương thức Update:
Cú pháp:
o update(Uri, ContentValues, where, selectionArgs)
Uri đường dẫn truy xuất dữ liệu. – URI.
ContentValues: dữ liệu cần cập nhật. – ContentValues.
Where điều kiện dữ liệu được cập nhật. – String.
SelectionArgs: mảng tham số cho câu điều kiện. – String[].
Kết quả trả về:
o int: số lượng dòng dữ liệu đã được cập nhật.
- Phương thức Delete:
Cú pháp:
o delete(Uri, ContentValues, where, selectionArgs)
Uri đường dẫn truy xuất dữ liệu. – URI.
Where điều kiện dữ liệu được xóa. – String.
SelectionArgs: mảng tham số cho câu điều kiện. – String[].
Kết quả trả về:
o int: số lượng dòng dữ liệu đã được xóa.
2.
2.1. Vấn đề xây dựng ContentProvider
- Việc sử dụng ContentProvider trong ứng dụng khi cần xây dựng những tính năng sau
o Cung cấp các dữ liệu hoặc tập tin đặc trưng, phức tạp cho những ứng dụng khác.
o Cho phép người dùng sao chép các dữ liệu vào các ứng dụng khác.
o Sử dụng và tùy chỉnh tính năng tìm kiếm dữ liệu trong ứng dụng.
- Thực hiện xây dựng ContentProvider:
o Xây dựng dữ liệu:
Dữ liệu tập tin (not recommended).
- Một số các phương thức để điều khiển Cursor thao tác trên dữ liệu:
o movetoFisrt(): trở về hàng đầu, false nếu cursors rỗng.
o movetoNext(): chuyển đến hàng tiếp theo, false nếu đang ở hàng cuối cùng.
o movetoPrevious(): chuyển đến hàng trước đó, false nếu đang ở đầu.
o movetoPosition(int position): chuyển đến vị trí xác định, false nếu vị trí không
thể tới.
o getColumnName(int columnIndex): trả về tên cột nếu biết chỉ số cột.
o getColumnIndex(String columnName): trả về chỉ số cột nếu biết tên cột.
o moveToLast(): chuyển đến vị trí cuối cùng, false nếu danh sách rỗng.
o getString(int columnIndex): lấy giá trị ở cột có chỉ số truyền vào.
o Ngoài ra thì còn một số hàm kiểm tra khác như boolean isAfterLast(),
isBeforeFirst(), isNull(columnIndex) …
Ví dụ:
if(cursor.moveToFirst() == false){
//không có dữ liệu
return;
}
//Cursor đã ở dòng dữ liệu đầu tiên.
//Thử truy xuất vào một cột nào đó để lấy dữ liệu
int columnIndex = cursor.getColumnIndex(People.NAME);
Bài 3
MENU - ACTION BAR – TOOLBAR
1. MENU
Menu là dạng Widget chứa các chức năng phụ hoặc các tùy chỉnh dành riêng cho từng ứng
dụng. Bao gồm các dạng cơ bản:
1.1. Option Menu
- Là menu chính trong ứng dụng chứa các thao tác cơ bản cho một ứng dụng được gọi
khi người dùng nhấn phím Menu.
- Từ phiên bản Android 2.3 trở xuống, thao tác gọi Menu được thực hiện bằng phím
Menu trên thiết bị.
- Từ phiên bản Android 3.0 trở đi, Option Menu được tích hợp vào thanh Action Bar.
o Tạo Menu từ trong tập tin XML:
<menu
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:showAsAction="ifRoom "
android:title="@string/action_settings"/>
<item
android:id="@+id/action_help"
android:title="@string/action_help"/>
</menu>
o Contextual Action Mode (API level 11): một thanh công cụ hiển thị phía trên ứng
dụng, nó cho phép người thực hiện nhiều thao tác khác nhau trên Item được lựa
chọn, hoặc thực hiện một thao tác trên nhiều Item nếu ứng dụng có hỗ trợ.
o Xử lý sự kiện trên Floating Context Menu bằng cách override phương thức
oncontextItemSelected()
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_share:
//Các hàm xử lý
return true;
default:
return false;
}
}
o Gọi thực hiện hàm setOnLongClickListener() nếu người dùng nhấn và giữ lâu
trên đối tượng nào đó (someView).
someView.setOnLongClickListener(new View.OnLongClickListener() {
// Called when the user long-clicks on someView
public boolean onLongClick(View view) {
if (mActionMode != null) {
return false;
}
mActionMode=
this.getActivity().startActionMode(mActionModeCallback);
view.setSelected(true);
return true;
}
});
listView.setMultiChoiceModeListener(new
MultiChoiceModeListener().
{
@Override
public boolean onActionItemClicked(ActionMode mode,
MenuItem item) {
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu
menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context, menu);
return true;
}
});
popup.show(); }
case R.id.vibrate:
case R.id.dont_vibrate:
if (item.isChecked())
item.setChecked(false);
else item.setChecked(true);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
2. ACTION BAR
2.1. Giới thiệu
Trong lần đầu giới thiệu chiếc Samsung Galaxy Nexus, Google đã loại bỏ nút Menu ra khỏi
cụm phím điều hướng chính của hệ thống, chỉ còn lại nút Quay về (Back), nút trở về màn hình
chính (Home) và nút liệt kê các ứng dụng đã chạy gần đây (Recents Apps). Nó biến thành một
thứ gọi là "Action Bar", nơi mà người dùng có thể khởi chạy các hoạt động tùy thuộc vào ứng
dụng.
- Action Bar có chức năng:
o Điều hướng giao diện ứng dụng.
o Hiển thị các thao tác trên toàn bộ hệ thống ứng dụng hoặc thao tác tại màn hình
hiển thị (tìm kiếm, chỉnh sửa, xóa…).
o Thao tác chuyển đến các giao diện khác nhau trong cùng một màn hình hiển thị
(tabhost, list navigation…).
- Những tính năng nào không thể hiện hết thì sẽ nằm trong dấu ba chấm dạng dọc ở cuối
Action Bar, gọi là Action Overflow.
- ActionBar có từ phiên bản Android 3.0 (API level 11).
- Các tổ hợp điều khiển trên ActionBar:
o App Icon: thường là logo của ứng dụng hoặc bất kỳ Icon nào mà bạn muốn.
o View Control: thường hiển thị Title cho nội dung màn hình hiện tại, có thể tùy
chỉnh thành một Spinner.
o Action Button: chứa một số Button để thực hiện chức năng quan trọng.
o Action Overflow: Chứa một Menu Dropdown các chức năng hiển thị.
android:id="@+id/action_check_updates"
android:icon="@drawable/ic_action_refresh"
android:showAsAction="ifRoom"
android:title="@string/action_check_updates"/>
</menu>
- Đối với mỗi thẻ item sẽ có một số thuộc tính quan trọng sau:
o android:id - id của Action Button.
o android:icon - icon hiển thị cho chức năng.
o android:title - tiêu đề cho chức năng.
o android:showAsAction - Xác định việc hiển thị cho Action Button.
- Tiếp tục, mở MainActivity ra và thực hiện kéo tập tin Menu vừa tạo vào cho ứng dụng.
Chúng ta sẽ thực hiện việc này trong phương thức onCreateOptionsMenu():
public booleanonCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar
if it is
present.
getMenuInflater().inflate(R.menu.action_bar_menu, menu);
return true;
}
case R.id.action_location_found:
LocationFound();
return true;
case R.id.action_help:
return true;
case R.id.action_refresh:
return true;
case R.id.action_check_updates:
return true;
default:
return true;
}
}
- Tiếp theo, chúng ta tìm hiểu việc hiển thị và ẩn thành Action Bar. Có 2 phương thức rất
đơn giản, đó là hide() và show()
actionBar.show();
actionBar.hide();
- Lưu ý: ứng dụng sử dụng việc hiển thị - giấu ActionBar liên tục có thể thay thế bằng
chế độ Overlay trên Android 4.3 và 4.4.
- Thay đổi App Icon cho Action Bar. Chúng ta sử dụng phương thức setIcon() để thay
đổi App Icon trên Action Bar
actionBar.setIcon(R.drawable.ico_actionbar);
- SplitActionBar: cơ chế cho phép hiển thị ActionBar ở dạng chia đôi khi có nhiều item.
o Sử dụng:
Khai báo thuộc tính uiOptions="splitActionBarWhenNarrow“ trong thẻ
<activity>.
o Ví dụ khai báo cho SplitActionBar cho các phiên bản cũ hơn: Cần khai báo thêm
thẻ <meta-data>
<manifest ...>
<activity uiOptions="splitActionBarWhenNarrow" ... >
<meta-data android:name="android.support.UI_OPTIONS"
android:value="splitActionBarWhenNarrow" />
</activity>
</manifest>
- Navigation Up Icon: chế độ hiển thị và tương tác với biểu tượng ActionBar cho phép
người dùng có thể quay về màn hình trước đó ứng dụng (tùy thuộc ngữ cảnh).
o Sử dụng: khai báo thông qua phương thức setDisplayHomeAsUpEnable()
o Ví dụ:
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
o Navigation Up Icon:
Khai báo sử dụng trong AndroidManifest.xml
Ví dụ:
<activity
android:name=“com.htsi.t3h.SecondActivity"
android:label="@string/title_activity_display_message“
android:parentActivityName="com.htsi.t3h.MainActivity”>
</activity>
tab = actionBar.newTab()
.setText(R.string.album)
.setTabListener(new
TabListener<AlbumFragment>(
this, "album", AlbumFragment.class));
actionBar.addTab(tab);
o List:
Dữ liệu màn hình có thể bao gồm nhiều trang hoặc chế độ hiển thị, mỗi
chế độ được chọn lựa từ Spinner thiết lập trên ActionBar.
android.R.layout.simple_spinner_dropdown_item);
// OnNavigationListner
OnNavigationListner mNavigationCallback= new
OnNavigationListener() {…}
// Thiết lập Adapter và lắng nghe sự kiện
actionBar.setListNavigationCallbacks(mSpinnerAdapter,
mNavigationCallback);
4. TOOLBAR
4.1. Giới thiệu
Từ phiên bản API 21 (Android 5.0 Lollipop), Android hỗ trợ Toolbar để thay thế ActionBar.
Toolbar được xem là bản cải tiến của ActionBar và được kết thừa từ ViewGroup, vẫn có thể
dùng một số thuộc tính hay phương thức của ActionBar như thêm Logo, Labels, Navigation
items… và có bổ sung thêm các phương thức để giúp thay đổi màu, tùy chỉnh kích thước hay
có thể thiết lập bất kỳ vị trí hiển thị trên giao diện… Có thể thiết lập hiển thị Toolbar cho
Activity nào đó bằng phương thức “setActionBar()”.
Toolbar cùng lúc có thể chứa các yếu tố sau:
- A Navigation Button. Nó có thể là Up arrow, navigation menu toggle, close, collapse,
done hay một số hình ảnh mà bạn tự thiết kế.
- A branded logo image. Có thể thiết lập chiều cao cho logo, thiết lập khoảng cách tùy ý.
- A title and subtitle. Thiết lập tiêu đề cho Toolbar, nhưng có thể nó sẽ bị che lấp khi ta
thiết lập logo quá lớn.
- One or more custom views. Có thể thiết lập một hoặc nhiều View do chúng ta tùy
chình. Để thiết lập vị trí hiển thị chúng ta cần thông qua lớp “Toolbar.LayoutParams”,
chẳng hạn như canh giữa theo chiều ngang thì chúng ta dùng biến cờ
CENTER_HORIZONTAL thông qua Gravity, vị trí được canh giữa trên không gian
trống còn lại (tức là nếu chúng ta đã thiết lập logo cho Toolbar rồi thì không đối tượng
View mà ta thêm vào thì sẽ nằm ở vị trí trống còn lại và được canh giữa theo chiều
ngang).
- An action menu. Cũng giống như thanh ActionBar, “menu” sẽ mằm ở vị trí cuối của
Toolbar.
Đến file xml để thêm Toolbar cho giao diện. Chúng ta nên thêm vào giao diện khi
chúng ta cần. Vì Toolbar là một ViewGroup nên có thể thêm ở các ViewGroup và có
thể thiết lập các thuộc tính ID, color, width và height. Chúng ta có thể thêm thuộc tính
margins (left và right) bằng cách dùng contentInsetEnd và contentInsetStart.
<Android.support.v7.widget.Toolbar
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:id="@+id/toolbar"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:background="#ff696969"
app:contentInsetEnd="0dp"
app:contentInsetStart="0dp"
></Android.support.v7.widget.Toolbar>
<item android:id="@+id/action_search"
android:title="@string/action_search"
android:icon="@drawable/ic_search"
android:showAsAction="ifRoom" />
<item android:id="@+id/action_share"
android:title="@string/action_share"
android:icon="@drawable/ic_share"
android:showAsAction="ifRoom" />
<item android:id="@+id/action_settings"
android:title="@string/action_settings"
android:orderInCategory="100"
android:showAsAction="never" />
</menu>
Bắt lại sự kiện khi người dùng tương tác lên các item của menu.
toolbar.setOnMenuItemClickListener(new
Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()){
case R.id.action_share:
Toast.makeText(MainActivity.this,
"Share",
Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
});
View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"Navigation",Toast.LENGTH_SHORT)
.show();
}
});
Bài 4
ACTION PROVIDER
VÀ ĐIỀU KHIỂN TÌM KIẾM
1. ACTION PROVIDER
- ActionProvider (API Level 14) là một dạng menu được đính kèm để chúng ta có thể
thao tác nhanh ngay trên ActionBar. Trong trường hợp cụ thể, chúng ta sẽ nghiên cứu
về ShareActionProvider – một dạng menu chia sẻ rất tiện lợi.
- ShareActionProvider có từ API level 14.
- Để tạo ra một ShareActionProvider chúng ta chỉ việc khai báo thuộc tính
android:actionProviderClass trong cặp thẻ <item> của file tài nguyên menu.
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_item_share"
android:showAsAction="ifRoom"
android:title="Share"
android:actionProviderClass=
"android.widget.ShareActionProvider" />
</menu>
(ShareActionProvider)item.getActionProvider();
Ví dụ sau đây sẽ hướng dẫn chi tiết về ứng dụng của điều khiển tìm kiếm này.
- Thực hiện kéo ListView vào tập tin activity_main.xml:
<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"
tools:context=".MainActivity" >
<ListView
android:id="@+id/listCountries"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >
</ListView>
</RelativeLayout>
- Sau đó trong thư mục res/menu tạo tập tin search_view.xml thực hiện khai báo như sau:
- Cho lớp MainActivity thực thi giao diện onQueryTextListener và tiến hành khai báo
các biến cần thiết.
- Trong hàm onCreate thực hiện khởi tạo và tham chiếu giá trị cho các biến đã khai báo ở
trên:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, COUNTRIES);
mListView = (ListView)
findViewById(R.id.listCountries);
mListView.setAdapter(adapter);
}
- Cuối cùng thực thi hai phương thức truy vấn dữ liệu khi người dùng nhập váo khung
SeachView, ở đây đơn giản ta gọi phương thức filter để Adapter tự sắp xếp dữ liệu.
@Override
public boolean onQueryTextChange(String newText) {
//Instant Search
if (TextUtils.isEmpty(newText)) {
adapter.getFilter().filter("");
mListView.clearTextFilter();
}else {
adapter.getFilter().filter(newText.toString());
}
return true;
}
- Thực hiện chạy ứng dụng: bấm vào biểu tượng tìm kiếm, một EditText sẽ xuất hiện,
tiến hành nhập liệu. Và ListView sẽ tự động tìm kiếm và sắp xếp dữ liệu cho chúng ta.
Hình 1.3. Hiển thị kết quả tìm kiếm với SearchView.
Bài 5
CÁC CHUYỂN HOẠT
TRONG ỨNG DỤNG
1. PROPERTY ANIMATION
- Property Animation là dạng chuyển hoạt hổ trợ chúng ta trong việc lập trình các chuyển
hoạt cho các thuộc tính của một đối tượng nào đó bằng các thay đổi 2 giá trị 0 và 1. Ví
dụ, khi ta có thể thay đổi màu sắc, độ trong suốt để làm hiệu ứng xuất hiện và biến mất
của đối tượng, hoặc thay đổi các kích thước dòng chữ chẳng hạn.
- Được giới thiệu từ phiên bản Android 3.0 (API 11) có thể nói đây là bộ công cụ mạnh
mẽ trong việc lập trình chuyển hoạt bởi vì chúng ta có thể ứng dụng nó vào bất kỳ
thuộc tính nào chúng ta muốn.
- Mỗi chuyển hoạt sẽ được chứa trong một tập tin XML riêng biệt trong thư mục
res/animator. Giống như Layout và Drawable, tên của tập tin sẽ được sử dụng làm định
danh cho chuyển hoạt đó. Việc định nghĩa các chuyển hoạt chỉ đơn giản là gán một giá
trị cho một thuộc tính nào đó, sau đó cấp phát cho đối tượng thực hiện chuyển hoạt đó.
-
R.animator.alpha_anim);
animOb.setTarget(txtHello);
animOb.start();
2. VIEW ANIMATION
2.1. Tween Animation
- Mỗi chuyển hoạt được chứa trong tập tin XML trong thư mục res/anim với các hiệu
ứng sau: alpha (ẩn hiện mờ), scale (cân chỉnh tỉ lệ), translate (chuyển động) và rotate
(quay góc). Mỗi hiệu ứng bao gồm các cặp thuộc tính và giá trị như bảng sau:
- Chúng ta có thể sử dụng cặp thẻ set để thiết lập nhiều hiệu ứng với nhau. Khi đó, các
hiệu ứng sẽ được bổ sung các một số thuộc tính để chỉnh sửa thời điểm và cách thức
mỗi hiệu ứng sẽ thực thi. Danh sách các thuộc tính như sau:
o duration – thời gian thực thi tất cả hiệu ứng, tính bằng mili giây.
o startOffset – độ trễ trước khi hiệu ứng bắt đầu.
o fillBeforetrue – cho phép biến đổi các hiệu ứng trước khi thực thi chuyển hoạt.
o fillAftertrue – cho phép biến đổi các hiệu ứng sau khi kết thúc chuyển hoạt.
o interpolator – thiết lập tốc độ của hiệu ứng thay đổi theo thời gian, để sử dụng
thuộc tính này ta sẽ tham chiếu đến tài nguyên chuyển hoạt của hệ thống
android:anim/interpolatorName.
- Nếu không thiết lập thuộc tính startOffset, tất cả hiệu ứng sẽ cùng thực thi đồng bộ với
nhau.
Ví dụ sau sẽ mô tả chuyển hoạt quay đối tượng một góc 360 độ, rung và mờ dần:
- Tạo file shrink_anim.xml trong thư mục res/anim:
<?xml version="1.0" encoding="utf-8"?>
<set android:interpolator="@android:anim/accelerate_interpolator"
xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="0%"
android:startOffset="500"
android:duration="1000"/>
<scale
android:fromXScale="1.0"
android:toXScale="0.0"
android:fromYScale="1.0"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="500"
android:duration="500" />
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:startOffset="500"
android:duration="500" />
</set>
<item android:drawable="@drawable/shark2"
android:duration="250"></item>
<item android:drawable="@drawable/shark3"
android:duration="250"></item>
<item android:drawable="@drawable/shark4"
android:duration="250"></item>
<item android:drawable="@drawable/shark5"
android:duration="250"></item>
<item android:drawable="@drawable/shark6"
android:duration="250"></item>
<item android:drawable="@drawable/shark7"
android:duration="250"></item>
<item android:drawable="@drawable/shark8"
android:duration="250"></item>
<item android:drawable="@drawable/shark9"
android:duration="250"></item>
</animation-list>
3. DRAWABLE ANIMATION
- Thư mục tài nguyên: res/drawable/filename.xml.
o Khai báo các thuộc tính trong XML:
AnimationDrawable - <animation-list>
<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot=["true" | "false"] >
<item
android:drawable="@[package:]drawabledrawable_resource_name"
android:duration="integer" />
</animation-list>
Bài 6
ASYNCTASK - THREAD – HANDLER
1. THREAD VÀ MULTITHREADING
1.1. Thread
Trong lập trình ứng dụng cho di động, một trong những vấn đề quan trọng cần giải quyết đó là
tài nguyên hạn hẹp của các thiết bị động. Các thiết bị di động hầu hết có tài nguyên rất hạn
chế, ngày nay tuy đã được cải thiện rất nhiều (nâng cấp CPU, GPU, RAM…), nhưng nhìn
chung lại, không thế chạy ứng dụng trên các thiết bị di động như trên PC, laptop… Do đó, việc
xử lí các thuật toán cần phải tinh giản và thực hiện một cách nhanh nhất có thể để có thể tiết
kiệm được chi phí tài nguyên.
Thread là đơn vị nhỏ nhất của tiến trình được định thời bởi hệ điều hành và được bao hàm
trong các tiến trình thực thi của máy tính. Mỗi một thread có một callstack cho các phương
thức, đối số và biến cục bộ của thread đó.
Android chạy trên một hệ điều hành nhân Linux. Các ứng dụng của Android được viết bằng
ngôn ngữ Java, và chúng chạy trong một máy ảo, đó không phải máy ảo Java(JVM) mà là máy
ảo Dalvik (Dalvik Virtual Machine). Mỗi một máy ảo Android khi chạy đều có ít nhất một
thread chính khi khởi động và có thể còn vài thread khác dùng để quản lý các tiến trình đang
chạy. Ứng dụng có thể tự khởi động thêm các thread phụ vào các mục đích cụ thể. Các thread
trong cùng một máy ảo tác động qua lại và được đồng bộ hóa bằng cách sử dụng các đối tượng
chia sẻ và các monitor liên quan đến các đối tượng đó.
- Mỗi Thread có một độ ưu tiên (số nguyên từ 1 - 10) dùng để xác định lượng thời gian
CPU (CPU time ) mà thread có thể sử dụng dựa vào phương thức setPriority(int).
- Các phương thức của Thread như sleep(), wait() , notify() và notifyAll()…
- Để tạo ra một thread khác ngoài thread chính trên, chúng ta có 2 cách:
o Cách 1:
Tạo 1 lớp mới kế thừa từ lớp java.lang.Thread và ghi đè lại phương thức
run() của lớp này:
public class MyThread extends Thread{
@Override
public void run() {
//do something }}
Sử dụng Thread:
MyThread t = new MyThread();
t.start();
o Cách 2:
Tạo 1 lớp và cho lớp này implement Interface Runnable:
public class MyRunnable implements Runnable{
@Override
public void run() {
//xử lý
}
}
Sử dụng thread:
MyRunnable b = new MyRunnable();
MyThread t = new MyThread(b);
t.start();
1.2. Multithreading
- Multithreading có nghĩa là đa luồng, nhiều thread. Với cơ chế đa luồng, các ứng dụng
của bạn có thể thực thi đồng thời nhiều dòng lệnh cùng lúc. Có nghĩa là bạn có thể làm
nhiều công việc đồng thời trong cùng một ứng dụng của bạn. Có thể hiểu một cách đơn
giản: hệ điều hành với cơ chế đa nhiệm cho phép nhiều ứng dụng chạy cùng lúc thì ứng
dụng với cơ chế đa luồng cho phép thực hiện nhiều công việc cùng lúc.
- Ưu điểm của việc sử dụng Multithreading:
o Các thread chia sẻ tài nguyên của tiến trình nhưng vẫn có thể được thực thi một
cách độc lập. Multi-thread sẽ rất hữu dụng khi dùng lập trình đa nhiệm.
o Các ứng dụng Multi-thread chạy nhanh hơn trên các máy tính hỗ trợ xử lý đa
luồng.
- Nhược điểm:
o Khó khăn trong việc lập trình, việc sử dụng multithreading không hề dễ dàng,
đòi hỏi lập trình viên có kinh nghiệm.
o Khó khăn trong việc quản lí.
o Có khả năng tiềm tàng xảy ra tình trang deadlock.
1.3. Handler
- Handler là đối tượng cho phép gửi, xử lí các thông điệp và các đối tương Runable có
liên quan đến hàng đợi thông điệp. Mỗi Handler có thể liên kết với một thread và hàng
đợi thông điệp của thread đó.
- Bạn có thể tạo ra một thread của riêng bạn và giao tiếp ngược với main thread của ứng
dụng thông qua một Handler. Điều này được thực hiện bằng cách gọi sendMessage
nhưng từ thread mới của bạn.
- Tạo một đối tượng Handler và ghi đè lại phương thức handleMessage để bắt và xử lý
các thông điệp liên lạc.
Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
//Kiểm tra message
if(msg != null){
//Xử lý message nhận được từ Thread
}
return true;
}
});
- Thread sẽ gửi tin nhắn lên Handler và Handler đóng vai trò kiểm tra tin nhắn là gì và
làm những việc tương ứng.
- Ta chú ý các phương thức sendMessage sau:
o sendMessage(): gửi tin nhắn lên Handler ngay lập tức.
o sendMessageAtFrontOfQueue(): gửi tin nhắn lên Handler và tin nhắn đó sẽ ưu
tiên giải quyết trước.
o sendMessageAtTime(): gửi tin nhắn vào thời điểm chỉ định trước.
o sendMessageDelayed(): gửi tin nhắn vào Handler sau một khoảng thời gian nhất
định.
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
Message mss = new Message();
mss.arg1 = 1;
handler.sendMessage(mss);
}
});
t1.start();
2. ASYNCTASK
- AsyncTask là đối tượng cho phép bạn thực hiện hành động xử lý phía background
(Thread ngầm) và trả kết quả lên UI thread (Thread chính) mà không cần phải xử lý
Thread hoặc Handler.
- Khi ứng dụng của bạn thực hiện một tác vụ dài, chiếm một khoảng thời gian nhất định.
Ví dụ như khi click nút Login, ứng dụng phải gửi request lên server để xử lý và trả kết
quả về. Nếu làm theo kiểu bình thường thì ứng dụng của bạn sẽ có cảm giác bị treo và
chậm, gây ảnh hưởng đến trải nghiệm người dùng. Trong tình huống này, để giải quyết
vấn đề chúng ta có thể sử dụng AsyncTask.
- Trong AsyncTask<Params, Progress, Result> có 3 đối số là các Generic Type:
o Params: Là giá trị (biến) được truyền vào khi gọi thực thi tiến trình và nó
sẽ được truyền vào doInBackground.
o Progress: Là giá trị (biến) dùng để update giao diện diện lúc tiến trình thực thi,
biến này sẽ được truyền vào hàm onProgressUpdate.
o Result: Là biến dùng để lưu trữ kết quả trả về sau khi tiến trình thực hiện xong.
Những đối số nào không sử dụng trong quá trình thực thi tiến trình thì ta
thay bằng kiểu Void.
- Thông thường trong một AsyncTask sẽ chứa 4 hàm, đó là :
o onPreExecute(): Tự động được gọi đầu tiên khi tiến trình được kích hoạt.
o doInBackground(): Được thực thi trong quá trình tiến trình chạy nền, thông qua
hàm này để ta gọi hàm onProgressUpdate để cập nhật giao diện (gọi
lệnh publishProgress). Ta không thể cập nhật giao diện trong
hàm doInBackground().
o onProgressUpdate(): Dùng để cập nhật giao diện lúc runtime.
o onPostExecute(): Sau khi tiến trình kết thúc thì hàm này sẽ tự động xảy ra. Ta có
thể lấy được kết quả trả về sau khi thực hiện tiến trình kết thúc ở đây.
Hình 1.1. Thứ tự hoạt động của các hàm trong AsyncTask.
Ví dụ:
@Override
protected void onPreExecute() {
super.onPreExecute();
startMillis = System.currentTimeMillis();
Log.d("Test", "onPreExecute");
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
Log.d("Test", "Công việc đang làm..." + values[0]);
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
Log.d("Test", "Thời gian kết thúc: "
+ (System.currentTimeMillis()-startMillis)/1000
+ " giây");
Log.d("Test", "Công việc hoàn thành.");
}
@Override
protected Void doInBackground(String... arg0) {
Log.d("Test", "doInBackground");
for (int i = 0; i < 3; i++) {
try {
Thread.sleep(2000);
publishProgress(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
}
- Lưu ý:
o Đối tượng của AsyncTask chỉ được dùng trong UI thread (Thread chính của ứng
dụng).
o Các phương thúc onPostExecute, onPreExecute, onProgressUpdate chỉ là tùy
chọn.
Bài 7
SERVICE – BROADCAST RECEIVER
VÀ NOTIFICATION
1. SERVICE
1.1. Giới thiệu
- Service được xem như một thành phần chạy ngầm phía bên dưới và hầu như không cần
giao diện để tương tác với người dùng, có thể ví dụ một số tác vụ tiêu tốn nhiều thời
gian như truy xuất, cập nhật dữ liệu, nhận và xử lý các thông báo người dùng, …
- Service giống như Activity thực hiện theo chu kỳ thời gian để quản lý sự thay đổi của
trạng thái.
- Trong AndroidManifest.xml cần phải khai báo:
<service android:name="com.your-company.MyService" />
trong cặp thẻ <application>
- Service chạy trên Main Thread nên có thể gây cản trở các tác vụ khác.
- Có 2 loại Service:
o “Started” Service: Service được gọi khi thành phần của ứng dụng gọi nó bằng
phương thức startService(). Và service sẽ chạy vô thời hạn. Loại service này
thực hiện công việc đơn lẻ như download, tính toán và service sẽ dừng một khi
công việc hòan thành.
o “Bound” Service: Service được gọi khi thành phần của ứng dụng gọi nó bằng
phương thức bindService(). Loại service đề nghị giao diện Client – Server cho
phép thành phần ứng dụng tương tác với nó, gửi yêu cầu, lấy kết quả. Một khi tất
cả thành phần ứng dụng ngừng liên kết, thì Service kết thúc .
- Vòng đời:
}
}
//Viết phương thức cho các client có thể gọi.
public int cong2So(int a, int b){
return a + b ;
}
}
- Trong MainActivity khai báo biến, khởi tạo các đối tượng giao diện:
Hình 1.2. Màn hình ứng dụng gọi Service cộng 2 số.
setContentView(R.layout.activity_main);
txtResult = (TextView) findViewById(R.id.txtResult);
btnCallService = (Button)
findViewById(R.id.btnCallService);
btnCallService.setOnClickListener(this);
}
}
- Tạo một đối tượng ServiceConnection chuyên dùng quản lý việc đóng mở kết nối đến
Service. Overide 2 phương thức onServiceDisconnected() và onServiceConnected() sau
nhằm bound đến MyService:
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
mBound = false;
}
@Override
public void onServiceConnected(ComponentName name, IBinder
service) {
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
};
- Trong hàm OnStart(): chúng ta dùng phương thức bindService(parameter) để gọi đến
MyService thông qua đối tượng Intent:
@Override
protected void onStart() {
super.onStart();
Intent i = new Intent(this, MyService.class);
bindService(i, mConnection, Context.BIND_AUTO_CREATE);
}
- Cuối cùng trong phương thức onClick của button ta gọi đến hàm cong2so(int,int) và
hiển thị kết quả trả về ra TextView:
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnCallService:
if(mBound){
//Cho service cộng 2 số 5 5
int result = mService.cong2So(5, 5);
txtResult.setText(String.valueOf(result));}
break;
default: break;
}
}
1.3. IntentService
- IntentService, đây là Service chạy độc lập với Main Thread của bạn, nó sẽ chạy
Background và thực hiện nền những gì bạn cần mà không ảnh hưởng đến Main Thread.
- Ví dụ:
public class HelloIntentService extends IntentService{
public HelloIntentService() {
super("HelloIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
long endTime = System.currentTimeMillis() +
5*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime -
System.currentTimeMillis());
} catch (Exception e) {}
}
}
}
}
2. BROADCAST RECEIVER
2.1. Tạo BroadcastReceiver
- Broadcast Receiver là bộ tiếp nhận và xử lý các Intent dựa trên các chỉ định của chúng
ta. Thành phần này sẽ cho phép mở các ứng dụng để xử lý các Intent tương ứng được
gửi lên từ hệ thống.
- Trong ứng dụng Android, đôi khi bạn cần phải nhận được tín hiệu nếu như một sự kiện
nào trong trên thiết bị được kích hoạt để xử lý cho các ứng dụng tốt hơn. Các sự kiện ví
dụ như là pin sắp cạn, máy vừa được khởi động hoặc một ứng dụng vừa được cài đặt
trên máy ..., khi đó, sử dụng Broadcast Receiver sẽ giúp chúng ta bắt được các sử kiện
này khi chúng bị kích hoạt.
- Để tạo một BroadcastReceiver, ta sẽ tạo một lớp kế thừa từ lớp BroadcastReceiver.
Ví dụ:
public class ConnectivityChangeReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Connectivity changed",
Toast.LENGTH_SHORT).show();
}
}
Chúng ta cũng nên hủy đăng ký khi Activity trong hàm onPause():
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}
Lưu ý: nếu tắt ứng dụng BroadcastReceive sẽ không còn lắng nghe.
3. NOTIFICATION
- Một thông báo (Notification) là thành phần cho phép gửi các thông báo đến người dùng
mà không chiếm quá nhiều việc điều khiển của người dùng trên thiết bị. Ví dụ, khi nhận
được một tin nhắn hay một thư điện tử, thiết bị sẽ sử dụng Notification để thông báo
người dùng thông qua nhạc chuông, đèn nền, thể hiện biểu tượng trên thanh tác vụ, …
- Thông thường một thông báo được tự động kích hoạt nhằm thông báo tới người dùng là
ứng dụng đó đã hoàn thành một công việc nào đó. Bạn có thể kích chọn trực tiếp vào
thông báo đó để khởi chạy lại ứng dụng đó khi nó đang nằm trong trạng thái ngủ.
- Ví dụ sau đây sẽ tạo một thông báo với âm thanh và rung thiết bị.
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final int NOTIF_ID = 1234;
int icon = R.drawable.email;
long when = System.currentTimeMillis();
String title = "New E-mail";
getSystemService(Context.NOTIFICATION_SERVICE);
Notification.Builder builder = new Builder(this);
0,notificationIntent, 0);
- Toast có thể được tạo và hiển thị trong Activity hoặc trong Servive.
- Không cho phép người sử dụng tương tác.
- Khi hiển thị sau khoảng thời gian nào đó sẽ tự đóng lại.
- Có 2 giá trị mặc định (ta nên sử dụng 2 giá trị này, không nên gõ con số cụ thể vào):
hằng số Toast.LENGTH_SHORT hiển thị trong 2 giây, Toast.LENGTH_LONG hiển
thị trong 3.5 giây.
Hình dưới đây cho bạn biết một Toast đang hiển thị:
Mục lục
Bài 1: Lưu trữ, truy vấn và sắp xếp dữ liệu với SQLite................................................... 1
1. Menu .................................................................................................................................. 20
4. ToolBar .............................................................................................................................. 35
1. Property Animation............................................................................................................ 45
2. Asynctask ........................................................................................................................... 55
1. Service ............................................................................................................................... 58
3. Notification ........................................................................................................................ 65
TÀI LIỆU
Tháng 06/2015
Trung Tâm Tin Học Đại Học Khoa Học Tự Nhiên TP.HCM
Bài 1
KHAI THÁC TÀI NGUYÊN INTERNET
- Lưu Cache: các trình duyệt chỉ có thể lưu giữ một lượng thông tin nhỏ về trang web
mà chúng làm việc, trong khi đó ứng dụng hoàn toàn có thể lưu trữ bất kỳ dữ liệu nào
mà lập trình viên mong muốn từ dữ liệu truy xuất đến thao tác người dùng. Khi có sự
cố về kết nối, ứng dụng sẽ lưu trữ lại thông tin tại thời điểm mất kết nối và tự động xử
lý khi thiết bị có lại kết nối.
- Năng lượng: các kết nối Internet khi được thực hiện sử dụng một lượng lớn năng
lượng cho mỗi lần kết nối, tuy nhiên việc xây dựng ứng dụng sẽ cho phép chúng ta tổ
chức quản lý kết nối cũng như duy trì các kết nối khi cần thiết.
- Tính năng thiết bị: các ứng dụng nền web hầu như không thể nào truy xuất đến phần
cứng cũng như các đặc tính quan trọng trên một thiết bị di động. Ví dụ: định vị, máy
ảnh, cảm biến… đương nhiên, khi xây dựng ứng dụng chúng ta hoàn toàn có thể dễ
dàng truy xuất các đặc tính thiết bị thông qua các API mà bộ SDK cung cấp.
1.3. Các hình thức kết nối Internet
Các thiết bị di động ở thời điểm hiện tại hỗ trợ khá nhiều hình thức kết nối đến Internet, tuy
nhiên ta có thể quy chung về dạng sau:
- Mobile Internet: một dạng kết nối thông qua hình thức cung cấp dịch vụ băng thông
của nhà mạng, bao gồm một số chuẩn phổ biến sau: GPRS, EDGE, 3G, 4G, LTE…
- Wifi: kết nối không dây và truyền dữ liệu ra Internet thông các thiết bị mạng (router,
switch…), ngoài ra thiết bị di động Android có khả năng phát tín hiệu mạng cho các
thiết bị khác.
Việc xây dựng ứng dụng thực hiện kết nối đến Internet phụ thuộc vào khá nhiều hình thức
kết nối mà thiết bị người dùng đang sử dụng. Do đó, để tối ưu hóa kết nối và tăng trải nghiệm
người dùng cần thực hiện sử dụng hình thức kết nối một cách hợp lý. Ta có thể thấy các
mạng di động thường có băng thông thấp và chi phí cao để sử dụng, trong khi đó Wifi lại tùy
thuộc và băng thông của nguồn kết nối.
1.4. Lớp khai báo kết nối
Việc khai báo kết nối tùy thuộc vào chuẩn giao thức kết nối và địa chỉ URL của máy chủ cần
kết nối:
- URL: lớp giải quyết phân giải tên miền thành địa chỉ IP.
o Định dạng: http://username:password@host:8080/directory/file?query#ref:
o Phương thức kết nối
openConnection
- URLConnection: lớp thực hiện kết nối đến URL được chỉ định cho việc đọc hoặc ghi
dữ liệu, hỗ trợ các giao thức:
o File: URIs
o FTP
o HTTP & HTTPS
o Jar
- URLConnection:
o Các phương thức quan trọng:
connect()
getContent()
getContentType()
getInputStream()
getOutputStream()
setDoInput – getDoInput
setDoOutput – getDoOutput
o Các lớp giao thức HTTP & HTTPS:
HttpURLConnection
HttpsURLConnection
Các phương thức quan trọng:
. disconnect()
. getContentEncoding()
. getResponseCode()
. getResponseMessage()
o Trong một vài trường hợp cần xin cấp quyền kiểm soát trạng thái Internet
<uses-permission
android:name="android.permission.ACCESS_NETWORK_STATE"/>
o Không được thực hiện kết nối Internet trực tiếp trên tiến trình chính của ứng
dụng. Sử dụng AsyncTask hoặc Thread để thay thế.
o Ví dụ:
URL url = new URL(“http://t3h.vn”);
URLConnection urlConnection = url.openConnection();
HttpURLConnection httpURLConnection =
(HttpURLConnection) urlConnection;
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStream inputStream =
httpURLConnection.getInputStream();
// Xử lý đọc dữ liệu từ InputStream
}
DownloadManager manager=(DownloadManager)getSystemService(DOWNLOAD_SERVICE);
Để khởi tạo yêu cầu tải một nội dung, tiến hành tạo đối tượng Request với tham số truyền
vào là một Uri, một dạng địa chỉ kết nối đến máy chủ chứa nội dung cần tải. Đối tượng này
sau đó sẽ được xếp vào hàng đợi để bắt đầu tải thông qua phương thức enqueue().
("http://developer.android.com/downloads/design/roboto-1.2.zip");
- Khi phương thức enqueue() được gọi, việc tải nội dung sẽ được bắt đầu thực hiện khi
kết nối mạng khả dụng và hàng đợi của Download Manager đang rỗng.
- Phương thức enqueue() cũng trả về một biến tham chiếu id_reference, được sử dụng
để thực hiện các thao tác liên quan đến yêu cầu tải đang được thực hiện trong hàng
đợi. Ví dụ, ta có thể thực hiện truy vấn xem trạng thái của yêu cầu tải đã hoàn thành
chưa hoặc đơn giản có thể hủy yêu cầu tải dựa trên tham chiếu này.
- Khi thực hiện tải một nội dung, chúng ta có thể cân nhắc về dung lượng của nội dung
và cho phép sử dụng các kết nối phù hợp nội dung đó thông qua phương thức
setAllowedNetworkTypes(), lựa chọn tải bằng Wi-fi hay mạng di động.
- Từ phiên bản Android 3.0, phương thức getRecommendedMaxBytesOverMobile()
được bổ sung cho phép ứng dụng có thể nhận biết dung lượng lớn nhất có thể mà thiết
bị có thể thực hiện tải thông qua kết nối của mạng di động.
- Để nhận biết việc hoàn thành tải nội dung, ta tiến hành xây dựng một
BroadcastReceiver để bắt lại hành động ACTION_DOWNLOAD_COMPLETE được
truyền thông bởi dịch vụ chạy ngầm DownloadMananager. Trong dữ liệu bắt được,
cũng bao gồm tham số EXTRA_DOWNLOAD_ID chứa biến tham chiếu đến nội
dung tải. Có thể xem đoạn code sau để hiểu thêm.
Hình 1.2
Tuy nhiên chúng ta hoàn toàn có thể tùy chỉnh thông tin hiển thị trên hộp thoại thông báo này
tường minh hơn thông qua các phương thức hỗ trợ trong đối tượng Request.
Ví dụ:
Kết quả:
Hình 1.3
Hộp thoại thông báo mặc định sẽ xuất hiện khi bắt đầu tải và tự đóng khi hoàn tất quá trình
tải, để thiết lập lại trạng thái này chúng ta có thể sử dụng phương thức
setNotificationVisibility() với các biến cờ tương ứng sau:
- Request.VISIBILITY_VISIBLE: tham số mặc định, chỉ hiển thị trong quá trình tải.
- Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED: hiển thị trong quá trình tải
và cả khi hoàn tất.
- Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION: chỉ hiển thị khi
hoàn tất quá trình tải.
- Request.VISIBILITY_HIDDEN: không hiển thị hộp thoại thông báo.
Đối với biến cờ VISIBILITY_HIDDEN cần cấp quyền trong AndroidManifest.xml
<uses-permission
android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"/>
- Các tập tin trong thư mục này sẽ không thể truy xuất bằng đường dẫn của tập tin, chỉ
có thể truy xuất thông qua Uri của tập tin đó.
- Tuy nhiên ta có thể thiết lập lại vị trí lưu trữ nội dung tải thông qua các phương thức
sau:
o setDestinationUri(Uri uri): chỉ định vị trí lưu trữ bất kỳ thông qua Uri.
Ví dụ:
File f = new File(Environment.getExternalStorageDirectory(),
uri.getLastPathSegment());
request.setDestinationUri(Uri.fromFile(f));
- Các hành động truy xuất đến bộ nhớ ngoài cần cấp quyền trong tập tin
AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Mặc định, đối với các trường hợp tải tập tin đa truyền thông (ví dụ: hình ảnh, âm nhạc, video,
...) các ứng dụng đa phương tiện như Galery, Music hay Video không thể tự động quét được
các nội dung này. Tuy nhiên, chúng ta có thể cho phép tập tin được quét lại khi hoàn tất việc
tải thông qua phương thức allowScanningByMediaScanner() trong đối tượng Request.
2.5. Truy vấn nội dung tải trong DownloadManager
- Để ứng dụng có thể quản lý các thông tin của nội dung tải như: trạng thái, tiến độ,
dung lượng, ... ta có thể thực hiện truy vấn Content Provider của Download Manager
thông qua đối tượng Query, kết quả trả về là một đối tượng Cursor. Có thể xem chi
tiết ở đoạn mã sau:
Query query = new Query();
query.setFilterById(id_reference);
Cursor cursor = manager.query(query);
if (cursor.moveToFirst()) {
String path = cursor.
getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
if (path != null)
imageView.setImageURI(Uri.parse(path));
}
Trong đoạn mã trên, để thực hiện truy vấn đúng nội dung đã tải ta gọi phương thức
setFilterById() với tham số là biến tham chiếu id_reference ta truy xuất được từ phương thức
enqueue() (Xem lại phần III.1).
Việc truy vấn được thực hiện thông qua phương thức query() trong đối tượng
DownloadManager, tham số truyền vào là đối tượng Query đã thiết lập bộ lọc. Kết quả trả về
thông qua đối tượng Cursor, để truy xuất dữ liệu trong Cursor, tiến hành truyền vào tên cột
của những trường dữ liệu tương ứng cần truy xuất. Tên cột của những trường dữ liệu được
định dạng COLUMN_*.
Trong ví dụ trênm, chúng ta truy xuất trường dữ liệu COLUMN_LOCAL_FILENAME trong
Cursor để lấy đường dẫn lưu trữ nội dung tấm ảnh được tải, sau đó thiết lập cho điều khiển
ImageView.
Bài 2
KẾT NỐI CÁC DỊCH VỤ WEB
THAO TÁC VỚI DỮ LIỆU XML VÀ JSON
Các Web Services cho phép các tổ chức thực hiện truyền thông dữ liệu mà không cần phải có
kiến thức về hệ thống IT phía sau tường lửa. Một số Web Services hiện nay có sẵn miễn phí
và càng ngày càng hướng dần vào các doanh nghiệp.
Một ví dụ về Web Service sẵn có là dịch vụ được cung cấp bởi PayPal cho phép những người
có tài khoản có thể thanh toán hoặc trả một phần hoặc thực hiện các giao dịch tìm kiếm, và
lấy lại các thông tin của từng giao dịch cụ thể.
1.2. Các chuẩn dịch vụ WEB
Việc tìm hiểu về các chuẩn dịch vụ WEB giúp chúng ta có thể đưa ra các lựa chọn phù hợp
với hệ thống triển khai, dữ liệu và các thiết bị truy xuất dữ liệu đầu cuối đầu cuối. Có thể liệt
kê một số chuẩn chính sau:
- UDDI (Universal Description, Discovery and Integrated).
- WSDL (Web Services Description Language).
- WSIL (Web Services Inspection Language).
- SOAP (Simple Object Access Protocol).
Hình 2.1. Minh họa cơ chế hoạt động của giao thức HTTP
- Ví dụ về HTTP – Request
GET http://www.fit.hcmus.edu.vn/vn/ HTTP/1.1
Accept: application/x-ms-application, image/jpeg,
application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap,
application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-
powerpoint, application/msword,
Accept-Language: vi-VN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1;
WOW64; Trident/4.0; GTB6.5; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT
5.1; SV1) ; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR
3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; OfficeLiveConnector.1.5;
OfficeLivePatch.1.3; InfoPath.3; AskTbGGSV5/5.8.0.12217)
chromeframe/6.0.472.63
Accept-Encoding: gzip, deflate Connection: Keep-Alive
Host: www.fit.hcmus.edu.vn
Cookie:
.ASPXANONYMOUS=MG6LCiuSywEkAAAANTA2ZWNiYTAtYThiNy00MDA1LTkyN
jUtYTllYzAxNTA3MTU10
- Ví dụ về HTTP – Response
HTTP/1.0 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.0
X-AspNet-Version: 2.0.50727
Set-Cookie: DotNetNukeAnonymous=7db3c001-c407-4adb-a60f-053b5dc76dc2;
expires=Thu, 30-Sep-2010 03:12:33 GMT; path=/; HttpOnly
Set-Cookie: language=vi-VN; path=/; HttpOnly X-Powered-By: ASP.NET
Date: Thu, 30 Sep 2010 02:52:33 GMT Content-Length: 24404
X-Cache: MISS from vweb.hcmuns.edu.vn
Via: 1.0 vweb.hcmuns.edu.vn:80 (squid/2.6.STABLE16) Connection: keep-alive
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> ...
// Nội dung trang web
cung cấp đủ chức năng. Nhưng đây là mô hình cơ bản, dựa trên đó sẽ phát triển các
mô hình trao đổi phức tạp hơn.
Sender Receiver
Transport
Hình 2.2. Hệ thống Soap đơn giản.
- Một cấu trúc SOAP được định nghĩa gồm các phần: <Envelope>, <Header> và
<Body>.
- Trong việc truy xuất tài nguyên Internet trên thiết bị di động cần kiểm soát được các
vấn đề về kết nối. Ví dụ: ta cần kiểm soát việc cho phép người dùng tương tác với ứng
dụng ở chế độ ngoại tuyến và thực hiện cập nhật dữ liệu khi có kết nối. Có thể xem ví
dụ về việc sử dụng Broadcast Receiver để kiểm soát vấn đề này:
BroadcastReceiver mNetworkStateIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("HTSI", "CONNECTION CHANGED");
ConnectivityManager cm = ((ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE));
if (cm.getActiveNetworkInfo() != null) {
o Ở phương thức setRequestMethod ta có thể tự do thêm vào tên của cách thức
gọi phương thức từ dịch vụ RESTful như GET, POST, PUT, … Tuỳ thuộc vào
loại phương thức mà dịch vụ đó cung cấp. Ở ví dụ trên, do thực hiện gọi theo
loại phương thức GET, cũng như không có tham số truyền vào nên không khác
mấy so với cách thức mà chúng ta thực hiện ở phần đầu chương.
o Tuy nhiên hãy khảo sát cách thức để đăng nhập vào dịch vụ này. Ở đây, cần
thực hiện gửi dữ liệu người dùng cho dịch vụ theo dạng JSON và dạng sử dụng
POST để bảo mật dữ liệu.
HttpURLConnection connection = null;
Url url = new URL(“http://221.132.37.130:6969/OnlineShopWebService”);
Conn-ection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(10000);
connection.setReadTimeout(10000);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(true);
// Gửi dữ liệu thông qua OutputStream
OutputStream outputStream = new
BufferedOutputStream(connection.getOutputStream());
outputStream.write(incomingParams.getBytes());
outputStream.flush();
outputStream.close();
o Dữ liệu incomingParams được thực hiện chia thành từng byte nhỏ bằng
phương thức getBytes() trước khi được đưa vào OutputStream của kết nối. Dữ
liệu được định dạng là JSON khi dịch vụ nhận được thông qua phương thức
setRequestProperty().
- Sử dụng các lớp trong gói org.apache.http:
Đối với cách sử dụng các lớp HTTP trong Apache giúp chúng ta tường minh hơn
việc gọi đến Service. Ví dụ sử dụng hai lớp HttpGet và HttpPost:
o HttpGet: sau khi thực hiện có thể thực hiện truy xuất dữ liệu dạng InputStream
thông qua phương thức getEntity đối tượng HttpResponse.
o HttpPost: đối với POST cần xác định dạng dữ liệu cần thực hiện gửi lên dịch
vụ, ví dụ sau đây mô tả cách thức gửi dữ liệu dạng JSON, được đóng gói vào
đối tượng NameValuePair. Dữ liệu được trả về vẫn được truy xuất thông qua
đối tượng HttpResponse.
- Ví dụ:
<data>
<weather>
<date>2014-06-20</date>
<tempMaxC>13</tempMaxC>
<tempMaxF>56</tempMaxF>
<tempMinC>5</tempMinC>
<tempMinF>42</tempMinF>
<windspeedMiles>13</windspeedMiles>
<windspeedKmph>20</windspeedKmph>
<winddirection>WNW</winddirection>
<weatherCode>113</weatherCode>
<precipMM>0.0</precipMM>
</weather>
</data>
Hình 2.4.
- XML Pull Parser: cho phép trình bày các thành phần trong tập tin theo dạng chuỗi
các thẻ (tag), việc ghi dữ liệu XML được biểu diễn thông qua hai đối tượng
XmlSerializer và StringWritter.
xmlSerializer.setOutput(stringWriter);
xmlSerializer.startDocument("UTF-8", true);
xmlSerializer.startTag("", "data");
xmlSerializer.attribute("", "source", "weather.t3h.vn");
xmlSerializer.startTag("", "weather");
xmlSerializer.startTag("", "date");
xmlSerializer.text("20-06-2014");
xmlSerializer.endTag("", "date");
xmlSerializer.startTag("", "tempMaxC");
xmlSerializer.text("13");
xmlSerializer.endTag("", "tempMaxC");
xmlSerializer.startTag("", "tempMaxF");
xmlSerializer.text("56");
xmlSerializer.endTag("", "tempMaxF");
xmlSerializer.endTag("", "weather");
xmlSerializer.endTag("", "data");
xmlSerializer.endDocument();
textXML.setText(stringWriter.toString());
Hình 2.5
4.2.2. Đọc dữ liệu XML
- DOM Parser: giao diện lập trình ứng dụng (API) có dạng một cây cấu trúc dữ liệu,
các đối tượng cần khởi tạo khi sử dụng:
o Element: đại diện cho một thẻ trong XML.
o NodeList: đại diện cho một thẻ có chứa nhiều thẻ con.
o Document: tập tin tài liệu được khởi tạo từ dữ liệu XML thông qua
DocumentBuilder.
o DocumentBuilder: đối tượng hỗ trợ chuyển đổi dữ liệu XML thành cấu trúc
tập tin XML cho việc đọc ghi dữ liệu.
o DocumentBuilderFactory: khởi tạo đối tượng DocumentBuilder.
sample_xmlxml:
<data>
<weather>
<date>2014-06-20</date>
<tempMaxC>13</tempMaxC>
<tempMaxF>56</tempMaxF>
<tempMinC>5</tempMinC>
<tempMinF>42</tempMinF>
<windspeedMiles>13</windspeedMiles>
<windspeedKmph>20</windspeedKmph>
<winddirection>WNW</winddirection>
<weatherCode>113</weatherCode>
<precipMM>0.0</precipMM>
</weather>
</data>
- Ví dụ xử lý XML với DOM: truy xuất dữ liệu thẻ <weather> trong đoạn XML trên.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
InputStream inputStream = getAssets().open("sample_xml.xml");
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(inputStream);
Element element = document.getDocumentElement();
NodeList nodeList = element.getElementsByTagName("weather");
if (nodeList == null)
return;
for (int i=0; i<nodeList.getLength(); i++) {
Element weather = (Element) nodeList.item(i);
for (int x=0; x < weather.getChildNodes().getLength(); x++) {
- XML Pull Parser: cho phép trình bày các thành phần trong tập tin theo dạng chuỗi
các thẻ (tag) và các đánh dấu (event), để làm việc với XML Pull Parser cần khảo sát
các thuộc tính và các đối tượng sau:
o XmlPullParserFactory: khởi tạo đối tượng XmlPullParser từ tập tin tài liệu
XML.
o XmlPullParer: đối tượng kiểm soát việc duyệt và truy xuất dữ liệu.
o START_DOCUMENT: điểm đánh dấu bắt đầu của tập tin XML.
o END_DOCUMENT: điểm đánh dấu kết thúc của tập tin XML.
o START_TAG: điểm đánh dấu bắt đầu cặp thẻ XML.
o END_TAG: điểm đánh dấu kết thúc cặp thẻ XML.
- Ví dụ xử lý XML với DOM: truy xuất dữ liệu các thẻ con trong thẻ <weather> đoạn
XML trên.
InputStream inputStream = getAssets().open("sample_xml.xml");
XmlPullParserFactory xmlPullParserFactory = XmlPullParserFactory.newInstance();
XmlPullParser xpp = xmlPullParserFactory.newPullParser();
xpp.setInput(inputStream, null);
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
String tagName = xpp.getName();
// Bỏ qua dữ liệu của thẻ data & weather
if (!tagName.equalsIgnoreCase("data") &&
!tagName.equalsIgnoreCase("weather"))
Log.d("HTSI", tagName + " = " + xpp.nextText());
} eventType = xpp.next();
}
o Một đối tượng mảng có bao gồm nhều phần tử con có thứ tự. Các phần từ con
được bao trong cặp “[]” và chia cách nhau bởi dấu “,”. Mỗi phần tử con có thể
là một giá trị đơn lẻ như: số, chuỗi, true-false, null hoặc một object khác, thậm
chí có thể là một mảng.
- Ví dụ 2:
{
"product":"Google Nexus 5",
"color":
[
"grey","white","black"
],
"memory":
[
16,32,64
]
}
- Để thực hiện ghi dữ liệu JSON, cần xác định rõ cấu trúc của dữ liệu cần lưu trữ. Nếu
dữ liệu cần ghi là một đối tượng, dữ liệu sẽ được ghi vào một JSONObject; nếu dữ
liệu là một mảng, dữ liệu sẽ được ghi vào một JSONArray.
- Ví dụ 1: ghi dữ liệu có cấu trúc đơn giản dạng JSONObject:
{
"date":"17-06-2015",
"tempMaxC":13,
"tempMaxF":56
}
// Khởi tạo đối tượng JSONObject
JSONObject jsonObject = new JSONObject();
Bài 3
GOOGLE MAP
- Cài đặt GPSDK: thực hiện cài đặt gói API từ công cụ Android SDK Manager .
Hình 3.2. Cài đặt gói API từ công cụ Android SDK Manager
- GPSDK trên thiết bị, thường có 4 trạng thái:
o Google Play Store đã được cài đặt cùng các dịch vụ đi kèm (phổ biến).
o Google Play Store đã được cài đặt nhưng các dịch vụ chưa được cài đặt.
o Google Play Store chưa được cập nhật phiên bản mới nhất.
o Google Play Store không được cài đặt trên thiết bị (máy ảo).
o Google Play Store tự động cập nhật các dịch vụ khi có kết nối internet.
- Kiểm tra trạng thái của GPSDK:
o Thực hiện kiểm tra trong onResume bằng phương thức
isGooglePlayServiceAvailable().
o Kết quả trả về:
SUCCESS
SERVICE_MISSING
SERVICE_VERSION_UPDATE_REQUIRED
SERVICE_DISABLE
- Thực hiện gọi phương thức getErrorDialog() để hướng dẫn người cập nhật GPSDK
hoặc kích hoạt trong phần Setting.
- Cần thực hiện kiểm tra đối tượng GoogleMap trước khi tương tác. Mã lệnh kiểm tra
như sau:
private void setUpMapIfNeeded(){
//Khởi tạo đối tượng GoogleMap nếu chưa có giá trị
if( mMap == null){
mMap = mapFragment.getMap();
// Kiểm tra đối tượng GoogleMap đã được khởi tạo thành công
if( mMap != null) {
// Thực hiện các tùy chỉnh trên đối tượng GoogleMap
mMap.setMapType (GoogleMap.MAP_TYPE_TERRAIN);
}
}
}
- Thiết lập các giá trị ban đầu và điều khiển cho GoogleMap bao gồm:
o Góc nhìn (Camera).
Thu phóng (zoom).
Chuyển điểm (location).
Xoay (bearing).
Góc nghiêng (titl).
o La bàn và điều khiển thu phóng.
o Các điều khiển cử chỉ trên bản đồ.
- Thiết lập các giá trị ban đầu và điều khiển cho GoogleMap trong XML:
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.google.android.gms.maps.MapFragment"/>
- Thực hiện tùy chỉnh GoogleMap thông qua đối tượng GoogleMapOptions:
GoogleMapOptions mapOptions = new GoogleMapOptions();
mapOptions.mapType(GoogleMap.MAP_TYPE_HYBRID)
.scrollGesturesEnabled(true)
.rorateGesturesEnabled(true)
.zoomControlsEnabled(true);
2.4.2. InfoWindow:
- InfoWindow được thể hiện phía trên đối tượng Marker thể hiện các thông tin cần thiết
về vị trí đang định vị.
- Chỉ một đối tượng InfoWindow hiển thị ở một thời điểm và có thể điều khiển thông
qua hai phương thức:
o showInfoWindow().
o hideInfoWindow().
- Để tùy chỉnh InfoWindow trong lớp GoogleMap hỗ trợ giao diện
InfoWindowAdapter bao gồm 2 phương thức:
o getInfoWindow(Marker).
o getInfoContents(Marker).
- Gọi phương thức setInfoWindowAdapter để thiết lập InfoWindow cho đối tượng
GoogleMap.
- Google Maps API cung cấp các giao diện cho phép bắt lại các sự kiện tương với
Marker và InfoWindow.
o OnMarkerClickListener.
o OnMarkerDragListener.
o OnInfoWindowClickListener.
2.4.3. Shape:
- Shape bao gồm các đối tượng hình học được vẽ trên bản đồ bao gồm các dạng sau:
o Polyline
o Polygons
o Circle
- Polyline: được tạo bằng các nối các điểm dựa trên toạ độ điểm. Ví dụ minh họa:
PolylineOptions options = new PolylineOptions()
.add(new LatLng(10.919618, 106.523438))
.add(new LatLng(13.410994, 123.046875))
.add(new LatLng(35.746512, 139.833984));
Polyline polyline = mMap.addPolyline(options);
Hình 3.7. Minh họa sử dụng Polyline Hình 3.8. Minh họa sử dụng Polyline
- Polygon: giống với Polyline được tạo bằng các nối các điểm dựa trên toạ độ điểm, tuy
nhiên Polygon cho phép khép kín các tọa độ và thao tác vùng đã khép kín.
List<LatLng> getPoints()
int getStrokeColor()
float getStrokeWidth()
float getZIndex()
boolean isGeodesic()
boolean isVisible()
PolygonOptions strokeColor(int color)
PolygonOptions strokeWidth(float width)
PolygonOptions visible(boolean visible)
void writeToParcel(Parcel out, int flags)
PolygonOptions zIndex(float zIndex)
- Circle: đối tượng hình học (hình tròn) được xác định trên bản đồ thông qua bán kính
và tâm.
CircleOptions circleOptions = new CircleOptions();
circleOptions.center(HCM).radius(5);
Circle circle = mMap.addCircle(circleOptions);
circle.setFillColor(Color.CYAN);
circle.setStrokeColor(Color.WHITE);
LatLng getCenter()
int getFillColor()
String getId()
double getRadius()
int getStrokeColor()
float getStrokeWidth()
float getZIndex()
boolean isVisible()
void remove()
void setCenter(LatLng center)
void setFillColor(int color)
void setRadius(double radius)
void setStrokeColor(int color)
void setStrokeWidth(float width)
void setVisible(boolean visible)
void setZIndex(float zIndex)
Bài 4
GOOGLE CLOUD MESSAGING
1. GIỚI THIỆU
- Google Cloud Messaging (GCM) là một dịch vụ cho phép gửi dữ liệu từ máy chủ của
bạn đến các thiết bị Android của người dùng, và ngược lại.
- GCM được sử dụng cho hoạt động giao dịch giữa các ứng dụng và máy chủ hỗ trợ đầu
cuối. Cloud Messaging hiện đang được tích hợp vào Google Play Services và nhờ
những cải tiến mạnh mẽ, Cloud Messaging giờ đây tương trợ kết nối liên tục và truyền
tải thông điệp ngược dòng (upstream). Do đó, thiết bị có thể gởi phản hồi trở lại máy
chủ mà không còn chỉ một chiều từ máy chủ đến thiết bị như trước đây.
- Nhờ tính năng truyền tải ngược, các thông báo (Notification) mà bạn nhận được và bỏ
lỡ trên thiết bị này có thể được đồng bộ với thiết bị khác. Bạn sẽ không phải soát lại
hàng loạt các thông báo tương tự trên điện thoại khi chuyển sang sử dụng chiếc máy
tính bảng của mình.
- GCM là hoàn toàn miễn phí và không giới hạn băng thông. Dịch vụ hoạt động trên các
gói dữ liệu có dung lượng nhỏ hơn 4kb và tin nhắn tới thiết bị Android là tức thời
(Push-notification).
- GCM là phù hợp cho việc xây dựng các ứng dụng nhắn tin tức thời hoặc tương tác
giữa người dùng và nhà phát triển ứng dụng.
- Ví dụ:
o Thông báo tới thiết bị Android của người khi có một email mới. GCM gửi
thông báo tới người quản lý khi có một đơn đặt hàng trên trang Web của họ.
- Gửi tin nhắn tới cả một cộng đồng như: cồng đồng nhân viên thuộc cùng một công ty,
học sinh hoặc phụ huynh của một trường học với chi phí thấp nhất và hiệu quả nhất.
- Nguyên tắc hoạt động:
Hãy cùng xem hình dưới để hiểu rõ hơn.
Hình 4.2. Nguyên tắc hoạt động khi Web Server gửi thông báo
về thiết bị thông qua Google Cloud Messaging.
o Một khi dự án đã được tạo ra, một trang xuất hiện hiển thị ID dự án của bạn. Ví
dụ: id dự án của bạn là engaged-root-93803
Hình 4.4. Minh hoạ màn hình tổng quan của dự án trên Google Developers Console.
o Sao chép số ID Project này lưu lại. Bạn sẽ sử dụng nó như GCM sender ID.
- Sau đó, bạn cần kích hoạt API cho GCM
o Trong thanh bên trên bên trái, chọn mục API & auth → Chọn tiếp APIs
o Tìm đến mục Google Cloud Messaging for Android và “Enable API”.
Hình 4.5 Kích hoạt Google Cloud Messaging trong dự án của bạn 1
Hình 4.6. Kích hoạt Google Cloud Messaging trong dự án của bạn 2
- Bây giờ bạn đã có thể lấy API Key với các bước sau:
o Trong thanh bên trên bên trái, chọn API & auth → Sau đó chọn Credentials.
o Trong phần Public API access, nhấp vào Create new key.
o Trong hộp thoại Create a new key, nhấp vào Server key.
o Trong hộp thoại IP address bên dưới nhập vào địa chỉ IP Web Server của bạn.
Dùng địa chỉ 0.0.0.0/0 cho mục đích thử nghiệm.
o Nhấp vào Create.
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});
regService = builder.build();
}
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
String regId = gcm.register(SENDER_ID);
msg = "Device registered, registration ID=" + regId;
//Gửi ID đăng ký đến server của bạn qua HTTP. Như vậy, nó có
//thể sử dụng GCM/ HTTP hoặc CSS để gửi tin nhắn đến các
//ứng dụng của bạn
regService.register(regId).execute();
public GcmIntentService() {
super("GcmIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
@Override
public void run() {
Toast.makeText(getApplicationContext(), message,
Toast.LENGTH_LONG).show();
}
});
}
}
Mã nguồn cho lớp GcmBroadcastReceiver.java
Sau khi thêm 2 lớp GcmIntentService.java và lớp GcmBroadcastReceiver.java vào ứng dụng
Android, chúng ta đăng ký cho chúng bằng cách thêm đoạn mã vào tập tin
AndroidManifest.xml (đặt trong thẻ <application>) như sau:
<receiver
android:name=".GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="TEN_PACKAGE_CHUA_UNG_DUNG_CUA_BAN" />
</intent-filter>
</receiver>
<service android:name=".GcmIntentService" />
Bài 5
CÁC ĐIỀU KHIỂN ĐA TRUYỀN THÔNG
1. MEDIA PLAYER
1.1. Giới thiệu
- Android cung cấp lớp MediaPlayer để quản lý các tác vụ đa truyền thông bao gồm các
tập tin âm thanh, hình ảnh, video...
- Có thể truy xuất các tập tin media thông qua việc lưu trữ như tài nguyên ứng dụng, bộ
nhớ thiết bị, content provider hoặc thông qua URL.
- MediaPlayer quản lý các tập tin media và luồng xử lý thông qua một tập các trạng thái
sau:
o Khởi tạo đối tượng MediaPlayer.
o Chuẩn bị bộ thu phát MediaPlayer.
o Bắt đầu thực hiện thu phát.
o Thực hiện các thao tác Pause và Stop trên tập tin media trong khi đang thu
phát.
o Hoàn thành quá trình thu phát.
1.2. Xây dựng MediaPlayer Audio
- Android hỗ trợ truy xuất các tập tin Audio thông qua các lưu trữ như: tài nguyên ứng
dụng, bộ nhớ thiết bị, content provider và xử lý các luồng URL.
- Có thể đóng gói tập tin Audio vào thư mục res/raw như một dạng tài nguyên của ứng
dụng.
- Để thu phát một tập tin Audio cần tạo một đối tượng MediaPlayer và thiết lập nguồn
dữ liệu cho đối tượng này.
- Thực hiện thu phát bằng phương thức Create() truyền vào 2 tham số: context của ứng
dụng và một trong những dạng tài nguyên sau:
o Định danh của tài nguyên.
o URI trỏ đến nơi lưu trữ của tập tin trên thiết bị.
o URI trỏ đến tập tin trực tuyến thông qua URL.
o URI trỏ đến dòng dữ liệu trong bảng của content provider.
- Ví dụ tạo đối tượng MediaPlayer
Context appContext = getApplicatiionContext();
MediaPlayer filePlayer = MediaPlayer.create(appContext,
Uri.parse(file:///sdcard/localfile.mp3));
MediaPlayer urlPlayer = MediaPlayer.create(appContext,
Uri.parse(“http://site.com/audio/audio.mp3”));
MediaPalyer contentPlayer = MediaPlayer.create(appContext,
Settings.System.DEFAULT_RINGTONE_URI);
- Để thực thi việc thu phát tập tin Video cần tạo một màn hình cho việc trình chiếu. Có
hai cách để thực hiện công việc này:
o Sử dụng thành phần Video View, đóng gói các thao tác trên đối tượng
MediaPlayer (tạo trình chiếu, chuẩn bị và cấp phát tập tin) vào trong thành
phần View này.
o Xây dựng màn hình hiển thị riêng và gắn kết dữ liệu thông qua đối tượng
MediaPlayer.
1.3. Xây dựng MediaPlayer Video
- Để thực thi việc thu phát tập tin Video cần tạo một màn hình cho việc trình chiếu. Có
hai cách để thực hiện công việc này:
o Sử dụng thành phần Video View, đóng gói các thao tác trên đối tượng
MediaPlayer (tạo trình chiếu, chuẩn bị và cấp phát tập tin) vào trong thành
phần View này.
o Xây dựng màn hình hiển thị riêng và gắn kết dữ liệu thông qua đối tượng
MediaPlayer.
- Ví dụ tạo bộ thu phát bằng Video View:
VideoView videoView = (VideoView) findViewById(R.id.surface);
videoView.setKeepScreenOn(true);
videoView.setVideoPath(“/sdcard/test2.2gp”);
if(videoView.canSeekForward())
videoView.seekTo(videoView.getDuration()/2);
videoView.start();
[ ... do something ... ]
videoView.stopPlayback();
android:layout_height = “wrap_content”
android:layout_gravity= “center”>
</SurfaceView>
</LinearLayout>
- Tạo đối tượng Surface Holder để hỗ trợ việc cập nhật các nguồn xử lý bên dưới:
public class MyActivity extends Activity implements SurfaceHolder.Callback
{
private MediaPlayer mediaPlayer;
@Override
public void onCreate(Bundle saveInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mediaPlayer = new MediaPlayer();
SurfaceView surface = (SurfaceView) findViewById(R.id.surface);
SurfaceHolder holder = surface.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder.setFixedSize(400, 300);
}
}
- Khởi tạo nội dung của tập tin cần trình chiếu:
public void SurfaceCreated(SurfaceHolder holder)
{
try{
mediaPlayer.setDisplay(holder);
mediaPlayer.setDataSource(“/sdcard/test2.3gp”);
mediaPlayer.prepare();
mediaPlayer.start();
}
catch(IllegalArgumentException e)
{
Log.d(“MEDIA_PALYER”, e.getMessage());
}
catch(IllegalStateException e){
Log.d(“MEDIA_PALYER”, e.getMessage());
}
catch(IOException e)
{
Log.d(“MEDIA_PALYER”, e.getMessage());
}
}
1.4. Các điều khiển trên MediaPlayer
- MediaPlayer cung cấp một số phương thức cho việc điều khiển như getDuration,
getCurrentPositon, seekTo...
mediaPlayer.start();
int pos = mediaPlayer.getCurrentPosition();
int duration = mediaPlayer.getDuration();
mediaPlayer.seekTo(pos + (duration-pos)/10);
[ ... wait for a duration ... ]
mediaPlayer.stop();
- Một số phương thức khác như hỗ trợ âm thanh, chống khóa màn hình trong khi thu
phát, thiết lập các chế độ phát lại...
o Sử dụng phương thức isLooping() và setLooping() để thiết lập chế độ phát lại
cho tập tin media.
o Ví dụ:
if (!mediaPlayer.isLooping())
mediaPlayer.setLooping(true);
o Thiết lập Wake Clock giữ cho màn hình luôn mở khi đang phát bằng phương
thức setScreenOnWhilePlaying()
o Ví dụ:
mediaPlayer.setSreenOnWhilePlaying(true);
- Android cung cấp 2 lựa chọn trong việc thu âm thanh và hình ảnh:
o Sử dụng Intent để khởi chạy ứng dụng Video Camera. Lựa chọn này cho phép
chỉ định nơi lưu trữ, định dạng và chất lượng của hình ảnh thu được.
o Sử dụng lớp Media Recoder để xây dựng các thành phần UI, các thiết lập
record cho ứng dụng.
o Sử dụng Intent để thu hình ảnh: bằng cách truyền action
ACTION_VIDEO_CAPTURE vào một Intent và gửi Intent này đến một
Activity khác xử lý và trả về kết quả thu được.
- Ví dụ:
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
startActivityForResult(intent, RECORD_VIDEO);
- MediaStore hổ trợ hai URI cho phép lựa chọn trong quá trình thu hình ảnh:
o EXTRA_OUPUT: cho phép tùy chọn nơi lưu trữ.
o EXTRA_VIDEO_QUALITY: cho phép tùy chọn chất lượng hình ảnh thu
được.
- Ví dụ sử dụng Intent để thu hình ảnh:
private static int RECORD_VIDEO =1;
private static int HIGH_VIDEO_QUALITY = 1;
private static int MMS_VIDEO_QUALITY = 0;
private void recordVideo(Uri outputpath)
{
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
if(outputpath != null)
Intent.putExtra(MediaStore.EXTRA_OUTPUT, output);
Intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, HIGH_CIDEO_QUALITY);
startActivityForResult(intent, RECORD_VIDEO);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent
data)
{
if(requestCode == RECORD_VIDEO){
Uri recordVideo = data.getData();
}
}
- Sử dụng Media Recorder để thu âm thanh và hình ảnh: cần tạo đối tượng thuộc lớp
MediaRecoder để sử dụng.
- Ví dụ:
- Cần đăng ký quyền sử dụng cho ứng dụng trong file AndroidManifest.xml
<uses-permisson android:name= “android.permission.RECORD_AUDIO/>
<uses-permission android:name= “android.permission.RECORD_VIDEO/>
- MediaRecoder quản lý các tập tin media và luồng xử lý thông qua một tập các trạng
thái sau:
o Khởi tạo đối tượng MediaPlayer.
o Chỉ định nguồn vào của thiết bị thu.
o Thiết lập định dạng của tập tin đầu ra.
o Thiết lập các chỉ số như: bộ mã hóa, chất lượng hình ảnh, dung lượng xuất ra...
o Chọn tập tin để xuất.
o Chuẩn bị thu âm & hình ảnh.
o Tiến hành thu âm & hình ảnh.
o Hoàn thành quá trình thu.
- Ví dụ tạo MediaRecorder
MediaRecorder mediaRecorder = new MediaRecorder();
//chuẩn bị record
mediaRecorder.prepare();
mediaRecorder.release();
3. CAMERA
3.1. Điều khiển chụp hình với Camera
- Tùy chỉnh Camera thông qua đối tượng của Parameter trong lớp Camera:
Camera.Parameters parameters = camera.getParameters();
[... make changes ... ]
Camera.setParameter(parameters);
}
};
}
catch(IIOException e)
{
Log.d(“CAMERA”, e.getMessage());
}
}
};
Bài 6
TELEPHONY & SMS
1. TELEPHONE
- Tạo cuộc gọi bằng các sử dụng Intent để gọi Dialer có sẵn trong thiết bị. Ví dụ:
Intent intent = new Intent(Intetn.ACTION_DIAL, Uri.parse(“tel:123456”));
startActivity(intent);
- Thực hiện hành động gọi ACTION_CALL bằng cách nhấn nút Call trong thiết bị.
- Một số thông tin cần thiết cho việc quản lý chức năng Phone trên thiết bị:
o PhoneType (GSM - CDMA)
o UniqueID (IMEI – MIED)
o Sofware version
o Number
- Để truy xuất được các thông tin này cần thực hiện đăng ký trong
AndroidManifest.xml
<uses-permission android:name= “android.permission.READ_PHONE_STATE”/>
- Việc truy xuất quản lý bởi lớp TelephonyManager với phương thức
getSystemService(). Ví dụ:
String srvcName = Context.TELEPHONY_SERVICE;
TelephonyManager telephonyManager =
(TelephonyManager)getSystemService(srvcName);
int phoneType = telephonyManager.getPhoneType();
switch (phoneType) {
case (TelephonyManager.PHONE_TYPE_CDMA): break;
case (TelephonyManager.PHONE_TYPE_GSM) : break;
case (TelephonyManager.PHONE_TYPE_NONE): break;
default: break;
}
String deviceId = telephonyManager.getDeviceId();
o Đọc dữ liệu kết nối và các thay đổi trạng thái thông qua các phương thức
getDataSet() và getDataActivity()
o Các thay đổi trạng thái Phone được quản lý bởi lớp PhoneStateListener
o Cần đăng ký với Telephony Manager để khởi tạo các sự kiện muốn lắng nghe
để xử lý:
telephonyManager.listen(phoneStateListener,
PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR|
PhoneStateListener.LISTEN_CALL_STATE |
PhoneStateListener.LISTEN_CELL_LOCATION |
PhoneStateListener.LISTEN_DATA_ACTIVITY |
PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR |
PhoneStateListener.LISTEN_SERVICE_STATE |
PhoneStateListener.LISTEN_SIGNAL_STRENGTH);
- Xây dựng ứng dụng thay thế ứng dụng cuộc gọi có sẵn trong ứng dụng. Bao gồm 2
bước:
o Chặn những Intent đến của ứng dụng Dialer và xử lý.
o Tổ chức quản lí các cuộc gọi ra bên ngoài.
- Cần đăng ký các Intent cho Activity xử lý:
o Intent.ACTION_CALL_BUTTON
o Intent.ACTION_DIAL
o Intent.ACTION_VIEW
- Ví dụ đăng kí trong Intent trong AndroidManifest
<activity
android:name= “.MyDialerActivity”
android:label =”@string/app_name”>
<intent-filter>
<action android:name = “android.intent.action.CALL_BUTTON”/>
<category android:name = “android.intent.category.DEFAULT”/
</intent-filter>
<intent-filter>
<action android:name = “android.intent.action.VIEW”/>
<action android:name = “android.intent.action.DIAL” />
<category android:name = “android.intent.category.DEFAULT” />
<category android:name = “android.intent.category.BROWSANLE” />
<data android:scheme = “tel” />
</intent-filter>
</activity>
2. SMS
- Gửi tin nhắn bằng cách tạo một Intent để gọi ứng dụng Message trong thiết bị.
- Ví dụ:
o Tạo tin nhắn SMS
Intent smsIntent = new Intent(Intent.ACTION_SENDTO,Uri.parse(“sms:123456”));
smsIntent.putExtra(“sms_body”, “Press send to send me”);
startActivity(smsIntent);
- Ví dụ:
//Tạo tin nhắn MMS
Uri attached_Uri = Uri.parse("content://media/external/images/media/1");
Intent mmsIntent = new Intent(Intent.ACTION_SEND,attached_Uri);
mmsIntent.putExtra("sms_body", "Please see the attached image");
mmsIntent.putExtra("address", "07912355432");
mmsIntent.putExtra(Intent.EXTRA_STREAM, attached_Uri);
mmsIntent.setType("image/png");
startActivity(mmsIntent);
- Việc gửi tin nhắn được thực hiện bởi phương thức sendTextMessage của lớp
SmsManager
o Cú pháp:
sendTextMessage(Stringdestination Address,
String scAddress,
String text,
PendingIntent sentIntent,
PendingIntent deliveryIntent)
o Ví dụ:
String sendTo = “5551234”;
String myMessage = “Android supports programmatic SMS messaging!”;
smsManager.sendTextMessage(sendTo, null, myMessage, null, null);
- Theo dõi, xác nhận SMS tin nhắn đã được gửi bằng cách đăng ký BroadcastReceiver
để lắng nghe các hoạt động từ Pending Itent được tạo khi gửi tin nhắn.
o sentItent được gọi lên khi tin nhắn được gửi thành công hay lỗi.
Activity.RESULT_OK.
SmsManager.RESULT_ERROR_GENERIC_FAILURE.
SmsManager.RESULT_ERROR_RADIO_OFF.
SmsManager.RESULT_ERROR_NULL_PDU.
o deliveryIntent được gọi lên một khi thiết bị đích nhận được tin nhắn.
- Ví dụ về kiểm soát gửi tin nhắn
o Tạo Pending Intent
String SENT_SMS_ACTION = "SENT_SMS_ACTION " ;
String DELIVERED_SMS_ACTION = "DELIVERED_SMS_ACTION " ;
Intent sentIntent = new Intent(SENT_SMS_ACTION);
PendingIntent sentPI = PendingIntent.getBroadcast(getApplicationContext(),0,
sentIntent,0);
Intent deliveryIntent = new Intent(DELIVERED_SMS_ACTION);
PendingIntent deliverPI =
PendingIntent.getBroadcast(getApplicationContext(),0, deliveryIntent,0);
- Xử lý các tin nhắn dài hơn 160 ký tự bằng phương thức divideMessage() và
sendMultipartTextMessage().
o Cú pháp:
sendMultipartTextMessage(Stringdestination Address,
String scAddress,
ArrayList<String> parts,
ArrayList<PendingIntent> sentIntents,
ArrayList<PendingIntent> deliveryIntents)
o Ví dụ:
ArrayList<String> messageArray = smsManager.divideMessage(myMessage);
ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>();
for (int i = 0; i < messageArray.size(); i++)
sentIntents.add(sentPI);
smsManager.sendMultipartTextMessage(sendTo,null,messageArray, sentIntents,null);
o Ví dụ:
Intent sentIntent = new Intent(SENT_SMS_ACTION);
PendingIntent sentPI =
PendingIntent.getBroadcast(getApplicationContext(),0,sentIntent,0);
short destinationPort = 80;
byte[] data = [... your data ... ];
smsManager.sendDataMessage(sendTo,null,destinationPort,data, sentPI,null);
<receiver android:name="MySMSMonitor">
<intent-filter>
<action
android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
- Làm việc với các thư mục tin nhắn, cần đăng ký quyền trong AndroidManifest.xml
<uses-permission android:name=”android.permission.READ_SMS”/>
- Thực hiện truy vấn để lấy ra các thông tin về tin nhắn trong các thư mục với URI
tương ứng:
o All: content://sms/all
o Inbox : content://sms/inbox
o Sent: content://sms/sent
o Draft: content://sms/draft
o Outbox: content://sms/outbox
o Failed : content://sms/failed
o Queued: content://sms/queued
o Undelivered: content://sms/undelivered
o Conversations: content://sms/conversations
- Ví dụ truy vấn lấy nội dung các tin nhắn trong Inbox.
public class SMSInboxDemo extends ListActivity{
private ListAdapter adapter;
private static final Uri SMS_INBOX = Uri.parse(“content://sms/inbox”);
@Override
public void onCreate(Bundle bundle)
{
super.onCreate(bundle);
Cursor c = getContentResolver().Query(SMS_INBOX,null,null,null, null);
startManagingCursor(c);
String[] colums = new String[] {“body”};
int[] names = new int[] {R.id.row};
adapter=new SimpleCursorAdapter(this,R.layout.sms_inbox,c,colums,names);
setListAdapter(adapter);
}
}
Bài 7
BỘ CẢM BIẾN
- Ví dụ lấy thông tin cảm biến trên thiết bị thông qua SensorManager:
SensorManager mgr = (SensorManager)this.getSystemService(SENSOR_SERVICE);
Hình 7.1
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
- Override các onResume và onPause để thực hiện các thiết lập trên cảm biến.
- Ví dụ: đăng ký và hủy đăng ký bộ lắng nghe
@Override
protected void onResume(){
mgr.registerListener(this, light, SensorManager.SENSOR_DELAY_NORMAL);
super.onresume();
}
@Override
protected void onPause()
{
mgr.unregisterListener(this, light);
super.onPause();
}
- Trong phương thức registrerListener() ta thiết lập thông số để nắm bắt các giá trị thay
đổi của cảm biến.
o SENSOR_DELAY_NORMAL
o SENSOR_DELAY_UI
o SENSOR_DELAY_GAME
o SENSOR_DELAY_FASTEST
Hình 7.2
- Các thông số trên các trục x,y,z sẽ được tổng hợp và trả về duy nhất một giá trị
Rotation khi thiết bị thay đổi các trạng thái về phương hướng.
Hình 7.3
- Ví dụ sử dụng cảm biến gia tốc
SensorManager sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
Int sensorType = Sensor.TYPE_ACCELEROMATER;
Sm.registerListener(mySennorEventListener, sm.getDefaultSensor(sensorType),
SensorManager.SENSOR_DELAY_NORMAL);
final SennorEventListener mySennerEventListener = new SensorEventListener()
{
public void onSensorChanged(SensorEvent sensorEvent)
{
if(sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
{
float xAxis_lateralA = sensorEvent.values[0];
float yAxis_longitudinalA = sensorEvent.values[1];
float zAxis_verticalA = sensorEvent.values[2];
}
}
};
- Cần thực hiện phương thức isEnable() để kiểm tra trạng thái của cảm biến NFC.
- Không có phương thức cho phép tắt mở NFC.
startActivityForResult( new Intent(
android.provider.Settings.ACTION_WIRELESS_SETTINGS), 0);
- Thứ tự ưu tiên xử lý các gói Intent được gửi tới thiết bị:
o ACTION_NDEF_DISCOVERED: intent được sử dụng để khởi chạy một Activity
trong ứng dụng có đăng ký xử lý gói intent này.
o ACTION_TECH_DISCOVERED: nếu không có Activity nào đăng ký việc xử lý gói
intent đến, hệ thống sẽ khởi động ứng dụng thích hợp.
o ACTION_TAG_DISCOVERED: hệ thống chuyển sang xử lý kiểu dữ liệu Tag thông
thường.
Hình 7.4
- Cho phép ứng dụng chỉ cài đặt trên các thiết bị có hỗ trợ NFC:
<uses-feature android:name= “android.hardware.nfc” android:required=“true”/>
Mục lục
Bài 2: Kết nối các dịch vụ Web thao tác với dữ liệu XML và JSON .............................. 10
3. Xây dựng ứng dụng kết nối dịch vụ Web Restful ............................................................. 16
3. Camera ............................................................................................................................... 62
1. Telephone........................................................................................................................... 67
2. SMS ................................................................................................................................... 71