Tải bản đầy đủ (.docx) (38 trang)

Lập trình ứng dụng game trên Android

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (931.28 KB, 38 trang )

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN
KHOA CÔNG NGHỆ PHẦN MỀM

BÁO CÁO CUỐI KỲ

Môn ĐỒ ÁN MÔN HỌC
CHUYÊN NGÀNH
Đề tài : Lập trình ứng dụng game trên Android

Giảng viên :
ThS. Nguyễn Trác Thức
Sinh viên:
Nguyễn Công Huy
08520148
Võ Trường Thi

TP.HCM, ngày 01 tháng 06 năm 2012

08520375


LỜI MỞ ĐẦU
Ngày nay, điện thoại di động là một vật dụng không thể thiếu được trong cuộc sống. Nó
không chỉ có chức năng nghe gọi, mà còn có thể thực hiện được hầu hết những công việc
mà máy tính có thể làm, phục vụ cho nhu cầu văn phòng, giải trí và công việc.
Đặc biệt trong ngành phần mềm, game là một lĩnh vực đặc biệt, đang có bước phát triển
mạnh mẽ, khi mà nhu cầu giải trí trên các thiết bị di động của người sử dụng ngày một
tăng cao. Do đó, lập trình game trên các thiết bị di động đang là một xu hướng tất yếu của
các nhà làm phần mềm.
Điện thoại Android với số lượng người dùng đông đảo, cùng với sự đa dạng về cấu hình,
đa dạng về chủng loại, đang là mảnh đất màu mỡ cho các nhà phát triển game. Do đó,


google cũng đã hỗ trợ Android rất nhiều những thư viện để lập trình game hiệu quả, trong
đó có thể kể đến OpenGL, một thư viện đồ họa rất mạnh mẽ.
Với sự phát triển mạnh mẽ như vậy của Android, và lập trình game trên Android, cơ hội
cho lập trình viên là rất lớn. Vì vậy, nhóm đã chọn đề tài “Lập trình ứng dụng game trên
Android”. Trong đề tài này, nhóm sẽ trình bày cái nhìn cơ bản về lập trình game trên
Android và demo một ứng dụng game trong đó.
Cảm ơn thầy Nguyễn Trác Thức đã tận tình hướng dẫn chúng em hoàn thành đồ án này.


Mục lục


1. Tìm hiểu về Android.
1.1.

Giới thiệu

2.
3.
Android là một hệ điều hành dành cho các thiết bị di động, được
phát triển bởi Open Handset Alliance, dẫn đầu bởi Google.
4.
Android được phát triển bởi Google, dựa trên nền tảng Linux và các
phần mềm nguồn mở. Ban đầu nó được phát triển bởi Android Inc (sau đó
được Google mua lại) và gần đây nó trở thành một trong những phần mềm
đứng đầu của liên minh OHA (Open Handset Alliance - với khoảng 78
thành viên bao gồm cả nhà sản xuất, nhà phát triển ứng dụng... cho thiết bị
di dộng mà dẫn đầu là Google).
5.
Android được phát triển nhằm cạnh tranh với các hệ điều hành di

động khác như iOS (Apple), BlackBerry OS, Windows Mobile (Microsoft),
Symbian (Nokia), Samsung (Bada), WebOS (Palm)... Theo thống kê trong
quý II năm 2010 tại Mỹ, hệ điều hành Android chiếm thị phần 33% (cao
nhất) trong tổng số các hệ điều hành di động được bán ra, thứ 2 là
BlackBerry OS 28% và iOS (Apple) xếp thứ 3 với 22%.
5.1.

Cấu trúc hệ thống
6.
Android gồm các tầng thành phần như sau : Application, Application
Framework, Libraries, Linux Kernel.
7.

Báo cáo môn Đồ án môn học chuyên ngànhTrang 4


8.

9.

Các tầng cơ bản của nền tảng Android

9.1.1. Applications
10. Android cung cấp một bộ các ứng dụng tiện ích như email client,
SMS, lịch, bản đồ, trình duyệt … Tất cả đều được viết bằng ngôn ngữ
Java.
10.1.1.Application Framework.
11. Cung cấp một nền tảng mở cho các lập trình viên, giúp họ lập trình
ra những phần mềm với nhiều tính năng thú vị. Ở tầng này, Android
cung cấp khả năng truy cập tới phần cứng hệ thống, cũng như các dịch

vụ hệ điều hành cung cấp như thông tin vị trí, truy cập mạng, thông báo

12. Tầng này bao gồm các thành phần sau :
-

Một bộ các đối tượng View để xây dựng nên các ứng dụng bao gồm
list, grid, textboxes, buttons, và trình duyệt nhúng.

Báo cáo môn Đồ án môn học chuyên ngànhTrang 5


-

Content Providers cung cấp khả năng truy cập tới các dữ liệu của các
ứng dụng khác.

-

Resource Manager cung cấp khả năng truy cập tới các resource
không phải dạng code, như chuỗi, đồ họa và layout.

-

Notification Manager giúp hiện các alert lên status bar.

-

Activity Manager cung cấp khả năng quản lý vòng đời của ứng
dụng.


12.1.1.Libraries.
13. Android bao gồm một bộ các thư viện C/C++ sử dụng bởi các thành
phần khác nhau. Một số thư viện Android được sử dụng như :
-

System C library : Thư viện chuẩn C.

-

Thư viện đa phương tiện : dựa trên PacketVideo's OpenCORE, thư
viện hỗ trợ chơi các định dạng âm thanh và video phổ biến như
MPEG4, H.264, MP3, AAC, JPG, PNG…

-

Quản lý surface : Quản lý việc truy cập các hệ thống hiển thị bên
dưới, các lớp đồ họa 2D, 3D.

-

LibWebCore : Một engine trình duyệt hiện đại, được sử dụng trong
cả trình duyệt Android và WebView control.

-

SGL : Cơ sở của đồ họa 2D

-

3D libraries : thư viện đồ họa 3D OpenGL, sử dụng tăng tốc đồ họa

nếu phần cứng cho phép.

-

FreeType : thư viện render vector và bitmap font.

-

SQLite : Engine hệ quản trị cơ sở dữ liệu mạnh mẽ và nhẹ.

13.1.1.Android Runtimes
14. Mỗi ứng dụng Android chạy trên một tiến trình riêng, với một máy
ảo Dalvik. Máy ảo này thực thi file .dex, một dạng file được tối ưu cho
bộ nhớ nhỏ.
14.1.1.Nhân linux
Báo cáo môn Đồ án môn học chuyên ngànhTrang 6


15. Android dựa trên nhân linux 2.6 cho những dịch vụ hệ thống như
bảo mật, quản lý bộ nhớ, network stack và driver model. Nhân cũng
được coi như là một lớp ảo trung gian giữa phần cứng và phần mềm.
15.1. Các thành phần cơ bản của một ứng dụng Android.
16.
Một ứng dụng Android được tạo bởi một hay nhiều thành phần cơ
bản dưới đây:
16.1.1.Activity
17. Activity là thành phần có nhiệm vụ hiển thị ra giao diện của ứng
dụng. Một ứng dụng có thể bao gồm nhiều Activity. Chúng tồn tại độc
lập với nhau, nhưng cũng có thể gọi lẫn nhau. Một ứng dụng cũng có
thể gọi tới Activity của một ứng dụng khác (nếu được ứng dụng kia cho

phép).


Vòng đời của Activity

18.
19. Actitvity là thành phần quan trọng nhất và đóng vai trò chính trong
xây dựng ứng dụng Android.
20.
21. Hệ điều hành Android quản lý Activity theo dạng stack: khi một
Activity mới được khởi tạo, nó sẽ được xếp lên đầu của stack và trở
thành running activity, các Activity trước đó sẽ bị tạm dừng và chỉ hoạt
động trở lại khi Activity mới được giải phóng.
22.
23. Các trạng thái trong Activity:

Báo cáo môn Đồ án môn học chuyên ngànhTrang 7


24.

Báo cáo môn Đồ án môn học chuyên ngànhTrang 8


25. Running: Activity đang hiển thị trên màn hình (foreground).
26. Paused: Activity vẫn hiển thị (visible) nhưng không thể tương tác
(lost focus)
27. Stop: Activity bị thay thế hoàn toàn bởi Activity mới sẽ tiến đến
trạng thái stop
28. Killed: Khi hệ thống bị thiếu bộ nhớ, nó sẽ giải phóng các tiến trình

theo nguyên tắc ưu tiên. Các Activity ở trạng thái stop hoặc paused cũng
có thể bị giải phóng và khi nó được hiển thị lại thì các Activity này phải
khởi động lại hoàn toàn và phục hồi lại trạng thái trước đó.
29.
30.
• Khởi động Activity
31.
- Khai báo tường minh: cung cấp chính xác thông tin của activity cần
gọi (nếu cùng ứng dụng chỉ cần cung cấp tên class, nếu ứng dụng
khác nhau thì cung cấp tên package, tên class)
32.
33. Ví dụ: Gọi Activity tường minh
34.
35. Intent intent = new Intent(getApplicationContext(),
TargetActivity.class);
36. startActivity(intent);
37.
- Khai báo không tường minh: cung cấp thao tác cần làm gì, với loại
dữ liệu nào, thao tác thuộc nhóm nào… hệ thống sẽ tìm activity
tương ứng để khởi động.
38.
39. Ví dụ: Gọi Activity không tưởng minh
40.
41. Intent intent = new Intent(Intent.ACTION_VIEW);
42. intent.setData(MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
;

43. startActivity(intent);
44.
• Liên lạc giữa 2 Activity

45.
46. Khi khởi động một activity, ta có thể gửi kèm dữ liệu trong intent
như ví dụ sau:
47. intent.putExtra("value1", new String("Hello"));
48. intent.putExtra(“value2", new Long(100));Bên phía activity
được khởi động, có thể lấy dữ liệu được gửi như sau:

Báo cáo môn Đồ án môn học chuyên ngànhTrang 9


49. getIntent().getExtras().getString("value1");
50. getIntent().getExtras().getLong("value2");
51. Có thể khởi động một activity với một yêu cầu nào đó và activity kia
khi làm xong công việc sẽ trả lại kết quả cho activity trước
52.
53. Ví dụ activity A yêu cầu một activity làm giúp việc chụp ảnh,
activity B đáp ứng được việc này, sau khi user chụp ảnh xong sẽ trả lại
file ảnh cho activity A.
54.
55. Như thế sẽ đỡ tốn nhiều công sức làm một việc mà người khác đã
làm rồi.
55.1.1.Services
56. Service là một thành phần chạy nền, thực thi trong một thời gian dài.
Một service không cung cấp giao diện người dùng, mà chạy phía dưới,
không cần tương tác với người dùng. Một activity có thể khởi chạy một
dịch vụ và tương tác với chúng.
57. Một Service có thể được sử dụng theo 2 cách:
58.
59. - Nó có thể được bắt đầu và được cho phép hoạt động cho đến khi
một người nào đó dừng nó lại hoặc nó tự ngắt. Ở chế độ này, nó được

bắt đầu bằng cách gọi Context.startService() và dừng bằng lệnh
Context.stopService(). Nó có thể tự ngắt bằng lệnh Service.stopSelf()
hoặc Service.stopSelfResult(). Chỉ cần một lệnh stopService() để ngừng
Service lại cho dù lệnh startService() được gọi ra bao nhiêu lần.
60.
61. - Service có thể được vận hành theo như đã được lập trình việc sử
dụng một Interface mà nó định nghĩa. Các người dùng thiết lập một
đường truyền tới đối tượng Service và sử dụng đường kết nói đó để
thâm nhập vào Service. Kết nối này được thiết lập bằng cách gọi lệnh
Context.bindService() và được đóng lại bằng cách gọi lệnh
Context.unbindService(). Nhiều người dùng có thể kết nối tới cùng một
thiết bị. Nếu Service vẫn chưa được khởi chạy, lệnh bindService() có thể
tùy ý khởi chạy nó. Hai chế độ này thì không tách biệt toàn bộ. Bạn có
thể kết nối với một Service mà nó đã được bắt đầu với lệnh
startService(). Ví dụ, một Service nghe nhạc ở chế độ nền có thể được
bắt đầu bằng cách gọi lệnh startService() cùng với một đối tượng Intent
Báo cáo môn Đồ án môn học chuyên ngànhTrang 10


mà định dạng được âm nhạc để chơi. Chỉ sau đó, có thể là khi người sử
dụng muốn kiểm soát trình chơi nhạc hoặc biết thêm thông tin về bài hát
hiện tại đang chơi, thì sẽ có một Activity tạo lập một đường truyền tới
Service bằng cách gọi bindService(). Trong trường hợp như thế này,
stopService() sẽ không thực sự ngừng Service cho đến khi liên kết cuối
cùng được đóng lại.
62.
63. Giống như một Activity, một Service cũng có các phương thức chu
kỳ thời gian mà bạn có thể cài đặt để kiểm soát những sự thay đổi trong
trạng thái của nó. Những những phương thức của Service thì ít hơn là
của Activity – chỉ có 3- và chúng thì được sử dụng rộng rãi, không được

bảo vệ.
64. void onCreate()
65. void onStart(Intent intent)
66. void onDestroy()
67.
68. Bằng việc thực hiện những phương thức này, bạn có thể giám sát 2
vòng lặp của chu kỳ thời gian của mỗi Service.
69. Entire lifetime của một Service diễn ra giữa thời gian onCreate()
được gọi ra và thời gian mà onDestroy() trả lại. Giống như một Activity,
một Service lại tiết hành cài đặt ban đầu ở onCreate(), và giải phóng tát
cả các tài nguyên còn lại ở onDestroy() .
70.
71. Ví dụ, một Service phát lại nhạc có thể tạo ra một luồng và bắt đầu
chơi nhạc onCreate(),và sau đó luồng chơi nhạc sẽ dừng lại ở
onCreate(), Active lifetime của một Service bắt đầu bằng một lệnh tới
onStart(). Đâylà phương thức được chuyển giao đối tượng Intent mà đã
được thông qua để tới startService() Service âm nhạc sẽ mở đối tượng
Intent để quyết định xem sẽ chơi loại nhạc nào và bắt đầu phát nhạc.
72. Không có callback tương đương nào cho thời điểm Service ngừng lại
– không có phương thức onStop() .
73.
74. Các phương thức onCreate() và onDestroy() được gọi cho tất cả các
Service dù chúng có được bắt đầu bằng Context.startService() hoặc
Context.bindService() hay không. Tuy nhiên thì, onStart() chỉ được gọi
ra đối với các Service bắt đầu bằng startService().
75. Nếu một Service cho phép những Service khác kết nối với nó thì sẽ
có thêm các phương thức callback dành cho Service đó để thực hiên
76.
Báo cáo môn Đồ án môn học chuyên ngànhTrang 11



77. IBinder onBind(Intent intent)
78. boolean onUnbind(Intent intent)
79. void onRebind(Intent intent)
80.
81. Hàm callback onBind() thông qua đối tượng Intent đã đựoc truyền
đến bindService và onUnbind() được chuyển giao đối tượng mà đã được
chuyển đến. Nếu Service đang được chỉ định (binding), onBind() quay
trở lại kênh thông tin mà người dùng sử dụng để tương tác với Service.
Phương thức onUnbind() có thể yêu cầu onRebind() được gọi nếu một
người dùng kết nối với Service.
82.
83. Biểu đồ dưới đây minh họa cho các phương thức callback giành cho
một Service. Mặc dù, nó phân tách các Service được tạo ra thông qua
startService với các Service mà được tạo ra bằng bindService(). Hãy
nhớ rằng bất kì Service nào, cho dù nó được khởi tạo như thế nào thì nó
vẫn có thể cho phép các người dùng kết nối tới nó một cách hiệu quả
nhất, cho nên bất kì Service nào cũng có thể được chỉ định thông qua
các các phương thức onBind()và onUnbind().

Báo cáo môn Đồ án môn học chuyên ngànhTrang 12


84.

85. Service LifeCycle
85.1.1.Content Provider
86. Content Provider quản lý việc chia sẻ dữ liệu. Dữ liệu được lưu trữ
trong cơ sở dữ liệu, thẻ nhớ, trên Web. Thông qua content provider,
những ứng dụng khác có thể truy cập được những dữ liệu này.

86.1.1.Broadcast Receiver
Báo cáo môn Đồ án môn học chuyên ngànhTrang 13


87. Boardcast Receiver là thành phần đáp ứng lại những thông báo từ
phía hệ thống. Ví dụ như những thông báo tắt màn hình, pin yếu, …
Một ứng dụng cũng có thể tạo ra Broadcast Receiver, ví dụ như để
thông báo đã download xong một file nào đó. Tóm lại, Broadcast
Receiver là thành phần giúp phát ra một sự kiện nào đó tới toàn bộ hệ
thống, và một ứng dụng nào đó có thể nhận sự kiện này và xử lý tương
ứng.

88.

Kỹ thuật lập trình game trên Android.

89. Lập trình game về logic thì cũng giống như lập trình game trên các thiết bị khác.
Vấn đề ở đây là thiết bị di động Android có cấu hình khá thấp so với máy tính,
màn hình nhiều kích cỡ khác nhau, việc nhập liệu cũng không linh hoạt bằng. Vì
vậy lập trình game trên Android cũng đòi hỏi xử lý nhiều vấn đề phát sinh. Dưới
đây là một số kỹ thuật về lập trình game trên Android.
89.1. Thư viện đồ họa OpenGL

90.
91.
Như đã nói ở trên, thư viện đồ họa OpenGL là một thư viện đồ họa
3D, hỗ trợ tương tác trực tiếp với phần cứng, nhất là với bộ tăng tốc đồ họa.
Sử dụng thư viện đồ họa này, người dùng có thể tạo ra nhưng game có
những hiệu ứng phức tạp, chất lượng hình ảnh cao, mà vẫn giữ được sử
mượt mà cho game.

92.
OpengGL là một giao diện phần mềm độc lập với phần cứng
(hardware – independent software interface) hộ trợ cho lập trình đồ họa. Để
làm được điều này, OpenGL không thực hiện các tác vụ thuộc về hệ điều
hành cũng như không nhận dữ liệu nhập của người dùng (người dùng giao
tiếp với OpenGL thông qua OpenGL API). Nó là lớp trung gian giữa người
dùng và phần cứng. Nghĩa là nó giao tiếp trực tiếp với driver của thiết bị đồ
họa.
Báo cáo môn Đồ án môn học chuyên ngànhTrang 14


93.
Trong bộ NDK của Android đã tích hợp sẵn OpenGL ES, nên ta chỉ
việc include khi cần dùng đến những API của OpenGL.
94.
OpenGL vốn là một thư viện đồ họa 3D. Nhưng ta cũng có thể dùng
nó để vẽ hình ảnh 2D.
94.1.1.Khởi tạo OpenGL
95. Để tương tác được với OpenGL, trước tiên ta phải khởi tạo thiết bị
sử dụng OpenGL. Để khởi tạo, bên phía Java, ta tạo ra một lớp
GL2JNIView thừa kế từ lớp GLSurfaceView. GLSurfaceView là một
lớp được thừa kế từ lớp View, có tác dụng hiển thị hình ảnh được vẽ từ
OpenGL.
96. Trong hàm khởi tạo Activity, ta set view cho Activity là đối tượng
GL2JNIView.
97. mView

= new GL2JNIView(getApplication(), 320, 480);

98. setContentView(mView);

99. Tiếp theo, ta gọi một số hàm cài đặt phép chiếu của OpenGL, để
chuyển từ môi trường 2D sang 3D. Để tạo được hình ảnh 2D, ta sử dụng
phép chiếu song song. Trong hình bên dưới, bên trái là phép chiếu phối
cảnh, sẽ cho ta hình ảnh 3D, với cảm giác xa gần. Còn hình bên phải là
phép chiếu song song, sẽ loại bỏ cảm giác xa gần, cho ta hình ảnh 2D.
100.

Để tạo được hình ảnh này, ta dùng hàm

101.

glOrthof(0.0f, width, height, 0.f, -100.0f, 100.0f);

102.

Báo cáo môn Đồ án môn học chuyên ngànhTrang 15


103.

104.
105.
Tiếp theo, ta sẽ cấu hình một số thuộc tính, enable một số
chức năng như VertexArray (buffer chứa các đỉnh),
TexureCoordinateArray (mảng chứa tọa độ texture), chức năng vẽ với
kênh trong suốt alpha (Blend). Ngoài ra ta cũng disable một số chức
năng không cần thiết trong vẽ hình 2D như CullFace (loại bỏ hình ảnh
dựa vào chiều của các vertex, thường sử dụng trong 3D).
105.1.1. Texture
106.

Texture là lớp vật liệu để phủ lên bề mặt 3D. Nhưng ở đây khi
ta vẽ hình ảnh 2D, thì texture chính là những hình ảnh cần vẽ. Để load
được texture, chúng ta cần phải có một ImageData, là một mảng byte
màu. Mảng này được đọc ra từ file ảnh, trong trường hợp này là file
PNG. Sau khi khởi tạo texture, ta sẽ đưa mảng byte này gắn với texture
đó.
106.1.1. Vẽ texture
107.
Để vẽ được texture lên, ta cần phủ texture này lên một mảng đỉnh. Mảng
đỉnh này tạo ra một hình có dạng hình chữ nhật, với kích thước bằng kích thước ta
muốn vẽ lên màn hình. Sau đó, khi muốn vẽ phần nào của texture lên màn hình, ta

Báo cáo môn Đồ án môn học chuyên ngànhTrang 16


gán toạ độ tương ứng cho hình vẽ.
(0.0f, 0.0f)
108.

(1.0f, 0.0f)

109.

(1.0f, 0.0f)

110.

(1.0f,1.0f)
111.


111.1.

Thư viện âm thanh OpenAL

112.
113. Thư viện âm thanh OpenAL giúp cho việc chơi âm thanh hiệu quả
hơn. Thư viện này giúp tương tác trực tiếp với phần cứng âm thanh, đặc
biệt có khả năng tạo ra âm thanh vòm, làm cho game trở nên trung thực
hơn.
114. Các hàm chức năng chính của OpenAL được đóng gói trong source
object, audio buffer và single listener. Source object chứa con trỏ tới buffer,
vận tốc, vị trí và hướng của âm thanh. Listener object cũng tương tự source
object, nhưng là đối tượng người nghe. Buffer chứa dữ liệu âm thanh, định
dạng PCM. Renderring engine cần thiết cho việc tính toán khoảng cách, tạo
hiệu ứng Doppler…
115.

Trong NDK đã tích hợp các file header và thư viện OpenAL.

Báo cáo môn Đồ án môn học chuyên ngànhTrang 17


115.1.1. Khởi tạo OpenAL
116.

Để khởi tạo OpenAL, ta cần khởi tạo context cho device đó.

117.

_mContext = alcCreateContext(_mDevice,

contextAttribs);

118.

alcMakeContextCurrent(_mContext);

119.
Hàm alcCreateContext sẽ tạo ra context cho thiết bị, trong đó
_mDevice là id của thiết bị âm thanh. Thông thường điện thoại Android
chỉ có một chip xử lý âm thanh. Do đó ta gán _mDevice = 0.
120.
Hàm alcMakeContextCurrent sẽ gán context vừa tạo thành
context hiện tại.
120.1.1. Tạo đối tượng Audio
121.
Để tạo được đối tượng Audio, ta cần có audio data. Audio
data sẽ được load từ file
122.

Trước tiên ta load dữ liệu vào buffer:

123.
124.

alGenBuffers(1, &bufferID);

125.
này.

Sau đó ta tạo ra một source và gắn buffer vừa tạo vào source


126.
127.

alGenSources(1, &sourceID);

alBufferData(bufferID, format, auData, auDataSize,
samplesPerSec);

alSourcei(sourceID, AL_BUFFER, bufferID);

127.1.1. Chơi âm thanh.
128.
Trước khi chơi âm thanh, ta phải chỉ ra rằng ta đang sử dụng
source đó. Sau đó gọi hàm chơi âm thanh.
129.
130.
131.
132.
133.
134.

if (isLoop) {

135.

Tương tự cho là các hàm tạm dừng và dừng âm thanh.

alSourcei(sourceID, AL_LOOPING, AL_TRUE);
} else {

alSourcei(sourceID, AL_LOOPING, AL_FALSE);
}
alSourcePlay(sourceID);

Báo cáo môn Đồ án môn học chuyên ngànhTrang 18


135.1.
NDK
136. NDK là một tập hợp các công cụ cho phép nhúng code C/C++ vào
ứng dụng Android. Code C/C++ sẽ được biên dịch ra thành những thư viện
Linux. Những đoạn code viết bằng C/C++ sẽ được chạy trực tiếp không qua
máy ảo Dalvik, do đó làm tăng tốc độ thực thi của chương trình. Bên cạnh
đó, có nhiều thư viện được viết bằng C/C++, do đó có thể sử dụng được
những thư viện này ngay trên Android.
137.

NDK cung cấp một số hỗ trợ sau:

o Một tập hợp các Toos và files build dùng để tạo ra các thư viện mã từ
sources C và C++.
o Cách để nhúng các thư viện mã vào một file (.apk) gói ứng dụng mà chúng
ta có thể chạy được trên các thiết bị android.
o Tài liệu, ví dụ và một số hướng dẫn.
o Một bộ các thư viện C/C++ được hỗ trợ trong tất cả các phiên bản sau này
của hệ điều hành Android, bắt đầu từ Android 1.5. Từ phiên bản 2.3 trở đi,
hệ điều hành android còn hỗ trợ them cách viết Activity bằng C/C++.
138.

Khi nào thì dùng native code?


139.
Không phải khi nào NDK cũng đều có lợi với tất cả các ứng dụng.
Vì vậy chúng ta cần cân bằng lợi ích với nhược điểm của nó. Đặc biệt trong
trường hợp sử dụng native code không làm tăng hiệu suất thực thi mà làm tăng
sự phức tạp của ứng dụng. Nói chung chỉ nên sử dụng native lập trình nếu nó là
cần thiết đối với ứng dụng của mình không nên vì chúng ta thích chương trình
trong C/C++.
140.
- Framework Android cung cấp 2 cách để dùng native code : Dùng
Android framework để viết ứng dụng của mình và dùng JNI để truy cập API
được cung cấp bởi Android NDK. Kỹ thuật này cho phép chúng ta tận dụng
các tiện ích của Android Framework, nhưng vẫn cho phép chúng ta viết native
code khi cần thiết. Chúng ta có thể cài ứng dụng sử dụng Native code thông
qua JNI trên thiết bị chạy android 1.5 hoặc mới hơn.
141.
- Viết một native activity, cho phép chúng ta thực hiện cài đặt vòng
đời của ứng dụng android trên native code. Android SDK cung cấp lớp
NativeActivity cho phép chúng ta cài đặt vòng đời thông qua các hàm sau
(onCreate(), onResume(), ..).
Báo cáo môn Đồ án môn học chuyên ngànhTrang 19


142.
- Development tool NDK gồm một bộ công cụ (compilers,
linkers, ...) dùng để tạo ra mã nhị phân cho bộ vi xử lý ARM trên hệ điều hành
Linux, OS X, và Windows(với Cygwin). Cung cấp một bộ headers của hệ
thống cho các API native chuẩn mà được đảm bảo được hỗ trợ trong tất cả các
phiên bản sau này của nền tảng:






OpenGL ES 1.1 và OpenGL ES 2.0(thư viện graphics library) headers.
Libjnigraphics (Pixel buffer access) header(for Android 2.2. trở lên).
Thư viện OpenSL ES native audio.
API cho ứng dụng android.

143. NDK cũng cung cấp một hệ thống biên dịch giúp chúng ta làm việc hiệu
quả với mã nguồn của mình mà không cần điều khiển chi tiết các công cụ/ nền
tảng/ CPU/ ABI. Người dùng chỉ cần tạo các file biên dịch đơn giản để mô tả mã
nguồn của mình mà trong ứng dụng Android sử dụng. Và hệ thống biên dịch sẽ sử
dụng các file này để biên dịch, và tạo ra một thư viện động bỏ trực tiếp vào trong
dự án của mình.
144.

Hệ thống và phần mềm yêu cầu:

145.

- Hoàn tất cài đặt một Android SDK (bao gồm tất cả các phụ thuộc).

146.

- Phiên bản SDK Android 1.5 trở đi.

147. - Hệ điều hành hỗ trợ : Window XP (32-bit) hoặc vista (32- hoặc 64 -bit),
Mac Os x10.4.8 hoặc hơn (đối với X86), Linux (32 hoặc 64 bit, thử nghiệm trên
Linux Ubuntu Dapper Drake).

148.

- Các công cụ Cần Thiết:

149.

+ Đối với tất cả các nền tảng, bắt buộc GNU Make 3.81 trở lên.

150. + Đối với Window, bắt buộc Cygwin 1.7 trở lên. NDK không làm việc với
Cygwin 1.5.
151.

- Nền tảng Android tương thích.

152. Các thư viện native được tạo ra bởi Android NDK chỉ có thể sử dụng trên
các thiết bị Android phiên bản 1.5 trở đi. Điều này là do Bộ công cụ và ABI liên
quan đến những thay đổi làm cho các thư viện native không tương thích với hình
ảnh hệ thống 1.0 và 1.1. Vì lí do này nên chúng ta nên sử dụng thư viện native

Báo cáo môn Đồ án môn học chuyên ngànhTrang 20


được tạo ra với NDK trong ứng dụng mà được triển khai trên các thiết bị chạy trên
nền tảng android 1.5 trở đi.
153. Để đảm bảo tính tương thích, một ứng dụng dùng thư viện native tạo ra với
NDK phải khai báo <uses- sdk> phần tử trong file mainfese của nó, với một giá trị
thuộc tính của android:minSdkVersion 3 hoặc lớn hơn.
154.

Ví dụ:


155.
156.
157.

<manifest>
<uses-sdk android:minSdkVersion="3" />
... </manifest>

158.
159. - Hoạt động của JNI và quy trình biên dịch như chúng ta đều biết, ứng dụng
android chạy trên nền chính là Java. Muốn chạy C/C++ ta có hai giải pháp:
160.

+ Sử dụng JNI: từ android 1.5 trở về sau.

161. + Sử dụng Native Activity: từ android 2.3 trở về sau. Native Activity là
phương án lựa chọn tốt hơn, bởi vì chương trình sẽ không tốn chi phí giao dịch
giữa máy ảo Java và C/C++. Tuy nhiên, tới thời điểm hiện tại, số lươṇ g các thiết bị
hổ trợ Android 2.3 tưon̛ g đối hiếm nên chúng ta sẽ sử dụng giải pháp JNI.
162.
như sau:
163.

- Hoạt động của JNI được mô tả

+ Các phưon̛ g thức JNI được đánh dấu bằng từ khóa native.

164. + Các phưon̛ g thức này được viết bằng C++ và biên dịch ra thư viện liên kết
động .so.

165. + Thư viện liên kết động được Load lên trong chưon̛ g trình Java bằng lời
gọi System.loadLibrary(...);
166. + Khi trong chương trình Java có lời gọi tới hàm native, máy ảo Java sẽ tìm
kiếm trong thư viện động xem hàm này đã được cài đặt chưa, sau đó các đối tươṇ g
Java sẽ được chuyển thành C++ để thực hiện lời gọi tới C++.
167. + Trong C++ cũng cung cấp các thư viện cho phép giao tiếp tới máy ảo và
chương trình Java.
168.

Quy trình xây dựng một chương trình có sử dụng JNI như sau:

Báo cáo môn Đồ án môn học chuyên ngànhTrang 21


169.

- Khai báo phưon̛ g thức native ở trong lớp Java.

170. - Khai báo và cài đặt phương thức này trong C. (Nếu C++ thì phải sử dụng
extern “C” để tránh sửa tên trong C++). Quy tắc đặt tên hàm đó như sau:
171.

<tengoi_tenlop_tenphuongthuc>

172. Sau đó dùng NDK để biên dịch mã nguồn C thành thư viện liên kết động và
thư viện này được tự động bỏ vào thư mục lib của dự án android. Viết chưon̛ g trình
java gọi các hàm native này. Dùng bộ SDK để biên dịch thành ứng dụng apk.
173. - Do các bước sử dụng NDK để biên dịch được thực hiện trên dấu nhắc
lệnh, do đó chúng ta sẽ tạo tập tin lệnh để thực hiện điều này.
173.1.

174.

Lưu trữ thông tin.

175.
176.
Thông tin trong game trên Android có thể được lưu trữ trên SQLite
hoặc trên thẻ nhớ. Lưu trữ trên database sẽ có tính bảo mật cao hơn, chặt chẽ hơn.
Còn lưu trữ trên thẻ nhớ sẽ dễ backup hơn, dễ chuyển sang các thiết bị khác hơn.
177.
Ngoài hai cách lưu trữ thông tin như trên, Android còn cung cấp
cách lưu trữ thông tin thông qua đối tượng SharedReference. Thông tin lưu qua
đối tượng này sẽ được lưu tại thư mục của ứng dụng, nằm trong bộ nhớ trong của
máy.
178.

*Lưu trữ dữ liệu bằng SQLite:

179. Trong Android , cơ sở dữ liệu mà bạn tạo cho 1 ứng dụng thì chỉ ứng dụng
đó có quyền truy cập và sử dụng, các ứng dụng khác thì không. Khi đã được tạo,
cơ sở dữ liệu SQLite được chứa trong thư mục
/data/data//databases.
180.
Các bước thực hiện với CSDL:
1. Tạo 1 CSDL (thông thường chỉ cần làm 1 lần)
2. Mở CSDL đó
Báo cáo môn Đồ án môn học chuyên ngànhTrang 22


3. Thêm giá trị vào trong table

4. Truy vấn.
5. Đóng CSDL
1. Tạo cơ sở dữ liệu
Đầu tiên add 1 class DBAdapter để xử lý tất cả các thao tác liên quan đến
CSDL.
181.
182.
183.
184.
185.
186.
187.

public static final String KEY_ID = "_id";
public static final String KEY_NAME = "name";
private DatabaseHelper mDbHelper;
private SQLiteDatabase mDB;

private static final String DATABASE_CREATE = "create table users
(_id integer primary key autoincrement, "

188.
189.
190.
191.
192.
193.

+ "name text not null);";
private static final String DATABASE_NAME = "Database_Demo";

private static final String DATABASE_TABLE = "users";
private static final int DATABASE_VERSION = 2;
private final Context mContext;

194. Tạo 1 lớp bên trong DBAdapter được extend từ lớp SQLiteOpenHelper,
override 2 phương thức onCreate() và onUpgrade() để quản lý việc tạo CSDL và
version của CSDL đó.

195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.

private static class DatabaseHelper extends SQLiteOpenHelper{
public DatabaseHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
// TODO Auto-generated constructor stub
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub

db.execSQL(DATABASE_CREATE);
}
@Override

Báo cáo môn Đồ án môn học chuyên ngànhTrang 23


207.

public void onUpgrade(SQLiteDatabase db, int oldVersion, int
newVersion) {

208.
209.
210.
211.
212.
213.

214.

215.
216.
217.

// TODO Auto-generated method stub
Log.i(TAG, "Upgrading DB");
db.execSQL("DROP TABLE IF EXISTS users");
onCreate(db);
}

}

2. Mở CSDL

public DBAdapter open()
{

mDbHelper = new DatabaseHelper(mContext, DATABASE_NAME, null,
DATABASE_VERSION);

218.
219.
220.

221.

222.
223.
224.
225.
226.

mDB = mDbHelper.getWritableDatabase();
return this;
}

3. Thêm giá trị vào CSDL

public long createUser(String name){
ContentValues inititalValues = new ContentValues();

inititalValues.put(KEY_NAME, name);
return mDB.insert(DATABASE_TABLE, null, inititalValues);
}

227. 4. Truy vấn
Ta có thể get toàn bộ data hoặc có thể get data theo ID ( tiện cho việc chỉnh sửa
hay cập nhật thông tin của từng bản ghi).

228.
229.

public Cursor getAllUsers(){

230.

}

return mDB.query(DATABASE_TABLE, new String[] {KEY_ID,
KEY_NAME}, null, null, null, null, null);

231. Còn rất nhiều các thao tác như sửa, xóa, update.... bản ghi, tất cả các chức
năng đó đều được cung cấp bởi lớp SQLiteDatabase, ta chỉ cần cụ thể hóa bằng
các câu truy vấn là được.
Báo cáo môn Đồ án môn học chuyên ngànhTrang 24


5. Đóng CSDL

232.
233.

234.

235.

public void close(){
mDbHelper.close();
}

6. Sử dụng CSDL

Để test CSDL mà bạn vừa tạo, ta có thể thêm 1 vài dòng code để thêm 1 user và
hiển thị CSDL lên màn hình thông qua lớp Activity ban đầu:
Ví dụ ở đây ta tạo mới 1 user thông qua câu lệnh mDB.createUser("Username");
sau đó

236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.


public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mDB = new DBAdapter(this);
mDB.open();
mDB.createUser("Do Minh Thong");
getData();
}
private void getData(){
mCursor = mDB.getAllUsers();
startManagingCursor(mCursor);
String[] from = new String[]{DBAdapter.KEY_NAME};
int[] to = new int[] {R.id.text1};

SimpleCursorAdapter users = new SimpleCursorAdapter(this,
R.layout.users_row, mCursor, from, to);

250.
251.

setListAdapter(users);
}

252.
252.1.
-

Các thư viện khác.
libzip : đọc file zip, giúp đọc dữ liệu từ file apk.


-

libpng : đọc file png thành dữ liệu thô của hình ảnh.

Báo cáo môn Đồ án môn học chuyên ngànhTrang 25


×